mirror of
https://github.com/php/php-src.git
synced 2025-01-10 21:14:37 +08:00
- Move RecursiveArrayIterator into .c
- Add ability to control iterator class of ArrayObject - Implement option to make CachingIterator cache all read elements - Implement ArrayAccess to CachingIterator to access cached elements - Update docu - Update tests
This commit is contained in:
parent
9250fda033
commit
445e382454
@ -9,7 +9,7 @@
|
||||
* SPL - Standard PHP Library
|
||||
*/
|
||||
|
||||
/** @ingroup Examples
|
||||
/** @ingroup SPL
|
||||
* @brief A recursive array iterator
|
||||
* @author Marcus Boerger
|
||||
* @version 1.0
|
@ -175,6 +175,7 @@ PHP_FUNCTION(class_implements)
|
||||
SPL_ADD_CLASS(RangeException, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RecursiveDirectoryIterator, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RecursiveFilterIterator, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RecursiveArrayIterator, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RecursiveIteratorIterator, z_list, sub, allow, ce_flags); \
|
||||
SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
|
||||
|
@ -67,6 +67,7 @@
|
||||
*
|
||||
* - class ArrayObject implements IteratorAggregate
|
||||
* - class ArrayIterator implements Iterator
|
||||
* - class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
*
|
||||
* As the above suggest an ArrayObject creates an ArrayIterator when it comes to
|
||||
* iteration (e.g. ArrayObject instance used inside foreach).
|
||||
@ -511,9 +512,9 @@ class ArrayObject implements IteratorAggregate, ArrayAccess, Countable
|
||||
{
|
||||
/** Properties of the object have their normal functionality
|
||||
* when accessed as list (var_dump, foreach, etc.) */
|
||||
const STD_PROP_LIST = 0x00000001;
|
||||
const STD_PROP_LIST = 0x00000001;
|
||||
/** Array indices can be accessed as properties in read/write */
|
||||
const ARRAY_AS_PROPS = 0x00000002;
|
||||
const ARRAY_AS_PROPS = 0x00000002;
|
||||
|
||||
/** Construct a new array iterator from anything that has a hash table.
|
||||
* That is any Array or Object.
|
||||
@ -521,7 +522,7 @@ class ArrayObject implements IteratorAggregate, ArrayAccess, Countable
|
||||
* @param $array the array to use.
|
||||
* @param $flags see setFlags().
|
||||
*/
|
||||
function __construct($array, $flags = 0);
|
||||
function __construct($array, $flags = 0, $iterator_class = "ArrayIterator");
|
||||
|
||||
/** Set behavior flags.
|
||||
*
|
||||
|
@ -35,119 +35,22 @@
|
||||
#include "spl_array.h"
|
||||
#include "spl_exceptions.h"
|
||||
|
||||
SPL_METHOD(Array, __construct);
|
||||
SPL_METHOD(Array, getIterator);
|
||||
SPL_METHOD(Array, rewind);
|
||||
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, append);
|
||||
SPL_METHOD(Array, getArrayCopy);
|
||||
SPL_METHOD(Array, exchangeArray);
|
||||
SPL_METHOD(Array, seek);
|
||||
SPL_METHOD(Array, count);
|
||||
SPL_METHOD(Array, getFlags);
|
||||
SPL_METHOD(Array, setFlags);
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetSet, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_append, 0)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_seek, 0)
|
||||
ZEND_ARG_INFO(0, position)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_exchangeArray, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_setFlags, 0)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry spl_funcs_ArrayObject[] = {
|
||||
SPL_ME(Array, __construct, arginfo_array___construct, 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, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayObject specific */
|
||||
SPL_ME(Array, getIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, exchangeArray, arginfo_array_exchangeArray, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry spl_funcs_ArrayIterator[] = {
|
||||
SPL_ME(Array, __construct, arginfo_array___construct, 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, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayIterator specific */
|
||||
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, seek, arginfo_array_seek, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry spl_funcs_Countable[] = {
|
||||
SPL_ABSTRACT_ME(Countable, count, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
zend_object_handlers spl_handler_ArrayObject;
|
||||
PHPAPI zend_class_entry *spl_ce_ArrayObject;
|
||||
|
||||
zend_object_handlers spl_handler_ArrayIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_ArrayIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator;
|
||||
|
||||
PHPAPI zend_class_entry *spl_ce_Countable;
|
||||
|
||||
#define SPL_ARRAY_STD_PROP_LIST 0x00000001
|
||||
#define SPL_ARRAY_ARRAY_AS_PROPS 0x00000002
|
||||
#define SPL_ARRAY_IS_REF 0x01000000
|
||||
#define SPL_ARRAY_IS_SELF 0x02000000
|
||||
#define SPL_ARRAY_USE_OTHER 0x04000000
|
||||
#define SPL_ARRAY_INT_MASK 0xFF000000
|
||||
#define SPL_ARRAY_CLONE_MASK 0x03000003
|
||||
#define SPL_ARRAY_STD_PROP_LIST 0x00000001
|
||||
#define SPL_ARRAY_ARRAY_AS_PROPS 0x00000002
|
||||
#define SPL_ARRAY_IS_REF 0x01000000
|
||||
#define SPL_ARRAY_IS_SELF 0x02000000
|
||||
#define SPL_ARRAY_USE_OTHER 0x04000000
|
||||
#define SPL_ARRAY_INT_MASK 0xFF000000
|
||||
#define SPL_ARRAY_CLONE_MASK 0x03000007
|
||||
|
||||
typedef struct _spl_array_object {
|
||||
zend_object std;
|
||||
@ -160,6 +63,7 @@ typedef struct _spl_array_object {
|
||||
zend_function * fptr_offset_set;
|
||||
zend_function * fptr_offset_has;
|
||||
zend_function * fptr_offset_del;
|
||||
zend_class_entry* ce_get_iterator;
|
||||
} spl_array_object;
|
||||
|
||||
static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) {
|
||||
@ -275,6 +179,7 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
|
||||
intern->fptr_offset_del = NULL;
|
||||
}
|
||||
}
|
||||
intern->ce_get_iterator = spl_ce_ArrayIterator;
|
||||
zend_hash_internal_pointer_reset_ex(spl_array_get_hash_table(intern, 0 TSRMLS_CC), &intern->pos);
|
||||
return retval;
|
||||
}
|
||||
@ -551,7 +456,7 @@ SPL_METHOD(Array, offsetGet)
|
||||
Sets the value at the specified $index to $newval. */
|
||||
SPL_METHOD(Array, offsetSet)
|
||||
{
|
||||
zval *index, *value = NULL;
|
||||
zval *index, *value;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &index, &value) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
@ -865,7 +770,7 @@ zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void ArrayObject::__construct(array|object ar = array())
|
||||
/* {{{ 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)
|
||||
@ -874,6 +779,9 @@ SPL_METHOD(Array, __construct)
|
||||
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 */
|
||||
@ -882,11 +790,20 @@ SPL_METHOD(Array, __construct)
|
||||
|
||||
intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &ar_flags) == FAILURE) {
|
||||
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(U_CLASS_ENTRY(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_P(array) == IS_OBJECT && (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator)) {
|
||||
@ -914,13 +831,48 @@ SPL_METHOD(Array, __construct)
|
||||
}
|
||||
intern->ar_flags |= ar_flags;
|
||||
ZVAL_ADDREF(intern->array);
|
||||
|
||||
|
||||
spl_array_rewind(intern TSRMLS_CC);
|
||||
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void ArrayObject::setIteratorClass(string iterator_class)
|
||||
Set the class used in getIterator. */
|
||||
SPL_METHOD(Array, setIteratorClass)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
char *class_name;
|
||||
int class_name_len;
|
||||
zend_class_entry ** pce_get_iterator;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_lookup_class(class_name, class_name_len, &pce_get_iterator TSRMLS_CC) == FAILURE) {
|
||||
zend_throw_exception(U_CLASS_ENTRY(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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string ArrayObject::getIteratorClass()
|
||||
Get the class used in getIterator. */
|
||||
SPL_METHOD(Array, getIteratorClass)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
RETURN_STRING(intern->ce_get_iterator->name, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int ArrayObject::getFlags()
|
||||
Get flags */
|
||||
SPL_METHOD(Array, getFlags)
|
||||
@ -1004,7 +956,7 @@ SPL_METHOD(Array, getIterator)
|
||||
}
|
||||
|
||||
return_value->type = IS_OBJECT;
|
||||
return_value->value.obj = spl_array_object_new_ex(U_CLASS_ENTRY(spl_ce_ArrayIterator), &iterator, object TSRMLS_CC);
|
||||
return_value->value.obj = spl_array_object_new_ex(intern->ce_get_iterator, &iterator, object TSRMLS_CC);
|
||||
return_value->refcount = 1;
|
||||
return_value->is_ref = 1;
|
||||
}
|
||||
@ -1203,6 +1155,150 @@ SPL_METHOD(Array, valid)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RecursiveArrayIterator::hasChildren()
|
||||
Check whether current element has children (e.g. is an array) */
|
||||
SPL_METHOD(Array, hasChildren)
|
||||
{
|
||||
zval *object = getThis(), **entry;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ((intern->ar_flags & SPL_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;
|
||||
}
|
||||
|
||||
if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_BOOL(Z_TYPE_PP(entry) == IS_ARRAY || Z_TYPE_PP(entry) == IS_OBJECT);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto object RecursiveArrayIterator::getChildren()
|
||||
Create a sub iterator for the current element (same class as $this) */
|
||||
SPL_METHOD(Array, getChildren)
|
||||
{
|
||||
zval *object = getThis(), **entry;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((intern->ar_flags & SPL_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;
|
||||
}
|
||||
|
||||
if (zend_hash_get_current_data_ex(aht, (void **) &entry, &intern->pos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, *entry TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetSet, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_append, 0)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_seek, 0)
|
||||
ZEND_ARG_INFO(0, position)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_exchangeArray, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_setFlags, 0)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_setIteratorClass, 0)
|
||||
ZEND_ARG_INFO(0, iteratorClass)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry spl_funcs_ArrayObject[] = {
|
||||
SPL_ME(Array, __construct, arginfo_array___construct, 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, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayObject specific */
|
||||
SPL_ME(Array, getIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, exchangeArray, arginfo_array_exchangeArray, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setIteratorClass, arginfo_array_setIteratorClass, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getIteratorClass, NULL, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry spl_funcs_ArrayIterator[] = {
|
||||
SPL_ME(Array, __construct, arginfo_array___construct, 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, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayIterator specific */
|
||||
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, seek, arginfo_array_seek, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry spl_funcs_RecursiveArrayIterator[] = {
|
||||
SPL_ME(Array, hasChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry spl_funcs_Countable[] = {
|
||||
SPL_ABSTRACT_ME(Countable, count, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION(spl_array) */
|
||||
PHP_MINIT_FUNCTION(spl_array)
|
||||
{
|
||||
@ -1230,6 +1326,9 @@ PHP_MINIT_FUNCTION(spl_array)
|
||||
REGISTER_SPL_IMPLEMENTS(ArrayIterator, SeekableIterator);
|
||||
memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers));
|
||||
spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator;
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(RecursiveArrayIterator, ArrayIterator, spl_array_object_new, spl_funcs_RecursiveArrayIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(RecursiveArrayIterator, RecursiveIterator);
|
||||
|
||||
REGISTER_SPL_INTERFACE(Countable);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
extern PHPAPI zend_class_entry *spl_ce_ArrayObject;
|
||||
extern PHPAPI zend_class_entry *spl_ce_ArrayIterator;
|
||||
extern PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator;
|
||||
extern PHPAPI zend_class_entry *spl_ce_Countable;
|
||||
|
||||
PHP_MINIT_FUNCTION(spl_array);
|
||||
|
@ -89,6 +89,9 @@ typedef struct _spl_recursive_it_object {
|
||||
int level;
|
||||
RecursiveIteratorMode mode;
|
||||
int flags;
|
||||
zend_bool in_iteration;
|
||||
zend_function *beginIteration;
|
||||
zend_function *endIteration;
|
||||
zend_function *callHasChildren;
|
||||
zend_function *callGetChildren;
|
||||
zend_function *beginChildren;
|
||||
@ -123,7 +126,7 @@ static void spl_recursive_it_dtor(zend_object_iterator *_iter TSRMLS_DC)
|
||||
efree(iter);
|
||||
}
|
||||
|
||||
static int spl_recursive_it_valid_ex(spl_recursive_it_object *object TSRMLS_DC)
|
||||
static int spl_recursive_it_valid_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
|
||||
{
|
||||
zend_object_iterator *sub_iter;
|
||||
int level = object->level;
|
||||
@ -135,6 +138,10 @@ static int spl_recursive_it_valid_ex(spl_recursive_it_object *object TSRMLS_DC)
|
||||
}
|
||||
level--;
|
||||
}
|
||||
if (object->endIteration && object->in_iteration) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->endIteration, "endIteration", NULL);
|
||||
}
|
||||
object->in_iteration = 0;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -142,7 +149,7 @@ static int spl_recursive_it_valid(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
spl_recursive_it_object *object = (spl_recursive_it_object*)iter->data;
|
||||
|
||||
return spl_recursive_it_valid_ex(object TSRMLS_CC);
|
||||
return spl_recursive_it_valid_ex(object, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
|
||||
}
|
||||
|
||||
static void spl_recursive_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
|
||||
@ -306,6 +313,10 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zt
|
||||
if (sub_iter->funcs->rewind) {
|
||||
sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
|
||||
}
|
||||
if (object->beginIteration && !object->in_iteration) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->beginIteration, "beginIteration", NULL);
|
||||
}
|
||||
object->in_iteration = 1;
|
||||
spl_recursive_it_move_forward_ex(object, zthis TSRMLS_CC);
|
||||
}
|
||||
|
||||
@ -371,7 +382,16 @@ SPL_METHOD(RecursiveIteratorIterator, __construct)
|
||||
intern->level = 0;
|
||||
intern->mode = mode;
|
||||
intern->flags = flags;
|
||||
intern->in_iteration = 0;
|
||||
intern->ce = Z_OBJCE_P(object);
|
||||
zend_hash_find(&intern->ce->function_table, "beginiteration", sizeof("beginiteration"), (void **) &intern->beginIteration);
|
||||
if (intern->beginIteration->common.scope == U_CLASS_ENTRY(spl_ce_RecursiveIteratorIterator)) {
|
||||
intern->beginIteration = NULL;
|
||||
}
|
||||
zend_hash_find(&intern->ce->function_table, "enditeration", sizeof("enditeration"), (void **) &intern->endIteration);
|
||||
if (intern->endIteration->common.scope == U_CLASS_ENTRY(spl_ce_RecursiveIteratorIterator)) {
|
||||
intern->endIteration = NULL;
|
||||
}
|
||||
zend_hash_find(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren"), (void **) &intern->callHasChildren);
|
||||
if (intern->callHasChildren->common.scope == U_CLASS_ENTRY(spl_ce_RecursiveIteratorIterator)) {
|
||||
intern->callHasChildren = NULL;
|
||||
@ -417,7 +437,7 @@ SPL_METHOD(RecursiveIteratorIterator, valid)
|
||||
{
|
||||
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
RETURN_BOOL(spl_recursive_it_valid_ex(object TSRMLS_CC) == SUCCESS);
|
||||
RETURN_BOOL(spl_recursive_it_valid_ex(object, getThis() TSRMLS_CC) == SUCCESS);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto mixed RecursiveIteratorIterator::key()
|
||||
@ -497,6 +517,20 @@ SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
|
||||
RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginIteration()
|
||||
Called when iteration begins (after first rewind() call) */
|
||||
SPL_METHOD(RecursiveIteratorIterator, beginIteration)
|
||||
{
|
||||
/* nothing to do */
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::endIteration()
|
||||
Called when iteration ends (when valid() first returns false */
|
||||
SPL_METHOD(RecursiveIteratorIterator, endIteration)
|
||||
{
|
||||
/* nothing to do */
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
|
||||
Called for each element to test whether it has children */
|
||||
SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
|
||||
@ -637,6 +671,8 @@ static zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
|
||||
SPL_ME(RecursiveIteratorIterator, getDepth, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getSubIterator, arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getInnerIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, beginIteration, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, endIteration, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, callHasChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, callGetChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, beginChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
@ -765,6 +801,8 @@ static INLINE spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAME
|
||||
return NULL;
|
||||
}
|
||||
intern->u.caching.flags |= flags & CIT_PUBLIC;
|
||||
MAKE_STD_ZVAL(intern->u.caching.zcache);
|
||||
array_init(intern->u.caching.zcache);
|
||||
break;
|
||||
}
|
||||
case DIT_IteratorIterator: {
|
||||
@ -1097,7 +1135,7 @@ SPL_METHOD(RecursiveFilterIterator, getChildren)
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
|
||||
spl_instantiate_arg_ex1(U_CLASS_ENTRY(spl_ce_RecursiveFilterIterator), &return_value, 0, retval TSRMLS_CC);
|
||||
spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC);
|
||||
zval_ptr_dtor(&retval);
|
||||
} /* }}} */
|
||||
|
||||
@ -1131,7 +1169,7 @@ SPL_METHOD(ParentIterator, getChildren)
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
|
||||
spl_instantiate_arg_ex1(U_CLASS_ENTRY(spl_ce_ParentIterator), &return_value, 0, retval TSRMLS_CC);
|
||||
spl_instantiate_arg_ex1(Z_OBJCE_P(getThis()), &return_value, 0, retval TSRMLS_CC);
|
||||
zval_ptr_dtor(&retval);
|
||||
} /* }}} */
|
||||
|
||||
@ -1155,6 +1193,13 @@ static INLINE void spl_dual_it_free_storage(void *_object TSRMLS_DC)
|
||||
zval_ptr_dtor(&object->u.append.zarrayit);
|
||||
}
|
||||
|
||||
if (object->dit_type == DIT_CachingIterator || object->dit_type == DIT_CachingRecursiveIterator) {
|
||||
if (object->u.caching.zcache) {
|
||||
zval_ptr_dtor(&object->u.caching.zcache);
|
||||
object->u.caching.zcache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_destroy(object->std.properties);
|
||||
FREE_HASHTABLE(object->std.properties);
|
||||
|
||||
@ -1388,6 +1433,22 @@ static INLINE void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC)
|
||||
{
|
||||
if (spl_dual_it_fetch(intern, 1 TSRMLS_CC) == SUCCESS) {
|
||||
intern->u.caching.flags |= CIT_VALID;
|
||||
/* Full cache ? */
|
||||
if (intern->u.caching.flags & CIT_FULL_CACHE) {
|
||||
zval *zcacheval;
|
||||
|
||||
MAKE_STD_ZVAL(zcacheval);
|
||||
ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0);
|
||||
switch(intern->current.key_type) {
|
||||
case HASH_KEY_IS_STRING:
|
||||
zend_u_symtable_update(HASH_OF(intern->u.caching.zcache), IS_STRING, intern->current.str_key, intern->current.str_key_len, &zcacheval, sizeof(void*), NULL);
|
||||
break;
|
||||
case HASH_KEY_IS_LONG:
|
||||
add_index_zval(intern->u.caching.zcache, intern->current.int_key, zcacheval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Recursion ? */
|
||||
if (intern->dit_type == DIT_CachingRecursiveIterator) {
|
||||
zval *retval, *zchildren, zflags;
|
||||
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "haschildren", &retval);
|
||||
@ -1459,6 +1520,7 @@ static INLINE void spl_caching_it_next(spl_dual_it_object *intern TSRMLS_DC)
|
||||
static INLINE void spl_caching_it_rewind(spl_dual_it_object *intern TSRMLS_DC)
|
||||
{
|
||||
spl_dual_it_rewind(intern TSRMLS_CC);
|
||||
zend_hash_clean(HASH_OF(intern->u.caching.zcache));
|
||||
spl_caching_it_next(intern TSRMLS_CC);
|
||||
}
|
||||
|
||||
@ -1534,12 +1596,165 @@ SPL_METHOD(CachingIterator, __toString)
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto void CachingIterator::offsetSet(mixed index, mixed newval)
|
||||
Set given index in cache */
|
||||
SPL_METHOD(CachingIterator, offsetSet)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
void *arKey;
|
||||
uint nKeyLength;
|
||||
zend_uchar type;
|
||||
zval *value;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
|
||||
zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_BadMethodCallException), 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Tz", &arKey, &nKeyLength, &type, &value) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
value->refcount++;
|
||||
zend_u_symtable_update(HASH_OF(intern->u.caching.zcache), type, arKey, nKeyLength+1, &value, sizeof(value), NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string CachingIterator::offsetGet(mixed index)
|
||||
Return the internal cache if used */
|
||||
SPL_METHOD(CachingIterator, offsetGet)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
void *arKey;
|
||||
uint nKeyLength;
|
||||
zend_uchar type;
|
||||
zval **value;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
|
||||
zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_BadMethodCallException), 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "T", &arKey, &nKeyLength, &type) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_u_symtable_find(HASH_OF(intern->u.caching.zcache), type, arKey, nKeyLength+1, (void**)&value) == FAILURE) {
|
||||
zend_error(E_NOTICE, "Undefined index: %R", type, arKey);
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_ZVAL(*value, 1, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void CachingIterator::offsetUnset(mixed index)
|
||||
Unset given index in cache */
|
||||
SPL_METHOD(CachingIterator, offsetUnset)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
void *arKey;
|
||||
uint nKeyLength;
|
||||
zend_uchar type;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
|
||||
zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_BadMethodCallException), 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "T", &arKey, &nKeyLength, &type) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_u_symtable_del(HASH_OF(intern->u.caching.zcache), type, arKey, nKeyLength+1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool CachingIterator::offsetExists(mixed index)
|
||||
Return whether the requested index exists */
|
||||
SPL_METHOD(CachingIterator, offsetExists)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
void *arKey;
|
||||
uint nKeyLength;
|
||||
zend_uchar type;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (!(intern->u.caching.flags & CIT_FULL_CACHE)) {
|
||||
zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_BadMethodCallException), 0 TSRMLS_CC, "%v does not use a full cache (see CachingIterator::__construct)", Z_OBJCE_P(getThis())->name);
|
||||
}
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "T", &arKey, &nKeyLength, &type) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_BOOL(zend_u_symtable_exists(HASH_OF(intern->u.caching.zcache), type, arKey, nKeyLength+1));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int CachingIterator::getFlags()
|
||||
Return the internal flags */
|
||||
SPL_METHOD(CachingIterator, getFlags)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
RETURN_LONG(intern->u.caching.flags);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void CachingIterator::setFlags()
|
||||
Set the internal flags */
|
||||
SPL_METHOD(CachingIterator, setFlags)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
long flags;
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", flags) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((intern->u.caching.flags & CIT_CALL_TOSTRING) != 0 && (flags & ~CIT_CALL_TOSTRING) == 0) {
|
||||
zend_throw_exception(U_CLASS_ENTRY(spl_ce_InvalidArgumentException), "Unsetting flag CALL_TO_STRING is not possible", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
if ((flags && CIT_FULL_CACHE) != 0 && (intern->u.caching.flags & CIT_FULL_CACHE) == 0) {
|
||||
/* clear on (re)enable */
|
||||
zend_hash_clean(HASH_OF(intern->u.caching.zcache));
|
||||
}
|
||||
intern->u.caching.flags = (intern->u.caching.flags & ~CIT_PUBLIC) | (flags & CIT_PUBLIC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_caching_it___construct, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_caching_it_setFlags, 0)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it_offsetGet, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_caching_it_offsetSet, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry spl_funcs_CachingIterator[] = {
|
||||
SPL_ME(CachingIterator, __construct, arginfo_caching_it___construct, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, rewind, NULL, ZEND_ACC_PUBLIC)
|
||||
@ -1550,6 +1765,12 @@ static zend_function_entry spl_funcs_CachingIterator[] = {
|
||||
SPL_ME(CachingIterator, hasNext, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, __toString, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(dual_it, getInnerIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, setFlags, arginfo_caching_it_setFlags, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, offsetGet, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, offsetSet, arginfo_caching_it_offsetSet, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, offsetUnset, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CachingIterator, offsetExists, arginfo_caching_it_offsetGet, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -1842,7 +2063,7 @@ SPL_METHOD(AppendIterator, append)
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &it, U_CLASS_ENTRY(zend_ce_iterator)) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &it, U_CLASS_ENTRY(zend_ce_iterator)) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
spl_array_iterator_append(intern->u.append.zarrayit, it TSRMLS_CC);
|
||||
@ -2032,9 +2253,11 @@ PHP_MINIT_FUNCTION(spl_iterators)
|
||||
|
||||
REGISTER_SPL_STD_CLASS_EX(CachingIterator, spl_dual_it_new, spl_funcs_CachingIterator);
|
||||
REGISTER_SPL_ITERATOR(CachingIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(CachingIterator, ArrayAccess);
|
||||
|
||||
REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CALL_TOSTRING", CIT_CALL_TOSTRING);
|
||||
REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "CATCH_GET_CHILD", CIT_CATCH_GET_CHILD);
|
||||
REGISTER_SPL_CLASS_CONST_LONG(CachingIterator, "FULL_CACHE", CIT_FULL_CACHE);
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(CachingRecursiveIterator, CachingIterator, spl_dual_it_new, spl_funcs_CachingRecursiveIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(CachingRecursiveIterator, RecursiveIterator);
|
||||
|
@ -64,12 +64,13 @@ typedef enum {
|
||||
|
||||
enum {
|
||||
/* public */
|
||||
CIT_CALL_TOSTRING = 1,
|
||||
CIT_CATCH_GET_CHILD = 2,
|
||||
CIT_PUBLIC = CIT_CALL_TOSTRING|CIT_CATCH_GET_CHILD,
|
||||
CIT_CALL_TOSTRING = 0x00000001,
|
||||
CIT_CATCH_GET_CHILD = 0x00000002,
|
||||
CIT_FULL_CACHE = 0x00000004,
|
||||
CIT_PUBLIC = 0x00FFFFFF,
|
||||
/* private */
|
||||
CIT_VALID = 4,
|
||||
CIT_HAS_CHILDREN = 8
|
||||
CIT_VALID = 0x01000000,
|
||||
CIT_HAS_CHILDREN = 0x02000000,
|
||||
};
|
||||
|
||||
typedef struct _spl_dual_it_object {
|
||||
@ -95,9 +96,10 @@ typedef struct _spl_dual_it_object {
|
||||
long count;
|
||||
} limit;
|
||||
struct {
|
||||
int flags; /* CIT_VALID, CIT_CALL_TOSTRING, CIT_CATCH_GET_CHILD */
|
||||
int flags; /* CIT_VALID, CIT_CALL_TOSTRING, CIT_CATCH_GET_CHILD, ... */
|
||||
zval *zstr;
|
||||
zval *zchildren;
|
||||
zval *zcache;
|
||||
} caching;
|
||||
struct {
|
||||
zval *zarrayit;
|
||||
|
@ -5,22 +5,9 @@ SPL: ArrayIterator implementing RecursiveIterator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiceArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->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), RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
$dir = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
foreach ($dir as $file) {
|
||||
print "$file\n";
|
||||
|
39
ext/spl/tests/array_009a.phpt
Executable file
39
ext/spl/tests/array_009a.phpt
Executable file
@ -0,0 +1,39 @@
|
||||
--TEST--
|
||||
SPL: ArrayIterator implementing RecursiveIterator
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("spl")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class MyRecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
return new MyRecursiveArrayIterator($this->current());
|
||||
}
|
||||
}
|
||||
|
||||
$array = array(1, 2 => array(21, 22 => array(221, 222), 23 => array(231)), 3);
|
||||
|
||||
$dir = new RecursiveIteratorIterator(new MyRecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
foreach ($dir as $file) {
|
||||
print "$file\n";
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
1
|
||||
21
|
||||
221
|
||||
222
|
||||
231
|
||||
3
|
||||
===DONE===
|
@ -5,17 +5,6 @@ Bug #31926 (php in free() error with RecursiveArrayIterator)
|
||||
|
||||
$array = array(0 => array('world'));
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements
|
||||
RecursiveIterator {
|
||||
function hasChildren() {
|
||||
return (is_array($this->current()));
|
||||
}
|
||||
|
||||
function getChildren() {
|
||||
return new self($this->current());
|
||||
}
|
||||
}
|
||||
|
||||
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
|
||||
foreach($it as $key => $val) {
|
||||
var_dump($key, $val);
|
||||
|
@ -3,19 +3,8 @@ SPL: RecursiveIteratorIterator and beginChildren/endChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
class MyRecursiveArrayIterator extends RecursiveArrayIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
if (!parent::valid())
|
||||
@ -28,6 +17,12 @@ class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::getChildren();
|
||||
}
|
||||
}
|
||||
|
||||
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
@ -73,7 +68,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
}
|
||||
}
|
||||
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"))), array("ca"), "d"))) as $k=>$v)
|
||||
foreach(new RecursiveArrayIteratorIterator(new MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"))), array("ca"), "d"))) as $k=>$v)
|
||||
{
|
||||
echo "$k=>$v\n";
|
||||
}
|
||||
@ -87,14 +82,14 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>a
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
@ -106,38 +101,38 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(3)
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>bcaa
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(3)
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ca
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
3=>d
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
===DONE===
|
||||
|
@ -3,19 +3,6 @@ SPL: RecursiveIteratorIterator and beginChildren/endChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
}
|
||||
|
||||
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
{
|
||||
function rewind()
|
||||
|
@ -3,19 +3,6 @@ SPL: RecursiveIteratorIterator and beginChildren/endChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
}
|
||||
|
||||
class Menu extends ArrayObject
|
||||
{
|
||||
function getIterator()
|
||||
|
@ -3,19 +3,8 @@ SPL: RecursiveIteratorIterator and hasChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
class MyRecursiveArrayIterator extends RecursiveArrayIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
if (!parent::valid())
|
||||
@ -28,6 +17,12 @@ class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::getChildren();
|
||||
}
|
||||
}
|
||||
|
||||
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
@ -105,7 +100,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
}
|
||||
}
|
||||
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
foreach(new RecursiveArrayIteratorIterator(new MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
{
|
||||
if (is_array($v)) $v = join('',$v);
|
||||
echo "$k=>$v\n";
|
||||
@ -122,7 +117,7 @@ RecursiveArrayIteratorIterator::key
|
||||
0=>a
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
@ -131,7 +126,7 @@ RecursiveArrayIteratorIterator::key
|
||||
0=>ba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
@ -145,10 +140,10 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
@ -159,19 +154,19 @@ RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
MyRecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ca
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
@ -179,7 +174,7 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
3=>d
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
===DONE===
|
||||
|
@ -3,13 +3,8 @@ SPL: RecursiveIteratorIterator and callHasChildren/callGetChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
class MyRecursiveArrayIterator extends RecursiveArrayIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
@ -102,7 +97,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
return NULL;
|
||||
}
|
||||
echo __METHOD__ . "(ok:{$this->over})\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
return new MyRecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function beginChildren()
|
||||
@ -118,7 +113,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
|
||||
try
|
||||
{
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
foreach(new RecursiveArrayIteratorIterator(new MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
{
|
||||
if (is_array($v)) $v = join('',$v);
|
||||
echo "$k=>$v\n";
|
||||
@ -166,7 +161,7 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(ok:0)
|
||||
@ -181,9 +176,9 @@ RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(skip)
|
||||
|
@ -3,13 +3,8 @@ SPL: RecursiveIteratorIterator and catch getChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
class MyRecursiveArrayIterator extends RecursiveArrayIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
@ -102,7 +97,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
throw new Exception("Thrown in callGetChildren()");
|
||||
}
|
||||
echo __METHOD__ . "(ok:{$this->over})\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
return new MyRecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function beginChildren()
|
||||
@ -118,7 +113,7 @@ class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
|
||||
try
|
||||
{
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
foreach(new RecursiveArrayIteratorIterator(new MyRecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
{
|
||||
if (is_array($v)) $v = join('',$v);
|
||||
echo "$k=>$v\n";
|
||||
@ -166,7 +161,7 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(ok:0)
|
||||
@ -181,9 +176,9 @@ RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(2)
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(throw)
|
||||
@ -192,7 +187,7 @@ RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
3=>d
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIterator::valid = false
|
||||
MyRecursiveArrayIterator::valid = false
|
||||
===DONE===
|
||||
|
49
ext/spl/tests/iterator_024.phpt
Executable file
49
ext/spl/tests/iterator_024.phpt
Executable file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
SPL: RecursiveIteratorIterator with custom iterator class
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$ar = array(1, 2, array(31, 32, array(331)), 4);
|
||||
|
||||
foreach(new RecursiveIteratorIterator(new ArrayObject($ar, 0, "RecursiveArrayIterator")) as $v) echo "$v\n";
|
||||
|
||||
$it = new ArrayObject($ar);
|
||||
var_dump($it->getIteratorClass());
|
||||
|
||||
try
|
||||
{
|
||||
foreach(new RecursiveIteratorIterator(new ArrayObject($ar)) as $v) echo "$v\n";
|
||||
}
|
||||
catch (InvalidArgumentException $e)
|
||||
{
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "===MANUAL===\n";
|
||||
|
||||
$it->setIteratorClass("RecursiveArrayIterator");
|
||||
var_dump($it->getIteratorClass());
|
||||
foreach(new RecursiveIteratorIterator($it) as $v) echo "$v\n";
|
||||
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
string(13) "ArrayIterator"
|
||||
An instance of RecursiveIterator or IteratorAggregate creating it is required
|
||||
===MANUAL===
|
||||
string(22) "RecursiveArrayIterator"
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
===DONE===
|
92
ext/spl/tests/iterator_025.phpt
Executable file
92
ext/spl/tests/iterator_025.phpt
Executable file
@ -0,0 +1,92 @@
|
||||
--TEST--
|
||||
SPL: RecursiveIteratorIterator and begin/endIteration()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class MyRecursiveIteratorIterator extends RecursiveIteratorIterator
|
||||
{
|
||||
function beginIteration()
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
|
||||
function endIteration()
|
||||
{
|
||||
echo __METHOD__ . "()\n";
|
||||
}
|
||||
}
|
||||
|
||||
$ar = array(1, 2, array(31, 32, array(331)), 4);
|
||||
|
||||
$it = new MyRecursiveIteratorIterator(new ArrayObject($ar, 0, "RecursiveArrayIterator"));
|
||||
|
||||
foreach($it as $v) echo "$v\n";
|
||||
|
||||
echo "===MORE===\n";
|
||||
|
||||
foreach($it as $v) echo "$v\n";
|
||||
|
||||
echo "===MORE===\n";
|
||||
|
||||
$it->rewind();
|
||||
foreach($it as $v) echo "$v\n";
|
||||
var_dump($it->valid());
|
||||
|
||||
echo "===MANUAL===\n";
|
||||
|
||||
$it->rewind();
|
||||
while($it->valid())
|
||||
{
|
||||
echo $it->current() . "\n";
|
||||
$it->next();
|
||||
break;
|
||||
}
|
||||
$it->rewind();
|
||||
while($it->valid())
|
||||
{
|
||||
echo $it->current() . "\n";
|
||||
$it->next();
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
MyRecursiveIteratorIterator::beginIteration()
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
MyRecursiveIteratorIterator::endIteration()
|
||||
===MORE===
|
||||
MyRecursiveIteratorIterator::beginIteration()
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
MyRecursiveIteratorIterator::endIteration()
|
||||
===MORE===
|
||||
MyRecursiveIteratorIterator::beginIteration()
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
MyRecursiveIteratorIterator::endIteration()
|
||||
bool(false)
|
||||
===MANUAL===
|
||||
MyRecursiveIteratorIterator::beginIteration()
|
||||
1
|
||||
1
|
||||
2
|
||||
31
|
||||
32
|
||||
331
|
||||
4
|
||||
MyRecursiveIteratorIterator::endIteration()
|
||||
===DONE===
|
34
ext/spl/tests/iterator_026.phpt
Executable file
34
ext/spl/tests/iterator_026.phpt
Executable file
@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
SPL: CachingIterator::hasNext()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$ar = array(1, 2, array(31, 32, array(331)), 4);
|
||||
|
||||
$it = new RecursiveArrayIterator($ar);
|
||||
$it = new CachingRecursiveIterator($it);
|
||||
$it = new RecursiveIteratorIterator($it);
|
||||
|
||||
foreach($it as $k=>$v)
|
||||
{
|
||||
echo "$k=>$v\n";
|
||||
echo "hasNext: " . ($it->getInnerIterator()->hasNext() ? "yes" : "no") . "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
0=>1
|
||||
hasNext: yes
|
||||
1=>2
|
||||
hasNext: yes
|
||||
0=>31
|
||||
hasNext: yes
|
||||
1=>32
|
||||
hasNext: yes
|
||||
0=>331
|
||||
hasNext: no
|
||||
3=>4
|
||||
hasNext: no
|
||||
===DONE===
|
83
ext/spl/tests/iterator_027.phpt
Executable file
83
ext/spl/tests/iterator_027.phpt
Executable file
@ -0,0 +1,83 @@
|
||||
--TEST--
|
||||
SPL: CachingIterator::FULL_CACHE
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$ar = array(1, 2, array(31, 32, array(331)), 4);
|
||||
|
||||
$it = new RecursiveArrayIterator($ar);
|
||||
$it = new RecursiveIteratorIterator($it);
|
||||
$it = new CachingIterator($it, CachingIterator::FULL_CACHE);
|
||||
|
||||
foreach($it as $k=>$v)
|
||||
{
|
||||
echo "$k=>$v\n";
|
||||
}
|
||||
|
||||
echo "===CHECK===\n";
|
||||
|
||||
for ($i = 0; $i < 4; $i++)
|
||||
{
|
||||
if (isset($it[$i]))
|
||||
{
|
||||
var_dump($i, $it[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
$it[2] = 'foo';
|
||||
$it[3] = 'bar';
|
||||
$it['baz'] = '25';
|
||||
|
||||
var_dump($it[2]);
|
||||
var_dump($it[3]);
|
||||
var_dump($it['baz']);
|
||||
|
||||
unset($it[0]);
|
||||
unset($it[2]);
|
||||
unset($it['baz']);
|
||||
|
||||
var_dump(isset($it[0])); // unset
|
||||
var_dump(isset($it[1])); // still present
|
||||
var_dump(isset($it[2])); // unset
|
||||
var_dump(isset($it[3])); // still present
|
||||
var_dump(isset($it['baz']));
|
||||
|
||||
echo "===REWIND===\n";
|
||||
|
||||
$it->rewind(); // cleans and reads first element
|
||||
var_dump(isset($it[0])); // pre-fetched
|
||||
var_dump(isset($it[1])); // deleted
|
||||
var_dump(isset($it[2])); // unset
|
||||
var_dump(isset($it[3])); // deleted
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECT--
|
||||
0=>1
|
||||
1=>2
|
||||
0=>31
|
||||
1=>32
|
||||
0=>331
|
||||
3=>4
|
||||
===CHECK===
|
||||
int(0)
|
||||
int(331)
|
||||
int(1)
|
||||
int(32)
|
||||
int(3)
|
||||
int(4)
|
||||
string(3) "foo"
|
||||
string(3) "bar"
|
||||
string(2) "25"
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(false)
|
||||
===REWIND===
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(false)
|
||||
bool(false)
|
||||
===DONE===
|
Loading…
Reference in New Issue
Block a user