summaryrefslogtreecommitdiff
path: root/ext/spl/internal
diff options
context:
space:
mode:
authorMark A. Hershberger <mah@debian.(none)>2009-03-25 19:39:21 -0400
committerMark A. Hershberger <mah@debian.(none)>2009-03-25 19:39:21 -0400
commit6821b67124604da690c5e9276d5370d679c63ac8 (patch)
treebefb4ca2520eb577950cef6cb76d10b914cbf67a /ext/spl/internal
parentcd0b49c72aee33b3e44a9c589fcd93b9e1c7a64f (diff)
downloadphp-6821b67124604da690c5e9276d5370d679c63ac8.tar.gz
Imported Upstream version 5.3.0RC1upstream/5.3.0_RC1upstream/5.3.0RC1
Diffstat (limited to 'ext/spl/internal')
-rwxr-xr-xext/spl/internal/multipleiterator.inc223
-rwxr-xr-xext/spl/internal/recursivetreeiterator.inc132
-rw-r--r--ext/spl/internal/spldoublylinkedlist.inc277
-rwxr-xr-xext/spl/internal/splobjectstorage.inc96
-rw-r--r--ext/spl/internal/splqueue.inc71
-rw-r--r--ext/spl/internal/splstack.inc48
6 files changed, 834 insertions, 13 deletions
diff --git a/ext/spl/internal/multipleiterator.inc b/ext/spl/internal/multipleiterator.inc
new file mode 100755
index 000000000..e977ca369
--- /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
+ *
+ * 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/recursivetreeiterator.inc b/ext/spl/internal/recursivetreeiterator.inc
new file mode 100755
index 000000000..b35718ee8
--- /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
+ *
+ * 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/spldoublylinkedlist.inc b/ext/spl/internal/spldoublylinkedlist.inc
new file mode 100644
index 000000000..ba6443edc
--- /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
+ *
+ * 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/splobjectstorage.inc b/ext/spl/internal/splobjectstorage.inc
index a6adafb67..9d06a05a6 100755
--- a/ext/spl/internal/splobjectstorage.inc
+++ b/ext/spl/internal/splobjectstorage.inc
@@ -4,7 +4,7 @@
* @ingroup SPL
* @brief class SplObjectStorage
* @author Marcus Boerger
- * @date 2003 - 2005
+ * @date 2003 - 2008
*
* SPL - Standard PHP Library
*/
@@ -12,7 +12,7 @@
/**
* @brief Object storage
* @author Marcus Boerger
- * @version 1.0
+ * @version 1.1
* @since PHP 5.1.2
*
* This container allows to store objects uniquly without the need to compare
@@ -20,7 +20,7 @@
* here therefore has a complexity of O(n) while the actual implementation has
* complexity O(1).
*/
-class SplObjectStorage implements Iterator, Countable
+class SplObjectStorage implements Iterator, Countable, ArrayAccess
{
private $storage = array();
private $index = 0;
@@ -50,7 +50,27 @@ class SplObjectStorage implements Iterator, Countable
*/
function current()
{
- return current($this->storage);
+ $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
@@ -68,16 +88,16 @@ class SplObjectStorage implements Iterator, Countable
return count($this->storage);
}
- /** @param obj object to look for
+ /** @param $obj object to look for
* @return whether $obj is contained in storage
- */
+ */
function contains($obj)
{
if (is_object($obj))
{
- foreach($this->storage as $object)
+ foreach($this->storage as $element)
{
- if ($object === $obj)
+ if ($object === $element[0])
{
return true;
}
@@ -86,13 +106,15 @@ class SplObjectStorage implements Iterator, Countable
return false;
}
- /** @param $obj new object to attach to storage if not yet contained
+ /** @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)
+ function attach($obj, $inf = NULL)
{
if (is_object($obj) && !$this->contains($obj))
{
- $this->storage[] = $obj;
+ $this->storage[] = array($obj, $inf);
}
}
@@ -102,9 +124,9 @@ class SplObjectStorage implements Iterator, Countable
{
if (is_object($obj))
{
- foreach($this->storage as $idx => $object)
+ foreach($this->storage as $idx => $element)
{
- if ($object === $obj)
+ if ($object === $element[0])
{
unset($this->storage[$idx]);
$this->rewind();
@@ -113,6 +135,54 @@ class SplObjectStorage implements Iterator, Countable
}
}
}
+
+ /** @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 000000000..f795eabbc
--- /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
+ *
+ * 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 000000000..4d3c62bab
--- /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
+ *
+ * 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;
+ }
+}
+
+?>