All pastes #1091667 Raw Edit

rewbs

public text v1 · immutable
#1091667 ·published 2008-08-03 10:03 UTC
rendered paste body
Index: 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