andrei Tue Aug 1 21:50:44 2006 UTC Modified files: /php-src unicode-progress.txt /php-src/ext/standard array.c Log: Whew. Fix up extract to params API, Unicode support, and simplify it as well.
http://cvs.php.net/viewvc.cgi/php-src/unicode-progress.txt?r1=1.30&r2=1.31&diff_format=u Index: php-src/unicode-progress.txt diff -u php-src/unicode-progress.txt:1.30 php-src/unicode-progress.txt:1.31 --- php-src/unicode-progress.txt:1.30 Fri Jul 21 23:25:08 2006 +++ php-src/unicode-progress.txt Tue Aug 1 21:50:44 2006 @@ -13,9 +13,6 @@ array_multisort() Add SORT_LOCALE_STRING, test - extract() - Params API, fix php_valid_var_name(), test - natsort(), natcasesort() Params API Either port strnatcmp() to support Unicode or maybe use ICU's numeric collation @@ -54,6 +51,7 @@ array_walk_recursive() compact() count() + extract() in_array() min() max() http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.375&r2=1.376&diff_format=u Index: php-src/ext/standard/array.c diff -u php-src/ext/standard/array.c:1.375 php-src/ext/standard/array.c:1.376 --- php-src/ext/standard/array.c:1.375 Fri Jul 21 23:47:40 2006 +++ php-src/ext/standard/array.c Tue Aug 1 21:50:44 2006 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: array.c,v 1.375 2006/07/21 23:47:40 andrei Exp $ */ +/* $Id: array.c,v 1.376 2006/08/01 21:50:44 andrei Exp $ */ #include "php.h" #include "php_ini.h" @@ -1234,133 +1234,164 @@ /* }}} */ -static int php_valid_var_name(char *var_name) +static int php_valid_var_name(zstr var_name, int var_name_len, int var_name_type) { - int len, i; - - if (!var_name) - return 0; - - len = strlen(var_name); + int i; - if (!isalpha((int)((unsigned char *)var_name)[0]) && var_name[0] != '_') + if (!var_name.v) return 0; - if (len > 1) { - for (i=1; i<len; i++) { - if (!isalnum((int)((unsigned char *)var_name)[i]) && var_name[i] != '_') { - return 0; + if (var_name_type == IS_STRING) { + if (!isalpha((int)((unsigned char *)var_name.s)[0]) && var_name.s[0] != '_') + return 0; + + if (var_name_len > 1) { + for (i=1; i<var_name_len; i++) { + if (!isalnum((int)((unsigned char *)var_name.s)[i]) && var_name.s[i] != '_') { + return 0; + } } } + } else { + if (!zend_is_valid_identifier(var_name.u, var_name_len)) { + return 0; + } } return 1; } +static int php_extract_prefix_varname(zval *result, zval *prefix, zstr var_name, + int var_name_len, int var_name_type TSRMLS_DC) +{ + Z_UNILEN_P(result) = Z_UNILEN_P(prefix) + 1 + var_name_len; + if (UG(unicode)) { + Z_TYPE_P(result) = IS_UNICODE; + Z_USTRVAL_P(result) = eumalloc(Z_USTRLEN_P(result)+1); + u_memcpy(Z_USTRVAL_P(result), Z_USTRVAL_P(prefix), Z_USTRLEN_P(prefix)); + Z_USTRVAL_P(result)[Z_USTRLEN_P(prefix)] = (UChar) 0x5f /*'_'*/; + if (var_name_type == IS_UNICODE) { + u_memcpy(Z_USTRVAL_P(result)+Z_USTRLEN_P(prefix)+1, var_name.u, var_name_len+1); + } else { + UChar *buf; + int buf_len; + UErrorCode status = U_ZERO_ERROR; + + zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), + &buf, &buf_len, var_name.s, var_name_len, &status); + if (U_FAILURE(status)) { + zval_dtor(result); + ZVAL_NULL(result); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert variable name to Unicode string"); + return FAILURE; + } + if (buf_len > var_name_len) { + Z_USTRLEN_P(result) = Z_USTRLEN_P(prefix) + 1 + buf_len; + Z_USTRVAL_P(result) = eurealloc(Z_USTRVAL_P(result), Z_USTRLEN_P(result)+1); + } + u_memcpy(Z_USTRVAL_P(result)+Z_USTRLEN_P(prefix)+1, buf, buf_len+1); + } + } else { + Z_TYPE_P(result) = IS_STRING; + Z_STRVAL_P(result) = emalloc(Z_STRLEN_P(result)+1); + memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix)); + Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_'; + if (var_name_type == IS_STRING) { + memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(prefix)+1, var_name.s, var_name_len+1); + } else { + char *buf; + int buf_len; + UErrorCode status = U_ZERO_ERROR; + + zend_convert_from_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), + &buf, &buf_len, var_name.u, var_name_len, &status); + if (U_FAILURE(status)) { + zval_dtor(result); + ZVAL_NULL(result); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert variable name to string"); + return FAILURE; + } + if (buf_len > var_name_len) { + Z_STRLEN_P(result) = Z_STRLEN_P(prefix) + 1 + buf_len; + Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), Z_STRLEN_P(result)+1); + } + memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(prefix)+1, buf, buf_len+1); + } + } + + return SUCCESS; +} -/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]]) +/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]]) U Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { - zval **var_array, **z_extract_type, **prefix; + zval *var_array, *prefix = NULL; + long extract_type = EXTR_OVERWRITE; zval **entry, *data; zstr var_name; ulong num_key; uint var_name_len; - int var_exists, extract_type, key_type, count = 0; + int var_exists, key_type, count = 0; int extract_refs = 0; HashPosition pos; - switch (ZEND_NUM_ARGS()) { - case 1: - if (zend_get_parameters_ex(1, &var_array) == FAILURE) { - WRONG_PARAM_COUNT; - } - extract_type = EXTR_OVERWRITE; - break; - - case 2: - if (zend_get_parameters_ex(2, &var_array, &z_extract_type) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long_ex(z_extract_type); - extract_type = Z_LVAL_PP(z_extract_type); - extract_refs = (extract_type & EXTR_REFS); - extract_type &= 0xff; - if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Prefix expected to be specified"); - return; - } - break; - - case 3: - if (zend_get_parameters_ex(3, &var_array, &z_extract_type, &prefix) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long_ex(z_extract_type); - extract_type = Z_LVAL_PP(z_extract_type); - extract_refs = (extract_type & EXTR_REFS); - extract_type &= 0xff; - convert_to_text_ex(prefix); - break; - - default: - WRONG_PARAM_COUNT; - break; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|lz/", &var_array, + &extract_type, &prefix) == FAILURE) { + return; } + extract_refs = (extract_type & EXTR_REFS); + extract_type &= 0xff; + if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown extract type"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid extract type"); return; } - if (Z_TYPE_PP(var_array) != IS_ARRAY) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument should be an array"); + if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS + && ZEND_NUM_ARGS() < 3) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "specified extract type requires the prefix parameter"); return; } - - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(var_array), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(var_array), (void **)&entry, &pos) == SUCCESS) { + + if (prefix) { + convert_to_text(prefix); + if (!php_valid_var_name(Z_UNIVAL_P(prefix), Z_UNILEN_P(prefix), Z_TYPE_P(prefix))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "prefix is not a valid identifier"); + return; + } + } + + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&entry, &pos) == SUCCESS) { zval final_name; ZVAL_NULL(&final_name); - key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(var_array), &var_name, &var_name_len, &num_key, 0, &pos); + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &var_name, &var_name_len, &num_key, 0, &pos); var_exists = 0; if (key_type == HASH_KEY_IS_STRING || - key_type == HASH_KEY_IS_UNICODE) { + key_type == HASH_KEY_IS_UNICODE) { if (key_type == HASH_KEY_IS_STRING) { - key_type = IS_STRING; + key_type = IS_STRING; } else { - key_type = IS_UNICODE; + key_type = IS_UNICODE; } var_name_len--; var_exists = zend_u_hash_exists(EG(active_symbol_table), key_type, var_name, var_name_len + 1); } else if (key_type == HASH_KEY_IS_LONG && - (extract_type == EXTR_PREFIX_ALL || - extract_type == EXTR_PREFIX_INVALID)) { - zval num; - - ZVAL_LONG(&num, num_key); - convert_to_text(&num); - Z_STRLEN(final_name) = Z_UNILEN_PP(prefix) + 1 + Z_UNILEN(num); - if (UG(unicode)) { - Z_TYPE(final_name) = IS_UNICODE; - Z_USTRVAL(final_name) = eumalloc(Z_USTRLEN(final_name)+1); - memcpy(Z_USTRVAL(final_name), Z_USTRVAL_PP(prefix), UBYTES(Z_USTRLEN_PP(prefix))); - Z_USTRVAL(final_name)[Z_USTRLEN_PP(prefix)] = '_'; - memcpy(Z_USTRVAL(final_name)+Z_USTRLEN_PP(prefix)+1, Z_USTRVAL(num), UBYTES(Z_USTRLEN(num)+1)); - } else { - Z_TYPE(final_name) = IS_STRING; - Z_STRVAL(final_name) = emalloc(Z_STRLEN(final_name)+1); - memcpy(Z_STRVAL(final_name), Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); - Z_STRVAL(final_name)[Z_STRLEN_PP(prefix)] = '_'; - memcpy(Z_STRVAL(final_name)+Z_STRLEN_PP(prefix)+1, Z_STRVAL(num), Z_STRLEN(num)+1); - } + (extract_type == EXTR_PREFIX_ALL || + extract_type == EXTR_PREFIX_INVALID)) { + zval num; + + ZVAL_LONG(&num, num_key); + convert_to_text(&num); + php_extract_prefix_varname(&final_name, prefix, Z_UNIVAL(num), Z_UNILEN(num), Z_TYPE(num)); zval_dtor(&num); } else { - zend_hash_move_forward_ex(Z_ARRVAL_PP(var_array), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos); continue; } @@ -1381,66 +1412,26 @@ case EXTR_PREFIX_IF_EXISTS: if (var_exists) { - Z_STRLEN(final_name) = Z_UNILEN_PP(prefix) + 1 + var_name_len; - if (UG(unicode)) { - Z_TYPE(final_name) = IS_UNICODE; - Z_USTRVAL(final_name) = eumalloc(Z_USTRLEN(final_name)+1); - memcpy(Z_USTRVAL(final_name), Z_USTRVAL_PP(prefix), UBYTES(Z_USTRLEN_PP(prefix))); - Z_USTRVAL(final_name)[Z_USTRLEN_PP(prefix)] = '_'; - memcpy(Z_USTRVAL(final_name)+Z_USTRLEN_PP(prefix)+1, var_name.u, UBYTES(var_name_len+1)); - } else { - Z_TYPE(final_name) = IS_STRING; - Z_STRVAL(final_name) = emalloc(Z_STRLEN(final_name)+1); - memcpy(Z_STRVAL(final_name), Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); - Z_STRVAL(final_name)[Z_STRLEN_PP(prefix)] = '_'; - memcpy(Z_STRVAL(final_name)+Z_STRLEN_PP(prefix)+1, var_name.s, var_name_len+1); - } + php_extract_prefix_varname(&final_name, prefix, var_name, var_name_len, key_type); } break; case EXTR_PREFIX_SAME: - if (!var_exists) { + if (!var_exists && var_name_len != 0) { ZVAL_TEXTL(&final_name, var_name, var_name_len, 1); } /* break omitted intentionally */ case EXTR_PREFIX_ALL: if (Z_TYPE(final_name) == IS_NULL && var_name_len != 0) { - Z_STRLEN(final_name) = Z_UNILEN_PP(prefix) + 1 + var_name_len; - if (UG(unicode)) { - Z_TYPE(final_name) = IS_UNICODE; - Z_USTRVAL(final_name) = eumalloc(Z_USTRLEN(final_name)+1); - memcpy(Z_USTRVAL(final_name), Z_USTRVAL_PP(prefix), UBYTES(Z_USTRLEN_PP(prefix))); - Z_USTRVAL(final_name)[Z_USTRLEN_PP(prefix)] = '_'; - memcpy(Z_USTRVAL(final_name)+Z_USTRLEN_PP(prefix)+1, var_name.u, UBYTES(var_name_len+1)); - } else { - Z_TYPE(final_name) = IS_STRING; - Z_STRVAL(final_name) = emalloc(Z_STRLEN(final_name)+1); - memcpy(Z_STRVAL(final_name), Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); - Z_STRVAL(final_name)[Z_STRLEN_PP(prefix)] = '_'; - memcpy(Z_STRVAL(final_name)+Z_STRLEN_PP(prefix)+1, var_name.s, var_name_len+1); - } + php_extract_prefix_varname(&final_name, prefix, var_name, var_name_len, key_type); } break; case EXTR_PREFIX_INVALID: if (Z_TYPE(final_name) == IS_NULL) { - /* FIXME: Unicode support??? */ - if (!php_valid_var_name(var_name.s)) { - Z_STRLEN(final_name) = Z_UNILEN_PP(prefix) + 1 + var_name_len; - if (UG(unicode)) { - Z_TYPE(final_name) = IS_UNICODE; - Z_USTRVAL(final_name) = eumalloc(Z_USTRLEN(final_name)+1); - memcpy(Z_USTRVAL(final_name), Z_USTRVAL_PP(prefix), UBYTES(Z_USTRLEN_PP(prefix))); - Z_USTRVAL(final_name)[Z_USTRLEN_PP(prefix)] = '_'; - memcpy(Z_USTRVAL(final_name)+Z_USTRLEN_PP(prefix)+1, var_name.u, UBYTES(var_name_len+1)); - } else { - Z_TYPE(final_name) = IS_STRING; - Z_STRVAL(final_name) = emalloc(Z_STRLEN(final_name)+1); - memcpy(Z_STRVAL(final_name), Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); - Z_STRVAL(final_name)[Z_STRLEN_PP(prefix)] = '_'; - memcpy(Z_STRVAL(final_name)+Z_STRLEN_PP(prefix)+1, var_name.s, var_name_len+1); - } + if (!php_valid_var_name(var_name, var_name_len, key_type)) { + php_extract_prefix_varname(&final_name, prefix, var_name, var_name_len, key_type); } else { ZVAL_TEXTL(&final_name, var_name, var_name_len, 1); } @@ -1455,41 +1446,38 @@ } if (Z_TYPE(final_name) != IS_NULL) { - /* FIXME: Unicode support??? */ - if (php_valid_var_name(Z_STRVAL(final_name))) { - if (extract_refs) { - zval **orig_var; + if (extract_refs) { + zval **orig_var; - if (zend_u_hash_find(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, (void **) &orig_var) == SUCCESS) { - SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); - zval_add_ref(entry); - - zval_ptr_dtor(orig_var); + if (zend_u_hash_find(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, (void **) &orig_var) == SUCCESS) { + SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); + zval_add_ref(entry); + + zval_ptr_dtor(orig_var); - *orig_var = *entry; + *orig_var = *entry; + } else { + if (var_array->refcount > 1) { + SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); } else { - if ((*var_array)->refcount > 1) { - SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); - } else { - (*entry)->is_ref = 1; - } - zval_add_ref(entry); - zend_u_hash_update(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, (void **) entry, sizeof(zval *), NULL); + (*entry)->is_ref = 1; } - } else { - MAKE_STD_ZVAL(data); - *data = **entry; - zval_copy_ctor(data); - - ZEND_U_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, data, 1, 0); + zval_add_ref(entry); + zend_u_hash_update(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, (void **) entry, sizeof(zval *), NULL); } + } else { + MAKE_STD_ZVAL(data); + *data = **entry; + zval_copy_ctor(data); - count++; + ZEND_U_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name)+1, data, 1, 0); } + + count++; } zval_dtor(&final_name); - zend_hash_move_forward_ex(Z_ARRVAL_PP(var_array), &pos); + zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos); } RETURN_LONG(count);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php