Skip to content

Commit

Permalink
- Before we later run into BC trouble we split flags into two params …
Browse files Browse the repository at this point in the history
…mode

  and flags now before branching for 5.1.
  • Loading branch information
helly25 committed Jul 28, 2005
1 parent d608181 commit 0b34e04
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 13 deletions.
12 changes: 6 additions & 6 deletions ext/spl/internal/recursiveiteratoriterator.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
13 changes: 6 additions & 7 deletions ext/spl/spl_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -333,19 +332,19 @@ 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)
{
zval *object = getThis();
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);
Expand All @@ -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) {
Expand Down
198 changes: 198 additions & 0 deletions ext/spl/tests/iterator_023.phpt
Original file line number Diff line number Diff line change
@@ -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===

0 comments on commit 0b34e04

Please sign in to comment.