From 0b34e041e3d451089e5827d0aa2a942689b6b60c Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Thu, 28 Jul 2005 21:09:02 +0000 Subject: [PATCH] - Before we later run into BC trouble we split flags into two params mode and flags now before branching for 5.1. --- .../internal/recursiveiteratoriterator.inc | 12 +- ext/spl/spl_iterators.c | 13 +- ext/spl/tests/iterator_023.phpt | 198 ++++++++++++++++++ 3 files changed, 210 insertions(+), 13 deletions(-) create mode 100755 ext/spl/tests/iterator_023.phpt diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc index 66cffc48752f8..d77f9850da401 100755 --- a/ext/spl/internal/recursiveiteratoriterator.inc +++ b/ext/spl/internal/recursiveiteratoriterator.inc @@ -12,7 +12,7 @@ define('RIT_LEAVES_ONLY', 0); define('RIT_SELF_FIRST', 1); define('RIT_CHILD_FIRST', 2); -define('RIT_CATCH_GET_CHILD', 256); +define('RIT_CATCH_GET_CHILD', 2); /** * @brief Iterates through recursive iterators @@ -34,20 +34,20 @@ class RecursiveIteratorIterator implements OuterIterator /** Construct from RecursiveIterator * * @param it RecursiveIterator to iterate - * @param flags Operation mode (one of): + * @param mode Operation mode (one of): * - RIT_LEAVES_ONLY only show leaves * - RIT_SELF_FIRST show parents prior to their childs * - RIT_CHILD_FIRST show all childs prior to their parent - * or'ed with the following flags: + * @param flags Control flags, zero or any combination of the following * - RIT_CATCH_GET_CHILD which catches exceptions during * getChildren() calls and simply jumps to the next * element. */ - function __construct(RecursiveIterator $it, $flags) + function __construct(RecursiveIterator $it, $mode = RIT_LEAVES_ONLY, $flags = 0) { $this->ait[0] = $it; - $this->mode = $flags & 0xFF; - $this->flags = $flags & ~0xFF; + $this->mode = $mode; + $this->flags = $flags; } /** Rewind to top iterator as set in constructor diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 2924b909666ff..34e6886d9725a 100755 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -65,8 +65,7 @@ typedef enum { RIT_CHILD_FIRST = 2 } RecursiveIteratorMode; -#define RIT_MODE_MASK 0x000000FF -#define RIT_CATCH_GET_CHILD 0x00000100 +#define RIT_CATCH_GET_CHILD CIT_CATCH_GET_CHILD typedef enum { RS_NEXT = 0, @@ -333,7 +332,7 @@ zend_object_iterator_funcs spl_recursive_it_iterator_funcs = { spl_recursive_it_rewind }; -/* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int flags = RIT_LEAVES_ONLY]) throws InvalidArgumentException +/* {{{ proto RecursiveIteratorIterator::__construct(RecursiveIterator|IteratorAggregate it [, int mode = RIT_LEAVES_ONLY [, int flags = 0]]) throws InvalidArgumentException Creates a RecursiveIteratorIterator from a RecursiveIterator. */ SPL_METHOD(RecursiveIteratorIterator, __construct) { @@ -341,11 +340,11 @@ SPL_METHOD(RecursiveIteratorIterator, __construct) spl_recursive_it_object *intern; zval *iterator; zend_class_entry *ce_iterator; - long mode = RIT_LEAVES_ONLY; + long mode = RIT_LEAVES_ONLY, flags = 0; php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException TSRMLS_CC); - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &iterator, &mode) == SUCCESS) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o|ll", &iterator, &mode, &flags) == SUCCESS) { if (instanceof_function(Z_OBJCE_P(iterator), zend_ce_aggregate TSRMLS_CC)) { zval *aggregate = iterator; zend_call_method_with_0_params(&aggregate, Z_OBJCE_P(aggregate), &Z_OBJCE_P(aggregate)->iterator_funcs.zf_new_iterator, "getiterator", &iterator); @@ -362,8 +361,8 @@ SPL_METHOD(RecursiveIteratorIterator, __construct) intern = (spl_recursive_it_object*)zend_object_store_get_object(object TSRMLS_CC); intern->iterators = emalloc(sizeof(spl_sub_iterator)); intern->level = 0; - intern->mode = mode & RIT_MODE_MASK; - intern->flags = mode & ~RIT_MODE_MASK; + intern->mode = mode; + intern->flags = flags; intern->ce = Z_OBJCE_P(object); zend_hash_find(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren"), (void **) &intern->callHasChildren); if (intern->callHasChildren->common.scope == spl_ce_RecursiveIteratorIterator) { diff --git a/ext/spl/tests/iterator_023.phpt b/ext/spl/tests/iterator_023.phpt new file mode 100755 index 0000000000000..46aa26ac71d55 --- /dev/null +++ b/ext/spl/tests/iterator_023.phpt @@ -0,0 +1,198 @@ +--TEST-- +SPL: RecursiveIteratorIterator and catch getChildren +--FILE-- +current()); + } + + function getChildren() + { + echo __METHOD__ . "\n"; + return $this->current(); + } + + function valid() + { + if (!parent::valid()) + { + echo __METHOD__ . " = false\n"; + return false; + } + else + { + return true; + } + } +} + +class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator +{ + private $max_depth; + private $over = 0; + private $skip = false; + + function __construct($it, $max_depth) + { + $this->max_depth = $max_depth; + parent::__construct($it, RIT_LEAVES_ONLY, RIT_CATCH_GET_CHILD); + } + + function rewind() + { + echo __METHOD__ . "\n"; + $this->skip = false; + parent::rewind(); + } + + function valid() + { + echo __METHOD__ . "\n"; + if ($this->skip) + { + $this->skip = false; + $this->next(); + } + 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 callHasChildren() + { + $this->skip = false; + $has = parent::callHasChildren(); + $res = $this->getDepth() < $this->max_depth && $has; + echo __METHOD__ . "(".$this->getDepth().") = ".($res?"yes":"no")."/".($has?"yes":"no")."\n"; + if ($has && !$res) + { + $this->over++; + if ($this->over == 2) { + $this->skip = true; + } + } + return $res; + } + + function callGetChildren() + { + if ($this->over == 2) + { + echo __METHOD__ . "(throw)\n"; + throw new Exception("Thrown in callGetChildren()"); + } + echo __METHOD__ . "(ok:{$this->over})\n"; + return new RecursiveArrayIterator($this->current()); + } + + function beginChildren() + { + echo __METHOD__ . "(".$this->getDepth().")\n"; + } + + function endChildren() + { + echo __METHOD__ . "(".$this->getDepth().")\n"; + } +} + +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) + { + if (is_array($v)) $v = join('',$v); + echo "$k=>$v\n"; + } +} +catch(UnexpectedValueException $e) +{ + echo $e->getMessage() . "\n"; +} + +?> +===DONE=== + +--EXPECT-- +RecursiveArrayIteratorIterator::rewind +RecursiveArrayIteratorIterator::callHasChildren(0) = no/no +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +0=>a +RecursiveArrayIteratorIterator::next +RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes +RecursiveArrayIteratorIterator::callGetChildren(ok:0) +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::beginChildren(1) +RecursiveArrayIteratorIterator::callHasChildren(1) = no/no +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +0=>ba +RecursiveArrayIteratorIterator::next +RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes +RecursiveArrayIteratorIterator::callGetChildren(ok:0) +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::beginChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(2) = no/no +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +0=>bba +RecursiveArrayIteratorIterator::next +RecursiveArrayIteratorIterator::callHasChildren(2) = no/no +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +1=>bbb +RecursiveArrayIteratorIterator::next +RecursiveArrayIterator::valid = false +RecursiveArrayIteratorIterator::endChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes +RecursiveArrayIteratorIterator::callGetChildren(ok:0) +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::beginChildren(2) +RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +0=>bcaa +RecursiveArrayIteratorIterator::next +RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes +RecursiveArrayIteratorIterator::valid +RecursiveArrayIteratorIterator::next +RecursiveArrayIterator::valid = false +RecursiveArrayIteratorIterator::endChildren(2) +RecursiveArrayIterator::valid = false +RecursiveArrayIteratorIterator::endChildren(1) +RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes +RecursiveArrayIteratorIterator::callGetChildren(throw) +RecursiveArrayIteratorIterator::callHasChildren(0) = no/no +RecursiveArrayIteratorIterator::current +RecursiveArrayIteratorIterator::key +3=>d +RecursiveArrayIteratorIterator::next +RecursiveArrayIterator::valid = false +RecursiveArrayIteratorIterator::valid +RecursiveArrayIterator::valid = false +===DONE===