helly Sun Sep 25 08:01:32 2005 EDT
Added files:
/php-src/ext/spl/tests iterator_028.phpt
Modified files:
/php-src/ext/spl spl_iterators.c
/php-src/ext/spl/internal recursiveiteratoriterator.inc
Log:
- Implement RecursiveIteratorIterator::setMaxDepth()/getMaxDepth()
http://cvs.php.net/diff.php/php-src/ext/spl/spl_iterators.c?r1=1.85&r2=1.86&ty=u
Index: php-src/ext/spl/spl_iterators.c
diff -u php-src/ext/spl/spl_iterators.c:1.85
php-src/ext/spl/spl_iterators.c:1.86
--- php-src/ext/spl/spl_iterators.c:1.85 Sun Sep 18 12:51:20 2005
+++ php-src/ext/spl/spl_iterators.c Sun Sep 25 08:01:31 2005
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_iterators.c,v 1.85 2005/09/18 16:51:20 helly Exp $ */
+/* $Id: spl_iterators.c,v 1.86 2005/09/25 12:01:31 helly Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -89,6 +89,7 @@
int level;
RecursiveIteratorMode mode;
int flags;
+ int max_depth;
zend_bool in_iteration;
zend_function *beginIteration;
zend_function *endIteration;
@@ -119,7 +120,7 @@
sub_iter->funcs->dtor(sub_iter TSRMLS_CC);
zval_ptr_dtor(&object->iterators[object->level--].zobject);
}
- erealloc(object->iterators, sizeof(spl_sub_iterator));
+ object->iterators = erealloc(object->iterators,
sizeof(spl_sub_iterator));
object->level = 0;
zval_ptr_dtor(&iter->zobject);
@@ -206,14 +207,23 @@
has_children = zend_is_true(retval);
zval_ptr_dtor(&retval);
if (has_children) {
- switch (object->mode) {
- case RIT_LEAVES_ONLY:
- case RIT_CHILD_FIRST:
-
object->iterators[object->level].state = RS_CHILD;
- goto next_step;
- case RIT_SELF_FIRST:
-
object->iterators[object->level].state = RS_SELF;
- goto next_step;
+ if (object->max_depth == -1 ||
object->max_depth > object->level) {
+ switch (object->mode) {
+ case RIT_LEAVES_ONLY:
+ case RIT_CHILD_FIRST:
+
object->iterators[object->level].state = RS_CHILD;
+ goto next_step;
+ case RIT_SELF_FIRST:
+
object->iterators[object->level].state = RS_SELF;
+ goto next_step;
+ }
+ } else {
+ /* do not recurse into
*/
+ if (object->mode ==
RIT_LEAVES_ONLY) {
+ /* this is not
a leave, so skip it */
+
object->iterators[object->level].state = RS_NEXT;
+ goto next_step;
+ }
}
}
}
@@ -382,8 +392,10 @@
intern->level = 0;
intern->mode = mode;
intern->flags = flags;
+ intern->max_depth = -1;
intern->in_iteration = 0;
intern->ce = Z_OBJCE_P(object);
+
zend_hash_find(&intern->ce->function_table, "beginiteration",
sizeof("beginiteration"), (void **) &intern->beginIteration);
if (intern->beginIteration->common.scope ==
U_CLASS_ENTRY(spl_ce_RecursiveIteratorIterator)) {
intern->beginIteration = NULL;
@@ -588,6 +600,36 @@
/* nothing to do */
} /* }}} */
+/* {{{ proto RecursiveIterator
RecursiveIteratorIterator::setMaxDepth([$max_depth = -1])
+ Set the maximum allowed depth (or any depth if pmax_depth = -1] */
+SPL_METHOD(RecursiveIteratorIterator, setMaxDepth)
+{
+ spl_recursive_it_object *object =
(spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ long max_depth = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &max_depth)
== FAILURE) {
+ return;
+ }
+ if (max_depth < -1) {
+ zend_throw_exception(U_CLASS_ENTRY(spl_ce_OutOfRangeException),
"Parameter max_depth must be >= -1", 0 TSRMLS_CC);
+ return;
+ }
+ object->max_depth = max_depth;
+} /* }}} */
+
+/* {{{ proto RecursiveIterator RecursiveIteratorIterator::getMaxDepth()
+ Return the maximum accepted depth or false if any depth is allowed */
+SPL_METHOD(RecursiveIteratorIterator, getMaxDepth)
+{
+ spl_recursive_it_object *object =
(spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (object->max_depth == -1) {
+ RETURN_FALSE;
+ } else {
+ RETURN_LONG(object->max_depth);
+ }
+} /* }}} */
+
static union _zend_function *spl_recursive_it_get_method(zval **object_ptr,
char *method, int method_len TSRMLS_DC)
{
union _zend_function *function_handler;
@@ -620,6 +662,7 @@
zval_ptr_dtor(&object->iterators[object->level--].zobject);
}
efree(object->iterators);
+ object->iterators = NULL;
}
zend_hash_destroy(object->std.properties);
@@ -661,23 +704,30 @@
ZEND_ARG_INFO(0, level)
ZEND_END_ARG_INFO();
+static
+ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_setMaxDepth, 0)
+ ZEND_ARG_INFO(0, max_depth)
+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, __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, beginIteration, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, endIteration, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, callHasChildren, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, callGetChildren, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, beginChildren, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, endChildren, NULL,
ZEND_ACC_PUBLIC)
- SPL_ME(RecursiveIteratorIterator, nextElement, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, getInnerIterator, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, beginIteration, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, endIteration, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, callHasChildren, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, callGetChildren, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, beginChildren, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, endChildren, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, nextElement, NULL,
ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, setMaxDepth,
arginfo_recursive_it_setMaxDepth, ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveIteratorIterator, getMaxDepth, NULL,
ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
@@ -1439,13 +1489,10 @@
MAKE_STD_ZVAL(zcacheval);
ZVAL_ZVAL(zcacheval, intern->current.data, 1, 0);
- switch(intern->current.key_type) {
- case HASH_KEY_IS_STRING:
-
zend_u_symtable_update(HASH_OF(intern->u.caching.zcache), IS_STRING,
intern->current.str_key, intern->current.str_key_len, &zcacheval,
sizeof(void*), NULL);
- break;
- case HASH_KEY_IS_LONG:
-
add_index_zval(intern->u.caching.zcache, intern->current.int_key, zcacheval);
- break;
+ if (intern->current.key_type == HASH_KEY_IS_LONG) {
+ add_index_zval(intern->u.caching.zcache,
intern->current.int_key, zcacheval);
+ } else {
+
zend_u_symtable_update(HASH_OF(intern->u.caching.zcache),
intern->current.key_type, intern->current.str_key, intern->current.str_key_len,
&zcacheval, sizeof(void*), NULL);
}
}
/* Recursion ? */
http://cvs.php.net/diff.php/php-src/ext/spl/internal/recursiveiteratoriterator.inc?r1=1.15&r2=1.16&ty=u
Index: php-src/ext/spl/internal/recursiveiteratoriterator.inc
diff -u php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.15
php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.16
--- php-src/ext/spl/internal/recursiveiteratoriterator.inc:1.15 Wed Sep 14
23:31:37 2005
+++ php-src/ext/spl/internal/recursiveiteratoriterator.inc Sun Sep 25
08:01:31 2005
@@ -12,7 +12,7 @@
/**
* @brief Iterates through recursive iterators
* @author Marcus Boerger
- * @version 1.2
+ * @version 1.3
* @since PHP 5.0
*
* The objects of this class are created by instances of RecursiveIterator.
@@ -33,9 +33,10 @@
const CATCH_GET_CHILD = 2;
private $ait = array();
- private $count = 0;
+ private $level = 0;
private $mode = self::LEAVES_ONLY;
private $flags = 0;
+ private $max_depth = -1;
/** Construct from RecursiveIterator
*
@@ -61,8 +62,8 @@
*/
function rewind()
{
- while ($this->count) {
- unset($this->ait[$this->count--]);
+ while ($this->level) {
+ unset($this->ait[$this->level--]);
$this->endChildren();
}
$this->ait[0]->rewind();
@@ -74,13 +75,13 @@
*/
function valid()
{
- $count = $this->count;
- while ($count) {
- $it = $this->ait[$count];
+ $level = $this->level;
+ while ($level >= 0) {
+ $it = $this->ait[$level];
if ($it->valid()) {
return true;
}
- $count--;
+ $level--;
$this->endChildren();
}
return false;
@@ -90,7 +91,7 @@
*/
function key()
{
- $it = $this->ait[$this->count];
+ $it = $this->ait[$this->level];
return $it->key();
}
@@ -98,7 +99,7 @@
*/
function current()
{
- $it = $this->ait[$this->count];
+ $it = $this->ait[$this->level];
return $it->current();
}
@@ -106,46 +107,61 @@
*/
function next()
{
- while ($this->count) {
- $it = $this->ait[$this->count];
+ while ($this->level >= 0) {
+ $it = $this->ait[$this->level];
if ($it->valid()) {
if (!$it->recursed && callHasChildren()) {
- $it->recursed = true;
- try
- {
- $sub = callGetChildren();
+ if ($this->max_depth == -1 ||
$this->max_depth > $this->level) {
+ $it->recursed = true;
+ try
+ {
+ $sub =
callGetChildren();
+ }
+ catch (Exception $e)
+ {
+ if (!($this->flags &
self::CATCH_GET_CHILD))
+ {
+ throw $e;
+ }
+ $it->next();
+ continue;
+ }
+ $sub->recursed = false;
+ $sub->rewind();
+ if ($sub->valid()) {
+
$this->ait[++$this->level] = $sub;
+ if (!$sub instanceof
RecursiveIterator) {
+ throw new
Exception(get_class($sub).'::getChildren() must return an object that
implements RecursiveIterator');
+ }
+ $this->beginChildren();
+ return;
+ }
+ unset($sub);
}
- catch (Exception $e)
+ else
{
- if (!($this->flags &
self::CATCH_GET_CHILD))
+ /* do not recurse because of
depth restriction */
+ if ($this->flages &
self::LEVAES_ONLY)
{
- throw $e;
+ $it->next();
+ continue;
}
- $it->next();
- continue;
- }
- $sub->recursed = false;
- $sub->rewind();
- if ($sub->valid()) {
- $this->ait[++$this->count] =
$sub;
- if (!$sub instanceof
RecursiveIterator) {
- throw new
Exception(get_class($sub).'::getChildren() must return an object that
implements RecursiveIterator');
+ else
+ {
+ return; // we want the
parent
}
- $this->beginChildren();
+ }
+ $it->next();
+ $it->recursed = false;
+ if ($it->valid()) {
return;
}
- unset($sub);
- }
- $it->next();
- $it->recursed = false;
- if ($it->valid()) {
- return;
+ $it->recursed = false;
}
- $it->recursed = false;
}
- if ($this->count) {
- unset($this->ait[$this->count--]);
- $it = $this->ait[$this->count];
+ else if ($this->level > 0) {
+ unset($this->ait[$this->level--]);
+ $it = $this->ait[$this->level];
$this->endChildren();
callNextElement(false);
}
@@ -159,7 +175,7 @@
function getSubIterator($level = NULL)
{
if (is_null($level)) {
- $level = $this->count;
+ $level = $this->level;
}
return @$this->ait[$level];
}
@@ -184,7 +200,7 @@
*/
function callHasChildren()
{
- return $this->ait[$this->count]->hasChildren();
+ return $this->ait[$this->level]->hasChildren();
}
/** @return current sub iterators current children
@@ -192,7 +208,7 @@
*/
function callGetChildren()
{
- return $this->ait[$this->count]->getChildren();
+ return $this->ait[$this->level]->getChildren();
}
/** Called right after calling getChildren() and its rewind().
@@ -230,6 +246,24 @@
/** Called when the next element is available
*/
function nextElement();
+
+ /** @param max_depth new maximum allowed depth or -1 for any depth
+ */
+ function setMaxDepth($max_depth = -1)
+ {
+ $max_depth = (int)$max_depth;
+ if ($max_depth < -1) {
+ throw new OutOfRangeException('Parameter max_depth must
be >= -1');
+ }
+ $this->max_depth = $max_depth;
+ }
+
+ /** @return maximum allowed depth or false if any depth is allowed
+ */
+ function getMaxDepth()
+ {
+ return $this->max_depth == -1 ? false : $this->max_depth;
+ }
}
?>
\ No newline at end of file
http://cvs.php.net/co.php/php-src/ext/spl/tests/iterator_028.phpt?r=1.1&p=1
Index: php-src/ext/spl/tests/iterator_028.phpt
+++ php-src/ext/spl/tests/iterator_028.phpt
--TEST--
SPL: RecursiveIteratorIterator and setMaxDepth()
--FILE--
<?php
$ar = array(1, 2, array(31, 32, array(331, array(3321, array(33221)))), 4);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($ar));
echo "===?===\n";
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===2===\n";
$it->setMaxDepth(2);
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===X===\n";
$it->setMaxDepth();
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===3===\n";
$it->setMaxDepth(3);
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===5===\n";
$it->setMaxDepth(5);
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===0===\n";
$it->setMaxDepth(0);
var_dump($it->getMaxDepth());
foreach($it as $v) echo $it->getDepth() . ": $v\n";
echo "===-1===\n";
$it->setMaxDepth(-1);
var_dump($it->getMaxDepth());
try
{
$it->setMaxDepth(4);
$it->setMaxDepth(-2);
}
catch(Exception $e)
{
var_dump($e->getMessage());
}
var_dump($it->getMaxDepth());
?>
===DONE===
<?php exit(0); ?>
--EXPECT--
===?===
bool(false)
0: 1
0: 2
1: 31
1: 32
2: 331
3: 3321
4: 33221
0: 4
===2===
int(2)
0: 1
0: 2
1: 31
1: 32
2: 331
0: 4
===X===
bool(false)
0: 1
0: 2
1: 31
1: 32
2: 331
3: 3321
4: 33221
0: 4
===3===
int(3)
0: 1
0: 2
1: 31
1: 32
2: 331
3: 3321
0: 4
===5===
int(5)
0: 1
0: 2
1: 31
1: 32
2: 331
3: 3321
4: 33221
0: 4
===0===
int(0)
0: 1
0: 2
0: 4
===-1===
bool(false)
string(33) "Parameter max_depth must be >= -1"
int(4)
===DONE===
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php