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

Reply via email to