andrei Thu Aug 18 18:51:49 2005 EDT Modified files: /php-src/ext/standard array.c Log: Rework range() to be able to work on binary strings and also on Unicode code points. Binary strings are not interpreted as numeric. http://cvs.php.net/diff.php/php-src/ext/standard/array.c?r1=1.317&r2=1.318&ty=u Index: php-src/ext/standard/array.c diff -u php-src/ext/standard/array.c:1.317 php-src/ext/standard/array.c:1.318 --- php-src/ext/standard/array.c:1.317 Thu Aug 18 11:14:07 2005 +++ php-src/ext/standard/array.c Thu Aug 18 18:51:46 2005 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: array.c,v 1.317 2005/08/18 15:14:07 dmitry Exp $ */ +/* $Id: array.c,v 1.318 2005/08/18 22:51:46 andrei Exp $ */ #include "php.h" #include "php_ini.h" @@ -1701,22 +1701,6 @@ } /* }}} */ -static void u_add_next_index_stringl(zval *arg, char *str, uint length, int duplicate TSRMLS_DC) -{ - if (UG(unicode)) { - UErrorCode status = U_ZERO_ERROR; - UChar *u_str; - int32_t u_len; - - zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, str, length, &status); - add_next_index_unicodel(arg, u_str, u_len, 0); - if (!duplicate) { - efree(str); - } - } else { - add_next_index_stringl(arg, str, length, duplicate); - } -} /* {{{ proto array range(mixed low, mixed high[, int step]) Create an array containing the range of integers or characters from low to high (inclusive) */ @@ -1725,6 +1709,7 @@ zval *zlow, *zhigh, *zstep = NULL; int err = 0, is_step_double = 0; double step = 1.0; + zend_uchar str_type; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/|z/", &zlow, &zhigh, &zstep) == FAILURE) { RETURN_FALSE; @@ -1746,35 +1731,37 @@ } } + /* Unify types */ + str_type = zend_get_unified_string_type(2, Z_TYPE_P(zlow), Z_TYPE_P(zhigh)); + if (str_type == (zend_uchar)-1) { + zend_error(E_WARNING, "Cannot mix binary and Unicode parameters"); + return; + } + convert_to_explicit_type(zlow, str_type); + convert_to_explicit_type(zhigh, str_type); + /* Initialize the return_value as an array. */ array_init(return_value); - if (Z_TYPE_P(zlow) == IS_UNICODE) { - convert_to_string(zlow); - } - - if (Z_TYPE_P(zhigh) == IS_UNICODE) { - convert_to_string(zhigh); - } - /* If the range is given as strings, generate an array of characters. */ - if (Z_TYPE_P(zlow) == IS_STRING && - Z_TYPE_P(zhigh) == IS_STRING && - Z_STRLEN_P(zlow) >= 1 && - Z_STRLEN_P(zhigh) >= 1) { - int type1, type2; + if ((Z_TYPE_P(zlow) == IS_STRING || Z_TYPE_P(zlow) == IS_BINARY) && + Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) { + zend_uchar type1, type2; unsigned char *low, *high; long lstep = (long) step; - type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0); - type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0); - - if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) { - goto double_str; - } else if (type1 == IS_LONG || type2 == IS_LONG) { - goto long_str; + if (Z_TYPE_P(zlow) == IS_STRING) { + type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0); + type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0); + + if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) { + goto double_str; + } else if (type1 == IS_LONG || type2 == IS_LONG) { + goto long_str; + } } + /* safe to use STR versions for binary since they access the same fields */ low = (unsigned char *)Z_STRVAL_P(zlow); high = (unsigned char *)Z_STRVAL_P(zhigh); @@ -1784,7 +1771,11 @@ goto err; } for (; *low >= *high; (*low) -= (unsigned int)lstep) { - u_add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + if (Z_TYPE_P(zlow) == IS_STRING) { + add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + } else { + add_next_index_binaryl(return_value, low, 1, 1 TSRMLS_CC); + } if (((signed int)*low - lstep) < 0) { break; } @@ -1795,15 +1786,68 @@ goto err; } for (; *low <= *high; (*low) += (unsigned int)lstep) { - u_add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + if (Z_TYPE_P(zlow) == IS_STRING) { + add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + } else { + add_next_index_binaryl(return_value, low, 1, 1 TSRMLS_CC); + } if (((signed int)*low + lstep) > 255) { break; } } } else { - u_add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + if (Z_TYPE_P(zlow) == IS_STRING) { + add_next_index_stringl(return_value, low, 1, 1 TSRMLS_CC); + } else { + add_next_index_binaryl(return_value, low, 1, 1 TSRMLS_CC); + } + } + } else if (Z_TYPE_P(zlow) == IS_UNICODE && + Z_USTRLEN_P(zlow) >= 1 && Z_USTRLEN_P(zhigh) >= 1) { + zend_uchar type1, type2; + UChar32 low, high; + uint32_t lstep = (uint32_t) step; + UChar buf[2]; + + type1 = is_numeric_unicode(Z_USTRVAL_P(zlow), Z_USTRLEN_P(zlow), NULL, NULL, 0); + type2 = is_numeric_unicode(Z_USTRVAL_P(zhigh), Z_USTRLEN_P(zhigh), NULL, NULL, 0); + + if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) { + goto double_str; + } else if (type1 == IS_LONG || type2 == IS_LONG) { + goto long_str; } + low = zend_get_codepoint_at(Z_USTRVAL_P(zlow), Z_USTRLEN_P(zlow), 0); + high = zend_get_codepoint_at(Z_USTRVAL_P(zhigh), Z_USTRLEN_P(zhigh), 0); + + if (low > high) { /* Negative Steps */ + if (lstep <= 0) { + err = 1; + goto err; + } + for (; low >= high; low -= lstep) { + /* no need to check return value of zend_codepoint_to_uchar() + since the range endpoints will always be valid */ + add_next_index_unicodel(return_value, buf, zend_codepoint_to_uchar(low, buf), 1 TSRMLS_CC); + if (((int32_t)low - lstep) < 0) { + break; + } + } + } else if (high > low) { /* Positive Steps */ + if (lstep <= 0) { + err = 1; + goto err; + } + for (; low <= high; low += lstep) { + add_next_index_unicodel(return_value, buf, zend_codepoint_to_uchar(low, buf), 1 TSRMLS_CC); + if (((int32_t)low + lstep) > UCHAR_MAX_VALUE) { + break; + } + } + } else { + add_next_index_unicodel(return_value, buf, zend_codepoint_to_uchar(low, buf), 1 TSRMLS_CC); + } } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { double low, high; double_str:
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php