helly           Sat Jul 19 15:56:59 2008 UTC

  Added files:                 (Branch: PHP_5_3)
    /php-src/ext/spl/examples   multipleiterator.inc 
  Log:
  - MFH Add MultipleIterator 
(http://blog.somabo.de/2008/01/multipleiterator-for-php.html)
  

http://cvs.php.net/viewvc.cgi/php-src/ext/spl/examples/multipleiterator.inc?view=markup&rev=1.1
Index: php-src/ext/spl/examples/multipleiterator.inc
+++ php-src/ext/spl/examples/multipleiterator.inc
<?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;
        }
}



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to