mirror of
https://github.com/php/php-src.git
synced 2024-12-02 06:13:40 +08:00
158 lines
3.7 KiB
PHP
158 lines
3.7 KiB
PHP
<?php
|
|
|
|
/** @file cachingiterator.inc
|
|
* @ingroup SPL
|
|
* @brief class CachingIterator
|
|
* @author Marcus Boerger
|
|
* @date 2003 - 2009
|
|
*
|
|
* SPL - Standard PHP Library
|
|
*/
|
|
|
|
/**
|
|
* @brief Cached iteration over another Iterator
|
|
* @author Marcus Boerger
|
|
* @version 1.2
|
|
* @since PHP 5.0
|
|
*
|
|
* This iterator wrapper does a one ahead iteration. This way it knows whether
|
|
* the inner iterator has one more element.
|
|
*
|
|
* @note If you want to convert the elements into strings and the inner
|
|
* Iterator is an internal Iterator then you need to provide the
|
|
* flag CALL_TOSTRING to do the conversion when the actual element
|
|
* is being fetched. Otherwise the conversion would happen with the
|
|
* already changed iterator. If you do not need this then it you should
|
|
* omit this flag because it costs unnecessary work and time.
|
|
*/
|
|
class CachingIterator implements OuterIterator
|
|
{
|
|
const CALL_TOSTRING = 0x00000001;
|
|
const CATCH_GET_CHILD = 0x00000002;
|
|
const TOSTRING_USE_KEY = 0x00000010;
|
|
const TOSTRING_USE_CURRENT = 0x00000020;
|
|
|
|
private $it;
|
|
private $current;
|
|
private $key;
|
|
private $valid;
|
|
private $strValue;
|
|
|
|
/** Construct from another iterator
|
|
*
|
|
* @param it Iterator to cache
|
|
* @param flags Bitmask:
|
|
* - CALL_TOSTRING (whether to call __toString() for every element)
|
|
*/
|
|
function __construct(Iterator $it, $flags = self::CALL_TOSTRING)
|
|
{
|
|
if ((($flags & self::CALL_TOSTRING) && ($flags & (self::TOSTRING_USE_KEY|self::TOSTRING_USE_CURRENT)))
|
|
|| ((flags & (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT)) == (self::CIT_TOSTRING_USE_KEY|self::CIT_TOSTRING_USE_CURRENT)))
|
|
{
|
|
throw new InvalidArgumentException('Flags must contain only one of CIT_CALL_TOSTRING, CIT_TOSTRING_USE_KEY, CIT_TOSTRING_USE_CURRENT');
|
|
}
|
|
$this->it = $it;
|
|
$this->flags = $flags & (0x0000FFFF);
|
|
$this->next();
|
|
}
|
|
|
|
/** Rewind the Iterator
|
|
*/
|
|
function rewind()
|
|
{
|
|
$this->it->rewind();
|
|
$this->next();
|
|
}
|
|
|
|
/** Forward to the next element
|
|
*/
|
|
function next()
|
|
{
|
|
if ($this->valid = $this->it->valid()) {
|
|
$this->current = $this->it->current();
|
|
$this->key = $this->it->key();
|
|
if ($this->flags & self::CALL_TOSTRING) {
|
|
if (is_object($this->current)) {
|
|
$this->strValue = $this->current->__toString();
|
|
} else {
|
|
$this->strValue = (string)$this->current;
|
|
}
|
|
}
|
|
} else {
|
|
$this->current = NULL;
|
|
$this->key = NULL;
|
|
$this->strValue = NULL;
|
|
}
|
|
$this->it->next();
|
|
}
|
|
|
|
/** @return whether the iterator is valid
|
|
*/
|
|
function valid()
|
|
{
|
|
return $this->valid;
|
|
}
|
|
|
|
/** @return whether there is one more element
|
|
*/
|
|
function hasNext()
|
|
{
|
|
return $this->it->valid();
|
|
}
|
|
|
|
/** @return the current element
|
|
*/
|
|
function current()
|
|
{
|
|
return $this->current;
|
|
}
|
|
|
|
/** @return the current key
|
|
*/
|
|
function key()
|
|
{
|
|
return $this->key;
|
|
}
|
|
|
|
/** Aggregate the inner iterator
|
|
*
|
|
* @param func Name of method to invoke
|
|
* @param params Array of parameters to pass to method
|
|
*/
|
|
function __call($func, $params)
|
|
{
|
|
return call_user_func_array(array($this->it, $func), $params);
|
|
}
|
|
|
|
/** @return the string represenatation that was generated for the current
|
|
* element
|
|
* @throw exception when CALL_TOSTRING was not specified in constructor
|
|
*/
|
|
function __toString()
|
|
{
|
|
if ($this->flags & self::TOSTRING_USE_KEY)
|
|
{
|
|
return $this->key;
|
|
}
|
|
else if ($this->flags & self::TOSTRING_USE_CURRENT)
|
|
{
|
|
return $this->current;
|
|
}
|
|
if (!$this->flags & self::CALL_TOSTRING)
|
|
{
|
|
throw new exception('CachingIterator does not fetch string value (see CachingIterator::__construct)');
|
|
}
|
|
return $this->strValue;
|
|
}
|
|
|
|
/**
|
|
* @return The inner iterator
|
|
*/
|
|
function getInnerIterator()
|
|
{
|
|
return $this->it;
|
|
}
|
|
}
|
|
|
|
?>
|