- Implement InfiniteIterator in C

This commit is contained in:
Marcus Boerger 2004-10-31 19:49:18 +00:00
parent 081dac3026
commit de3a8ea3e1
6 changed files with 175 additions and 103 deletions

View File

@ -1,102 +0,0 @@
<?php
/** @file infiniteiterator.inc
* @ingroup Examples
* @brief class InfiniteIterator
* @author Marcus Boerger
* @date 2003 - 2004
*
* SPL - Standard PHP Library
*/
/** @ingroup Examples
* @brief An infinite Iterator
* @author Marcus Boerger
* @version 1.0
*
* This Iterator takes another Iterator and infinitvely iterates it by
* rewinding it when its end is reached.
*
* \note Even an InfiniteIterator stops if its inner Iterator is empty.
*
\verbatim
$it = new ArrayIterator(array(1,2,3));
$infinite = new InfiniteIterator($it);
$limit = new LimitIterator($infinite, 0, 5);
foreach($limit as $val=>$key)
{
echo "$val=>$key\n";
}
\endverbatim
*/
class InfiniteIterator implements OuterIterator
{
/** @internal
* The inner Iterator. */
private $it;
/** Construct from another Iterator.
* @param $it the inner Iterator.
*/
function __construct(Iterator $it)
{
$this->it = $it;
}
/** @return the inner iterator
*/
function getInnerIterator()
{
return $this->it;
}
/** Rewind the inner iterator.
* @return void
*/
function rewind()
{
$this->getInnerIterator()->rewind();
}
/** @return whether the current element is valid
*/
function valid()
{
return $this->getInnerIterator()->valid();
}
/** @return the current value
*/
function current()
{
return $this->getInnerIterator()->current();
}
/** @return the current key
*/
function key()
{
return $this->getInnerIterator()->key();
}
/** Move the inner Iterator forward to its next element or rewind it.
* @return void
*/
function next()
{
$this->getInnerIterator()->next();
if (!$this->getInnerIterator()->valid())
{
$this->getInnerIterator()->rewind();
}
}
/** Aggregates the inner iterator
*/
function __call($func, $params)
{
return call_user_func_array(array($this->getInnerIterator(), $func), $params);
}
}
?>

View File

@ -0,0 +1,47 @@
<?php
/** @file infiniteiterator.inc
* @ingroup SPL
* @brief class InfiniteIterator
* @author Marcus Boerger
* @date 2003 - 2004
*
* SPL - Standard PHP Library
*/
/** @ingroup Examples
* @brief An infinite Iterator
* @author Marcus Boerger
* @version 1.1
*
* This Iterator takes another Iterator and infinitvely iterates it by
* rewinding it when its end is reached.
*
* \note Even an InfiniteIterator stops if its inner Iterator is empty.
*
\verbatim
$it = new ArrayIterator(array(1,2,3));
$infinite = new InfiniteIterator($it);
$limit = new LimitIterator($infinite, 0, 5);
foreach($limit as $val=>$key)
{
echo "$val=>$key\n";
}
\endverbatim
*/
class InfiniteIterator extends IteratorIterator
{
/** Move the inner Iterator forward to its next element or rewind it.
* @return void
*/
function next()
{
$this->getInnerIterator()->next();
if (!$this->getInnerIterator()->valid())
{
$this->getInnerIterator()->rewind();
}
}
}
?>

View File

@ -167,6 +167,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(CachingRecursiveIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(FilterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(InfiniteIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(IteratorIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \

View File

@ -47,6 +47,7 @@ zend_class_entry *spl_ce_CachingRecursiveIterator;
zend_class_entry *spl_ce_OuterIterator;
zend_class_entry *spl_ce_IteratorIterator;
zend_class_entry *spl_ce_NoRewindIterator;
zend_class_entry *spl_ce_InfiniteIterator;
function_entry spl_funcs_RecursiveIterator[] = {
SPL_ABSTRACT_ME(RecursiveIterator, hasChildren, NULL)
@ -1440,7 +1441,37 @@ static zend_function_entry spl_funcs_NoRewindIterator[] = {
{NULL, NULL, NULL}
};
zend_object_iterator_funcs spl_norewind_it_iterator_funcs;
/* {{{ proto InfiniteIterator::__construct(Iterator it)
Create an iterator from another iterator */
SPL_METHOD(InfiniteIterator, __construct)
{
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, zend_ce_iterator, DIT_InfiniteIterator);
} /* }}} */
/* {{{ proto InfiniteIterator::next()
Prevent a call to inner iterators rewind() (internally the current data will be fetched if valid()) */
SPL_METHOD(InfiniteIterator, next)
{
spl_dual_it_object *intern;
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_dual_it_next(intern, 1 TSRMLS_CC);
if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
spl_dual_it_fetch(intern, 0 TSRMLS_CC);
} else {
spl_dual_it_rewind(intern TSRMLS_CC);
if (spl_dual_it_valid(intern TSRMLS_CC) == SUCCESS) {
spl_dual_it_fetch(intern, 0 TSRMLS_CC);
}
}
} /* }}} */
static zend_function_entry spl_funcs_InfiniteIterator[] = {
SPL_ME(InfiniteIterator, __construct, arginfo_norewind_it___construct, ZEND_ACC_PUBLIC)
SPL_ME(InfiniteIterator, next, NULL, ZEND_ACC_PUBLIC)
};
/* {{{ array iterator_to_array(IteratorAggregate it)
Copy the iterator into an array */
@ -1575,6 +1606,8 @@ PHP_MINIT_FUNCTION(spl_iterators)
REGISTER_SPL_IMPLEMENTS(IteratorIterator, OuterIterator);
REGISTER_SPL_IMPLEMENTS(NoRewindIterator, OuterIterator);
REGISTER_SPL_SUB_CLASS_EX(InfiniteIterator, IteratorIterator, spl_dual_it_new, spl_funcs_InfiniteIterator);
return SUCCESS;
}
/* }}} */

View File

@ -35,6 +35,7 @@ extern zend_class_entry *spl_ce_CachingRecursiveIterator;
extern zend_class_entry *spl_ce_OuterIterator;
extern zend_class_entry *spl_ce_IteratorIterator;
extern zend_class_entry *spl_ce_NoRewindIterator;
extern zend_class_entry *spl_ce_InfiniteIterator;
PHP_MINIT_FUNCTION(spl_iterators);
@ -48,6 +49,7 @@ typedef enum {
DIT_CachingRecursiveIterator,
DIT_IteratorIterator,
DIT_NoRewindIterator,
DIT_InfiniteIterator,
} dual_it_type;
enum {

91
ext/spl/tests/iterator_008.phpt Executable file
View File

@ -0,0 +1,91 @@
--TEST--
SPL: InfiniteIterator
--SKIPIF--
<?php if (!extension_loaded("spl")) print "skip"; ?>
--FILE--
<?php
class ArrayIteratorEx extends ArrayIterator
{
function rewind()
{
echo __METHOD__ . "\n";
parent::rewind();
}
function valid()
{
echo __METHOD__ . "\n";
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();
}
}
$it = new InfiniteIterator(new ArrayIteratorEx(range(0,2)));
$pos =0;
foreach ($it as $v) {
var_dump($v);
if ($pos++ > 5) {
break;
}
}
?>
===DONE===
<?php exit(0); ?>
--EXPECT--
ArrayIteratorEx::rewind
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(0)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(1)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(2)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::rewind
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(0)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(1)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(2)
ArrayIteratorEx::next
ArrayIteratorEx::valid
ArrayIteratorEx::rewind
ArrayIteratorEx::valid
ArrayIteratorEx::current
ArrayIteratorEx::key
int(0)
===DONE===