From: Dmitry Stogov Date: Wed, 27 Jun 2007 10:27:04 +0000 (+0000) Subject: Implemented ++ and -- operations for unicode strings X-Git-Tag: BEFORE_IMPORT_OF_MYSQLND~375 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eae255addf943f5afafbe57e5a1785a265523c59;p=php Implemented ++ and -- operations for unicode strings --- diff --git a/Zend/tests/decrement_001.phpt b/Zend/tests/decrement_001.phpt index 6ade8ad163..6449187a34 100644 --- a/Zend/tests/decrement_001.phpt +++ b/Zend/tests/decrement_001.phpt @@ -58,3 +58,29 @@ array(0) { float(-2147483649) float(-2147483649) Done +--UEXPECTF-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +int(-1) +int(0) +float(1.5) +int(-1) +unicode(6) "string" +int(122) +float(1.5) +NULL +bool(true) +bool(false) +object(stdClass)#%d (0) { +} +array(0) { +} +float(-2147483649) +float(-2147483649) +Done diff --git a/Zend/tests/decrement_001_64bit.phpt b/Zend/tests/decrement_001_64bit.phpt index 7ad24b76f7..2e79d76c85 100644 --- a/Zend/tests/decrement_001_64bit.phpt +++ b/Zend/tests/decrement_001_64bit.phpt @@ -58,3 +58,29 @@ array(0) { float(-9.2233720368548E+18) float(-9.2233720368548E+18) Done +--UEXPECTF-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +int(-1) +int(0) +float(1.5) +int(-1) +unicode(6) "string" +int(122) +float(1.5) +NULL +bool(true) +bool(false) +object(stdClass)#%d (0) { +} +array(0) { +} +float(-9.2233720368548E+18) +float(-9.2233720368548E+18) +Done diff --git a/Zend/tests/increment_001.phpt b/Zend/tests/increment_001.phpt index 3638474971..fa524664f3 100644 --- a/Zend/tests/increment_001.phpt +++ b/Zend/tests/increment_001.phpt @@ -58,3 +58,29 @@ array(0) { float(2147483648) float(2147483648) Done +--UEXPECTF-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +unicode(1) "1" +int(2) +float(3.5) +int(1) +unicode(6) "strinh" +int(124) +float(3.5) +int(1) +bool(true) +bool(false) +object(stdClass)#%d (0) { +} +array(0) { +} +float(2147483648) +float(2147483648) +Done diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index acecc56109..e245150a62 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2274,6 +2274,80 @@ static void increment_string(zval *str) } } +static void increment_unicode(zval *str) +{ + int carry=0; + int pos=Z_USTRLEN_P(str)-1; + UChar *s=Z_USTRVAL_P(str); + UChar *t; + int last=0; /* Shut up the compiler warning */ + int ch; + + if (Z_USTRLEN_P(str) == 0) { + USTR_FREE(Z_USTRVAL_P(str)); + ZVAL_ASCII_STRINGL(str, "1", sizeof("1")-1, 1); + return; + } + + while (pos >= 0) { + ch = s[pos]; + if (ch >= 'a' && ch <= 'z') { + if (ch == 'z') { + s[pos] = 'a'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last=LOWER_CASE; + } else if (ch >= 'A' && ch <= 'Z') { + if (ch == 'Z') { + s[pos] = 'A'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last=UPPER_CASE; + } else if (ch >= '0' && ch <= '9') { + if (ch == '9') { + s[pos] = '0'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last = NUMERIC; + } else { + carry=0; + break; + } + if (carry == 0) { + break; + } + pos--; + } + + if (carry) { + t = (UChar *) eumalloc(Z_USTRLEN_P(str)+1+1); + memcpy(t+1, Z_USTRVAL_P(str), UBYTES(Z_USTRLEN_P(str))); + Z_USTRLEN_P(str)++; + t[Z_USTRLEN_P(str)] = 0; + switch (last) { + case NUMERIC: + t[0] = '1'; + break; + case UPPER_CASE: + t[0] = 'A'; + break; + case LOWER_CASE: + t[0] = 'a'; + break; + } + USTR_FREE(Z_USTRVAL_P(str)); + Z_USTRVAL_P(str) = t; + } +} ZEND_API int increment_function(zval *op1) { @@ -2323,8 +2397,34 @@ ZEND_API int increment_function(zval *op1) } } break; - case IS_UNICODE: - zend_error(E_ERROR, "Unsupported operand type"); + case IS_UNICODE: { + long lval; + double dval; + UChar *ustrval = Z_USTRVAL_P(op1); + + switch (is_numeric_unicode(ustrval, Z_USTRLEN_P(op1), &lval, &dval, 0)) { + case IS_LONG: + if (lval == LONG_MAX) { + /* switch to double */ + double d = (double)lval; + ZVAL_DOUBLE(op1, d+1); + } else { + Z_LVAL_P(op1) = lval+1; + Z_TYPE_P(op1) = IS_LONG; + } + efree(ustrval); /* should never be empty_string */ + break; + case IS_DOUBLE: + Z_DVAL_P(op1) = dval+1; + Z_TYPE_P(op1) = IS_DOUBLE; + efree(ustrval); /* should never be empty_string */ + break; + default: + /* Perl style string increment */ + increment_unicode(op1); + break; + } + } break; default: return FAILURE; @@ -2376,7 +2476,29 @@ ZEND_API int decrement_function(zval *op1) } break; case IS_UNICODE: - zend_error(E_ERROR, "Unsupported operand type"); + if (Z_USTRLEN_P(op1) == 0) { /* consider as 0 */ + USTR_FREE(Z_USTRVAL_P(op1)); + Z_LVAL_P(op1) = -1; + Z_TYPE_P(op1) = IS_LONG; + break; + } + switch (is_numeric_unicode(Z_USTRVAL_P(op1), Z_USTRLEN_P(op1), &lval, &dval, 0)) { + case IS_LONG: + USTR_FREE(Z_USTRVAL_P(op1)); + if (lval == LONG_MIN) { + double d = (double)lval; + ZVAL_DOUBLE(op1, d-1); + } else { + Z_LVAL_P(op1) = lval-1; + Z_TYPE_P(op1) = IS_LONG; + } + break; + case IS_DOUBLE: + USTR_FREE(Z_USTRVAL_P(op1)); + Z_DVAL_P(op1) = dval - 1; + Z_TYPE_P(op1) = IS_DOUBLE; + break; + } break; default: return FAILURE;