mirror of
https://github.com/php/php-src.git
synced 2025-01-20 10:43:40 +08:00
- Implement InfiniteIterator in C
This commit is contained in:
parent
081dac3026
commit
de3a8ea3e1
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
47
ext/spl/internal/infiniteiterator.inc
Executable file
47
ext/spl/internal/infiniteiterator.inc
Executable 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -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); \
|
||||
|
@ -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;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -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
91
ext/spl/tests/iterator_008.phpt
Executable 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===
|
Loading…
Reference in New Issue
Block a user