Browse Source

- Add RecursiveIteratorIterator::beginChildren(), endChildren()

PHP-5.1
Marcus Boerger 22 years ago
parent
commit
3b7e24cab2
  1. 18
      ext/spl/internal/recursiveiteratoriterator.inc
  2. 91
      ext/spl/spl_iterators.c
  3. 143
      ext/spl/tests/iterator_014.phpt

18
ext/spl/internal/recursiveiteratoriterator.inc

@ -46,6 +46,7 @@ class RecursiveIteratorIterator implements OuterIterator
{
while ($this->count) {
unset($this->ait[$this->count--]);
$this->endChildren();
}
$this->ait[0]->rewind();
$this->ait[0]->recursed = false;
@ -62,6 +63,7 @@ class RecursiveIteratorIterator implements OuterIterator
return true;
}
$count--;
$this->endChildren();
}
return false;
}
@ -98,7 +100,8 @@ class RecursiveIteratorIterator implements OuterIterator
$this->ait[++$this->count] = $sub;
if (!$sub instanceof RecursiveIterator) {
throw new Exception(get_class($sub).'::getChildren() must return an object that implements RecursiveIterator');
}
}
$this->beginChildren();
return;
}
unset($sub);
@ -113,6 +116,7 @@ class RecursiveIteratorIterator implements OuterIterator
if ($this->count) {
unset($this->ait[$this->count--]);
$it = $this->ait[$this->count];
$this->endChildren();
}
}
}
@ -142,6 +146,18 @@ class RecursiveIteratorIterator implements OuterIterator
{
return $this->level;
}
/** Called right after calling getChildren()
*/
function beginChildren()
{
}
/** Called after current child iterator is invalid
*/
function endChildren()
{
}
}
?>

91
ext/spl/spl_iterators.c

@ -59,40 +59,6 @@ function_entry spl_funcs_RecursiveIterator[] = {
{NULL, NULL, NULL}
};
SPL_METHOD(RecursiveIteratorIterator, __construct);
SPL_METHOD(RecursiveIteratorIterator, rewind);
SPL_METHOD(RecursiveIteratorIterator, valid);
SPL_METHOD(RecursiveIteratorIterator, key);
SPL_METHOD(RecursiveIteratorIterator, current);
SPL_METHOD(RecursiveIteratorIterator, next);
SPL_METHOD(RecursiveIteratorIterator, getDepth);
SPL_METHOD(RecursiveIteratorIterator, getSubIterator);
SPL_METHOD(RecursiveIteratorIterator, getInnerIterator);
static
ZEND_BEGIN_ARG_INFO(arginfo_recursive_it___construct, 0)
ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_getSubIterator, 0)
ZEND_ARG_INFO(0, level)
ZEND_END_ARG_INFO();
static zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
SPL_ME(RecursiveIteratorIterator, __construct, arginfo_recursive_it___construct, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, rewind, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, valid, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, key, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, current, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, next, NULL, ZEND_ACC_PUBLIC)
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)
{NULL, NULL, NULL}
};
typedef enum {
RIT_LEAVES_ONLY = 0,
RIT_SELF_FIRST = 1,
@ -190,7 +156,7 @@ static int spl_recursive_it_get_current_key(zend_object_iterator *iter, char **s
}
}
static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object TSRMLS_DC)
static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
{
zend_object_iterator *iterator;
zval *zobject;
@ -262,6 +228,7 @@ next_step:
if (sub_iter->funcs->rewind) {
sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
}
zend_call_method_with_0_params(&zthis, NULL, NULL, "beginchildren", NULL);
goto next_step;
}
/* no more elements */
@ -269,13 +236,14 @@ next_step:
iterator->funcs->dtor(iterator TSRMLS_CC);
zval_ptr_dtor(&object->iterators[object->level].zobject);
object->level--;
zend_call_method_with_0_params(&zthis, NULL, NULL, "endchildren", NULL);
} else {
return; /* done completeley */
}
}
}
static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object TSRMLS_DC)
static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object, zval *zthis TSRMLS_DC)
{
zend_object_iterator *sub_iter;
@ -283,6 +251,7 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object TSRMLS_DC
sub_iter = object->iterators[object->level].iterator;
sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
zval_ptr_dtor(&object->iterators[object->level--].zobject);
zend_call_method_with_0_params(&zthis, NULL, NULL, "endchildren", NULL);
}
erealloc(object->iterators, sizeof(spl_sub_iterator));
object->iterators[0].state = RS_START;
@ -290,17 +259,17 @@ static void spl_recursive_it_rewind_ex(spl_recursive_it_object *object TSRMLS_DC
if (sub_iter->funcs->rewind) {
sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
}
spl_recursive_it_move_forward_ex(object TSRMLS_CC);
spl_recursive_it_move_forward_ex(object, zthis TSRMLS_CC);
}
static void spl_recursive_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
{
spl_recursive_it_move_forward_ex((spl_recursive_it_object*)iter->data TSRMLS_CC);
spl_recursive_it_move_forward_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
}
static void spl_recursive_it_rewind(zend_object_iterator *iter TSRMLS_DC)
{
spl_recursive_it_rewind_ex((spl_recursive_it_object*)iter->data TSRMLS_CC);
spl_recursive_it_rewind_ex((spl_recursive_it_object*)iter->data, ((spl_recursive_it_iterator*)iter)->zobject TSRMLS_CC);
}
static zend_object_iterator *spl_recursive_it_get_iterator(zend_class_entry *ce, zval *zobject TSRMLS_DC)
@ -361,7 +330,7 @@ SPL_METHOD(RecursiveIteratorIterator, rewind)
{
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_recursive_it_rewind_ex(object TSRMLS_CC);
spl_recursive_it_rewind_ex(object, getThis() TSRMLS_CC);
} /* }}} */
/* {{{ proto bolean RecursiveIteratorIterator::valid()
@ -412,7 +381,7 @@ SPL_METHOD(RecursiveIteratorIterator, next)
{
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_recursive_it_move_forward_ex(object TSRMLS_CC);
spl_recursive_it_move_forward_ex(object, getThis() TSRMLS_CC);
} /* }}} */
/* {{{ proto int RecursiveIteratorIterator::getDepth()
@ -450,6 +419,20 @@ SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
} /* }}} */
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginChildren()
Called when recursing one level down */
SPL_METHOD(RecursiveIteratorIterator, beginChildren)
{
/* nothing to do */
} /* }}} */
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::endChildren()
Called when end recursing one level */
SPL_METHOD(RecursiveIteratorIterator, endChildren)
{
/* nothing to do */
} /* }}} */
static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *method, int method_len TSRMLS_DC)
{
union _zend_function *function_handler;
@ -512,6 +495,32 @@ static zend_object_value spl_RecursiveIteratorIterator_new(zend_class_entry *cla
}
/* }}} */
static
ZEND_BEGIN_ARG_INFO(arginfo_recursive_it___construct, 0)
ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_getSubIterator, 0)
ZEND_ARG_INFO(0, level)
ZEND_END_ARG_INFO();
static zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
SPL_ME(RecursiveIteratorIterator, __construct, arginfo_recursive_it___construct, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, rewind, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, valid, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, key, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, current, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, next, NULL, ZEND_ACC_PUBLIC)
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, beginChildren, NULL, ZEND_ACC_PUBLIC)
SPL_ME(RecursiveIteratorIterator, endChildren, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
#if MBO_0
static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_entry *class_type TSRMLS_DC)
{

143
ext/spl/tests/iterator_014.phpt

@ -0,0 +1,143 @@
--TEST--
SPL: RecursiveIteratorIterator and beginChildren/endChildren
--FILE--
<?php
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
{
function hasChildren()
{
return is_array($this->current());
}
function getChildren()
{
echo __METHOD__ . "\n";
return new RecursiveArrayIterator($this->current());
}
function valid()
{
if (!parent::valid())
{
echo __METHOD__ . " = false\n";
return false;
}
else
{
return true;
}
}
}
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
{
function rewind()
{
echo __METHOD__ . "\n";
parent::rewind();
}
function valid()
{
echo __METHOD__ . "\n";
return parent::valid();
}
function current()
{
echo __METHOD__ . "\n";
return parent::current();
}
function key()
{
echo __METHOD__ . "\n";
return parent::key();
}
function next()
{
echo __METHOD__ . "\n";
parent::next();
}
function beginChildren()
{
echo __METHOD__ . "(".$this->getDepth().")\n";
}
function endChildren()
{
echo __METHOD__ . "(".$this->getDepth().")\n";
}
}
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"))), array("ca"), "d"))) as $k=>$v)
{
echo "$k=>$v\n";
}
?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
RecursiveArrayIteratorIterator::rewind
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
0=>a
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::getChildren
RecursiveArrayIteratorIterator::beginChildren(1)
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
0=>ba
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::getChildren
RecursiveArrayIteratorIterator::beginChildren(2)
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
0=>bba
RecursiveArrayIteratorIterator::next
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
1=>bbb
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::endChildren(1)
RecursiveArrayIterator::getChildren
RecursiveArrayIteratorIterator::beginChildren(2)
RecursiveArrayIterator::getChildren
RecursiveArrayIteratorIterator::beginChildren(3)
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
0=>bcaa
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::endChildren(2)
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::endChildren(1)
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::endChildren(0)
RecursiveArrayIterator::getChildren
RecursiveArrayIteratorIterator::beginChildren(1)
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
0=>ca
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::endChildren(0)
RecursiveArrayIteratorIterator::valid
RecursiveArrayIteratorIterator::current
RecursiveArrayIteratorIterator::key
3=>d
RecursiveArrayIteratorIterator::next
RecursiveArrayIterator::valid = false
RecursiveArrayIteratorIterator::valid
RecursiveArrayIterator::valid = false
===DONE===
Loading…
Cancel
Save