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

Reply via email to