diff options
| author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:59 -0400 |
|---|---|---|
| committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:59 -0400 |
| commit | ce7edc9b3c7370f32fec0bc7a8ec3e29ed9a5f61 (patch) | |
| tree | acdb9a8816483652a9db1a47db71df5df43707c5 /ext/spl/internal | |
| parent | 10f5b47dc7c1cf2b9a00991629f43652710322d3 (diff) | |
| download | php-ce7edc9b3c7370f32fec0bc7a8ec3e29ed9a5f61.tar.gz | |
Imported Upstream version 5.1.1upstream/5.1.1
Diffstat (limited to 'ext/spl/internal')
| -rwxr-xr-x | ext/spl/internal/appenditerator.inc | 122 | ||||
| -rwxr-xr-x | ext/spl/internal/cachingiterator.inc | 100 | ||||
| -rwxr-xr-x | ext/spl/internal/cachingrecursiveiterator.inc | 53 | ||||
| -rwxr-xr-x | ext/spl/internal/emptyiterator.inc | 62 | ||||
| -rwxr-xr-x | ext/spl/internal/filteriterator.inc | 38 | ||||
| -rwxr-xr-x | ext/spl/internal/infiniteiterator.inc | 48 | ||||
| -rwxr-xr-x | ext/spl/internal/iteratoriterator.inc | 121 | ||||
| -rwxr-xr-x | ext/spl/internal/limititerator.inc | 72 | ||||
| -rwxr-xr-x | ext/spl/internal/norewinditerator.inc | 28 | ||||
| -rwxr-xr-x | ext/spl/internal/outeriterator.inc | 25 | ||||
| -rwxr-xr-x | ext/spl/internal/parentiterator.inc | 33 | ||||
| -rwxr-xr-x | ext/spl/internal/recursivearrayiterator.inc | 59 | ||||
| -rwxr-xr-x | ext/spl/internal/recursivecachingiterator.inc | 99 | ||||
| -rwxr-xr-x | ext/spl/internal/recursivefilteriterator.inc | 62 | ||||
| -rwxr-xr-x | ext/spl/internal/recursiveiterator.inc | 21 | ||||
| -rwxr-xr-x | ext/spl/internal/recursiveiteratoriterator.inc | 154 | ||||
| -rwxr-xr-x | ext/spl/internal/seekableiterator.inc | 31 | ||||
| -rwxr-xr-x | ext/spl/internal/splfileobject.inc | 353 | ||||
| -rwxr-xr-x | ext/spl/internal/splobjectstorage.inc | 118 |
19 files changed, 1504 insertions, 95 deletions
diff --git a/ext/spl/internal/appenditerator.inc b/ext/spl/internal/appenditerator.inc new file mode 100755 index 000000000..74f254d11 --- /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 - 2005 + * + * 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 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); + } +} + +?>
\ No newline at end of file diff --git a/ext/spl/internal/cachingiterator.inc b/ext/spl/internal/cachingiterator.inc index 48b732104..6714821f6 100755 --- a/ext/spl/internal/cachingiterator.inc +++ b/ext/spl/internal/cachingiterator.inc @@ -1,35 +1,77 @@ <?php
-define('CIT_CALL_TOSTRING', 1);
-define('CIT_CATCH_GET_CHILD', 2);
+/** @file cachingiterator.inc
+ * @ingroup SPL
+ * @brief class CachingIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2005
+ *
+ * SPL - Standard PHP Library
+ */
-class CachingIterator
+/**
+ * @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
{
- protected $it;
- protected $current;
- protected $key;
- protected $valid;
- protected $strValue;
+ const CALL_TOSTRING = 0x00000001;
+ const CATCH_GET_CHILD = 0x00000002;
+ const TOSTRING_USE_KEY = 0x00000010;
+ const TOSTRING_USE_CURRENT = 0x00000020;
- function __construct(Iterator $it, $flags = CIT_CALL_TOSTRING)
+ 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 & (CIT_CALL_TOSTRING|CIT_CATCH_GET_CHILD);
+ $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 & CIT_CALL_TOSTRING) {
+ if ($this->flags & self::CALL_TOSTRING) {
if (is_object($this->current)) {
$this->strValue = $this->current->__toString();
} else {
@@ -44,38 +86,72 @@ class CachingIterator $this->it->next();
}
+ /** @return whether teh 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 & CIT_CALL_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;
+ }
}
?>
\ No newline at end of file diff --git a/ext/spl/internal/cachingrecursiveiterator.inc b/ext/spl/internal/cachingrecursiveiterator.inc deleted file mode 100755 index c706e195d..000000000 --- a/ext/spl/internal/cachingrecursiveiterator.inc +++ /dev/null @@ -1,53 +0,0 @@ -<?php
-
-class CachingRecursiveIterator extends CachingIterator implements RecursiveIterator
-{
- protected $hasChildren;
- protected $getChildren;
-
- function __construct(RecursiveIterator $it, $flags = CIT_CALL_TOSTRING)
- {
- parent::__construct($it, $flags);
- }
-
- function rewind();
- {
- $this->hasChildren = false;
- $this->getChildren = NULL;
- parent::rewind();
- }
-
- function next()
- {
- if ($this->hasChildren = $this->it->hasChildren()) {
- try {
- //$this->getChildren = new CachingRecursiveIterator($this->it->getChildren(), $this->flags);
- // workaround memleaks...
- $child = $this->it->getChildren();
- $this->getChildren = new CachingRecursiveIterator($child, $this->flags);
- }
- catch(Exception $e) {
- if (!$this->flags & CIT_CATCH_GET_CHILD) {
- throw $e;
- }
- $this->hasChildren = false;
- $this->getChildren = NULL;
- }
- } else {
- $this->getChildren = NULL;
- }
- parent::next();
- }
-
- function hasChildren()
- {
- return $this->hasChildren;
- }
-
- function getChildren()
- {
- return $this->getChildren;
- }
-}
-
-?>
\ No newline at end of file diff --git a/ext/spl/internal/emptyiterator.inc b/ext/spl/internal/emptyiterator.inc new file mode 100755 index 000000000..a72a8b1a4 --- /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 - 2005
+ *
+ * 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 index 051c99e75..ddf161355 100755 --- a/ext/spl/internal/filteriterator.inc +++ b/ext/spl/internal/filteriterator.inc @@ -1,17 +1,31 @@ <?php
+/** @file filteriterator.inc + * @ingroup SPL + * @brief class FilterIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * SPL - Standard PHP Library + */ + /**
* @brief Regular expression filter for string iterators
* @author Marcus Boerger
- * @version 1.0
+ * @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 Iterator
+abstract class FilterIterator implements OuterIterator
{
- protected $it;
+ private $it;
/**
* Constructs a filter around an iterator whose elemnts are strings.
@@ -92,6 +106,24 @@ abstract class FilterIterator implements Iterator 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 100755 index 000000000..2dbe8d865 --- /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 - 2005
+ *
+ * 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 100755 index 000000000..c76412ed0 --- /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 - 2005
+ *
+ * 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 IteratorItaerator 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->it, $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;
+}
+
+?>
\ No newline at end of file diff --git a/ext/spl/internal/limititerator.inc b/ext/spl/internal/limititerator.inc index 3283f39db..b87f3c586 100755 --- a/ext/spl/internal/limititerator.inc +++ b/ext/spl/internal/limititerator.inc @@ -1,13 +1,39 @@ <?php
-class LimitIterator implements Iterator
+/** @file limititerator.inc + * @ingroup SPL + * @brief class LimitIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * 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
{
- protected $it;
- protected $offset;
- protected $count;
+ private $it;
+ private $offset;
+ private $count;
private $pos;
- // count === NULL means all
+ /** Construct
+ *
+ * @param it Iterator to limit
+ * @param offset Offset to first element
+ * @param count Maximum number of elements to show or NULL for all
+ */
function __construct(Iterator $it, $offset = 0, $count = -1)
{
if ($offset < 0) {
@@ -22,6 +48,11 @@ class LimitIterator implements Iterator $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);
@@ -39,6 +70,8 @@ class LimitIterator implements Iterator }
}
+ /** Rewind to offset specified in constructor
+ */
function rewind()
{
$this->it->rewind();
@@ -46,27 +79,56 @@ class LimitIterator implements Iterator $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/norewinditerator.inc b/ext/spl/internal/norewinditerator.inc new file mode 100755 index 000000000..296fe2b92 --- /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 - 2005
+ *
+ * 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 100755 index 000000000..d3068f029 --- /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 - 2005 + * + * 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 index 782d10343..9e0ebfa25 100755 --- a/ext/spl/internal/parentiterator.inc +++ b/ext/spl/internal/parentiterator.inc @@ -1,21 +1,42 @@ <?php
-class ParentIterator extends FilterIterator implements RecursiveIterator
+/** @file parentiterator.inc + * @ingroup SPL + * @brief class FilterIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * 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
{
+ /** @param $it the RecursiveIterator to filter
+ */
function __construct(RecursiveIterator $it)
{
parent::__construct($it);
}
+
+ /** @return whetehr the current element has children
+ */
function accept()
{
return $this->it->hasChildren();
}
- function hasChildren()
- {
- return $this->it->hasChildren();
- }
-
+ /** @return the ParentIterator for the current elements children
+ */
function getChildren()
{
return new ParentIterator($this->it->getChildren());
diff --git a/ext/spl/internal/recursivearrayiterator.inc b/ext/spl/internal/recursivearrayiterator.inc new file mode 100755 index 000000000..833a65686 --- /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 - 2005
+ *
+ * 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 100755 index 000000000..327514687 --- /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 - 2005 + * + * 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 100755 index 000000000..0e17845e1 --- /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 - 2005
+ *
+ * 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 index 715f6b06a..063fc905c 100755 --- a/ext/spl/internal/recursiveiterator.inc +++ b/ext/spl/internal/recursiveiterator.inc @@ -1,8 +1,29 @@ <?php
+/** @file recursiveiterator.inc + * @ingroup SPL + * @brief class RecursiveIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * SPL - Standard PHP Library + */ + +/**
+ * @brief Interface for recursive iteration with RecursiveIteratorIterator
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.0
+ */
interface RecursiveIterator implements 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();
}
diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc index ad1ba7a29..ba32e4ee9 100755 --- a/ext/spl/internal/recursiveiteratoriterator.inc +++ b/ext/spl/internal/recursiveiteratoriterator.inc @@ -1,31 +1,77 @@ <?php
+/** @file recursiveiteratoriterator.inc
+ * @ingroup SPL
+ * @brief class RecursiveIteratorIterator
+ * @author Marcus Boerger
+ * @date 2003 - 2005
+ *
+ * SPL - Standard PHP Library
+ */
+
/**
* @brief Iterates through recursive iterators
* @author Marcus Boerger
- * @version 1.0
+ * @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 Iterator
+class RecursiveIteratorIterator implements OuterIterator
{
- protected $ait = array();
- protected $count = 0;
+ /** 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;
- function __construct(RecursiveIterator $it)
+ 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;
@@ -35,37 +81,57 @@ class RecursiveIteratorIterator implements Iterator 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 && $it->hasChildren()) {
+ if (!$it->recursed && callHasChildren()) {
$it->recursed = true;
- $sub = $it->getChildren();
+ 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);
@@ -80,10 +146,16 @@ class RecursiveIteratorIterator implements Iterator 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)) {
@@ -92,10 +164,72 @@ class RecursiveIteratorIterator implements Iterator 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/seekableiterator.inc b/ext/spl/internal/seekableiterator.inc index 5f6b36c28..af66c60c3 100755 --- a/ext/spl/internal/seekableiterator.inc +++ b/ext/spl/internal/seekableiterator.inc @@ -1,6 +1,18 @@ <?php
-/** \brief seekable iterator
+/** @file seekableiterator.inc + * @ingroup SPL + * @brief class SeekableIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * 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
@@ -13,17 +25,24 @@ interface SeekableIterator implements Iterator * \param $index position to seek to
* \return void
*
- * \note The method should throw an exception if it is not possible to
- * seek to the given position.
- */
+ * 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();
+ $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/splfileobject.inc b/ext/spl/internal/splfileobject.inc new file mode 100755 index 000000000..bb1a23929 --- /dev/null +++ b/ext/spl/internal/splfileobject.inc @@ -0,0 +1,353 @@ +<?php
+
+/** @file splfileobject.inc
+ * @ingroup SPL
+ * @brief class FileObject
+ * @author Marcus Boerger
+ * @date 2003 - 2005
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup SPL
+ * @brief Object representation for any stream
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 5.1
+ */
+class SplFileObject 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;
+
+ /**
+ * 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 the filename as specified in the constructor
+ */
+ function getFilename()
+ {
+ return $this->fname;
+ }
+
+ /**
+ * @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 = ';', $enclosure = '')
+ {
+ $this->freeLine();
+ $this->lnum++;
+ return fgetcsv($this->fp, $this->max_len, $delimiter, $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 100755 index 000000000..b01a85096 --- /dev/null +++ b/ext/spl/internal/splobjectstorage.inc @@ -0,0 +1,118 @@ +<?php
+
+/** @file splobjectstorage.inc + * @ingroup SPL + * @brief class SplObjectStorage + * @author Marcus Boerger + * @date 2003 - 2005 + * + * SPL - Standard PHP Library + */ + +/**
+ * @brief Object storage
+ * @author Marcus Boerger
+ * @version 1.0
+ * @since PHP 6.0
+ *
+ * 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
+{
+ 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()
+ {
+ return current($this->storage);
+ }
+
+ /** 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 $object)
+ {
+ if ($object === $obj)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /** @param $obj new object to attach to storage if not yet contained
+ */
+ function attach($obj)
+ {
+ if (is_object($obj) && !$this->contains($obj))
+ {
+ $this->storage[] = $obj;
+ }
+ }
+
+ /** @param $obj object to remove from storage
+ */
+ function detach($obj)
+ {
+ if (is_object($obj))
+ {
+ foreach($this->storage as $idx => $object)
+ {
+ if ($object === $obj)
+ {
+ unset($this->storage[$idx]);
+ $this->rewind();
+ return;
+ }
+ }
+ }
+ }
+}
+
+?>
\ No newline at end of file |
