rendered paste bodyIndex: spl_array.c
===================================================================
RCS file: /repository/php-src/ext/spl/spl_array.c,v
retrieving revision 1.71.2.17.2.13.2.19
diff -u -w -p -r1.71.2.17.2.13.2.19 spl_array.c
--- spl_array.c 26 Jul 2008 12:34:10 -0000 1.71.2.17.2.13.2.19
+++ spl_array.c 3 Aug 2008 09:59:32 -0000
@@ -924,50 +924,16 @@ zend_object_iterator *spl_array_get_iter
}
/* }}} */
-/* {{{ proto void ArrayObject::__construct(array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]])
- proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0])
- Cronstructs a new array iterator from a path. */
-SPL_METHOD(Array, __construct)
-{
- zval *object = getThis();
- spl_array_object *intern;
- zval **array;
- long ar_flags = 0;
- char *class_name;
- int class_name_len;
- zend_class_entry ** pce_get_iterator;
-
- if (ZEND_NUM_ARGS() == 0) {
- return; /* nothing to do */
- }
- php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException TSRMLS_CC);
-
- intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ls", &array, &ar_flags, &class_name, &class_name_len) == FAILURE) {
- php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
- return;
- }
+/* {{{ spl_array_set_array */
+static void spl_array_set_array(zval *object, spl_array_object *intern, zval **array, long ar_flags, int just_array TSRMLS_DC) {
if (Z_TYPE_PP(array) == IS_ARRAY) {
SEPARATE_ZVAL_IF_NOT_REF(array);
}
- if (ZEND_NUM_ARGS() > 2) {
- if (zend_lookup_class(class_name, class_name_len, &pce_get_iterator TSRMLS_CC) == FAILURE) {
- zend_throw_exception(spl_ce_InvalidArgumentException, "A class that implements Iterator must be specified", 0 TSRMLS_CC);
- php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
- return;
- }
- intern->ce_get_iterator = *pce_get_iterator;
- }
-
- ar_flags &= ~SPL_ARRAY_INT_MASK;
-
if (Z_TYPE_PP(array) == IS_OBJECT && (Z_OBJ_HT_PP(array) == &spl_handler_ArrayObject || Z_OBJ_HT_PP(array) == &spl_handler_ArrayIterator)) {
zval_ptr_dtor(&intern->array);
- if (ZEND_NUM_ARGS() == 1)
- {
+ if (just_array) {
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(*array TSRMLS_CC);
ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;
}
@@ -996,9 +962,50 @@ SPL_METHOD(Array, __construct)
|| !spl_array_get_hash_table(intern, 0 TSRMLS_CC)) {
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_PP(array)->name, intern->std.ce->name);
+ }
+ }
+
+ spl_array_rewind(intern TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ proto void ArrayObject::__construct(array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]])
+ proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0])
+ Cronstructs a new array iterator from a path. */
+SPL_METHOD(Array, __construct)
+{
+ zval *object = getThis();
+ spl_array_object *intern;
+ zval **array;
+ long ar_flags = 0;
+ char *class_name;
+ int class_name_len;
+ zend_class_entry ** pce_get_iterator;
+
+ if (ZEND_NUM_ARGS() == 0) {
+ return; /* nothing to do */
+ }
+ php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException TSRMLS_CC);
+
+ intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ls", &array, &ar_flags, &class_name, &class_name_len) == FAILURE) {
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
return;
}
+
+ if (ZEND_NUM_ARGS() > 2) {
+ if (zend_lookup_class(class_name, class_name_len, &pce_get_iterator TSRMLS_CC) == FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException, "A class that implements Iterator must be specified", 0 TSRMLS_CC);
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+ return;
}
+ intern->ce_get_iterator = *pce_get_iterator;
+ }
+
+ ar_flags &= ~SPL_ARRAY_INT_MASK;
+
+ spl_array_set_array(object, intern, array, ar_flags, ZEND_NUM_ARGS() == 1 TSRMLS_CC);
spl_array_rewind(intern TSRMLS_CC);
@@ -1081,31 +1088,9 @@ SPL_METHOD(Array, exchangeArray)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array) == FAILURE) {
return;
}
- if (Z_TYPE_PP(array) == IS_OBJECT && intern == (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC)) {
- zval_ptr_dtor(&intern->array);
- array = &object;
- intern->array = object;
- } else if (Z_TYPE_PP(array) == IS_OBJECT && (Z_OBJ_HT_PP(array) == &spl_handler_ArrayObject || Z_OBJ_HT_PP(array) == &spl_handler_ArrayIterator)) {
- spl_array_object *other = (spl_array_object*)zend_object_store_get_object(*array TSRMLS_CC);
- zval_ptr_dtor(&intern->array);
- intern->array = other->array;
- } else {
- if (Z_TYPE_PP(array) != IS_OBJECT && !HASH_OF(*array)) {
- zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC);
- return;
- }
- zval_ptr_dtor(&intern->array);
- intern->array = *array;
- intern->ar_flags &= ~SPL_ARRAY_USE_OTHER;
- }
- if (object == *array) {
- intern->ar_flags |= SPL_ARRAY_IS_SELF;
- } else {
- intern->ar_flags &= ~SPL_ARRAY_IS_SELF;
- }
- Z_ADDREF_P(intern->array);
- spl_array_rewind(intern TSRMLS_CC);
+ spl_array_set_array(object, intern, array, 0L, 1 TSRMLS_CC);
+
}
/* }}} */
Index: tests/arrayObject_exchange_basic1.phpt
===================================================================
RCS file: tests/arrayObject_exchange_basic1.phpt
diff -N tests/arrayObject_exchange_basic1.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/arrayObject_exchange_basic1.phpt 3 Aug 2008 09:44:39 -0000
@@ -0,0 +1,40 @@
+--TEST--
+ArrayObject::exchange() and copy-on-write references
+--FILE--
+<?php
+$ao = new ArrayObject();
+$swapIn = array();
+$cowRef = $swapIn; // create a copy-on-write ref to $swapIn
+$ao->exchangeArray($swapIn);
+
+$ao['a'] = 'adding element to $ao';
+$swapIn['b'] = 'adding element to $swapIn';
+$ao['c'] = 'adding another element to $ao';
+
+echo "\n--> swapIn: ";
+var_dump($swapIn);
+
+echo "\n--> cowRef: ";
+var_dump($cowRef);
+
+echo "\n--> ao: ";
+var_dump($ao);
+?>
+--EXPECTF--
+--> swapIn: array(1) {
+ ["b"]=>
+ string(25) "adding element to $swapIn"
+}
+
+--> cowRef: array(0) {
+}
+
+--> ao: object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ array(2) {
+ ["a"]=>
+ string(21) "adding element to $ao"
+ ["c"]=>
+ string(29) "adding another element to $ao"
+ }
+}
Index: tests/arrayObject_exchange_basic2.phpt
===================================================================
RCS file: tests/arrayObject_exchange_basic2.phpt
diff -N tests/arrayObject_exchange_basic2.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/arrayObject_exchange_basic2.phpt 3 Aug 2008 09:48:20 -0000
@@ -0,0 +1,33 @@
+--TEST--
+ArrayObject::exchangeArray(object)
+--FILE--
+<?php
+echo "--> exchangeArray(array):\n";
+$ao = new ArrayObject();
+$ao->exchangeArray(array('original'));
+var_dump($ao);
+
+echo "\n--> exchangeArray(object):\n";
+$obj = new stdClass;
+$obj->newProp = 'changed';
+$ao->exchangeArray($obj);
+var_dump($ao);
+?>
+--EXPECTF--
+--> exchangeArray(array):
+object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ array(1) {
+ [0]=>
+ string(8) "original"
+ }
+}
+
+--> exchangeArray(object):
+object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ object(stdClass)#%d (1) {
+ ["newProp"]=>
+ string(7) "changed"
+ }
+}
\ No newline at end of file