johannes Thu Jul 31 20:17:07 2008 UTC Added files: /php-src/ext/standard/tests array_replace.phpt
Modified files: /php-src/ext/standard array.c basic_functions.c php_array.h Log: - Add array_replace/array_replace_recursive (Mett Wilmas)
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.457&r2=1.458&diff_format=u Index: php-src/ext/standard/array.c diff -u php-src/ext/standard/array.c:1.457 php-src/ext/standard/array.c:1.458 --- php-src/ext/standard/array.c:1.457 Thu Jul 24 03:06:16 2008 +++ php-src/ext/standard/array.c Thu Jul 31 20:17:06 2008 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: array.c,v 1.457 2008/07/24 03:06:16 felipe Exp $ */ +/* $Id: array.c,v 1.458 2008/07/31 20:17:06 johannes Exp $ */ #include "php.h" #include "php_ini.h" @@ -2500,10 +2500,75 @@ } /* }}} */ -static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive) /* {{{ */ +PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC) /* {{{ */ +{ + zval **src_entry, **dest_entry; + zstr string_key; + uint string_key_len; + ulong num_key; + HashPosition pos; + + for (zend_hash_internal_pointer_reset_ex(src, &pos); + zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS; + zend_hash_move_forward_ex(src, &pos)) { + zend_uchar utype; + + switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) { + case HASH_KEY_IS_STRING: + utype = IS_STRING; + goto ukey; + case HASH_KEY_IS_UNICODE: + utype = IS_UNICODE; +ukey: + if (Z_TYPE_PP(src_entry) != IS_ARRAY || + zend_u_hash_find(dest, utype, string_key, string_key_len, (void **)&dest_entry) == FAILURE || + Z_TYPE_PP(dest_entry) != IS_ARRAY) { + + Z_ADDREF_PP(src_entry); + zend_u_hash_update(dest, utype, string_key, string_key_len, src_entry, sizeof(zval *), NULL); + + continue; + } + break; + + case HASH_KEY_IS_LONG: + if (Z_TYPE_PP(src_entry) != IS_ARRAY || + zend_hash_index_find(dest, num_key, (void **)&dest_entry) == FAILURE || + Z_TYPE_PP(dest_entry) != IS_ARRAY) { + + Z_ADDREF_PP(src_entry); + zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL); + + continue; + } + break; + } + + if (Z_ARRVAL_PP(src_entry)->nApplyCount > 1 || Z_ARRVAL_PP(dest_entry)->nApplyCount > 1 || (*src_entry == *dest_entry && Z_ISREF_PP(dest_entry) && (Z_REFCOUNT_PP(dest_entry) % 2))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected"); + return 0; + } + SEPARATE_ZVAL(dest_entry); + Z_ARRVAL_PP(dest_entry)->nApplyCount++; + Z_ARRVAL_PP(src_entry)->nApplyCount++; + + if (!php_array_replace_recursive(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC)) { + Z_ARRVAL_PP(dest_entry)->nApplyCount--; + Z_ARRVAL_PP(src_entry)->nApplyCount--; + return 0; + } + Z_ARRVAL_PP(dest_entry)->nApplyCount--; + Z_ARRVAL_PP(src_entry)->nApplyCount--; + } + + return 1; +} +/* }}} */ + +static void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace) /* {{{ */ { zval ***args = NULL; - int argc, i, params_ok = 1; + int argc, i, params_ok = 1, init_size = 0; /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); @@ -2522,6 +2587,12 @@ if (Z_TYPE_PP(args[i]) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument #%d is not an array", i + 1); params_ok = 0; + } else { + int num = zend_hash_num_elements(Z_ARRVAL_PP(args[i])); + + if (num > init_size) { + init_size = num; + } } } if (params_ok == 0) { @@ -2529,12 +2600,16 @@ return; } - array_init(return_value); + array_init_size(return_value, init_size); - for (i=0; i<argc; i++) { - SEPARATE_ZVAL(args[i]); - convert_to_array_ex(args[i]); - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC); + for (i = 0; i < argc; i++) { + if (!replace) { + php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC); + } else if (recursive && i > 0) { /* First array will be copied directly instead */ + php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]) TSRMLS_CC); + } else { + zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1); + } } efree(args); @@ -2545,7 +2620,7 @@ Merges elements from passed arrays into one array */ PHP_FUNCTION(array_merge) { - php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); } /* }}} */ @@ -2553,7 +2628,23 @@ Recursively merges elements from passed arrays into one array */ PHP_FUNCTION(array_merge_recursive) { - php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); +} +/* }}} */ + +/* {{{ proto array array_replace(array arr1, array arr2 [, array ...]) U + Replaces elements from passed arrays into one array */ +PHP_FUNCTION(array_replace) +{ + php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); +} +/* }}} */ + +/* {{{ proto array array_replace_recursive(array arr1, array arr2 [, array ...]) U + Recursively replaces elements from passed arrays into one array */ +PHP_FUNCTION(array_replace_recursive) +{ + php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1); } /* }}} */ http://cvs.php.net/viewvc.cgi/php-src/ext/standard/basic_functions.c?r1=1.909&r2=1.910&diff_format=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.909 php-src/ext/standard/basic_functions.c:1.910 --- php-src/ext/standard/basic_functions.c:1.909 Tue Jul 29 17:28:07 2008 +++ php-src/ext/standard/basic_functions.c Thu Jul 31 20:17:06 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.909 2008/07/29 17:28:07 pajoye Exp $ */ +/* $Id: basic_functions.c,v 1.910 2008/07/31 20:17:06 johannes Exp $ */ #include "php.h" #include "php_streams.h" @@ -459,6 +459,20 @@ ZEND_END_ARG_INFO() static +ZEND_BEGIN_ARG_INFO_EX(arginfo_array_replace, 0, 0, 2) + ZEND_ARG_INFO(0, arr1) /* ARRAY_INFO(0, arg, 0) */ + ZEND_ARG_INFO(0, arr2) /* ARRAY_INFO(0, arg, 0) */ + ZEND_ARG_INFO(0, ...) /* ARRAY_INFO(0, ..., 0) */ +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_array_replace_recursive, 0, 0, 2) + ZEND_ARG_INFO(0, arr1) /* ARRAY_INFO(0, arg, 0) */ + ZEND_ARG_INFO(0, arr2) /* ARRAY_INFO(0, arg, 0) */ + ZEND_ARG_INFO(0, ...) /* ARRAY_INFO(0, arg, 0) */ +ZEND_END_ARG_INFO() + +static ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys, 0, 0, 1) ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */ ZEND_ARG_INFO(0, search_value) @@ -3731,6 +3745,8 @@ PHP_FE(array_slice, arginfo_array_slice) PHP_FE(array_merge, arginfo_array_merge) PHP_FE(array_merge_recursive, arginfo_array_merge_recursive) + PHP_FE(array_replace, arginfo_array_replace) + PHP_FE(array_replace_recursive, arginfo_array_replace_recursive) PHP_FE(array_keys, arginfo_array_keys) PHP_FE(array_values, arginfo_array_values) PHP_FE(array_count_values, arginfo_array_count_values) http://cvs.php.net/viewvc.cgi/php-src/ext/standard/php_array.h?r1=1.58&r2=1.59&diff_format=u Index: php-src/ext/standard/php_array.h diff -u php-src/ext/standard/php_array.h:1.58 php-src/ext/standard/php_array.h:1.59 --- php-src/ext/standard/php_array.h:1.58 Mon Dec 31 07:12:16 2007 +++ php-src/ext/standard/php_array.h Thu Jul 31 20:17:06 2008 @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_array.h,v 1.58 2007/12/31 07:12:16 sebastian Exp $ */ +/* $Id: php_array.h,v 1.59 2008/07/31 20:17:06 johannes Exp $ */ #ifndef PHP_ARRAY_H #define PHP_ARRAY_H @@ -66,6 +66,8 @@ PHP_FUNCTION(array_slice); PHP_FUNCTION(array_merge); PHP_FUNCTION(array_merge_recursive); +PHP_FUNCTION(array_replace); +PHP_FUNCTION(array_replace_recursive); PHP_FUNCTION(array_keys); PHP_FUNCTION(array_values); PHP_FUNCTION(array_count_values); @@ -102,6 +104,7 @@ PHPAPI HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC); +PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src TSRMLS_DC); PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC); PHPAPI int php_array_data_compare(const void *a, const void *b TSRMLS_DC); PHPAPI void php_set_compare_func(int sort_type TSRMLS_DC); http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/array_replace.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/array_replace.phpt +++ php-src/ext/standard/tests/array_replace.phpt --TEST-- Test array_replace and array_replace_recursive --FILE-- <?php $array1 = array( 0 => 'dontclobber', '1' => 'unclobbered', 'test2' => 0.0, 'test3' => array( 'testarray2' => true, 1 => array( 'testsubarray1' => 'dontclobber2', 'testsubarray2' => 'dontclobber3', ), ), ); $array2 = array( 1 => 'clobbered', 'test3' => array( 'testarray2' => false, ), 'test4' => array( 'clobbered3' => array(0, 1, 2), ), ); $array3 = array(array(array(array()))); $array4 = array(); $array4[] = &$array4; echo " -- Testing array_replace() --\n"; $data = array_replace($array1, $array2); var_dump($data); echo " -- Testing array_replace_recursive() --\n"; $data = array_replace_recursive($array1, $array2); var_dump($data); echo " -- Testing array_replace_recursive() w/ endless recusrsion --\n"; $data = array_replace_recursive($array3, $array4); var_dump($data); ?> --EXPECTF-- -- Testing array_replace() -- array(5) { [0]=> unicode(11) "dontclobber" [1]=> unicode(9) "clobbered" [u"test2"]=> float(0) [u"test3"]=> array(1) { [u"testarray2"]=> bool(false) } [u"test4"]=> array(1) { [u"clobbered3"]=> array(3) { [0]=> int(0) [1]=> int(1) [2]=> int(2) } } } -- Testing array_replace_recursive() -- array(5) { [0]=> unicode(11) "dontclobber" [1]=> unicode(9) "clobbered" [u"test2"]=> float(0) [u"test3"]=> array(2) { [u"testarray2"]=> bool(false) [1]=> array(2) { [u"testsubarray1"]=> unicode(12) "dontclobber2" [u"testsubarray2"]=> unicode(12) "dontclobber3" } } [u"test4"]=> array(1) { [u"clobbered3"]=> array(3) { [0]=> int(0) [1]=> int(1) [2]=> int(2) } } } -- Testing array_replace_recursive() w/ endless recusrsion -- Warning: array_replace_recursive(): recursion detected in %s on line %d array(1) { [0]=> array(1) { [0]=> array(1) { [0]=> array(0) { } } } }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php