cvs: php-src /ext/spl spl_iterators.c /ext/spl/internal recursiveiteratoriterator.inc /ext/spl/tests iterator_028.phpt

From: Date: Sun, 25 Sep 2005 12:01:32 +0000
Subject: cvs: php-src /ext/spl spl_iterators.c /ext/spl/internal recursiveiteratoriterator.inc /ext/spl/tests iterator_028.phpt
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-34131@lists.php.net to get a copy of this message
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===
« previous php.cvs (#34131) next »