From: Marcus Boerger Date: Sun, 25 Apr 2004 11:14:11 +0000 (+0000) Subject: Fix several issues X-Git-Tag: RELEASE_0_1~378 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5b755c40ea640c03006bb5ae79bc8c23b1761753;p=php Fix several issues - bugfix #27063 - bugfix #27929 - bugfix #28099 - bugfix #28125 # The amount of code is needed to solve the return by reference problem. # dual_it and derived also need their own iterator handlers to be able # to return by reference. --- diff --git a/ext/spl/examples/directorytree.php b/ext/spl/examples/directorytree.php index de6cdc76b2..53d7ce0f3f 100755 --- a/ext/spl/examples/directorytree.php +++ b/ext/spl/examples/directorytree.php @@ -25,7 +25,7 @@ EOF; $length = $argc > 3 ? $argv[3] : -1; echo $argv[1]."\n"; -foreach(new LimitIterator(new DirectoryTreeIterator($argv[1]), @$argv[2], $length) as $file) { +foreach(new LimitIterator(new DirectoryTreeIterator($argv[1]), @$argv[2], $length) as $key=>$file) { //foreach(new DirectoryTreeIterator($argv[1]) as $file) { echo $file . "\n"; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 1b08d54063..22a7379f89 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -32,7 +32,6 @@ #include "spl_engine.h" #include "spl_array.h" - SPL_METHOD(Array, __construct); SPL_METHOD(Array, getIterator); SPL_METHOD(Array, rewind); @@ -40,25 +39,51 @@ SPL_METHOD(Array, current); SPL_METHOD(Array, key); SPL_METHOD(Array, next); SPL_METHOD(Array, valid); +SPL_METHOD(Array, offsetExists); +SPL_METHOD(Array, offsetGet); +SPL_METHOD(Array, offsetSet); +SPL_METHOD(Array, offsetUnset); +SPL_METHOD(Array, getArrayCopy); static ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0) ZEND_ARG_INFO(0, array) ZEND_END_ARG_INFO(); +static +ZEND_BEGIN_ARG_INFO(arginfo_array_offsetGet, 0) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO(); + +static +ZEND_BEGIN_ARG_INFO(arginfo_array_offsetSet, 0) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO(); + static zend_function_entry spl_funcs_ArrayObject[] = { SPL_ME(Array, __construct, arginfo_array___construct, ZEND_ACC_PUBLIC) SPL_ME(Array, getIterator, NULL, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetExists, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetGet, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetSet, arginfo_array_offsetSet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetUnset, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; static zend_function_entry spl_funcs_ArrayIterator[] = { - SPL_ME(Array, __construct, arginfo_array___construct, ZEND_ACC_PRIVATE) + SPL_ME(Array, __construct, arginfo_array___construct, ZEND_ACC_PUBLIC) SPL_ME(Array, rewind, NULL, ZEND_ACC_PUBLIC) SPL_ME(Array, current, NULL, ZEND_ACC_PUBLIC) SPL_ME(Array, key, NULL, ZEND_ACC_PUBLIC) SPL_ME(Array, next, NULL, ZEND_ACC_PUBLIC) SPL_ME(Array, valid, NULL, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetExists, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetGet, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetSet, arginfo_array_offsetSet, ZEND_ACC_PUBLIC) + SPL_ME(Array, offsetUnset, arginfo_array_offsetGet, ZEND_ACC_PUBLIC) + SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; @@ -164,7 +189,6 @@ static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRML zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(offset)); return EG(uninitialized_zval_ptr); } else { - (*retval)->refcount++; return *retval; } case IS_DOUBLE: @@ -283,6 +307,62 @@ static int spl_array_has_dimension(zval *object, zval *offset, int check_empty T } /* }}} */ +/* {{{ proto bool ArrayObject::offsetExists(mixed $index) + Returns whether the requested $index exists. */ +SPL_METHOD(Array, offsetExists) +{ + zval *index; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + return; + } + RETURN_BOOL(spl_array_has_dimension(getThis(), index, 1 TSRMLS_CC) == SUCCESS); +} /* }}} */ + +/* {{{ proto bool ArrayObject::offsetGet(mixed $index) + Returns the value at the specified $index. */ +SPL_METHOD(Array, offsetGet) +{ + zval *index, *value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + return; + } + value = spl_array_read_dimension(getThis(), index, BP_VAR_R TSRMLS_CC); + RETURN_ZVAL(value, 0, 1); +} /* }}} */ + +/* {{{ proto bool ArrayObject::offsetSet(mixed $index, mixed $newval) + Sets the value at the specified $index to $newval. */ +SPL_METHOD(Array, offsetSet) +{ + zval *index, *value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == FAILURE) { + return; + } + spl_array_write_dimension(getThis(), index, value TSRMLS_CC); +} /* }}} */ + +/* {{{ proto bool ArrayObject::offsetUnset(mixed $index) + Unsets the value at the specified $index. */ +SPL_METHOD(Array, offsetUnset) +{ + zval *index; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &index) == FAILURE) { + return; + } + spl_array_unset_dimension(getThis(), index TSRMLS_CC); +} /* }}} */ + +/* {{ proto array ArrayObject::getArrayCopy() + Return a copy of the contained array */ +SPL_METHOD(Array, getArrayCopy) +{ + zval *object = getThis(), *tmp; + spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + + array_init(return_value); + zend_hash_copy(HASH_OF(return_value), HASH_OF(intern->array), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*)); +} /* }}} */ + /* {{{ spl_array_get_properties */ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) { @@ -292,11 +372,186 @@ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) } /* }}} */ +SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */ +{ + HashTable *ht = HASH_OF(intern->array); + Bucket *p; + +/* IS_CONSISTENT(ht);*/ + +/* HASH_PROTECT_RECURSION(ht);*/ + p = ht->pListHead; + while (p != NULL) { + if (p == intern->pos) { + return SUCCESS; + } + p = p->pListNext; + } +/* HASH_UNPROTECT_RECURSION(ht); */ + zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos); + return FAILURE; +} +/* }}} */ + +static void spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */ +{ + char *string_key; + uint string_length; + ulong num_key; + HashTable *aht = HASH_OF(intern->array); + + if (Z_TYPE_P(intern->array) == IS_OBJECT) { + do { + if (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) { + if (!string_length || string_key[0]) { + break; + } + } else { + break; + } + if (zend_hash_has_more_elements_ex(aht, &intern->pos) != SUCCESS) { + break; + } + zend_hash_move_forward_ex(aht, &intern->pos); + } while (1); + } +} +/* }}} */ + +/* define an overloaded iterator structure */ +typedef struct { + zend_object_iterator intern; + spl_array_object *object; +} spl_array_it; + +static void spl_array_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + + zval_ptr_dtor((zval**)&iterator->intern.data); + + efree(iterator); +} +/* }}} */ + +static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + spl_array_object *object = iterator->object; + HashTable *aht = HASH_OF(object->array); + + if (!aht) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and is no longer an array"); + return FAILURE; + } + + if (object->pos && object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and internal position is no longer valid"); + return FAILURE; + } else { + return zend_hash_has_more_elements_ex(aht, &object->pos); + } +} +/* }}} */ + +static void spl_array_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + spl_array_object *object = iterator->object; + HashTable *aht = HASH_OF(object->array); + + if (zend_hash_get_current_data_ex(aht, (void**)data, &object->pos) == FAILURE) { + *data = NULL; + } +} +/* }}} */ + +static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + spl_array_object *object = iterator->object; + HashTable *aht = HASH_OF(object->array); + + if (!aht) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array"); + return HASH_KEY_NON_EXISTANT; + } + + if (object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and internal position is no longer valid"); + return HASH_KEY_NON_EXISTANT; + } + + return zend_hash_get_current_key_ex(aht, str_key, str_key_len, int_key, 1, &object->pos); +} +/* }}} */ + +static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + spl_array_object *object = iterator->object; + HashTable *aht = HASH_OF(object->array); + + if (!aht) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and is no longer an array"); + return; + } + + if (object->array->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid"); + } else { + zend_hash_move_forward_ex(aht, &object->pos); + spl_array_skip_protected(object TSRMLS_CC); + } +} +/* }}} */ + +static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = (spl_array_it *)iter; + spl_array_object *object = iterator->object; + HashTable *aht = HASH_OF(object->array); + + if (!aht) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array"); + return; + } + + zend_hash_internal_pointer_reset_ex(aht, &object->pos); + spl_array_skip_protected(object TSRMLS_CC); +} +/* }}} */ + +/* iterator handler table */ +zend_object_iterator_funcs spl_array_it_funcs = { + spl_array_it_dtor, + spl_array_it_valid, + spl_array_it_get_current_data, + spl_array_it_get_current_key, + spl_array_it_move_forward, + spl_array_it_rewind +}; + +zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) /* {{{ */ +{ + spl_array_it *iterator = emalloc(sizeof(spl_array_it)); + spl_array_object *array_object = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); + + object->refcount++; + iterator->intern.data = (void*)object; + iterator->intern.funcs = &spl_array_it_funcs; + iterator->object = array_object; + + return (zend_object_iterator*)iterator; +} +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION(spl_array) */ PHP_MINIT_FUNCTION(spl_array) { REGISTER_SPL_STD_CLASS_EX(ArrayObject, spl_array_object_new, spl_funcs_ArrayObject); zend_class_implements(spl_ce_ArrayObject TSRMLS_CC, 1, zend_ce_aggregate); + zend_class_implements(spl_ce_ArrayObject TSRMLS_CC, 1, zend_ce_arrayaccess); memcpy(&spl_handler_ArrayObject, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); spl_handler_ArrayObject.clone_obj = spl_array_object_clone; spl_handler_ArrayObject.read_dimension = spl_array_read_dimension; @@ -307,7 +562,9 @@ PHP_MINIT_FUNCTION(spl_array) REGISTER_SPL_STD_CLASS_EX(ArrayIterator, spl_array_object_new, spl_funcs_ArrayIterator); zend_class_implements(spl_ce_ArrayIterator TSRMLS_CC, 1, zend_ce_iterator); + zend_class_implements(spl_ce_ArrayIterator TSRMLS_CC, 1, zend_ce_arrayaccess); memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers)); + spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator; return SUCCESS; } @@ -377,28 +634,6 @@ SPL_METHOD(Array, getIterator) } /* }}} */ -/* {{{ spl_hash_pos_exists */ -SPL_API int spl_hash_pos_exists(spl_array_object * intern TSRMLS_DC) -{ - HashTable *ht = HASH_OF(intern->array); - Bucket *p; - -/* IS_CONSISTENT(ht);*/ - -/* HASH_PROTECT_RECURSION(ht);*/ - p = ht->pListHead; - while (p != NULL) { - if (p == intern->pos) { - return SUCCESS; - } - p = p->pListNext; - } -/* HASH_UNPROTECT_RECURSION(ht); */ - zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos); - return FAILURE; -} -/* }}} */ - /* {{{ proto void ArrayIterator::rewind() Rewind array back to the start */ SPL_METHOD(Array, rewind) @@ -413,6 +648,7 @@ SPL_METHOD(Array, rewind) } zend_hash_internal_pointer_reset_ex(aht, &intern->pos); + spl_array_skip_protected(intern TSRMLS_CC); } /* }}} */ @@ -430,7 +666,7 @@ SPL_METHOD(Array, current) return; } - if (intern->array->is_ref && spl_hash_pos_exists(intern TSRMLS_CC) == FAILURE) { + if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return; } @@ -459,14 +695,14 @@ SPL_METHOD(Array, key) return; } - if (intern->array->is_ref && spl_hash_pos_exists(intern TSRMLS_CC) == FAILURE) { + if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); return; } - switch (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos)) { + switch (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 1, &intern->pos)) { case HASH_KEY_IS_STRING: - RETVAL_STRINGL(string_key, string_length - 1, 1); + RETVAL_STRINGL(string_key, string_length - 1, 0); break; case HASH_KEY_IS_LONG: RETVAL_LONG(num_key); @@ -490,10 +726,11 @@ SPL_METHOD(Array, next) return; } - if (intern->array->is_ref && spl_hash_pos_exists(intern TSRMLS_CC) == FAILURE) { + if (intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); } else { zend_hash_move_forward_ex(aht, &intern->pos); + spl_array_skip_protected(intern TSRMLS_CC); } } /* }}} */ @@ -511,7 +748,7 @@ SPL_METHOD(Array, valid) return; } - if (intern->pos && intern->array->is_ref && spl_hash_pos_exists(intern TSRMLS_CC) == FAILURE) { + if (intern->pos && intern->array->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid"); RETURN_FALSE; } else { diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 6fe4f754e2..7784acde1e 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -699,8 +699,8 @@ SPL_METHOD(dual_it, key) intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC); if (intern->current.data) { - if (intern->current.key_type == IS_STRING) { - RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len, 1); + if (intern->current.key_type == HASH_KEY_IS_STRING) { + RETURN_STRINGL(intern->current.str_key, intern->current.str_key_len-1, 1); } else { RETURN_LONG(intern->current.int_key); } diff --git a/ext/spl/tests/array_003.phpt b/ext/spl/tests/array_003.phpt index b7de6a78ae..386c7bcf7d 100755 --- a/ext/spl/tests/array_003.phpt +++ b/ext/spl/tests/array_003.phpt @@ -5,6 +5,10 @@ SPL: ArrayObject from object --FILE-- $val) +{ + echo "$key => $val\n"; +} + ?> ===DONE=== @@ -46,4 +55,7 @@ ArrayObject Object [imp] => implicit [dyn] => dynamic ) +pub => public +imp => implicit +dyn => dynamic ===DONE=== diff --git a/ext/spl/tests/array_004.phpt b/ext/spl/tests/array_004.phpt index a10386befc..4c850329ae 100755 --- a/ext/spl/tests/array_004.phpt +++ b/ext/spl/tests/array_004.phpt @@ -117,11 +117,11 @@ echo "Done\n"; 1=>1 - 0=>0 1=>1 - 1=>1 -Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d +Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d 1=>1 - 0=>0 1=>1 - 2=>2 -Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d +Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d 0=>0 - 0=>0 0=>0 - 2=>2 2=>2 - 0=>0 @@ -133,11 +133,11 @@ Notice: ArrayIterator::next(): Array was modified outside object and internal po 1=>1 - 0=>0 1=>1 - 1=>1 -Notice: ArrayIterator::next(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d +Notice: main(): ArrayIterator::next(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d -Notice: ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d +Notice: main(): ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d -Notice: ArrayIterator::next(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d +Notice: main(): ArrayIterator::next(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d -Notice: ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d +Notice: main(): ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d Done diff --git a/ext/spl/tests/array_006.phpt b/ext/spl/tests/array_006.phpt new file mode 100755 index 0000000000..5dd9bdec7a --- /dev/null +++ b/ext/spl/tests/array_006.phpt @@ -0,0 +1,32 @@ +--TEST-- +SPL: ArrayIterator without ArrayObject +--SKIPIF-- + +--INI-- +allow_call_time_pass_reference=1 +--FILE-- +0, 1=>1, 2=>2); +$obj = new ArrayIterator($arr); + +foreach($obj as $ak=>$av) { + foreach($obj as $bk=>$bv) { + if ($ak==0 && $bk==0) { + $arr[0] = "modify"; + } + echo "$ak=>$av - $bk=>$bv\n"; + } +} + +?> +===DONE=== + +--EXPECTF-- +==Normal== +0=>0 - 0=>0 +0=>0 - 1=>1 +0=>0 - 2=>2 +===DONE=== diff --git a/ext/spl/tests/array_007.phpt b/ext/spl/tests/array_007.phpt new file mode 100755 index 0000000000..3e74e00da4 --- /dev/null +++ b/ext/spl/tests/array_007.phpt @@ -0,0 +1,65 @@ +--TEST-- +SPL: ArrayObject/Iterator from IteratorAggregate +--SKIPIF-- + +--FILE-- +imp = "implicit"; + } + + function getIterator() + { + $it = new ArrayObject($this); + return $it->getIterator(); + } +}; + +$test = new test; +$test->dyn = "dynamic"; + +print_r($test); + +print_r($test->getIterator()); + +foreach($test as $key => $val) +{ + echo "$key => $val\n"; +} + +?> +===DONE=== + +--EXPECTF-- +test Object +( + [pub] => public + [pro:protected] => protected + [pri:private] => private + [imp] => implicit + [dyn] => dynamic +) +ArrayIterator Object +( + [pub] => public + [pro:protected] => protected + [pri:private] => private + [imp] => implicit + [dyn] => dynamic +) +pub => public +imp => implicit +dyn => dynamic +===DONE=== diff --git a/ext/spl/tests/array_008.phpt b/ext/spl/tests/array_008.phpt new file mode 100755 index 0000000000..613e324776 --- /dev/null +++ b/ext/spl/tests/array_008.phpt @@ -0,0 +1,62 @@ +--TEST-- +SPL: ArrayIterator and foreach reference +--SKIPIF-- + +--INI-- +allow_call_time_pass_reference=1 +--FILE-- +0, 1=>1, 2=>2); +$obj = new ArrayObject($arr); + +foreach($obj as $ak=>&$av) { + foreach($obj as $bk=>&$bv) { + if ($ak==0 && $bk==0) { + $bv = "modify"; + } + echo "$ak=>$av - $bk=>$bv\n"; + } +} + +echo "==UseRef==\n"; + +$arr = array(0=>0, 1=>1, 2=>2); +$obj = new ArrayObject(&$arr); + +foreach($obj as $ak=>&$av) { + foreach($obj as $bk=>&$bv) { + if ($ak==0 && $bk==0) { + $bv = "modify"; + } + echo "$ak=>$av - $bk=>$bv\n"; + } +} + +?> +===DONE=== + +--EXPECTF-- +==Normal== +0=>modify - 0=>modify +0=>modify - 1=>1 +0=>modify - 2=>2 +1=>1 - 0=>modify +1=>1 - 1=>1 +1=>1 - 2=>2 +2=>2 - 0=>modify +2=>2 - 1=>1 +2=>2 - 2=>2 +==UseRef== +0=>modify - 0=>modify +0=>modify - 1=>1 +0=>modify - 2=>2 +1=>1 - 0=>modify +1=>1 - 1=>1 +1=>1 - 2=>2 +2=>2 - 0=>modify +2=>2 - 1=>1 +2=>2 - 2=>2 +===DONE=== diff --git a/ext/spl/tests/array_009.phpt b/ext/spl/tests/array_009.phpt new file mode 100755 index 0000000000..f9c5fe1c73 --- /dev/null +++ b/ext/spl/tests/array_009.phpt @@ -0,0 +1,37 @@ +--TEST-- +SPL: ArrayIterator implementing RecursiveIterator +--FILE-- +current()); + } + + function getChildren() + { + return new RecursiceArrayIterator($this->current()); + } +} + +$array = array(1, 2 => array(21, 22 => array(221, 222), 23 => array(231)), 3); + +$dir = new RecursiveIteratorIterator(new RecursiceArrayIterator($array), RIT_LEAVES_ONLY); + +foreach ($dir as $file) { + print "$file\n"; +} + +?> +===DONE=== + +--EXPECT-- +1 +21 +221 +222 +231 +3 +===DONE=== diff --git a/ext/spl/tests/array_010.phpt b/ext/spl/tests/array_010.phpt new file mode 100755 index 0000000000..2c59b3be18 --- /dev/null +++ b/ext/spl/tests/array_010.phpt @@ -0,0 +1,148 @@ +--TEST-- +SPL: ArrayIterator implements ArrayAccess +--SKIPIF-- + +--FILE-- +'3rd', '4th'=>4)); + +var_dump($obj->getArrayCopy()); + +echo "===EMPTY===\n"; +var_dump(empty($obj[0])); +var_dump(empty($obj[1])); +var_dump(empty($obj[2])); +var_dump(empty($obj['4th'])); +var_dump(empty($obj['5th'])); +var_dump(empty($obj[6])); + +echo "===isset===\n"; +var_dump(isset($obj[0])); +var_dump(isset($obj[1])); +var_dump(isset($obj[2])); +var_dump(isset($obj['4th'])); +var_dump(isset($obj['5th'])); +var_dump(isset($obj[6])); + +echo "===offsetGet===\n"; +var_dump($obj[0]); +var_dump($obj[1]); +var_dump($obj[2]); +var_dump($obj['4th']); +var_dump($obj['5th']); +var_dump($obj[6]); + +echo "===offsetSet===\n"; +echo "WRITE 1\n"; +$obj[1] = 'Changed 1'; +var_dump($obj[1]); +echo "WRITE 2\n"; +$obj['4th'] = 'Changed 4th'; +var_dump($obj['4th']); +echo "WRITE 3\n"; +$obj['5th'] = 'Added 5th'; +var_dump($obj['5th']); +echo "WRITE 4\n"; +$obj[6] = 'Added 6'; +var_dump($obj[6]); + +var_dump($obj[0]); +var_dump($obj[2]); + +$x = $obj[6] = 'changed 6'; +var_dump($obj[6]); +var_dump($x); + +echo "===unset===\n"; +var_dump($obj->getArrayCopy()); +unset($obj[2]); +unset($obj['4th']); +unset($obj[7]); +unset($obj['8th']); +var_dump($obj->getArrayCopy()); + +?> +===DONE=== + +--EXPECTF-- +array(4) { + [0]=> + string(3) "1st" + [1]=> + int(1) + [2]=> + string(3) "3rd" + ["4th"]=> + int(4) +} +===EMPTY=== +bool(false) +bool(false) +bool(false) +bool(false) +bool(true) +bool(true) +===isset=== +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +===offsetGet=== +string(3) "1st" +int(1) +string(3) "3rd" +int(4) + +Notice: Undefined index: 5th in %sarray_010.php on line %d +NULL + +Notice: Undefined offset: 6 in %sarray_010.php on line %d +NULL +===offsetSet=== +WRITE 1 +string(9) "Changed 1" +WRITE 2 +string(11) "Changed 4th" +WRITE 3 +string(9) "Added 5th" +WRITE 4 +string(7) "Added 6" +string(3) "1st" +string(3) "3rd" +string(9) "changed 6" +string(9) "changed 6" +===unset=== +array(6) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + [2]=> + string(3) "3rd" + ["4th"]=> + string(11) "Changed 4th" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} + +Notice: Undefined offset: 7 in %sarray_010.php on line %d + +Notice: Undefined index: 8th in %sarray_010.php on line %d +array(4) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} +===DONE=== diff --git a/ext/spl/tests/array_011.phpt b/ext/spl/tests/array_011.phpt new file mode 100755 index 0000000000..09b132cfef --- /dev/null +++ b/ext/spl/tests/array_011.phpt @@ -0,0 +1,37 @@ +--TEST-- +SPL: ArrayIterator, LimitIterator and string keys +--SKIPIF-- + +--FILE-- + 0, 'one' => 1, 'two' => 2, 'three' => 3, 'four' => 4, 'five' => 5); +//foreach (new ArrayIterator($a) as $k => $v) +foreach (new LimitIterator(new ArrayIterator($a), 1, 3) as $k => $v) +{ + var_dump(array($k, $v)); +} + +?> +===DONE=== + +--EXPECT-- +array(2) { + [0]=> + string(3) "one" + [1]=> + int(1) +} +array(2) { + [0]=> + string(3) "two" + [1]=> + int(2) +} +array(2) { + [0]=> + string(5) "three" + [1]=> + int(3) +} +===DONE=== diff --git a/ext/spl/tests/iterator_get_inner.phpt b/ext/spl/tests/iterator_get_inner.phpt new file mode 100755 index 0000000000..25a9ce218d --- /dev/null +++ b/ext/spl/tests/iterator_get_inner.phpt @@ -0,0 +1,55 @@ +--TEST-- +SPL: Iterator using getInnerIterator +--FILE-- +current()); + } + + function getChildren() + { + return new RecursiceArrayIterator($this->current()); + } +} + +class CrashIterator extends FilterIterator implements RecursiveIterator +{ + function accept() + { + return true; + } + + function hasChildren() + { + return $this->getInnerIterator()->hasChildren(); + } + + function getChildren() + { + return new RecursiceArrayIterator($this->getInnerIterator()->current()); + } +} + +$array = array(1, 2 => array(21, 22 => array(221, 222), 23 => array(231)), 3); + +$dir = new RecursiveIteratorIterator(new CrashIterator(new RecursiceArrayIterator($array)), RIT_LEAVES_ONLY); + +foreach ($dir as $file) { + print "$file\n"; +} + +?> +===DONE=== + +--EXPECT-- +1 +21 +221 +222 +231 +3 +===DONE=== diff --git a/ext/spl/tests/limititerator.phpt b/ext/spl/tests/limititerator.phpt index 37ba0cbf1b..4e6006621b 100755 --- a/ext/spl/tests/limititerator.phpt +++ b/ext/spl/tests/limititerator.phpt @@ -1,5 +1,5 @@ --TEST-- -SPL: SeekableIterator +SPL: SeekableIterator and string keys --SKIPIF-- --FILE--