Browse Source
- MFH Add MultipleIterator (http://blog.somabo.de/2008/01/multipleiterator-for-php.html)
PECL
- MFH Add MultipleIterator (http://blog.somabo.de/2008/01/multipleiterator-for-php.html)
PECL
1 changed files with 223 additions and 0 deletions
@ -0,0 +1,223 @@ |
|||
<?php |
|||
/** @file multipleiterator.inc |
|||
* @ingroup Examples |
|||
* @brief class MultipleIterator |
|||
* @author Johannes Schlueter |
|||
* @author Marcus Boerger |
|||
* @date 2008 |
|||
* |
|||
* SPL - Standard PHP Library |
|||
*/ |
|||
|
|||
/** @ingroup Examples |
|||
* @brief Iterator that iterates over several iterators one after the other |
|||
* @author Johannes Schlueter |
|||
* @author Marcus Boerger |
|||
* @version 1.0 |
|||
* @since PHP 5.3 |
|||
*/ |
|||
class MultipleIterator implements Iterator |
|||
{ |
|||
/** Inner Iterators */ |
|||
private $iterators; |
|||
|
|||
/** Flags: const MIT_* */ |
|||
private $flags; |
|||
|
|||
/** do not require all sub iterators to be valid in iteration */ |
|||
const MIT_NEED_ANY = 0; |
|||
|
|||
/** require all sub iterators to be valid in iteration */ |
|||
const MIT_NEED_ALL = 1; |
|||
|
|||
/** keys are created from sub iterators position */ |
|||
const MIT_KEYS_NUMERIC = 0; |
|||
|
|||
/** keys are created from sub iterators associated infromation */ |
|||
const MIT_KEYS_ASSOC = 2; |
|||
|
|||
/** Construct a new empty MultipleIterator |
|||
* @param flags MIT_* flags |
|||
*/ |
|||
public function __construct($flags = self::MIT_NEED_ALL|self::MIT_KEYS_NUMERIC) |
|||
{ |
|||
$this->iterators = new SplObjectStorage(); |
|||
$this->flags = $flags; |
|||
} |
|||
|
|||
/** @return current flags MIT_* */ |
|||
public function getFlags() |
|||
{ |
|||
return $this->flags; |
|||
} |
|||
|
|||
/** @param $flags new flags. */ |
|||
public function setFlags($flags) |
|||
{ |
|||
$this->flags = $flags; |
|||
} |
|||
|
|||
/** @param $iter new Iterator to attach. |
|||
* @param $inf associative info forIteraotr, must be NULL, integer or string |
|||
* |
|||
* @throws IllegalValueException if a inf is none of NULL, integer or string |
|||
* @throws IllegalValueException if a inf is already an associated info |
|||
*/ |
|||
public function attachIterator(Iterator $iter, $inf = NULL) |
|||
{ |
|||
|
|||
if (!is_null($inf)) |
|||
{ |
|||
if (!is_int($inf) && !is_string($inf)) |
|||
{ |
|||
throw new IllegalValueException('Inf must be NULL, integer or string'); |
|||
} |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
if ($inf == $this->iterators->getInfo()) |
|||
{ |
|||
throw new IllegalValueException('Key duplication error'); |
|||
} |
|||
} |
|||
} |
|||
$this->iterators->attach($iter, $inf); |
|||
} |
|||
|
|||
/** @param $iter attached Iterator that should be detached. */ |
|||
public function detachIterator(Iterator $iter) |
|||
{ |
|||
$this->iterators->detach($iter); |
|||
} |
|||
|
|||
/** @param $iter Iterator to check |
|||
* @return whether $iter is attached or not |
|||
*/ |
|||
public function containsIterator(Iterator $iter) |
|||
{ |
|||
return $this->iterator->contains($iter); |
|||
} |
|||
|
|||
/** @return number of attached Iterator instances. */ |
|||
public function countIterators() |
|||
{ |
|||
return $this->iterators->count(); |
|||
} |
|||
|
|||
/** Rewind all attached Iterator instances. */ |
|||
public function rewind() |
|||
{ |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
$iter->rewind(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @return whether all or one sub iterator is valid depending on flags. |
|||
* In mode MIT_NEED_ALL we expect all sub iterators to be valid and |
|||
* return flase on the first non valid one. If that flag is not set we |
|||
* return true on the first valid sub iterator found. If no Iterator |
|||
* is attached, we always return false. |
|||
*/ |
|||
public function valid() |
|||
{ |
|||
if (!sizeof($this->iterators)) { |
|||
return false; |
|||
} |
|||
// The following code is an optimized version that executes as few |
|||
// valid() calls as necessary and that only checks the flags once. |
|||
$expect = $this->flags & self::MIT_NEED_ALL ? true : false; |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
if ($expect != $iter->valid()) |
|||
{ |
|||
return !$expect; |
|||
} |
|||
} |
|||
return $expect; |
|||
} |
|||
|
|||
/** Move all attached Iterator instances forward. That is invoke |
|||
* their next() method regardless of their state. |
|||
*/ |
|||
public function next() |
|||
{ |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
$iter->next(); |
|||
} |
|||
} |
|||
|
|||
/** @return false if no sub Iterator is attached and an array of |
|||
* all registered Iterator instances current() result. |
|||
* @throws RuntimeException if mode MIT_NEED_ALL is set and at least one |
|||
* attached Iterator is not valid(). |
|||
* @throws IllegalValueException if a key is NULL and MIT_KEYS_ASSOC is set. |
|||
*/ |
|||
public function current() |
|||
{ |
|||
if (!sizeof($this->iterators)) |
|||
{ |
|||
return false; |
|||
} |
|||
$retval = array(); |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
if ($it->valid()) |
|||
{ |
|||
if ($this->flags & self::MIT_KEYS_ASSOC) |
|||
{ |
|||
$key = $this->iterators->getInfo(); |
|||
if (is_null($key)) |
|||
{ |
|||
throw new IllegalValueException('Sub-Iterator is associated with NULL'); |
|||
} |
|||
$retval[$key] = $iter->current(); |
|||
} |
|||
else |
|||
{ |
|||
$retval[] = $iter->current(); |
|||
} |
|||
} |
|||
else if ($this->flags & self::MIT_NEED_ALL) |
|||
{ |
|||
throw new RuntimeException('Called current() with non valid sub iterator'); |
|||
} |
|||
else |
|||
{ |
|||
$retval[] = NULL; |
|||
} |
|||
} |
|||
return $retval; |
|||
} |
|||
|
|||
/** @return false if no sub Iterator is attached and an array of |
|||
* all registered Iterator instances key() result. |
|||
* @throws LogicException if mode MIT_NEED_ALL is set and at least one |
|||
* attached Iterator is not valid(). |
|||
*/ |
|||
public function key() |
|||
{ |
|||
if (!sizeof($this->iterators)) |
|||
{ |
|||
return false; |
|||
} |
|||
$retval = array(); |
|||
foreach($this->iterators as $iter) |
|||
{ |
|||
if ($it->valid()) |
|||
{ |
|||
$retval[] = $iter->key(); |
|||
} |
|||
else if ($this->flags & self::MIT_NEED_ALL) |
|||
{ |
|||
throw new LogicException('Called key() with non valid sub iterator'); |
|||
} |
|||
else |
|||
{ |
|||
$retval[] = NULL; |
|||
} |
|||
} |
|||
return $retval; |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue