- Add MultipleIterator (Arnaud, Marcus)

This commit is contained in:
Marcus Boerger 2008-07-22 22:54:15 +00:00
parent 0403ce45c6
commit 32f51050bc
8 changed files with 664 additions and 11 deletions

View File

@ -1,6 +1,6 @@
<?php
/** @file multipleiterator.inc
* @ingroup Examples
* @ingroup SPL
* @brief class MultipleIterator
* @author Johannes Schlueter
* @author Marcus Boerger
@ -9,7 +9,7 @@
* SPL - Standard PHP Library
*/
/** @ingroup Examples
/** @ingroup SPL
* @brief Iterator that iterates over several iterators one after the other
* @author Johannes Schlueter
* @author Marcus Boerger

View File

@ -1,7 +1,7 @@
<?php
/** @file recursivetreeiterator.inc
* @ingroup Examples
* @ingroup SPL
* @brief class RecursiveTreeIterator
* @author Marcus Boerger, Johannes Schlueter
* @date 2005

View File

@ -150,14 +150,6 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(ArrayIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplDoublyLinkedList, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplQueue, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplStack, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFixedArray, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
@ -174,6 +166,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(LengthException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LogicException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(MultipleIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OutOfBoundsException, z_list, sub, allow, ce_flags); \
@ -188,14 +181,23 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveIteratorIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveRegexIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveTreeIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RegexIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SimpleXMLIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplDoublyLinkedList, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFileInfo, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFileObject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFixedArray, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplObjectStorage, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplObserver, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplQueue, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplStack, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplSubject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplTempFileObject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \

View File

@ -35,6 +35,7 @@
#include "spl_directory.h"
#include "spl_array.h"
#include "spl_exceptions.h"
#include "spl_observer.h"
#include "ext/standard/php_smart_str.h"
#ifdef accept

View File

@ -35,6 +35,7 @@
extern PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator;
extern PHPAPI zend_class_entry *spl_ce_FilterIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
extern PHPAPI zend_class_entry *spl_ce_ParentIterator;

View File

@ -73,6 +73,8 @@ static const zend_function_entry spl_funcs_SplSubject[] = {
PHPAPI zend_class_entry *spl_ce_SplObserver;
PHPAPI zend_class_entry *spl_ce_SplSubject;
PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
PHPAPI zend_class_entry *spl_ce_MultipleIterator;
PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
typedef struct _spl_SplObjectStorage { /* {{{ */
@ -80,6 +82,7 @@ typedef struct _spl_SplObjectStorage { /* {{{ */
HashTable storage;
long index;
HashPosition pos;
long flags;
} spl_SplObjectStorage; /* }}} */
/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
@ -595,6 +598,298 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2)
ZEND_ARG_INFO(0, info)
ZEND_END_ARG_INFO()
typedef enum {
MIT_NEED_ANY = 0,
MIT_NEED_ALL = 1,
MIT_KEYS_NUMERIC = 0,
MIT_KEYS_ASSOC = 2
} MultipleIteratorFlags;
#define SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT 1
#define SPL_MULTIPLE_ITERATOR_GET_ALL_KEY 2
/* {{{ proto void MultipleIterator::__construct([int flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC]) U
Iterator that iterates over several iterators one after the other */
SPL_METHOD(MultipleIterator, __construct)
{
spl_SplObjectStorage *intern;
long flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC;
php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException TSRMLS_CC);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
return;
}
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
intern->flags = flags;
}
/* }}} */
/* {{{ proto int MultipleIterator::getFlags() U
Return current flags */
SPL_METHOD(MultipleIterator, getFlags)
{
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
RETURN_LONG(intern->flags);
}
/* }}} */
/* {{{ proto int MultipleIterator::setFlags(int flags) U
Set flags */
SPL_METHOD(MultipleIterator, setFlags)
{
spl_SplObjectStorage *intern;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) {
return;
}
}
/* }}} */
/* {{{ proto void attachIterator(Iterator iterator[, mixed info]) throws InvalidArgumentException U
Attach a new iterator */
SPL_METHOD(MultipleIterator, attachIterator)
{
spl_SplObjectStorage *intern;
zval *iterator = NULL, *info = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|z!", &iterator, zend_ce_iterator, &info) == FAILURE) {
return;
}
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (info != NULL) {
spl_SplObjectStorageElement *element;
zval compare_result;
if (Z_TYPE_P(info) != IS_LONG && Z_TYPE_P(info) != IS_STRING && Z_TYPE_P(info) != IS_UNICODE) {
zend_throw_exception(spl_ce_InvalidArgumentException, "Info must be NULL, integer or string", 0 TSRMLS_CC);
return;
}
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS) {
is_identical_function(&compare_result, info, element->inf TSRMLS_CC);
if (Z_LVAL(compare_result)) {
zend_throw_exception(spl_ce_InvalidArgumentException, "Key duplication error", 0 TSRMLS_CC);
return;
}
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
spl_object_storage_attach(intern, iterator, info TSRMLS_CC);
}
/* }}} */
/* {{{ proto void MultipleIterator::rewind() U
Rewind all attached iterator instances */
SPL_METHOD(MultipleIterator, rewind)
{
spl_SplObjectStorage *intern;
spl_SplObjectStorageElement *element;
zval *it;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
it = element->obj;
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_rewind, "rewind", NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
/* }}} */
/* {{{ proto void MultipleIterator::next() U
Move all attached iterator instances forward */
SPL_METHOD(MultipleIterator, next)
{
spl_SplObjectStorage *intern;
spl_SplObjectStorageElement *element;
zval *it;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
it = element->obj;
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_next, "next", NULL);
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
/* }}} */
/* {{{ proto bool MultipleIterator::valid() U
Return whether all or one sub iterator is valid depending on flags */
SPL_METHOD(MultipleIterator, valid)
{
spl_SplObjectStorage *intern;
spl_SplObjectStorageElement *element;
zval *it, *retval = NULL;
long expect, valid;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
if (!zend_hash_num_elements(&intern->storage)) {
RETURN_FALSE;
}
expect = (intern->flags & MIT_NEED_ALL) ? 1 : 0;
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
it = element->obj;
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
if (retval) {
valid = Z_LVAL_P(retval);
zval_ptr_dtor(&retval);
} else {
valid = 0;
}
if (expect != valid) {
RETURN_BOOL(!expect);
}
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
RETURN_BOOL(expect);
}
/* }}} */
static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_type, zval *return_value TSRMLS_DC) /* {{{ */
{
spl_SplObjectStorageElement *element;
zval *it, *retval = NULL;
int valid = 1, num_elements;
num_elements = zend_hash_num_elements(&intern->storage);
if (num_elements < 1) {
RETURN_FALSE;
}
array_init_size(return_value, num_elements);
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
it = element->obj;
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
if (retval) {
valid = Z_LVAL_P(retval);
zval_ptr_dtor(&retval);
} else {
valid = 0;
}
if (valid) {
if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_current, "current", &retval);
} else {
zend_call_method_with_0_params(&it, Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_key, "key", &retval);
}
if (!retval) {
zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0 TSRMLS_CC);
return;
}
} else if (intern->flags & MIT_NEED_ALL) {
if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
zend_throw_exception(spl_ce_RuntimeException, "Called current() with non valid sub iterator", 0 TSRMLS_CC);
} else {
zend_throw_exception(spl_ce_RuntimeException, "Called key() with non valid sub iterator", 0 TSRMLS_CC);
}
return;
} else {
ALLOC_INIT_ZVAL(retval);
}
if (intern->flags & MIT_KEYS_ASSOC) {
switch (Z_TYPE_P(element->inf)) {
case IS_LONG:
add_index_zval(return_value, Z_LVAL_P(element->inf), retval);
break;
case IS_STRING:
case IS_UNICODE:
add_u_assoc_zval_ex(return_value, Z_TYPE_P(element->inf), Z_UNIVAL_P(element->inf), Z_UNILEN_P(element->inf)+1U, retval);
break;
default:
zval_ptr_dtor(&retval);
zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is associated with NULL", 0 TSRMLS_CC);
return;
}
} else {
add_next_index_zval(return_value, retval);
}
zend_hash_move_forward_ex(&intern->storage, &intern->pos);
}
}
/* }}} */
/* {{{ proto array current() throws RuntimeException throws InvalidArgumentException U
Return an array of all registered Iterator instances current() result */
SPL_METHOD(MultipleIterator, current)
{
spl_SplObjectStorage *intern;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value TSRMLS_CC);
}
/* }}} */
/* {{{ proto array MultipleIterator::key() U
Return an array of all registered Iterator instances key() result */
SPL_METHOD(MultipleIterator, key)
{
spl_SplObjectStorage *intern;
intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_multiple_iterator_get_all(intern, SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value TSRMLS_CC);
}
/* }}} */
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_attachIterator, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_ARG_INFO(0, infos)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_detachIterator, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_containsIterator, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
ZEND_END_ARG_INFO();
static const zend_function_entry spl_funcs_MultipleIterator[] = {
SPL_ME(MultipleIterator, __construct, NULL, 0)
SPL_ME(MultipleIterator, getFlags, NULL, 0)
SPL_ME(MultipleIterator, setFlags, NULL, 0)
SPL_ME(MultipleIterator, attachIterator, arginfo_MultipleIterator_attachIterator, 0)
SPL_MA(MultipleIterator, detachIterator, SplObjectStorage, detach, arginfo_MultipleIterator_detachIterator, 0)
SPL_MA(MultipleIterator, containsIterator, SplObjectStorage, contains, arginfo_MultipleIterator_containsIterator, 0)
SPL_MA(MultipleIterator, countIterators, SplObjectStorage, count, NULL, 0)
/* Iterator */
SPL_ME(MultipleIterator, rewind, NULL, 0)
SPL_ME(MultipleIterator, valid, NULL, 0)
SPL_ME(MultipleIterator, key, NULL, 0)
SPL_ME(MultipleIterator, current, NULL, 0)
SPL_ME(MultipleIterator, next, NULL, 0)
{NULL, NULL, NULL}
};
static const zend_function_entry spl_funcs_SplObjectStorage[] = {
SPL_ME(SplObjectStorage, attach, arginfo_attach, 0)
SPL_ME(SplObjectStorage, detach, arginfo_Object, 0)
@ -635,6 +930,14 @@ PHP_MINIT_FUNCTION(spl_observer)
REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Serializable);
REGISTER_SPL_IMPLEMENTS(SplObjectStorage, ArrayAccess);
REGISTER_SPL_STD_CLASS_EX(MultipleIterator, spl_SplObjectStorage_new, spl_funcs_MultipleIterator);
REGISTER_SPL_ITERATOR(MultipleIterator);
REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ANY", MIT_NEED_ANY);
REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ALL", MIT_NEED_ALL);
REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_NUMERIC", MIT_KEYS_NUMERIC);
REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_ASSOC", MIT_KEYS_ASSOC);
return SUCCESS;
}
/* }}} */

View File

@ -27,6 +27,7 @@
extern PHPAPI zend_class_entry *spl_ce_SplObserver;
extern PHPAPI zend_class_entry *spl_ce_SplSubject;
extern PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
extern PHPAPI zend_class_entry *spl_ce_MultipleIterator;
PHP_MINIT_FUNCTION(spl_observer);

View File

@ -0,0 +1,345 @@
--TEST--
SPL: MultipleIterator
--FILE--
<?php
$iter1 = new ArrayIterator(array(1,2,3));
$iter2 = new ArrayIterator(array(1,2));
$iter3 = new ArrayIterator(array(new stdClass(),"string",3));
$m = new MultipleIterator();
echo "-- Default flags, no iterators --\n";
foreach($m as $value) {
var_dump($value);
}
var_dump($m->current());
$m->attachIterator($iter1);
$m->attachIterator($iter2);
$m->attachIterator($iter3);
echo "-- Default flags, MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC --\n";
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC));
foreach($m as $value) {
var_dump($m->key(), $value);
}
try {
$m->current();
} catch(RuntimeException $e) {
echo "RuntimeException thrown: " . $e->getMessage() . "\n";
}
try {
$m->key();
} catch(RuntimeException $e) {
echo "RuntimeException thrown: " . $e->getMessage() . "\n";
}
echo "-- Flags = MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC);
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC));
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Default flags, added element --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC);
$iter2[] = 3;
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated with NULL --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_ASSOC);
$m->rewind();
try {
$m->current();
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC --\n";
$m->attachIterator($iter1, "iter1");
$m->attachIterator($iter2, b"iter2");
$m->attachIterator($iter3, 3);
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Associate with invalid value --\n";
try {
$m->attachIterator($iter3, new stdClass());
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Associate with duplicate value --\n";
try {
$m->attachIterator($iter3, "iter1");
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Count, contains, detach, count, contains, iterate --\n";
var_dump($m->countIterators());
var_dump($m->containsIterator($iter2));
var_dump($m->detachIterator($iter2));
var_dump($m->countIterators());
var_dump($m->containsIterator($iter2));
foreach($m as $value) {
var_dump($m->key(), $value);
}
?>
--EXPECTF--
-- Default flags, no iterators --
bool(false)
-- Default flags, MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC --
bool(true)
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
RuntimeException thrown: Called current() with non valid sub iterator
RuntimeException thrown: Called key() with non valid sub iterator
-- Flags = MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC --
bool(true)
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
array(3) {
[0]=>
int(2)
[1]=>
NULL
[2]=>
int(2)
}
array(3) {
[0]=>
int(3)
[1]=>
NULL
[2]=>
int(3)
}
-- Default flags, added element --
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
int(2)
}
array(3) {
[0]=>
int(3)
[1]=>
int(3)
[2]=>
int(3)
}
-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated with NULL --
InvalidArgumentException thrown: Sub-Iterator is associated with NULL
-- Flags |= MultipleIterator::MIT_KEYS_ASSOC --
array(3) {
[u"iter1"]=>
int(0)
["iter2"]=>
int(0)
[3]=>
int(0)
}
array(3) {
[u"iter1"]=>
int(1)
["iter2"]=>
int(1)
[3]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[u"iter1"]=>
int(1)
["iter2"]=>
int(1)
[3]=>
int(1)
}
array(3) {
[u"iter1"]=>
int(2)
["iter2"]=>
int(2)
[3]=>
unicode(6) "string"
}
array(3) {
[u"iter1"]=>
int(2)
["iter2"]=>
int(2)
[3]=>
int(2)
}
array(3) {
[u"iter1"]=>
int(3)
["iter2"]=>
int(3)
[3]=>
int(3)
}
-- Associate with invalid value --
InvalidArgumentException thrown: Info must be NULL, integer or string
-- Associate with duplicate value --
InvalidArgumentException thrown: Key duplication error
-- Count, contains, detach, count, contains, iterate --
int(3)
bool(true)
NULL
int(2)
bool(false)
array(2) {
[u"iter1"]=>
int(0)
[3]=>
int(0)
}
array(2) {
[u"iter1"]=>
int(1)
[3]=>
object(stdClass)#%d (0) {
}
}
array(2) {
[u"iter1"]=>
int(1)
[3]=>
int(1)
}
array(2) {
[u"iter1"]=>
int(2)
[3]=>
unicode(6) "string"
}
array(2) {
[u"iter1"]=>
int(2)
[3]=>
int(2)
}
array(2) {
[u"iter1"]=>
int(3)
[3]=>
int(3)
}