dualiterator.inc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /** @file dualiterator.inc
  3. * @ingroup Examples
  4. * @brief class DualIterator
  5. * @author Marcus Boerger
  6. * @date 2003 - 2006
  7. *
  8. * SPL - Standard PHP Library
  9. */
  10. /** @ingroup Examples
  11. * @brief Synchronous iteration over two iterators
  12. * @author Marcus Boerger
  13. * @version 1.3
  14. */
  15. class DualIterator implements Iterator
  16. {
  17. const CURRENT_LHS = 0x01;
  18. const CURRENT_RHS = 0x02;
  19. const CURRENT_ARRAY = 0x03;
  20. const CURRENT_0 = 0x00;
  21. const KEY_LHS = 0x10;
  22. const KEY_RHS = 0x20;
  23. const KEY_0 = 0x00;
  24. const DEFAULT_FLAGS = 0x13;
  25. private $lhs;
  26. private $rhs;
  27. private $flags;
  28. /** construct iterator from two iterators
  29. *
  30. * @param lhs Left Hand Side Iterator
  31. * @param rhs Right Hand Side Iterator
  32. * @param flags iteration flags
  33. */
  34. function __construct(Iterator $lhs, Iterator $rhs,
  35. $flags = 0x13 /*DualIterator::DEFAULT_FLAGS*/)
  36. {
  37. $this->lhs = $lhs;
  38. $this->rhs = $rhs;
  39. $this->flags = $flags;
  40. }
  41. /** @return Left Hand Side Iterator
  42. */
  43. function getLHS()
  44. {
  45. return $this->lhs;
  46. }
  47. /** @return Right Hand Side Iterator
  48. */
  49. function getRHS()
  50. {
  51. return $this->rhs;
  52. }
  53. /** @param flags new flags
  54. */
  55. function setFlags($flags)
  56. {
  57. $this->flags = $flags;
  58. }
  59. /** @return current flags
  60. */
  61. function getFlags()
  62. {
  63. return $this->flags;
  64. }
  65. /** rewind both inner iterators
  66. */
  67. function rewind(): void
  68. {
  69. $this->lhs->rewind();
  70. $this->rhs->rewind();
  71. }
  72. /** @return whether both inner iterators are valid
  73. */
  74. function valid(): bool
  75. {
  76. return $this->lhs->valid() && $this->rhs->valid();
  77. }
  78. /** @return current value depending on CURRENT_* flags
  79. */
  80. function current(): mixed
  81. {
  82. switch($this->flags & 0x0F)
  83. {
  84. default:
  85. case self::CURRENT_ARRAY:
  86. return array($this->lhs->current(), $this->rhs->current());
  87. case self::CURRENT_LHS:
  88. return $this->lhs->current();
  89. case self::CURRENT_RHS:
  90. return $this->rhs->current();
  91. case self::CURRENT_0:
  92. return NULL;
  93. }
  94. }
  95. /** @return key value depending on KEY_* flags
  96. */
  97. function key(): mixed
  98. {
  99. switch($this->flags & 0xF0)
  100. {
  101. default:
  102. case self::KEY_LHS:
  103. return $this->lhs->key();
  104. case self::KEY_RHS:
  105. return $this->rhs->key();
  106. case self::KEY_0:
  107. return NULL;
  108. }
  109. }
  110. /** move both inner iterators forward
  111. */
  112. function next(): void
  113. {
  114. $this->lhs->next();
  115. $this->rhs->next();
  116. }
  117. /** @return whether both inner iterators are valid and have identical
  118. * current and key values or both are non valid.
  119. */
  120. function areIdentical()
  121. {
  122. return $this->valid()
  123. ? $this->lhs->current() === $this->rhs->current()
  124. && $this->lhs->key() === $this->rhs->key()
  125. : $this->lhs->valid() == $this->rhs->valid();
  126. }
  127. /** @return whether both inner iterators are valid and have equal current
  128. * and key values or both are non valid.
  129. */
  130. function areEqual()
  131. {
  132. return $this->valid()
  133. ? $this->lhs->current() == $this->rhs->current()
  134. && $this->lhs->key() == $this->rhs->key()
  135. : $this->lhs->valid() == $this->rhs->valid();
  136. }
  137. /** Compare two iterators
  138. *
  139. * @param lhs Left Hand Side Iterator
  140. * @param rhs Right Hand Side Iterator
  141. * @param identical whether to use areEqual() or areIdentical()
  142. * @return whether both iterators are equal/identical
  143. *
  144. * @note If one implements RecursiveIterator the other must do as well.
  145. * And if both do then a recursive comparison is being used.
  146. */
  147. static function compareIterators(Iterator $lhs, Iterator $rhs,
  148. $identical = false)
  149. {
  150. if ($lhs instanceof RecursiveIterator)
  151. {
  152. if ($rhs instanceof RecursiveIterator)
  153. {
  154. $it = new RecursiveDualIterator($lhs, $rhs,
  155. self::CURRENT_0 | self::KEY_0);
  156. $it = new RecursiveCompareDualIterator($it);
  157. }
  158. else
  159. {
  160. return false;
  161. }
  162. }
  163. else
  164. {
  165. $it = new DualIterator($lhs, $rhs, self::CURRENT_0 | self::KEY_0);
  166. }
  167. if ($identical)
  168. {
  169. foreach($it as $n)
  170. {
  171. if (!$it->areIdentical())
  172. {
  173. return false;
  174. }
  175. }
  176. }
  177. else
  178. {
  179. foreach($it as $n)
  180. {
  181. if (!$it->areEqual())
  182. {
  183. return false;
  184. }
  185. }
  186. }
  187. return $identical ? $it->areIdentical() : $it->areEqual();
  188. }
  189. }
  190. ?>