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