mirror of
https://github.com/php/php-src.git
synced 2025-01-20 10:43:40 +08:00
- Before we later run into BC trouble we split flags into two params mode
and flags now before branching for 5.1.
This commit is contained in:
parent
d608181dc7
commit
0b34e041e3
@ -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
|
||||
|
@ -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) {
|
||||
|
198
ext/spl/tests/iterator_023.phpt
Executable file
198
ext/spl/tests/iterator_023.phpt
Executable file
@ -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===
|
Loading…
Reference in New Issue
Block a user