summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2005-07-28 21:09:02 +0000
committerMarcus Boerger <helly@php.net>2005-07-28 21:09:02 +0000
commit0b34e041e3d451089e5827d0aa2a942689b6b60c (patch)
tree81ab4ef7c4ef5976d13d717bc76dbf04d4b1d80b /ext
parentd608181dc79fd65579f7cce171a35e027957887e (diff)
downloadphp-git-0b34e041e3d451089e5827d0aa2a942689b6b60c.tar.gz
- Before we later run into BC trouble we split flags into two params mode
and flags now before branching for 5.1.
Diffstat (limited to 'ext')
-rwxr-xr-xext/spl/internal/recursiveiteratoriterator.inc12
-rwxr-xr-xext/spl/spl_iterators.c13
-rwxr-xr-xext/spl/tests/iterator_023.phpt198
3 files changed, 210 insertions, 13 deletions
diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc
index 66cffc4875..d77f9850da 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 2924b90966..34e6886d97 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 0000000000..46aa26ac71
--- /dev/null
+++ b/ext/spl/tests/iterator_023.phpt
@@ -0,0 +1,198 @@
+--TEST--
+SPL: RecursiveIteratorIterator and catch getChildren
+--FILE--
+<?php
+
+class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
+{
+ function hasChildren()
+ {
+ return is_array($this->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===
+<?php exit(0); ?>
+--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===