]> granicus.if.org Git - php/commitdiff
- MFH DualIterator
authorMarcus Boerger <helly@php.net>
Sun, 9 Jul 2006 10:24:32 +0000 (10:24 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 9 Jul 2006 10:24:32 +0000 (10:24 +0000)
ext/spl/examples/dualiterator.inc [new file with mode: 0755]
ext/spl/examples/recursivedualiterator.inc [new file with mode: 0755]
ext/spl/examples/tests/dualiterator_001.phpt [new file with mode: 0755]

diff --git a/ext/spl/examples/dualiterator.inc b/ext/spl/examples/dualiterator.inc
new file mode 100755 (executable)
index 0000000..dae381f
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+
+/** @file DualIterator.inc
+ * @ingroup Examples
+ * @brief class DualIterator
+ * @author  Marcus Boerger
+ * @date    2003 - 2006
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup Examples
+ * @brief   Synchronous iteration over two iterators
+ * @author  Marcus Boerger
+ * @version 1.1
+ */
+class DualIterator implements Iterator
+{
+       const CURRENT_LHS   = 0x01;
+       const CURRENT_RHS   = 0x02;
+       const CURRENT_ARRAY = 0x03;
+       const CURRENT_0     = 0x00;
+
+       const KEY_LHS   = 0x10;
+       const KEY_RHS   = 0x20;
+       const KEY_ARRAY = 0x30;
+       const KEY_0     = 0x00;
+       
+       const DEFAULT_FLAGS = 0x33;
+       
+       private $lhs;
+       private $rhs;
+       private $flags;
+
+       /** construct iterator from two iterators
+        *
+        * @param lhs   Left  Hand Side Iterator
+        * @param rhs   Right Hand Side Iterator
+        * @param flags iteration flags
+        */
+       function __construct(Iterator $lhs, Iterator $rhs, 
+                                       $flags = 0x33 /*DualIterator::DEFAULT_FLAGS*/)
+       {
+               $this->lhs   = $lhs;
+               $this->rhs   = $rhs;
+               $this->flags = $flags;
+       }
+
+       /** @return Left Hand Side Iterator
+        */
+       function getLHS()
+       {
+               return $this->lhs;
+       }
+
+       /** @return Right Hand Side Iterator
+        */
+       function getRHS()
+       {
+               return $this->rhs;
+       }
+
+       /** @param flags new flags
+        */
+       function setFlags($flags)
+       {
+               $this->flags = $flags;
+       }
+
+       /** @return current flags
+        */
+       function getFlags()
+       {
+               return $this->flags;
+       }
+
+       /** rewind both inner iterators
+        */     
+       function rewind()
+       {
+               $this->lhs->rewind();
+               $this->rhs->rewind();   
+       }
+
+       /** @return whether both inner iterators are valid
+        */     
+       function valid()
+       {
+               return $this->lhs->valid() && $this->rhs->valid();      
+       }
+
+       /** @return current value depending on CURRENT_* flags
+        */     
+       function current()
+       {
+               switch($this->flags & 0x0F)
+               {
+               default:
+               case self::CURRENT_ARRAY:
+                       return array($this->lhs->current(), $this->rhs->current());
+               case self::CURRENT_LHS:
+                       return $this->lhs->current();
+               case self::CURRENT_RHS:
+                       return $this->rhs->current();
+               case self::CURRENT_0:
+                       return NULL;
+               }
+       }
+
+       /** @return current value depending on KEY_* flags
+        */     
+       function key()
+       {
+               switch($this->flags & 0xF0)
+               {
+               default:
+               case self::CURRENT_ARRAY:
+                       return array($this->lhs->key(), $this->rhs->key());
+               case self::CURRENT_LHS:
+                       return $this->lhs->key();
+               case self::CURRENT_RHS:
+                       return $this->rhs->key();
+               case self::CURRENT_0:
+                       return NULL;
+               }
+       }
+
+       /** move both inner iterators forward
+        */     
+       function next()
+       {
+               $this->lhs->next();
+               $this->rhs->next();
+       }
+
+       /** @return whether both inner iterators are valid and have identical 
+        * current and key values or both are non valid.
+        */
+       function areIdentical()
+       {
+               return $this->valid()
+                    ? $this->lhs->current() === $this->rhs->current()
+                       && $this->lhs->key()     === $this->rhs->key()
+                        : $this->lhs->valid()   ==  $this->rhs->valid();
+       }
+
+       /** @return whether both inner iterators are valid and have equal current 
+        * and key values or both are non valid.
+        */
+       function areEqual()
+       {
+               return $this->valid()
+                    ? $this->lhs->current() ==  $this->rhs->current()
+                       && $this->lhs->key()     ==  $this->rhs->key()
+                        : $this->lhs->valid()   ==  $this->rhs->valid();
+       }
+
+       /** Compare two iterators
+        *
+        * @param lhs   Left  Hand Side Iterator
+        * @param rhs   Right Hand Side Iterator
+        * @param identical whether to use areEqual() or areIdentical()
+        * @return whether both iterators are equal/identical
+        *
+        * @note If one implements RecursiveIterator the other must do as well.
+        *       And if both do then a recursive comparison is being used.
+        */
+       static function compareIterators(Iterator $lhs, Iterator $rhs, 
+                                        $identical = false)
+       {
+               if ($lhs instanceof RecursiveIterator)
+               {
+                       if ($rhs instanceof RecursiveIterator)
+                       {
+                               $it = new RecursiveDualIterator($lhs, $rhs, 
+                                                               self::CURRENT_0 | self::KEY_0);
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+               else
+               {
+                       $it = new DualIterator($lhs, $rhs, self::CURRENT_0 | self::KEY_0);
+               }
+
+               if ($identical)
+               {
+                       foreach(new RecursiveIteratorIterator($it) as $n)
+                       {
+                               if (!$it->areIdentical())
+                               {
+                                       return false;
+                               }
+                       }
+               }
+               else
+               {
+                       foreach($it as $n)
+                       {
+                               if (!$it->areEqual())
+                               {
+                                       return false;
+                               }
+                       }
+               }
+               return $identical ? $it->areIdentical() : $it->areEqual();
+       }
+}
+
+?>
diff --git a/ext/spl/examples/recursivedualiterator.inc b/ext/spl/examples/recursivedualiterator.inc
new file mode 100755 (executable)
index 0000000..702e0cd
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+/** @file recursivedualiterator.inc
+ * @ingroup Examples
+ * @brief class RecursiveDualIterator
+ * @author  Marcus Boerger
+ * @date    2003 - 2006
+ *
+ * SPL - Standard PHP Library
+ */
+
+/** @ingroup Examples
+ * @brief   Synchronous iteration over two recursive iterators
+ * @author  Marcus Boerger
+ * @version 1.0
+ */
+class RecursiveDualIterator extends DualIterator implements RecursiveIterator
+{
+       private $ref;
+
+       /** construct iterator from two iterators
+        *
+        * @param lhs   Left  Hand Side Iterator
+        * @param rhs   Right Hand Side Iterator
+        * @param flags iteration flags
+        */
+       function __construct(RecursiveIterator $lhs, RecursiveIterator $rhs, 
+                               $flags = 0x33 /*DualIterator::DEFAULT_FLAGS*/)
+       {
+               parent::__construct($lhs, $rhs, $flags);
+       }
+
+       /** @return whether both LHS and RHS have children
+        */
+       function hasChildren()
+       {
+               return $this->getLHS()->hasChildren() && $this->getRHS()->hasChildren();        
+       }
+
+       /** @return new RecursiveDualIterator (late binding) for the two inner 
+        * iterators current children.
+        */
+       function getChildren()
+       {
+               if (empty($this->ref))
+               {
+                       $this->ref = new ReflectionClass($this);
+               }
+               return $this->ref->newInstance(
+                                       $this->getLHS()->getChildren(), $this->getRHS()->getChildren(), $this->getFlags());
+       }
+
+       /** @return whether both inner iterators are valid, have same hasChildren()
+        * state and identical current and key values or both are non valid.
+        */
+       function areIdentical()
+       {
+               return $this->getLHS()->hasChildren() === $this->getRHS()->hasChildren()
+                       && parent::areIdentical();
+       }
+
+       /** @return whether both inner iterators are valid, have same hasChildren()
+        * state and equal current and key values or both are invalid.
+        */
+       function areEqual()
+       {
+               return $this->getLHS()->hasChildren() === $this->getRHS()->hasChildren()
+                       && parent::areEqual();
+       }
+}
+
+?>
diff --git a/ext/spl/examples/tests/dualiterator_001.phpt b/ext/spl/examples/tests/dualiterator_001.phpt
new file mode 100755 (executable)
index 0000000..5577c4d
--- /dev/null
@@ -0,0 +1,47 @@
+--TEST--
+SPL: DualIterator
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+function spl_examples_autoload($classname)
+{
+       include(dirname(__FILE__) . '/../' . strtolower($classname) . '.inc');
+}
+
+spl_autoload_register('spl_examples_autoload');
+
+function test($a, $b, $identical = false)
+{
+       var_dump(DualIterator::compareIterators(
+                                       new RecursiveArrayIterator($a), 
+                                       new RecursiveArrayIterator($b), 
+                                       $identical));
+}
+
+test(array(1,2,3), array(1,2,3));
+test(array(1,2,3), array(1,2));
+test(array(1,array(21,22),3), array(1,array(21,22),3));
+test(array(1,array(21,22),3), array(1,array(21,22,23),3));
+test(array(1,array(21,22),3), array(1,array(21,22,3)));
+test(array(1,array(21,22),3), array(1,array(21),array(22),3));
+test(array(1,2,3), array(1,"2",3), false);
+test(array(1,2,3), array(1,"2",3), true);
+test(array(1,array(21,22),3), array(1,array(21,"22"),3), false);
+test(array(1,array(21,22),3), array(1,array(21,"22"),3), true);
+
+?>
+===DONE===
+--EXPECT--
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+===DONE===