Annotation of embedaddon/php/ext/standard/versioning.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Stig Sæther Bakken <ssb@php.net>                             |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #include <stdio.h>
                     22: #include <sys/types.h>
                     23: #include <ctype.h>
                     24: #include <stdlib.h>
                     25: #include <string.h>
                     26: #include "php.h"
                     27: #include "php_versioning.h"
                     28: 
                     29: #define sign(n) ((n)<0?-1:((n)>0?1:0))
                     30: 
                     31: /* {{{ php_canonicalize_version() */
                     32: 
                     33: PHPAPI char *
                     34: php_canonicalize_version(const char *version)
                     35: {
                     36:     int len = strlen(version);
                     37:     char *buf = safe_emalloc(len, 2, 1), *q, lp, lq;
                     38:     const char *p;
                     39: 
                     40:     if (len == 0) {
                     41:         *buf = '\0';
                     42:         return buf;
                     43:     }
                     44: 
                     45:     p = version;
                     46:     q = buf;
                     47:     *q++ = lp = *p++;
                     48: 
                     49:     while (*p) {
                     50: /*  s/[-_+]/./g;
                     51:  *  s/([^\d\.])([^\D\.])/$1.$2/g;
                     52:  *  s/([^\D\.])([^\d\.])/$1.$2/g;
                     53:  */
                     54: #define isdig(x) (isdigit(x)&&(x)!='.')
                     55: #define isndig(x) (!isdigit(x)&&(x)!='.')
                     56: #define isspecialver(x) ((x)=='-'||(x)=='_'||(x)=='+')
                     57: 
                     58:                lq = *(q - 1);
                     59:                if (isspecialver(*p)) {
                     60:                        if (lq != '.') {
                     61:                                *q++ = '.';
                     62:                        }
                     63:                } else if ((isndig(lp) && isdig(*p)) || (isdig(lp) && isndig(*p))) {
                     64:                        if (lq != '.') {
                     65:                                *q++ = '.';
                     66:                        }
                     67:                        *q++ = *p;
                     68:                } else if (!isalnum(*p)) {
                     69:                        if (lq != '.') {
                     70:                                *q++ = '.';
                     71:                        }
                     72:                } else {
                     73:                        *q++ = *p;
                     74:                }
                     75:                lp = *p++;
                     76:     }
                     77:     *q++ = '\0';
                     78:     return buf;
                     79: }
                     80: 
                     81: /* }}} */
                     82: /* {{{ compare_special_version_forms() */
                     83: 
                     84: typedef struct {
                     85:        const char *name;
                     86:        int order;
                     87: } special_forms_t;
                     88: 
                     89: static int
                     90: compare_special_version_forms(char *form1, char *form2)
                     91: {
                     92:        int found1 = -1, found2 = -1;
                     93:        special_forms_t special_forms[11] = {
                     94:                {"dev", 0},
                     95:                {"alpha", 1},
                     96:                {"a", 1},
                     97:                {"beta", 2},
                     98:                {"b", 2},
                     99:                {"RC", 3},
                    100:                {"rc", 3},
                    101:                {"#", 4},
                    102:                {"pl", 5},
                    103:                {"p", 5},
                    104:                {NULL, 0},
                    105:        };
                    106:        special_forms_t *pp;
                    107: 
                    108:        for (pp = special_forms; pp && pp->name; pp++) {
                    109:                if (strncmp(form1, pp->name, strlen(pp->name)) == 0) {
                    110:                        found1 = pp->order;
                    111:                        break;
                    112:                }
                    113:        }
                    114:        for (pp = special_forms; pp && pp->name; pp++) {
                    115:                if (strncmp(form2, pp->name, strlen(pp->name)) == 0) {
                    116:                        found2 = pp->order;
                    117:                        break;
                    118:                }
                    119:        }
                    120:        return sign(found1 - found2);
                    121: }
                    122: 
                    123: /* }}} */
                    124: /* {{{ php_version_compare() */
                    125: 
                    126: PHPAPI int
                    127: php_version_compare(const char *orig_ver1, const char *orig_ver2)
                    128: {
                    129:        char *ver1;
                    130:        char *ver2;
                    131:        char *p1, *p2, *n1, *n2;
                    132:        long l1, l2;
                    133:        int compare = 0;
                    134: 
                    135:        if (!*orig_ver1 || !*orig_ver2) {
                    136:                if (!*orig_ver1 && !*orig_ver2) {
                    137:                        return 0;
                    138:                } else {
                    139:                        return *orig_ver1 ? 1 : -1;
                    140:                }
                    141:        }
                    142:        if (orig_ver1[0] == '#') {
                    143:                ver1 = estrdup(orig_ver1);
                    144:        } else {
                    145:                ver1 = php_canonicalize_version(orig_ver1);
                    146:        }
                    147:        if (orig_ver2[0] == '#') {
                    148:                ver2 = estrdup(orig_ver2);
                    149:        } else {
                    150:                ver2 = php_canonicalize_version(orig_ver2);
                    151:        }
                    152:        p1 = n1 = ver1;
                    153:        p2 = n2 = ver2;
                    154:        while (*p1 && *p2 && n1 && n2) {
                    155:                if ((n1 = strchr(p1, '.')) != NULL) {
                    156:                        *n1 = '\0';
                    157:                }
                    158:                if ((n2 = strchr(p2, '.')) != NULL) {
                    159:                        *n2 = '\0';
                    160:                }
                    161:                if (isdigit(*p1) && isdigit(*p2)) {
                    162:                        /* compare element numerically */
                    163:                        l1 = strtol(p1, NULL, 10);
                    164:                        l2 = strtol(p2, NULL, 10);
                    165:                        compare = sign(l1 - l2);
                    166:                } else if (!isdigit(*p1) && !isdigit(*p2)) {
                    167:                        /* compare element names */
                    168:                        compare = compare_special_version_forms(p1, p2);
                    169:                } else {
                    170:                        /* mix of names and numbers */
                    171:                        if (isdigit(*p1)) {
                    172:                                compare = compare_special_version_forms("#N#", p2);
                    173:                        } else {
                    174:                                compare = compare_special_version_forms(p1, "#N#");
                    175:                        }
                    176:                }
                    177:                if (compare != 0) {
                    178:                        break;
                    179:                }
                    180:                if (n1 != NULL) {
                    181:                        p1 = n1 + 1;
                    182:                }
                    183:                if (n2 != NULL) {
                    184:                        p2 = n2 + 1;
                    185:                }
                    186:        }
                    187:        if (compare == 0) {
                    188:                if (n1 != NULL) {
                    189:                        if (isdigit(*p1)) {
                    190:                                compare = 1;
                    191:                        } else {
                    192:                                compare = php_version_compare(p1, "#N#");
                    193:                        }
                    194:                } else if (n2 != NULL) {
                    195:                        if (isdigit(*p2)) {
                    196:                                compare = -1;
                    197:                        } else {
                    198:                                compare = php_version_compare("#N#", p2);
                    199:                        }
                    200:                }
                    201:        }
                    202:        efree(ver1);
                    203:        efree(ver2);
                    204:        return compare;
                    205: }
                    206: 
                    207: /* }}} */
                    208: /* {{{ proto int version_compare(string ver1, string ver2 [, string oper])
                    209:   Compares two "PHP-standardized" version number strings */
                    210: 
                    211: PHP_FUNCTION(version_compare)
                    212: {
                    213:        char *v1, *v2, *op = NULL;
                    214:        int v1_len, v2_len, op_len = 0;
                    215:        int compare, argc;
                    216: 
                    217:        argc = ZEND_NUM_ARGS();
                    218:        if (zend_parse_parameters(argc TSRMLS_CC, "ss|s", &v1, &v1_len, &v2,
                    219:                                                          &v2_len, &op, &op_len) == FAILURE) {
                    220:                return;
                    221:        }
                    222:        compare = php_version_compare(v1, v2);
                    223:        if (argc == 2) {
                    224:                RETURN_LONG(compare);
                    225:        }
                    226:        if (!strncmp(op, "<", op_len) || !strncmp(op, "lt", op_len)) {
                    227:                RETURN_BOOL(compare == -1);
                    228:        }
                    229:        if (!strncmp(op, "<=", op_len) || !strncmp(op, "le", op_len)) {
                    230:                RETURN_BOOL(compare != 1);
                    231:        }
                    232:        if (!strncmp(op, ">", op_len) || !strncmp(op, "gt", op_len)) {
                    233:                RETURN_BOOL(compare == 1);
                    234:        }
                    235:        if (!strncmp(op, ">=", op_len) || !strncmp(op, "ge", op_len)) {
                    236:                RETURN_BOOL(compare != -1);
                    237:        }
                    238:        if (!strncmp(op, "==", op_len) || !strncmp(op, "=", op_len) || !strncmp(op, "eq", op_len)) {
                    239:                RETURN_BOOL(compare == 0);
                    240:        }
                    241:        if (!strncmp(op, "!=", op_len) || !strncmp(op, "<>", op_len) || !strncmp(op, "ne", op_len)) {
                    242:                RETURN_BOOL(compare != 0);
                    243:        }
                    244:        RETURN_NULL();
                    245: }
                    246: 
                    247: /* }}} */
                    248: 
                    249: /*
                    250:  * Local variables:
                    251:  * tab-width: 4
                    252:  * c-basic-offset: 4
                    253:  * indent-tabs-mode: t
                    254:  * End:
                    255:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>