diff options
author | Marcus Boerger <helly@php.net> | 2005-09-15 03:38:03 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2005-09-15 03:38:03 +0000 |
commit | a29501195f4d0fff6023ed53fc19bfb90d7a0151 (patch) | |
tree | dd36643d00206a3bd2fb227f035c18075d87171c /ext | |
parent | b4dd030782ae49646cdefa8435e6c8acbbf17745 (diff) | |
download | php-git-a29501195f4d0fff6023ed53fc19bfb90d7a0151.tar.gz |
- MFH: Add new files
Diffstat (limited to 'ext')
-rwxr-xr-x | ext/spl/examples/recursivearrayiterator.inc | 55 | ||||
-rwxr-xr-x | ext/spl/internal/recursivefilteriterator.inc | 62 | ||||
-rwxr-xr-x | ext/spl/internal/splobjectstorage.inc | 118 | ||||
-rwxr-xr-x | ext/spl/tests/observer_002.phpt | 199 |
4 files changed, 434 insertions, 0 deletions
diff --git a/ext/spl/examples/recursivearrayiterator.inc b/ext/spl/examples/recursivearrayiterator.inc new file mode 100755 index 0000000000..305e54cad9 --- /dev/null +++ b/ext/spl/examples/recursivearrayiterator.inc @@ -0,0 +1,55 @@ +<?php + +/** @file recursivearrayiterator.inc + * @ingroup Examples + * @brief class RecursiveArrayIterator + * @author Marcus Boerger + * @date 2003 - 2005 + * + * SPL - Standard PHP Library + */ + +/** @ingroup Examples + * @brief A recursive array iterator + * @author Marcus Boerger + * @version 1.0 + * @since PHP 6.0 + * + * 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 (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/recursivefilteriterator.inc b/ext/spl/internal/recursivefilteriterator.inc new file mode 100755 index 0000000000..b651fb20ea --- /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/splobjectstorage.inc b/ext/spl/internal/splobjectstorage.inc new file mode 100755 index 0000000000..56690f499b --- /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 diff --git a/ext/spl/tests/observer_002.phpt b/ext/spl/tests/observer_002.phpt new file mode 100755 index 0000000000..5d006177f2 --- /dev/null +++ b/ext/spl/tests/observer_002.phpt @@ -0,0 +1,199 @@ +--TEST-- +SPL: SplObjectStorage +--FILE-- +<?php + +class MyObjectStorage extends SplObjectStorage +{ + function rewind() + { + echo __METHOD__ . "()\n"; + parent::rewind(); + } + + function valid() + { + echo __METHOD__ . "(" . (parent::valid() ? 1 : 0) . ")\n"; + return parent::valid(); + } + + function key() + { + echo __METHOD__ . "(" . parent::key() . ")\n"; + return parent::key(); + } + + function current() + { + echo __METHOD__ . "(" . parent::current()->getName() . ")\n"; + return parent::current(); + } + + function next() + { + echo __METHOD__ . "()\n"; + parent::next(); + } +} + +class ObserverImpl implements SplObserver +{ + protected $name = ''; + + function __construct($name = 'obj') + { + $this->name = '$' . $name; + } + + function update(SplSubject $subject) + { + echo $this->name . '->' . __METHOD__ . '(' . $subject->getName() . ");\n"; + } + + function getName() + { + return $this->name; + } +} + +class SubjectImpl implements SplSubject +{ + protected $name = ''; + protected $observers; + + function __construct($name = 'sub') + { + $this->observers = new MyObjectStorage; + $this->name = '$' . $name; + } + + function attach(SplObserver $observer) + { + echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n"; + $this->observers->attach($observer); + } + + function detach(SplObserver $observer) + { + echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n"; + $this->observers->detach($observer); + } + + function count() + { + return $this->observers->count(); + } + + function notify() + { + echo $this->name . '->' . __METHOD__ . "();\n"; + foreach($this->observers as $key => $observer) + { + $observer->update($this); + } + } + + function getName() + { + return $this->name; + } + + function contains($obj) + { + return $this->observers->contains($obj); + } +} + +$sub = new SubjectImpl; + +$ob1 = new ObserverImpl("ob1"); +$ob2 = new ObserverImpl("ob2"); +$ob3 = new ObserverImpl("ob3"); + +var_dump($sub->contains($ob1)); +$sub->attach($ob1); +var_dump($sub->contains($ob1)); +$sub->attach($ob1); +$sub->attach($ob2); +$sub->attach($ob3); +var_dump($sub->count()); + +$sub->notify(); + +$sub->detach($ob3); +var_dump($sub->count()); + +$sub->notify(); + +$sub->detach($ob2); +$sub->detach($ob1); +var_dump($sub->count()); + +$sub->notify(); + +$sub->attach($ob3); +var_dump($sub->count()); + +$sub->notify(); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECT-- +bool(false) +$sub->SubjectImpl::attach($ob1); +bool(true) +$sub->SubjectImpl::attach($ob1); +$sub->SubjectImpl::attach($ob2); +$sub->SubjectImpl::attach($ob3); +int(3) +$sub->SubjectImpl::notify(); +MyObjectStorage::rewind() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob1) +MyObjectStorage::key(0) +$ob1->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob2) +MyObjectStorage::key(1) +$ob2->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob3) +MyObjectStorage::key(2) +$ob3->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(0) +$sub->SubjectImpl::detach($ob3); +int(2) +$sub->SubjectImpl::notify(); +MyObjectStorage::rewind() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob1) +MyObjectStorage::key(0) +$ob1->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob2) +MyObjectStorage::key(1) +$ob2->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(0) +$sub->SubjectImpl::detach($ob2); +$sub->SubjectImpl::detach($ob1); +int(0) +$sub->SubjectImpl::notify(); +MyObjectStorage::rewind() +MyObjectStorage::valid(0) +$sub->SubjectImpl::attach($ob3); +int(1) +$sub->SubjectImpl::notify(); +MyObjectStorage::rewind() +MyObjectStorage::valid(1) +MyObjectStorage::current($ob3) +MyObjectStorage::key(0) +$ob3->ObserverImpl::update($sub); +MyObjectStorage::next() +MyObjectStorage::valid(0) +===DONE=== |