summaryrefslogtreecommitdiff
path: root/ext/spl/internal
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/spl/internal
downloadphp2-master.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/spl/internal')
-rw-r--r--ext/spl/internal/appenditerator.inc122
-rw-r--r--ext/spl/internal/cachingiterator.inc157
-rw-r--r--ext/spl/internal/emptyiterator.inc62
-rw-r--r--ext/spl/internal/filteriterator.inc127
-rw-r--r--ext/spl/internal/infiniteiterator.inc48
-rw-r--r--ext/spl/internal/iteratoriterator.inc121
-rw-r--r--ext/spl/internal/limititerator.inc134
-rw-r--r--ext/spl/internal/multipleiterator.inc223
-rw-r--r--ext/spl/internal/norewinditerator.inc28
-rw-r--r--ext/spl/internal/outeriterator.inc25
-rw-r--r--ext/spl/internal/parentiterator.inc32
-rw-r--r--ext/spl/internal/recursivearrayiterator.inc59
-rw-r--r--ext/spl/internal/recursivecachingiterator.inc99
-rw-r--r--ext/spl/internal/recursivefilteriterator.inc62
-rw-r--r--ext/spl/internal/recursiveiterator.inc30
-rw-r--r--ext/spl/internal/recursiveiteratoriterator.inc237
-rw-r--r--ext/spl/internal/recursiveregexiterator.inc61
-rw-r--r--ext/spl/internal/recursivetreeiterator.inc132
-rw-r--r--ext/spl/internal/regexiterator.inc170
-rw-r--r--ext/spl/internal/seekableiterator.inc48
-rw-r--r--ext/spl/internal/spldoublylinkedlist.inc277
-rw-r--r--ext/spl/internal/splfileobject.inc377
-rw-r--r--ext/spl/internal/splobjectstorage.inc188
-rw-r--r--ext/spl/internal/splqueue.inc71
-rw-r--r--ext/spl/internal/splstack.inc48
25 files changed, 2938 insertions, 0 deletions
diff --git a/ext/spl/internal/appenditerator.inc b/ext/spl/internal/appenditerator.inc
new file mode 100644
index 0000000..28e32b1
--- /dev/null
+++ b/ext/spl/internal/appenditerator.inc
@@ -0,0 +1,122 @@
+<?php
+
+/** @file appenditerator.inc
+ * @ingroup SPL
+ * @brief class AppendIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Iterator that iterates over several iterators one after the other
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ */
+class AppendIterator implements OuterIterator
+{
+ /** @internal array of inner iterators */
+ private $iterators;
+
+ /** Construct an empty AppendIterator
+ */
+ function __construct()
+ {
+ $this->iterators = new ArrayIterator();
+ }
+
+ /** Append an Iterator
+ * @param $it Iterator to append
+ *
+ * If the current state is invalid but the appended iterator is valid
+ * the AppendIterator itself becomes valid. However there will be no
+ * call to $it->rewind(). Also if the current state is invalid the inner
+ * ArrayIterator will be rewound und forwarded to the appended element.
+ */
+ function append(Iterator $it)
+ {
+ $this->iterators->append($it);
+ }
+
+ /** @return the current inner Iterator
+ */
+ function getInnerIterator()
+ {
+ return $this->iterators->current();
+ }
+
+ /** Rewind to the first element of the first inner Iterator.
+ * @return void
+ */
+ function rewind()
+ {
+ $this->iterators->rewind();
+ if ($this->iterators->valid())
+ {
+ $this->getInnerIterator()->rewind();
+ }
+ }
+
+ /** @return whether the current element is valid
+ */
+ function valid()
+ {
+ return $this->iterators->valid() && $this->getInnerIterator()->valid();
+ }
+
+ /** @return the current value if it is valid or \c NULL
+ */
+ function current()
+ {
+ /* Using $this->valid() would be exactly the same; it would omit
+ * the access to a non valid element in the inner iterator. Since
+ * the user didn't respect the valid() return value false this
+ * must be intended hence we go on. */
+ return $this->iterators->valid() ? $this->getInnerIterator()->current() : NULL;
+ }
+
+ /** @return the current key if it is valid or \c NULL
+ */
+ function key()
+ {
+ return $this->iterators->valid() ? $this->getInnerIterator()->key() : NULL;
+ }
+
+ /** Move to the next element. If this means to another Iterator that
+ * rewind that Iterator.
+ * @return void
+ */
+ function next()
+ {
+ if (!$this->iterators->valid())
+ {
+ return; /* done all */
+ }
+ $this->getInnerIterator()->next();
+ if ($this->getInnerIterator()->valid())
+ {
+ return; /* found valid element in current inner iterator */
+ }
+ $this->iterators->next();
+ while ($this->iterators->valid())
+ {
+ $this->getInnerIterator()->rewind();
+ if ($this->getInnerIterator()->valid())
+ {
+ return; /* found element as first elemet in another iterator */
+ }
+ $this->iterators->next();
+ }
+ }
+
+ /** Aggregates the inner iterator
+ */
+ function __call($func, $params)
+ {
+ return call_user_func_array(array($this->getInnerIterator(), $func), $params);
+ }
+}
+
+?>
diff --git a/ext/spl/internal/cachingiterator.inc b/ext/spl/internal/cachingiterator.inc
new file mode 100644
index 0000000..33258ab
--- /dev/null
+++ b/ext/spl/internal/cachingiterator.inc
@@ -0,0 +1,157 @@
+<?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 unneccessary 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;
+ }
+}
+
+?>
diff --git a/ext/spl/internal/emptyiterator.inc b/ext/spl/internal/emptyiterator.inc
new file mode 100644
index 0000000..ac80e79
--- /dev/null
+++ b/ext/spl/internal/emptyiterator.inc
@@ -0,0 +1,62 @@
+<?php
+
+/** @file emptyiterator.inc
+ * @ingroup SPL
+ * @brief class EmptyIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief An empty Iterator
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ */
+class EmptyIterator implements Iterator
+{
+ /** No operation.
+ * @return void
+ */
+ function rewind()
+ {
+ // nothing to do
+ }
+
+ /** @return \c false
+ */
+ function valid()
+ {
+ return false;
+ }
+
+ /** This function must not be called. It throws an exception upon access.
+ * @throw Exception
+ * @return void
+ */
+ function current()
+ {
+ throw new Exception('Accessing the value of an EmptyIterator');
+ }
+
+ /** This function must not be called. It throws an exception upon access.
+ * @throw Exception
+ * @return void
+ */
+ function key()
+ {
+ throw new Exception('Accessing the key of an EmptyIterator');
+ }
+
+ /** No operation.
+ * @return void
+ */
+ function next()
+ {
+ // nothing to do
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/filteriterator.inc b/ext/spl/internal/filteriterator.inc
new file mode 100644
index 0000000..3330cc9
--- /dev/null
+++ b/ext/spl/internal/filteriterator.inc
@@ -0,0 +1,127 @@
+<?php
+
+/** @file filteriterator.inc
+ * @ingroup SPL
+ * @brief class FilterIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Abstract filter for iterators
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.0
+ *
+ * Instances of this class act as a filter around iterators. In other words
+ * you can put an iterator into the constructor and the instance will only
+ * return selected (accepted) elements.
+ *
+ * The only thing that needs to be done to make this work is implementing
+ * method accept(). Typically this invloves reading the current element or
+ * key of the inner Iterator and checking whether it is acceptable.
+ */
+abstract class FilterIterator implements OuterIterator
+{
+ private $it;
+
+ /**
+ * Constructs a filter around another iterator.
+ *
+ * @param it Iterator to filter
+ */
+ function __construct(Iterator $it) {
+ $this->it = $it;
+ }
+
+ /**
+ * Rewind the inner iterator.
+ */
+ function rewind() {
+ $this->it->rewind();
+ $this->fetch();
+ }
+
+ /**
+ * Accept function to decide whether an element of the inner iterator
+ * should be accessible through the Filteriterator.
+ *
+ * @return whether or not to expose the current element of the inner
+ * iterator.
+ */
+ abstract function accept();
+
+ /**
+ * Fetch next element and store it.
+ *
+ * @return void
+ */
+ protected function fetch() {
+ while ($this->it->valid()) {
+ if ($this->accept()) {
+ return;
+ }
+ $this->it->next();
+ };
+ }
+
+ /**
+ * Move to next element
+ *
+ * @return void
+ */
+ function next() {
+ $this->it->next();
+ $this->fetch();
+ }
+
+ /**
+ * @return Whether more elements are available
+ */
+ function valid() {
+ return $this->it->valid();
+ }
+
+ /**
+ * @return The current key
+ */
+ function key() {
+ return $this->it->key();
+ }
+
+ /**
+ * @return The current value
+ */
+ function current() {
+ return $this->it->current();
+ }
+
+ /**
+ * hidden __clone
+ */
+ protected function __clone() {
+ // disallow clone
+ }
+
+ /**
+ * @return The inner iterator
+ */
+ function getInnerIterator()
+ {
+ return $this->it;
+ }
+
+ /** 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);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/infiniteiterator.inc b/ext/spl/internal/infiniteiterator.inc
new file mode 100644
index 0000000..04d7827
--- /dev/null
+++ b/ext/spl/internal/infiniteiterator.inc
@@ -0,0 +1,48 @@
+<?php
+
+/** @file infiniteiterator.inc
+ * @ingroup SPL
+ * @brief class InfiniteIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief An infinite Iterator
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.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();
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/iteratoriterator.inc b/ext/spl/internal/iteratoriterator.inc
new file mode 100644
index 0000000..37676e0
--- /dev/null
+++ b/ext/spl/internal/iteratoriterator.inc
@@ -0,0 +1,121 @@
+<?php
+
+/** @file iteratoriterator.inc
+ * @ingroup SPL
+ * @brief class IteratorIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Basic Iterator wrapper
+ * @since PHP 5.1
+ *
+ * This iterator wrapper allows to convert anything that is traversable into
+ * an Iterator. It is very important to understand that most classes that do
+ * not implement Iterator have their reasone to. Most likely they do not allow
+ * the full Iterator feature set. If so you need to provide techniques to
+ * prevent missuse. If you do not you must expect exceptions or fatal erros.
+ *
+ * It is also possible to derive the class and implement IteratorAggregate by
+ * downcasting the instances returned in getIterator. See the following
+ * example (assuming BaseClass implements Traversable):
+ \code
+ class SomeClass extends BaseClass implements IteratorAggregate
+ {
+ function getIterator()
+ {
+ return new IteratorIterator($this, 'BaseClass');
+ }
+ }
+ \endcode
+ *
+ * As you can see in the example this approach requires that the class to
+ * downcast to is actually a base class of the specified iterator to wrap.
+ * Omitting the downcast in the above example would result in an endless loop
+ * since IteratorIterator::__construct() would call SomeClass::getIterator().
+ */
+class IteratorIterator implements OuterIterator
+{
+ /** Construct an IteratorIterator from an Iterator or an IteratorAggregate.
+ *
+ * @param iterator inner iterator
+ * @param classname optional class the iterator has to be downcasted to
+ */
+ function __construct(Traversable $iterator, $classname = null)
+ {
+ if ($iterator instanceof IteratorAggregate)
+ {
+ $iterator = $iterator->getIterator();
+ }
+ if ($iterator instanceof Iterator)
+ {
+ $this->iterator = $iterator;
+ }
+ else
+ {
+ throw new Exception("Classes that only implement Traversable can be wrapped only after converting class IteratorIterator into c code");
+ }
+ }
+
+ /** \return the inner iterator as passed to the constructor
+ */
+ function getInnerIterator()
+ {
+ return $this->iterator;
+ }
+
+ /** \return whether the iterator is valid
+ */
+ function valid()
+ {
+ return $this->iterator->valid();
+ }
+
+ /** \return current key
+ */
+ function key()
+ {
+ return $this->iterator->key();
+ }
+
+ /** \return current value
+ */
+ function current()
+ {
+ return $this->iterator->current();
+ }
+
+ /** forward to next element
+ */
+ function next()
+ {
+ return $this->iterator->next();
+ }
+
+ /** rewind to the first element
+ */
+ function rewind()
+ {
+ return $this->iterator->rewind();
+ }
+
+ /** 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->iterator, $func), $params);
+ }
+
+ /** The inner iterator must be private because when this class will be
+ * converted to c code it won't no longer be available.
+ */
+ private $iterator;
+}
+
+?>
diff --git a/ext/spl/internal/limititerator.inc b/ext/spl/internal/limititerator.inc
new file mode 100644
index 0000000..c5bddea
--- /dev/null
+++ b/ext/spl/internal/limititerator.inc
@@ -0,0 +1,134 @@
+<?php
+
+/** @file limititerator.inc
+ * @ingroup SPL
+ * @brief class LimitIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Limited Iteration over another Iterator
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.0
+ *
+ * A class that starts iteration at a certain offset and only iterates over
+ * a specified amount of elements.
+ *
+ * This class uses SeekableIterator::seek() if available and rewind() plus
+ * a skip loop otehrwise.
+ */
+class LimitIterator implements OuterIterator
+{
+ private $it;
+ private $offset;
+ private $count;
+ private $pos;
+
+ /** Construct
+ *
+ * @param it Iterator to limit
+ * @param offset Offset to first element
+ * @param count Maximum number of elements to show or -1 for all
+ */
+ function __construct(Iterator $it, $offset = 0, $count = -1)
+ {
+ if ($offset < 0) {
+ throw new exception('Parameter offset must be > 0');
+ }
+ if ($count < 0 && $count != -1) {
+ throw new exception('Parameter count must either be -1 or a value greater than or equal to 0');
+ }
+ $this->it = $it;
+ $this->offset = $offset;
+ $this->count = $count;
+ $this->pos = 0;
+ }
+
+ /** Seek to specified position
+ * @param position offset to seek to (relative to beginning not offset
+ * specified in constructor).
+ * @throw exception when position is invalid
+ */
+ function seek($position) {
+ if ($position < $this->offset) {
+ throw new exception('Cannot seek to '.$position.' which is below offset '.$this->offset);
+ }
+ if ($position > $this->offset + $this->count && $this->count != -1) {
+ throw new exception('Cannot seek to '.$position.' which is behind offset '.$this->offset.' plus count '.$this->count);
+ }
+ if ($this->it instanceof SeekableIterator) {
+ $this->it->seek($position);
+ $this->pos = $position;
+ } else {
+ while($this->pos < $position && $this->it->valid()) {
+ $this->next();
+ }
+ }
+ }
+
+ /** Rewind to offset specified in constructor
+ */
+ function rewind()
+ {
+ $this->it->rewind();
+ $this->pos = 0;
+ $this->seek($this->offset);
+ }
+
+ /** @return whether iterator is valid
+ */
+ function valid() {
+ return ($this->count == -1 || $this->pos < $this->offset + $this->count)
+ && $this->it->valid();
+ }
+
+ /** @return current key
+ */
+ function key() {
+ return $this->it->key();
+ }
+
+ /** @return current element
+ */
+ function current() {
+ return $this->it->current();
+ }
+
+ /** Forward to nect element
+ */
+ function next() {
+ $this->it->next();
+ $this->pos++;
+ }
+
+ /** @return current position relative to zero (not to offset specified in
+ * constructor).
+ */
+ function getPosition() {
+ return $this->pos;
+ }
+
+ /**
+ * @return The inner iterator
+ */
+ function getInnerIterator()
+ {
+ return $this->it;
+ }
+
+ /** 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);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/multipleiterator.inc b/ext/spl/internal/multipleiterator.inc
new file mode 100644
index 0000000..2ed71d5
--- /dev/null
+++ b/ext/spl/internal/multipleiterator.inc
@@ -0,0 +1,223 @@
+<?php
+/** @file multipleiterator.inc
+ * @ingroup SPL
+ * @brief class MultipleIterator
+ * @author Johannes Schlueter
+ * @author Marcus Boerger
+ * @date 2008 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @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;
+ }
+}
diff --git a/ext/spl/internal/norewinditerator.inc b/ext/spl/internal/norewinditerator.inc
new file mode 100644
index 0000000..8747a61
--- /dev/null
+++ b/ext/spl/internal/norewinditerator.inc
@@ -0,0 +1,28 @@
+<?php
+
+/** @file norewinditerator.inc
+ * @ingroup SPL
+ * @brief class NoRewindIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief An Iterator wrapper that doesn't call rewind
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.1
+ */
+class NoRewindIterator extends IteratorIterator
+{
+ /** Simply prevent execution of inner iterators rewind().
+ */
+ function rewind()
+ {
+ // nothing to do
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/outeriterator.inc b/ext/spl/internal/outeriterator.inc
new file mode 100644
index 0000000..f26d29d
--- /dev/null
+++ b/ext/spl/internal/outeriterator.inc
@@ -0,0 +1,25 @@
+<?php
+
+/** @file outeriterator.inc
+ * @ingroup SPL
+ * @brief class OuterIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Interface to access the current inner iteraor of iterator wrappers
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ */
+interface OuterIterator extends Iterator
+{
+ /** @return inner iterator
+ */
+ function getInnerIterator();
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/parentiterator.inc b/ext/spl/internal/parentiterator.inc
new file mode 100644
index 0000000..cc377fc
--- /dev/null
+++ b/ext/spl/internal/parentiterator.inc
@@ -0,0 +1,32 @@
+<?php
+
+/** @file parentiterator.inc
+ * @ingroup SPL
+ * @brief class FilterIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Iterator to filter parents
+ * @author Marcus Boerger
+ * @version 1.2
+ * @since PHP 5.1
+ *
+ * This extended FilterIterator allows a recursive iteration using
+ * RecursiveIteratorIterator that only shows those elements which have
+ * children.
+ */
+class ParentIterator extends RecursiveFilterIterator
+{
+ /** @return whetehr the current element has children
+ */
+ function accept()
+ {
+ return $this->it->hasChildren();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursivearrayiterator.inc b/ext/spl/internal/recursivearrayiterator.inc
new file mode 100644
index 0000000..a9450e1
--- /dev/null
+++ b/ext/spl/internal/recursivearrayiterator.inc
@@ -0,0 +1,59 @@
+<?php
+
+/** @file recursivearrayiterator.inc
+ * @ingroup Examples
+ * @brief class RecursiveArrayIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief A recursive array iterator
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ *
+ * Passes the RecursiveIterator interface to the inner Iterator and provides
+ * the same functionality as FilterIterator. This allows you to skip parents
+ * and all their childs before loading them all. You need to care about
+ * function getChildren() because it may not always suit your needs. The
+ * builtin behavior uses reflection to return a new instance of the exact same
+ * class it is called from. That is you extend RecursiveFilterIterator and
+ * getChildren() will create instance of that class. The problem is that doing
+ * this does not transport any state or control information of your accept()
+ * implementation to the new instance. To overcome this problem you might
+ * need to overwrite getChildren(), call this implementation and pass the
+ * control vaules manually.
+ */
+class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
+{
+ /** @return whether the current element has children
+ */
+ function hasChildren()
+ {
+ return is_array($this->current());
+ }
+
+ /** @return an iterator for the current elements children
+ *
+ * @note the returned iterator will be of the same class as $this
+ */
+ function getChildren()
+ {
+ if ($this->current() instanceof self)
+ {
+ return $this->current();
+ }
+ if (empty($this->ref))
+ {
+ $this->ref = new ReflectionClass($this);
+ }
+ return $this->ref->newInstance($this->current());
+ }
+
+ private $ref;
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursivecachingiterator.inc b/ext/spl/internal/recursivecachingiterator.inc
new file mode 100644
index 0000000..0676d43
--- /dev/null
+++ b/ext/spl/internal/recursivecachingiterator.inc
@@ -0,0 +1,99 @@
+<?php
+
+/** @file recursivecachingiterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveCachingIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Cached recursive iteration over another Iterator
+ * @author Marcus Boerger
+ * @version 1.2
+ * @since PHP 5.1
+ *
+ * @see CachingIterator
+ */
+class RecursiveCachingIterator extends CachingIterator implements RecursiveIterator
+{
+ private $hasChildren;
+ private $getChildren;
+
+ /** Construct from another iterator
+ *
+ * @param it Iterator to cache
+ * @param flags Bitmask:
+ * - CALL_TOSTRING (whether to call __toString() for every element)
+ * - CATCH_GET_CHILD (whether to catch exceptions when trying to get childs)
+ */
+ function __construct(RecursiveIterator $it, $flags = self::CALL_TOSTRING)
+ {
+ parent::__construct($it, $flags);
+ }
+
+ /** Rewind Iterator
+ */
+ function rewind();
+ {
+ $this->hasChildren = false;
+ $this->getChildren = NULL;
+ parent::rewind();
+ }
+
+ /** Forward to next element if necessary then an Iterator for the Children
+ * will be created.
+ */
+ function next()
+ {
+ if ($this->hasChildren = $this->it->hasChildren())
+ {
+ try
+ {
+ $child = $this->it->getChildren();
+ if (!$this->ref)
+ {
+ $this->ref = new ReflectionClass($this);
+ }
+ $this->getChildren = $ref->newInstance($child, $this->flags);
+ }
+ catch(Exception $e)
+ {
+ if (!$this->flags & self::CATCH_GET_CHILD)
+ {
+ throw $e;
+ }
+ $this->hasChildren = false;
+ $this->getChildren = NULL;
+ }
+ } else
+ {
+ $this->getChildren = NULL;
+ }
+ parent::next();
+ }
+
+ private $ref;
+
+ /** @return whether the current element has children
+ * @note The check whether the Iterator for the children can be created was
+ * already executed. Hence when flag CATCH_GET_CHILD was given in
+ * constructor this fucntion returns false so that getChildren does
+ * not try to access those children.
+ */
+ function hasChildren()
+ {
+ return $this->hasChildren;
+ }
+
+ /** @return An Iterator for the children
+ */
+ function getChildren()
+ {
+ return $this->getChildren;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursivefilteriterator.inc b/ext/spl/internal/recursivefilteriterator.inc
new file mode 100644
index 0000000..b089919
--- /dev/null
+++ b/ext/spl/internal/recursivefilteriterator.inc
@@ -0,0 +1,62 @@
+<?php
+
+/** @file recursivefilteriterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveFilterIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Iterator to filter recursive iterators
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ *
+ * Passes the RecursiveIterator interface to the inner Iterator and provides
+ * the same functionality as FilterIterator. This allows you to skip parents
+ * and all their childs before loading them all. You need to care about
+ * function getChildren() because it may not always suit your needs. The
+ * builtin behavior uses reflection to return a new instance of the exact same
+ * class it is called from. That is you extend RecursiveFilterIterator and
+ * getChildren() will create instance of that class. The problem is that doing
+ * this does not transport any state or control information of your accept()
+ * implementation to the new instance. To overcome this problem you might
+ * need to overwrite getChildren(), call this implementation and pass the
+ * control vaules manually.
+ */
+abstract class RecursiveFilterIterator extends FilterIterator implements RecursiveIterator
+{
+ /** @param $it the RecursiveIterator to filter
+ */
+ function __construct(RecursiveIterator $it)
+ {
+ parent::__construct($it);
+ }
+
+ /** @return whether the current element has children
+ */
+ function hasChildren()
+ {
+ return $this->getInnerIterator()->hasChildren();
+ }
+
+ /** @return an iterator for the current elements children
+ *
+ * @note the returned iterator will be of the same class as $this
+ */
+ function getChildren()
+ {
+ if (empty($this->ref))
+ {
+ $this->ref = new ReflectionClass($this);
+ }
+ return $this->ref->newInstance($this->getInnerIterator()->getChildren());
+ }
+
+ private $ref;
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursiveiterator.inc b/ext/spl/internal/recursiveiterator.inc
new file mode 100644
index 0000000..1eab3d6
--- /dev/null
+++ b/ext/spl/internal/recursiveiterator.inc
@@ -0,0 +1,30 @@
+<?php
+
+/** @file recursiveiterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Interface for recursive iteration with RecursiveIteratorIterator
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.0
+ */
+interface RecursiveIterator extends Iterator
+{
+ /** @return whether the current element has children
+ */
+ function hasChildren();
+
+ /** @return the sub iterator for the current element
+ * @note The returned object must implement RecursiveIterator.
+ */
+ function getChildren();
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc
new file mode 100644
index 0000000..35fa801
--- /dev/null
+++ b/ext/spl/internal/recursiveiteratoriterator.inc
@@ -0,0 +1,237 @@
+<?php
+
+/** @file recursiveiteratoriterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveIteratorIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Iterates through recursive iterators
+ * @author Marcus Boerger
+ * @version 1.2
+ * @since PHP 5.0
+ *
+ * The objects of this class are created by instances of RecursiveIterator.
+ * Elements of those iterators may be traversable themselves. If so these
+ * sub elements are recursed into.
+ */
+class RecursiveIteratorIterator implements OuterIterator
+{
+ /** Mode: Only show leaves */
+ const LEAVES_ONLY = 0;
+ /** Mode: Show parents prior to their children */
+ const SELF_FIRST = 1;
+ /** Mode: Show all children prior to their parent */
+ const CHILD_FIRST = 2;
+
+ /** Flag: Catches exceptions during getChildren() calls and simply jumps
+ * to the next element. */
+ const CATCH_GET_CHILD = 0x00000002;
+
+ private $ait = array();
+ private $count = 0;
+ private $mode = self::LEAVES_ONLY;
+ private $flags = 0;
+
+ /** Construct from RecursiveIterator
+ *
+ * @param it RecursiveIterator to iterate
+ * @param mode Operation mode (one of):
+ * - LEAVES_ONLY only show leaves
+ * - SELF_FIRST show parents prior to their childs
+ * - CHILD_FIRST show all children prior to their parent
+ * @param flags Control flags, zero or any combination of the following
+ * (since PHP 5.1).
+ * - CATCH_GET_CHILD which catches exceptions during
+ * getChildren() calls and simply jumps to the next
+ * element.
+ */
+ function __construct(RecursiveIterator $it, $mode = self::LEAVES_ONLY, $flags = 0)
+ {
+ $this->ait[0] = $it;
+ $this->mode = $mode;
+ $this->flags = $flags;
+ }
+
+ /** Rewind to top iterator as set in constructor
+ */
+ function rewind()
+ {
+ while ($this->count) {
+ unset($this->ait[$this->count--]);
+ $this->endChildren();
+ }
+ $this->ait[0]->rewind();
+ $this->ait[0]->recursed = false;
+ callNextElement(true);
+ }
+
+ /** @return whether iterator is valid
+ */
+ function valid()
+ {
+ $count = $this->count;
+ while ($count) {
+ $it = $this->ait[$count];
+ if ($it->valid()) {
+ return true;
+ }
+ $count--;
+ $this->endChildren();
+ }
+ return false;
+ }
+
+ /** @return current key
+ */
+ function key()
+ {
+ $it = $this->ait[$this->count];
+ return $it->key();
+ }
+
+ /** @return current element
+ */
+ function current()
+ {
+ $it = $this->ait[$this->count];
+ return $it->current();
+ }
+
+ /** Forward to next element
+ */
+ function next()
+ {
+ while ($this->count) {
+ $it = $this->ait[$this->count];
+ if ($it->valid()) {
+ if (!$it->recursed && callHasChildren()) {
+ $it->recursed = true;
+ try
+ {
+ $sub = callGetChildren();
+ }
+ catch (Exception $e)
+ {
+ if (!($this->flags & self::CATCH_GET_CHILD))
+ {
+ throw $e;
+ }
+ $it->next();
+ continue;
+ }
+ $sub->recursed = false;
+ $sub->rewind();
+ if ($sub->valid()) {
+ $this->ait[++$this->count] = $sub;
+ if (!$sub instanceof RecursiveIterator) {
+ throw new Exception(get_class($sub).'::getChildren() must return an object that implements RecursiveIterator');
+ }
+ $this->beginChildren();
+ return;
+ }
+ unset($sub);
+ }
+ $it->next();
+ $it->recursed = false;
+ if ($it->valid()) {
+ return;
+ }
+ $it->recursed = false;
+ }
+ if ($this->count) {
+ unset($this->ait[$this->count--]);
+ $it = $this->ait[$this->count];
+ $this->endChildren();
+ callNextElement(false);
+ }
+ }
+ callNextElement(true);
+ }
+
+ /** @return Sub Iterator at given level or if unspecified the current sub
+ * Iterator
+ */
+ function getSubIterator($level = NULL)
+ {
+ if (is_null($level)) {
+ $level = $this->count;
+ }
+ return @$this->ait[$level];
+ }
+
+ /**
+ * @return The inner iterator
+ */
+ function getInnerIterator()
+ {
+ return $this->it;
+ }
+
+ /** @return Current Depth (Number of parents)
+ */
+ function getDepth()
+ {
+ return $this->level;
+ }
+
+ /** @return whether current sub iterators current element has children
+ * @since PHP 5.1
+ */
+ function callHasChildren()
+ {
+ return $this->ait[$this->count]->hasChildren();
+ }
+
+ /** @return current sub iterators current children
+ * @since PHP 5.1
+ */
+ function callGetChildren()
+ {
+ return $this->ait[$this->count]->getChildren();
+ }
+
+ /** Called right after calling getChildren() and its rewind().
+ * @since PHP 5.1
+ */
+ function beginChildren()
+ {
+ }
+
+ /** Called after current child iterator is invalid and right before it
+ * gets destructed.
+ * @since PHP 5.1
+ */
+ function endChildren()
+ {
+ }
+
+ private function callNextElement($after_move)
+ {
+ if ($this->valid())
+ {
+ if ($after_move)
+ {
+ if (($this->mode == self::SELF_FIRST && $this->callHasChildren())
+ || $this->mode == self::LEAVES_ONLY)
+ $this->nextElement();
+ }
+ else
+ {
+ $this->nextElement();
+ }
+ }
+ }
+
+ /** Called when the next element is available
+ */
+ function nextElement()
+ {
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursiveregexiterator.inc b/ext/spl/internal/recursiveregexiterator.inc
new file mode 100644
index 0000000..ffcff0c
--- /dev/null
+++ b/ext/spl/internal/recursiveregexiterator.inc
@@ -0,0 +1,61 @@
+<?php
+
+/** @file recursiveregexiterator.inc
+ * @ingroup SPL
+ * @brief class RegexIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Recursive regular expression filter for iterators
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ *
+ * This filter iterator assumes that the inner iterator
+ */
+class RecursiveRegexIterator extends RegexIterator implements RecursiveIterator
+{
+ /**
+ * Constructs a regular expression filter around an iterator whose
+ * elemnts or keys are strings.
+ *
+ * @param it inner iterator
+ * @param regex the regular expression to match
+ * @param mode operation mode (one of self::MATCH, self::GET_MATCH,
+ * self::ALL_MATCHES, self::SPLIT)
+ * @param flags special flags (self::USE_KEY)
+ * @param preg_flags global PREG_* flags, see preg_match(),
+ * preg_match_all(), preg_split()
+ */
+ function __construct(RecursiveIterator $it, $regex, $mode = 0, $flags = 0, $preg_flags = 0) {
+ parent::__construct($it, $regex, $mode, $flags, $preg_flags);
+ }
+
+ /** @return whether the current element has children
+ */
+ function hasChildren()
+ {
+ return $this->getInnerIterator()->hasChildren();
+ }
+
+ /** @return an iterator for the current elements children
+ *
+ * @note the returned iterator will be of the same class as $this
+ */
+ function getChildren()
+ {
+ if (empty($this->ref))
+ {
+ $this->ref = new ReflectionClass($this);
+ }
+ return $this->ref->newInstance($this->getInnerIterator()->getChildren());
+ }
+
+ private $ref;
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/recursivetreeiterator.inc b/ext/spl/internal/recursivetreeiterator.inc
new file mode 100644
index 0000000..dfcdc05
--- /dev/null
+++ b/ext/spl/internal/recursivetreeiterator.inc
@@ -0,0 +1,132 @@
+<?php
+
+/** @file recursivetreeiterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveTreeIterator
+ * @author Marcus Boerger, Johannes Schlueter
+ * @date 2005 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+
+/** @ingroup SPL
+ * @brief RecursiveIteratorIterator to generate ASCII graphic trees for the
+ * entries in a RecursiveIterator
+ * @author Marcus Boerger, Johannes Schlueter
+ * @version 1.1
+ * @since PHP 5.3
+ */
+class RecursiveTreeIterator extends RecursiveIteratorIterator
+{
+ const BYPASS_CURRENT = 0x00000004;
+ const BYPASS_KEY = 0x00000008;
+
+ private $rit_flags;
+
+ /**
+ * @param it iterator to use as inner iterator
+ * @param rit_flags flags passed to RecursiveIteratoIterator (parent)
+ * @param cit_flags flags passed to RecursiveCachingIterator (for hasNext)
+ * @param mode mode passed to RecursiveIteratoIterator (parent)
+ */
+ function __construct(RecursiveIterator $it, $rit_flags = self::BYPASS_KEY, $cit_flags = CachingIterator::CATCH_GET_CHILD, $mode = self::SELF_FIRST)
+ {
+ parent::__construct(new RecursiveCachingIterator($it, $cit_flags), $mode, $rit_flags);
+ $this->rit_flags = $rit_flags;
+ }
+
+ private $prefix = array(0=>'', 1=>'| ', 2=>' ', 3=>'|-', 4=>'\-', 5=>'');
+
+ /** Prefix used to start elements. */
+ const PREFIX_LEFT = 0;
+ /** Prefix used if $level < depth and hasNext($level) == true. */
+ const PREFIX_MID_HAS_NEXT = 1;
+ /** Prefix used if $level < depth and hasNext($level) == false. */
+ const PREFIX_MID_LAST = 2;
+ /** Prefix used if $level == depth and hasNext($level) == true. */
+ const PREFIX_END_HAS_NEXT = 3;
+ /** Prefix used if $level == depth and hasNext($level) == false. */
+ const PREFIX_END_LAST = 4;
+ /** Prefix used right in front of the current element. */
+ const PREFIX_RIGHT = 5;
+
+ /**
+ * Set prefix part as used in getPrefix() and stored in $prefix.
+ * @param $part any PREFIX_* const.
+ * @param $value new prefix string for specified part.
+ * @throws OutOfRangeException if 0 > $part or $part > 5.
+ */
+ function setPrefixPart($part, $value)
+ {
+ if (0 > $part || $part > 5) {
+ throw new OutOfRangeException();
+ }
+ $this->prefix[$part] = (string)$value;
+ }
+
+ /** @return string to place in front of current element
+ */
+ function getPrefix()
+ {
+ $tree = '';
+ for ($level = 0; $level < $this->getDepth(); $level++)
+ {
+ $tree .= $this->getSubIterator($level)->hasNext() ? $this->prefix[1] : $this->prefix[2];
+ }
+ $tree .= $this->getSubIterator($level)->hasNext() ? $this->prefix[3] : $this->prefix[4];
+
+ return $this->prefix[0] . $tree . $this->prefix[5];
+ }
+
+ /** @return string presentation build for current element
+ */
+ function getEntry()
+ {
+ return @(string)parent::current();
+ }
+
+ /** @return string to place after the current element
+ */
+ function getPostfix()
+ {
+ return '';
+ }
+
+ /** @return the current element prefixed and postfixed
+ */
+ function current()
+ {
+ if ($this->rit_flags & self::BYPASS_CURRENT)
+ {
+ return parent::current();
+ }
+ else
+ {
+ return $this->getPrefix() . $this->getEntry() . $this->getPostfix();
+ }
+ }
+
+ /** @return the current key prefixed and postfixed
+ */
+ function key()
+ {
+ if ($this->rit_flags & self::BYPASS_KEY)
+ {
+ return parent::key();
+ }
+ else
+ {
+ return $this->getPrefix() . parent::key() . $this->getPostfix();
+ }
+ }
+
+ /** Aggregates the inner iterator
+ */
+ function __call($func, $params)
+ {
+ return call_user_func_array(array($this->getSubIterator(), $func), $params);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/regexiterator.inc b/ext/spl/internal/regexiterator.inc
new file mode 100644
index 0000000..c6addb9
--- /dev/null
+++ b/ext/spl/internal/regexiterator.inc
@@ -0,0 +1,170 @@
+<?php
+
+/** @file regexiterator.inc
+ * @ingroup SPL
+ * @brief class RegexIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Regular expression filter for iterators
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ *
+ * This filter iterator assumes that the inner iterator
+ */
+class RegexIterator extends FilterIterator
+{
+ const USE_KEY = 0x00000001; /**< If present in $flags the key is
+ used rather then the current value. */
+
+ const MATCH = 0; /**< Mode: Executed a plain match only */
+ const GET_MATCH = 1; /**< Mode: Return the first matche (if any) */
+ const ALL_MATCHES = 2; /**< Mode: Return all matches (if any) */
+ const SPLIT = 3; /**< Mode: Return the split values (if any) */
+ const REPLACE = 4; /**< Mode: Replace the input key or current */
+
+ private $regex; /**< the regular expression to match against */
+ private $mode; /**< operation mode (one of self::MATCH,
+ self::GET_MATCH, self::ALL_MATCHES, self::SPLIT) */
+ private $flags; /**< special flags (self::USE_KEY) */
+ private $preg_flags;/**< PREG_* flags, see preg_match(), preg_match_all(),
+ preg_split() */
+ private $key; /**< the value used for key() */
+ private $current; /**< the value used for current() */
+
+ /**
+ * Constructs a regular expression filter around an iterator whose
+ * elemnts or keys are strings.
+ *
+ * @param it inner iterator
+ * @param regex the regular expression to match
+ * @param mode operation mode (one of self::MATCH, self::GET_MATCH,
+ * self::ALL_MATCHES, self::SPLIT)
+ * @param flags special flags (self::USE_KEY)
+ * @param preg_flags global PREG_* flags, see preg_match(),
+ * preg_match_all(), preg_split()
+ */
+ function __construct(Iterator $it, $regex, $mode = 0, $flags = 0, $preg_flags = 0) {
+ parent::__construct($it);
+ $this->regex = $regex;
+ $this->flags = $flags;
+ $this->mode = $mode;
+ $this->preg_flags = $preg_flags;
+ }
+
+ /**
+ * Match current or key against regular expression using mode, flags and
+ * preg_flags.
+ *
+ * @return whether this is a match
+ *
+ * @warning never call this twice for the same state
+ */
+ function accept()
+ {
+ $matches = array();
+ $this->key = parent::key();
+ $this->current = parent::current();
+ /* note that we use $this->current, rather than calling parent::current() */
+ $subject = ($this->flags & self::USE_KEY) ? $this->key : $this->current;
+ switch($this->mode)
+ {
+ case self::MATCH:
+ return preg_match($this->regex, $subject, $matches, $this->preg_flags);
+
+ case self::GET_MATCH:
+ $this->current = array();
+ return preg_match($this->regex, $subject, $this->current, $this->preg_flags) > 0;
+
+ case self::ALL_MATCHES:
+ $this->current = array();
+ return preg_match_all($this->regex, $subject, $this->current, $this->preg_flags) > 0;
+
+ case self::SPLIT:
+ $this->current = array();
+ preg_split($this->regex, $subject, $this->current, $this->preg_flags) > 1;
+
+ case self::REPLACE:
+ $this->current = array();
+ $result = preg_replace($this->regex, $this->replacement, $subject);
+ if ($this->flags & self::USE_KEY)
+ {
+ $this->key = $result;
+ }
+ else
+ {
+ $this->current = $result;
+ }
+ }
+ }
+
+ /** @return the key after accept has been called
+ */
+ function key()
+ {
+ return $this->key;
+ }
+
+ /** @return the current value after accept has been called
+ */
+ function current()
+ {
+ return $this->current;
+ }
+
+ /** @return current operation mode
+ */
+ function getMode()
+ {
+ return $this->mode;
+ }
+
+ /** @param mode new operaion mode
+ */
+ function setMode($mode)
+ {
+ $this->mode = $mode;
+ }
+
+ /** @return current operation flags
+ */
+ function getFlags()
+ {
+ return $this->flags;
+ }
+
+ /** @param flags new operaion flags
+ */
+ function setFlags($flags)
+ {
+ $this->flags = $flags;
+ }
+
+ /** @return current PREG flags
+ */
+ function getPregFlags()
+ {
+ return $this->preg_flags;
+ }
+
+ /** @param preg_flags new PREG flags
+ */
+ function setPregFlags($preg_flags)
+ {
+ $this->preg_flags = $preg_flags;
+ }
+
+ /** @return current regular expression
+ */
+ function getRegex()
+ {
+ return $this->regex;
+ }
+}
+
+?>
diff --git a/ext/spl/internal/seekableiterator.inc b/ext/spl/internal/seekableiterator.inc
new file mode 100644
index 0000000..b4f66bd
--- /dev/null
+++ b/ext/spl/internal/seekableiterator.inc
@@ -0,0 +1,48 @@
+<?php
+
+/** @file seekableiterator.inc
+ * @ingroup SPL
+ * @brief class SeekableIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @brief seekable iterator
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.0
+ *
+ * Turns a normal iterator ino a seekable iterator. When there is a way
+ * to seek on an iterator LimitIterator can use this to efficiently rewind
+ * to offset.
+ */
+interface SeekableIterator extends Iterator
+{
+ /** Seek to an absolute position
+ *
+ * \param $index position to seek to
+ * \return void
+ *
+ * The method should throw an exception if it is not possible to seek to
+ * the given position. Typically this exception should be of type
+ * OutOfBoundsException.
+ \code
+ function seek($index);
+ $this->rewind();
+ $position = 0;
+ while($position < $index && $this->valid()) {
+ $this->next();
+ $position++;
+ }
+ if (!$this->valid()) {
+ throw new OutOfBoundsException('Invalid seek position');
+ }
+ }
+ \endcode
+ */
+ function seek($index);
+}
+
+?> \ No newline at end of file
diff --git a/ext/spl/internal/spldoublylinkedlist.inc b/ext/spl/internal/spldoublylinkedlist.inc
new file mode 100644
index 0000000..e87e4b1
--- /dev/null
+++ b/ext/spl/internal/spldoublylinkedlist.inc
@@ -0,0 +1,277 @@
+<?php
+/** @file spldoublylinkedlist.inc
+ * @ingroup SPL
+ * @brief class SplDoublyLinkedList
+ * @author Etienne Kneuss
+ * @date 2008 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Doubly Linked List
+ * @since PHP 5.3
+ *
+ * The SplDoublyLinkedList class provides the main functionalities of a
+ * doubly linked list (DLL).
+ * @note The following userland implementation of Iterator is a bit different
+ * from the internal one. Internally, iterators generated by nested
+ * foreachs are independent, while they share the same traverse pointer
+ * in userland.
+ */
+class SplDoublyLinkedList implements Iterator, ArrayAccess, Countable
+{
+ protected $_llist = array();
+ protected $_it_mode = 0;
+ protected $_it_pos = 0;
+
+ /** Iterator mode
+ * @see setIteratorMode
+ */
+ const IT_MODE_LIFO = 0x00000002;
+
+ /** Iterator mode
+ * @see setIteratorMode
+ */
+ const IT_MODE_FIFO = 0x00000000;
+
+ /** Iterator mode
+ * @see setIteratorMode
+ */
+ const IT_MODE_KEEP = 0x00000000;
+
+ /** Iterator mode
+ * @see setIteratorMode
+ */
+ const IT_MODE_DELETE = 0x00000001;
+
+ /** @return the element popped from the end of the DLL.
+ * @throw RuntimeException If the datastructure is empty.
+ */
+ public function pop()
+ {
+ if (count($this->_llist) == 0) {
+ throw new RuntimeException("Can't pop from an empty datastructure");
+ }
+ return array_pop($this->_llist);
+ }
+
+ /** @return the element shifted from the beginning of the DLL.
+ * @throw RuntimeException If the datastructure is empty.
+ */
+ public function shift()
+ {
+ if (count($this->_llist) == 0) {
+ throw new RuntimeException("Can't shift from an empty datastructure");
+ }
+ return array_shift($this->_llist);
+ }
+
+ /** Pushes an element to the end of the DLL.
+ * @param $data variable to add to the DLL.
+ */
+ public function push($data)
+ {
+ array_push($this->_llist, $data);
+ return true;
+ }
+
+ /** Adds an element to the beginning of the DLL.
+ * @param $data variable to add to the DLL.
+ */
+ public function unshift($data)
+ {
+ array_unshift($this->_llist, $data);
+ return true;
+ }
+
+ /** @return the element at the beginning of the DLL.
+ */
+ public function top()
+ {
+ return end($this->_llist);
+ }
+
+ /** @return the element at the end of the DLL.
+ */
+ public function bottom()
+ {
+ return reset($this->_llist);
+ }
+
+ /** @return number elements in the DLL.
+ */
+ public function count()
+ {
+ return count($this->_llist);
+ }
+
+ /** @return whether the DLL is empty.
+ */
+ public function isEmpty()
+ {
+ return ($this->count() == 0);
+ }
+
+ /** Changes the iteration mode. There are two orthogonal sets of modes that
+ * can be set:
+ * - The direction of the iteration (either one or the other)
+ * - SplDoublyLnkedList::IT_MODE_LIFO (Stack style)
+ * - SplDoublyLnkedList::IT_MODE_FIFO (Queue style)
+ *
+ * - The behavior of the iterator (either one or the other)
+ * - SplDoublyLnkedList::IT_MODE_DELETE (Elements are deleted by the iterator)
+ * - SplDoublyLnkedList::IT_MODE_KEEP (Elements are traversed by the iterator)
+ *
+ * The default mode is 0 : SplDoublyLnkedList::IT_MODE_FIFO | SplDoublyLnkedList::IT_MODE_KEEP
+ *
+ * @param $mode new mode of iteration
+ */
+ public function setIteratorMode($mode)
+ {
+ $this->_it_mode = $mode;
+ }
+
+ /** @return the current iteration mode
+ * @see setIteratorMode
+ */
+ public function getIteratorMode()
+ {
+ return $this->_it_mode;
+ }
+
+ /** Rewind to top iterator as set in constructor
+ */
+ public function rewind()
+ {
+ if ($this->_it_mode & self::IT_MODE_LIFO) {
+ $this->_it_pos = count($this->_llist)-1;
+ } else {
+ $this->_it_pos = 0;
+ }
+ }
+
+ /** @return whether iterator is valid
+ */
+ public function valid()
+ {
+ return array_key_exists($this->_it_pos, $this->_llist);
+ }
+
+ /** @return current key
+ */
+ public function key()
+ {
+ return $this->_it_pos;
+ }
+
+ /** @return current object
+ */
+ public function current()
+ {
+ return $this->_llist[$this->_it_pos];
+ }
+
+ /** Forward to next element
+ */
+ public function next()
+ {
+ if ($this->_it_mode & self::IT_MODE_LIFO) {
+ if ($this->_it_mode & self::IT_MODE_DELETE) {
+ $this->pop();
+ }
+ $this->_it_pos--;
+ } else {
+ if ($this->_it_mode & self::IT_MODE_DELETE) {
+ $this->shift();
+ } else {
+ $this->_it_pos++;
+ }
+ }
+ }
+
+ /** @return whether a certain offset exists in the DLL
+ *
+ * @param $offset The offset
+ * @throw OutOfRangeException If the offset is either invalid or out of
+ * range.
+ */
+ public function offsetExists($offset)
+ {
+ if (!is_numeric($offset)) {
+ throw new OutOfRangeException("Offset invalid or out of range");
+ } else {
+ return array_key_exists($offset, $this->_llist);
+ }
+ }
+
+ /** @return the data at a certain offset in the DLL
+ *
+ * @param $offset The offset
+ * @throw OutOfRangeException If the offset is either invalid or out of
+ * range.
+ */
+ public function offsetGet($offset)
+ {
+ if ($this->_it_mode & self::IT_MODE_LIFO) {
+ $realOffset = count($this->_llist)-$offset;
+ } else {
+ $realOffset = $offset;
+ }
+
+ if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
+ throw new OutOfRangeException("Offset invalid or out of range");
+ } else {
+ return $this->_llist[$realOffset];
+ }
+ }
+
+ /** Defines the data at a certain offset in the DLL
+ *
+ * @param $offset The offset
+ * @param $value New value
+ * @throw OutOfRangeException If the offset is either invalid or out of
+ * range.
+ */
+ public function offsetSet($offset, $value)
+ {
+ if ($offset === null) {
+ return $this->push($value);
+ }
+
+ if ($this->_it_mode & self::IT_MODE_LIFO) {
+ $realOffset = count($this->_llist)-$offset;
+ } else {
+ $realOffset = $offset;
+ }
+
+ if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
+ throw new OutOfRangeException("Offset invalid or out of range");
+ } else {
+ $this->_llist[$realOffset] = $value;
+ }
+ }
+
+ /** Unsets the element at a certain offset in the DLL
+ *
+ * @param $offset The offset
+ * @throw OutOfRangeException If the offset is either invalid or out of
+ * range.
+ */
+ public function offsetUnset($offset)
+ {
+ if ($this->_it_mode & self::IT_MODE_LIFO) {
+ $realOffset = count($this->_llist)-$offset;
+ } else {
+ $realOffset = $offset;
+ }
+
+ if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
+ throw new OutOfRangeException("Offset invalid or out of range");
+ } else {
+ array_splice($this->_llist, $realOffset, 1);
+ }
+ }
+}
+
+?>
diff --git a/ext/spl/internal/splfileobject.inc b/ext/spl/internal/splfileobject.inc
new file mode 100644
index 0000000..46b941f
--- /dev/null
+++ b/ext/spl/internal/splfileobject.inc
@@ -0,0 +1,377 @@
+<?php
+
+/** @file splfileobject.inc
+ * @ingroup SPL
+ * @brief class FileObject
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Object representation for any stream
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.1
+ */
+class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator
+{
+ /** Flag: wheter to suppress new lines */
+ const DROP_NEW_LINE = 0x00000001;
+
+ private $fp;
+ private $fname;
+ private $line = NULL;
+ private $lnum = 0;
+ private $max_len = 0;
+ private $flags = 0;
+ private $delimiter= ',';
+ private $enclosure= '"';
+
+ /**
+ * Constructs a new file object
+ *
+ * @param $file_name The name of the stream to open
+ * @param $open_mode The file open mode
+ * @param $use_include_path Whether to search in include paths
+ * @param $context A stream context
+ * @throw RuntimeException If file cannot be opened (e.g. insufficient
+ * access rights).
+ */
+ function __construct($file_name, $open_mode = 'r', $use_include_path = false, $context = NULL)
+ {
+ $this->fp = fopen($file_name, $open_mode, $use_include_path, $context);
+ if (!$this->fp)
+ {
+ throw new RuntimeException("Cannot open file $file_name");
+ }
+ $this->fname = $file_name;
+ }
+
+ /**
+ * @return whether the end of the stream is reached
+ */
+ function eof()
+ {
+ return eof($this->fp);
+ }
+
+ /** increase current line number
+ * @return next line from stream
+ */
+ function fgets()
+ {
+ $this->freeLine();
+ $this->lnum++;
+ $buf = fgets($this->fp, $this->max_len);
+
+ return $buf;
+ }
+
+ /**
+ * @param delimiter character used as field separator
+ * @param enclosure end of
+ * @return array containing read data
+ */
+ function fgetcsv($delimiter = NULL, $enclosure = NULL)
+ {
+ $this->freeLine();
+ $this->lnum++;
+ switch(fun_num_args())
+ {
+ case 0:
+ $delimiter = $this->delimiter;
+ case 1:
+ $enclosure = $this->enclosure;
+ default:
+ case 2:
+ break;
+ }
+ return fgetcsv($this->fp, $this->max_len, $delimiter, $enclosure);
+ }
+
+ /**
+ * Set the delimiter and enclosure character used in fgetcsv
+ *
+ * @param delimiter new delimiter, defaults to ','
+ * @param enclosure new enclosure, defaults to '"'
+ */
+ function setCsvControl($delimiter = ';', $enclosure = '"')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ }
+
+ /**
+ * @return array(delimiter, enclosure) as used in fgetcsv
+ */
+ function getCsvControl($delimiter = ',', $enclosure = '"')
+ {
+ return array($this->delimiter, $this->enclosure);
+ }
+
+ /**
+ * @param operation lock operation (LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB)
+ * @retval $wouldblock whether the operation would block
+ */
+ function flock($operation, &$wouldblock)
+ {
+ return flock($this->fp, $operation, $wouldblock);
+ }
+
+ /**
+ * Flush current data
+ * @return success or failure
+ */
+ function fflush()
+ {
+ return fflush($this->fp);
+ }
+
+ /**
+ * @return current file position
+ */
+ function ftell()
+ {
+ return ftell($this->fp);
+ }
+
+ /**
+ * @param pos new file position
+ * @param whence seek method (SEEK_SET, SEEK_CUR, SEEK_END)
+ * @return Upon success, returns 0; otherwise, returns -1. Note that
+ * seeking past EOF is not considered an error.
+ */
+ function fseek($pos, $whence = SEEK_SET)
+ {
+ return fseek($this->fp, $pos, $whence);
+ }
+
+ /**
+ * @return next char from file
+ * @note a new line character does not increase $this->lnum
+ */
+ function fgetc()
+ {
+ $this->freeLine();
+ $c = fgetc($this->fp);
+ if ($c == '\n') {
+ $this->lnum++;
+ }
+ }
+
+ /** Read and return remaining part of stream
+ * @return size of remaining part passed through
+ */
+ function fpassthru()
+ {
+ return fpassthru($this->fp);
+ }
+
+ /** Get a line from the file and strip HTML tags
+ * @param $allowable_tags tags to keep in the string
+ */
+ function fgetss($allowable_tags = NULL)
+ {
+ return fgetss($this->fp, $allowable_tags);
+ }
+
+ /** Scan the next line
+ * @param $format string specifying format to parse
+ */
+ function fscanf($format /* , ... */)
+ {
+ $this->freeLine();
+ $this->lnum++;
+ return fscanf($this->fp, $format /* , ... */);
+ }
+
+ /**
+ * @param $str to write
+ * @param $length maximum line length to write
+ */
+ function fwrite($str, $length = NULL)
+ {
+ return fwrite($this->fp, $length);
+ }
+
+ /**
+ * @return array of file stat information
+ */
+ function fstat()
+ {
+ return fstat($this->fp);
+ }
+
+ /**
+ * @param $size new size to truncate file to
+ */
+ function ftruncate($size)
+ {
+ return ftruncate($this->fp, $size);
+ }
+
+ /**
+ * @param $flags new flag set
+ */
+ function setFlags($flags)
+ {
+ $this->flags = $flags;
+ }
+
+ /**
+ * @return current set of flags
+ */
+ function getFlags()
+ {
+ return $this->flags;
+ }
+
+ /**
+ * @param $max_len set the maximum line length read
+ */
+ function setMaxLineLen($max_len)
+ {
+ $this->max_len = $max_len;
+ }
+
+ /**
+ * @return current setting for max line
+ */
+ function getMaxLineLen()
+ {
+ return $this->max_len;
+ }
+
+ /**
+ * @return false
+ */
+ function hasChildren()
+ {
+ return false;
+ }
+
+ /**
+ * @return false
+ */
+ function getChildren()
+ {
+ return NULL;
+ }
+
+ /**
+ * Invalidate current line buffer and set line number to 0.
+ */
+ function rewind()
+ {
+ $this->freeLine();
+ $this->lnum = 0;
+ }
+
+ /**
+ * @return whether more data can be read
+ */
+ function valid()
+ {
+ return !$this->eof();
+ }
+
+ /**
+ * @note Fill current line buffer if not done yet.
+ * @return line buffer
+ */
+ function current()
+ {
+ if (is_null($this->line))
+ {
+ $this->line = getCurrentLine();
+ }
+ return $this->line;
+ }
+
+ /**
+ * @return line number
+ * @note fgetc() will increase the line number when reaing a new line char.
+ * This has the effect key() called on a read a new line will already
+ * return the increased line number.
+ * @note Line counting works as long as you only read the file and do not
+ * use fseek().
+ */
+ function key()
+ {
+ return $this->lnum;
+ }
+
+ /** Invalidate current line buffer.
+ */
+ function next()
+ {
+ $this->freeLine();
+ }
+
+ /**
+ * @return next line read from file and increase the line counter
+ */
+ private function readLine()
+ {
+ if ($this->eof())
+ {
+ $this->freeLine();
+ throw new RuntimeException("Cannot read from file " . $this->fname);
+ }
+ if ($this->line) {
+ $this->lnum++;
+ }
+ $this->freeLine();
+ $this->line = fgets($this->fp, $this->max_len);
+ return $this->line;
+ }
+
+ /**
+ * Free the current line buffer and increment the line counter
+ */
+ private function freeLine()
+ {
+ if ($this->line) {
+ $this->line = NULL;
+ }
+ }
+
+ /*
+ * @note If you DO overload this function key() and current() will increment
+ * $this->lnum automatically. If not then function reaLine() will do
+ * that for you.
+ */
+ function getCurrentLine()
+ {
+ $this->freeLine();
+ if ($this->eof())
+ {
+ throw new RuntimeException("Cannot read from file " . $this->fname);
+ }
+ $this->readLine();
+ }
+
+ /**
+ * @return current line
+ */
+ function __toString()
+ {
+ return current();
+ }
+
+ /**
+ * @param $line_pos Seek to this line
+ */
+ function seek($line_pos)
+ {
+ $this->rewind();
+ while($this->lnum < $line_pos && !$this->eof())
+ {
+ $this->getCurrentLine();
+ }
+ }
+}
+
+?>
diff --git a/ext/spl/internal/splobjectstorage.inc b/ext/spl/internal/splobjectstorage.inc
new file mode 100644
index 0000000..fa16406
--- /dev/null
+++ b/ext/spl/internal/splobjectstorage.inc
@@ -0,0 +1,188 @@
+<?php
+
+/** @file splobjectstorage.inc
+ * @ingroup SPL
+ * @brief class SplObjectStorage
+ * @author Marcus Boerger
+ * @date 2003 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/**
+ * @brief Object storage
+ * @author Marcus Boerger
+ * @version 1.1
+ * @since PHP 5.1.2
+ *
+ * This container allows to store objects uniquly without the need to compare
+ * them one by one. This is only possible internally. The code represenation
+ * here therefore has a complexity of O(n) while the actual implementation has
+ * complexity O(1).
+ */
+class SplObjectStorage implements Iterator, Countable, ArrayAccess
+{
+ private $storage = array();
+ private $index = 0;
+
+ /** Rewind to top iterator as set in constructor
+ */
+ function rewind()
+ {
+ rewind($this->storage);
+ }
+
+ /** @return whether iterator is valid
+ */
+ function valid()
+ {
+ return key($this->storage) !== false;
+ }
+
+ /** @return current key
+ */
+ function key()
+ {
+ return $this->index;
+ }
+
+ /** @return current object
+ */
+ function current()
+ {
+ $element = current($this->storage);
+ return $element ? $element[0] : NULL
+ }
+
+ /** @return get current object's associated information
+ * @since 5.3.0
+ */
+ function getInfo()
+ {
+ $element = current($this->storage);
+ return $element ? $element[1] : NULL
+ }
+
+ /** @return set current object's associated information
+ * @since 5.3.0
+ */
+ function setInfo($inf = NULL)
+ {
+ if ($this->valid()) {
+ $this->storage[$this->index][1] = $inf;
+ }
+ }
+
+ /** Forward to next element
+ */
+ function next()
+ {
+ next($this->storage);
+ $this->index++;
+ }
+
+ /** @return number of objects in storage
+ */
+ function count()
+ {
+ return count($this->storage);
+ }
+
+ /** @param $obj object to look for
+ * @return whether $obj is contained in storage
+ */
+ function contains($obj)
+ {
+ if (is_object($obj))
+ {
+ foreach($this->storage as $element)
+ {
+ if ($object === $element[0])
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /** @param $obj new object to attach to storage or object whose
+ * associative information is to be replaced
+ * @param $inf associative information stored along the object
+ */
+ function attach($obj, $inf = NULL)
+ {
+ if (is_object($obj) && !$this->contains($obj))
+ {
+ $this->storage[] = array($obj, $inf);
+ }
+ }
+
+ /** @param $obj object to remove from storage
+ */
+ function detach($obj)
+ {
+ if (is_object($obj))
+ {
+ foreach($this->storage as $idx => $element)
+ {
+ if ($object === $element[0])
+ {
+ unset($this->storage[$idx]);
+ $this->rewind();
+ return;
+ }
+ }
+ }
+ }
+
+ /** @param $obj new object to attach to storage or object whose
+ * associative information is to be replaced
+ * @param $inf associative information stored along the object
+ * @since 5.3.0
+ */
+ function offsetSet($obj, $inf)
+ {
+ $this->attach($obj, $inf);
+ }
+
+ /** @param $obj Exising object to look for
+ * @return associative information stored with object
+ * @throw UnexpectedValueException if Object $obj is not contained in
+ * storage
+ * @since 5.3.0
+ */
+ function offsetGet($obj)
+ {
+ if (is_object($obj))
+ {
+ foreach($this->storage as $idx => $element)
+ {
+ if ($object === $element[0])
+ {
+ return $element[1];
+ }
+ }
+ }
+ throw new UnexpectedValueException('Object not found');
+ }
+
+ /** @param $obj Exising object to look for
+ * @return associative information stored with object
+ * @since 5.3.0
+ */
+ function offsetUnset($obj)
+ {
+ $this->detach($obj);
+ }
+
+ /** @param $obj object to look for
+ * @return whether $obj is contained in storage
+ */
+ function offsetEsists($obj)
+ {
+ return $this->contains($obj);
+ }
+}
+
+?>
diff --git a/ext/spl/internal/splqueue.inc b/ext/spl/internal/splqueue.inc
new file mode 100644
index 0000000..368a259
--- /dev/null
+++ b/ext/spl/internal/splqueue.inc
@@ -0,0 +1,71 @@
+<?php
+
+/** @file splqueue.inc
+ * @ingroup SPL
+ * @brief class SplQueue
+ * @author Etienne Kneuss
+ * @date 2008 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Implementation of a Queue through a DoublyLinkedList. As SplQueue
+ * extends SplDoublyLinkedList, unshift() and pop() are still available
+ * even though they don't make much sense for a queue. For convenience,
+ * two aliases are available:
+ * - enqueue() is an alias of push()
+ * - dequeue() is an alias of shift()
+ *
+ * @since PHP 5.3
+ *
+ * The SplQueue class provides the main functionalities of a
+ * queue implemented using a doubly linked list (DLL).
+ */
+class SplQueue extends SplDoublyLinkedList
+{
+ protected $_it_mode = parent::IT_MODE_FIFO;
+
+ /** Changes the iteration mode. There are two orthogonal sets of modes that
+ * can be set:
+ *
+ * - The behavior of the iterator (either one or the other)
+ * - SplDoublyLnkedList::IT_MODE_DELETE (Elements are deleted by the iterator)
+ * - SplDoublyLnkedList::IT_MODE_KEEP (Elements are traversed by the iterator)
+ *
+ * The default mode is 0 : SplDoublyLnkedList::IT_MODE_LIFO | SplDoublyLnkedList::IT_MODE_KEEP
+ *
+ * @note The iteration's direction is not modifiable for queue instances
+ * @param $mode New mode of iteration
+ * @throw RuntimeException If the new mode affects the iteration's direction.
+ */
+ public function setIteratorMode($mode)
+ {
+ if ($mode & parent::IT_MODE_LIFO === parent::IT_MODE_LIFO) {
+ throw new RuntimeException("Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen");
+ }
+
+ $this->_it_mode = $mode;
+ }
+
+ /** @return the first element of the queue.
+ * @note dequeue is an alias of push()
+ * @see splDoublyLinkedList::push()
+ */
+ public function dequeue()
+ {
+ return parent::shift();
+ }
+
+ /** Pushes an element at the end of the queue.
+ * @param $data variable to add to the queue.
+ * @note enqueue is an alias of shift()
+ * @see splDoublyLinkedList::shift()
+ */
+ public function enqueue($data)
+ {
+ return parent::push($data);
+ }
+}
+
+?>
diff --git a/ext/spl/internal/splstack.inc b/ext/spl/internal/splstack.inc
new file mode 100644
index 0000000..70b1443
--- /dev/null
+++ b/ext/spl/internal/splstack.inc
@@ -0,0 +1,48 @@
+<?php
+
+/** @file splstack.inc
+ * @ingroup SPL
+ * @brief class SplStack
+ * @author Etienne Kneuss
+ * @date 2008 - 2009
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Implementation of a stack through a DoublyLinkedList. As SplStack
+ * extends SplDoublyLinkedList, shift() and unshift() are still available even
+ * though they don't make much sense for a stack.
+ * @since PHP 5.3
+ *
+ * The SplStack class provides the main functionalities of a
+ * stack implemented using a doubly linked list (DLL).
+ */
+class SplStack extends SplDoublyLinkedList
+{
+ protected $_it_mode = parent::IT_MODE_LIFO;
+
+ /** Changes the iteration mode. There are two orthogonal sets of modes that
+ * can be set:
+ *
+ * - The behavior of the iterator (either one or the other)
+ * - SplDoublyLnkedList::IT_MODE_DELETE (Elements are deleted by the iterator)
+ * - SplDoublyLnkedList::IT_MODE_KEEP (Elements are traversed by the iterator)
+ *
+ * The default mode is 0 : SplDoublyLnkedList::IT_MODE_LIFO | SplDoublyLnkedList::IT_MODE_KEEP
+ *
+ * @note The iteration's direction is not modifiable for stack instances
+ * @param $mode New mode of iteration
+ * @throw RuntimeException If the new mode affects the iteration's direction.
+ */
+ public function setIteratorMode($mode)
+ {
+ if ($mode & parent::IT_MODE_LIFO !== parent::IT_MODE_LIFO) {
+ throw new RuntimeException("Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen");
+ }
+
+ $this->_it_mode = $mode;
+ }
+}
+
+?>