]> granicus.if.org Git - php/commitdiff
- Add RecursiveIteratorIterator::beginChildren(), endChildren()
authorMarcus Boerger <helly@php.net>
Mon, 1 Nov 2004 22:54:12 +0000 (22:54 +0000)
committerMarcus Boerger <helly@php.net>
Mon, 1 Nov 2004 22:54:12 +0000 (22:54 +0000)
ext/spl/internal/recursiveiteratoriterator.inc
ext/spl/spl_iterators.c
ext/spl/tests/iterator_014.phpt [new file with mode: 0755]

index bb06fdbf2d9d6302107c976335c18455dd5e713c..6c564ee61ed2a3175fd2716d825a7a20df87bbea 100755 (executable)
@@ -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()
+       {
+       }
 }
 
 ?>
\ No newline at end of file
index eb9382eb03c3a5fc8a8d262b76d858a315843564..bdbd275d864eb0822b784c76d120f12f3271ce5e 100755 (executable)
@@ -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)
 {
diff --git a/ext/spl/tests/iterator_014.phpt b/ext/spl/tests/iterator_014.phpt
new file mode 100755 (executable)
index 0000000..ff8bb2c
--- /dev/null
@@ -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===