Annotation of embedaddon/php/ext/spl/internal/spldoublylinkedlist.inc, revision 1.1.1.1
1.1 misho 1: <?php
2: /** @file spldoublylinkedlist.inc
3: * @ingroup SPL
4: * @brief class SplDoublyLinkedList
5: * @author Etienne Kneuss
6: * @date 2008 - 2009
7: *
8: * SPL - Standard PHP Library
9: */
10:
11: /** @ingroup SPL
12: * @brief Doubly Linked List
13: * @since PHP 5.3
14: *
15: * The SplDoublyLinkedList class provides the main functionalities of a
16: * doubly linked list (DLL).
17: * @note The following userland implementation of Iterator is a bit different
18: * from the internal one. Internally, iterators generated by nested
19: * foreachs are independent, while they share the same traverse pointer
20: * in userland.
21: */
22: class SplDoublyLinkedList implements Iterator, ArrayAccess, Countable
23: {
24: protected $_llist = array();
25: protected $_it_mode = 0;
26: protected $_it_pos = 0;
27:
28: /** Iterator mode
29: * @see setIteratorMode
30: */
31: const IT_MODE_LIFO = 0x00000002;
32:
33: /** Iterator mode
34: * @see setIteratorMode
35: */
36: const IT_MODE_FIFO = 0x00000000;
37:
38: /** Iterator mode
39: * @see setIteratorMode
40: */
41: const IT_MODE_KEEP = 0x00000000;
42:
43: /** Iterator mode
44: * @see setIteratorMode
45: */
46: const IT_MODE_DELETE = 0x00000001;
47:
48: /** @return the element popped from the end of the DLL.
49: * @throw RuntimeException If the datastructure is empty.
50: */
51: public function pop()
52: {
53: if (count($this->_llist) == 0) {
54: throw new RuntimeException("Can't pop from an empty datastructure");
55: }
56: return array_pop($this->_llist);
57: }
58:
59: /** @return the element shifted from the beginning of the DLL.
60: * @throw RuntimeException If the datastructure is empty.
61: */
62: public function shift()
63: {
64: if (count($this->_llist) == 0) {
65: throw new RuntimeException("Can't shift from an empty datastructure");
66: }
67: return array_shift($this->_llist);
68: }
69:
70: /** Pushes an element to the end of the DLL.
71: * @param $data variable to add to the DLL.
72: */
73: public function push($data)
74: {
75: array_push($this->_llist, $data);
76: return true;
77: }
78:
79: /** Adds an element to the beginning of the DLL.
80: * @param $data variable to add to the DLL.
81: */
82: public function unshift($data)
83: {
84: array_unshift($this->_llist, $data);
85: return true;
86: }
87:
88: /** @return the element at the beginning of the DLL.
89: */
90: public function top()
91: {
92: return end($this->_llist);
93: }
94:
95: /** @return the element at the end of the DLL.
96: */
97: public function bottom()
98: {
99: return reset($this->_llist);
100: }
101:
102: /** @return number elements in the DLL.
103: */
104: public function count()
105: {
106: return count($this->_llist);
107: }
108:
109: /** @return whether the DLL is empty.
110: */
111: public function isEmpty()
112: {
113: return ($this->count() == 0);
114: }
115:
116: /** Changes the iteration mode. There are two orthogonal sets of modes that
117: * can be set:
118: * - The direction of the iteration (either one or the other)
119: * - SplDoublyLnkedList::IT_MODE_LIFO (Stack style)
120: * - SplDoublyLnkedList::IT_MODE_FIFO (Queue style)
121: *
122: * - The behavior of the iterator (either one or the other)
123: * - SplDoublyLnkedList::IT_MODE_DELETE (Elements are deleted by the iterator)
124: * - SplDoublyLnkedList::IT_MODE_KEEP (Elements are traversed by the iterator)
125: *
126: * The default mode is 0 : SplDoublyLnkedList::IT_MODE_FIFO | SplDoublyLnkedList::IT_MODE_KEEP
127: *
128: * @param $mode new mode of iteration
129: */
130: public function setIteratorMode($mode)
131: {
132: $this->_it_mode = $mode;
133: }
134:
135: /** @return the current iteration mode
136: * @see setIteratorMode
137: */
138: public function getIteratorMode()
139: {
140: return $this->_it_mode;
141: }
142:
143: /** Rewind to top iterator as set in constructor
144: */
145: public function rewind()
146: {
147: if ($this->_it_mode & self::IT_MODE_LIFO) {
148: $this->_it_pos = count($this->_llist)-1;
149: } else {
150: $this->_it_pos = 0;
151: }
152: }
153:
154: /** @return whether iterator is valid
155: */
156: public function valid()
157: {
158: return array_key_exists($this->_it_pos, $this->_llist);
159: }
160:
161: /** @return current key
162: */
163: public function key()
164: {
165: return $this->_it_pos;
166: }
167:
168: /** @return current object
169: */
170: public function current()
171: {
172: return $this->_llist[$this->_it_pos];
173: }
174:
175: /** Forward to next element
176: */
177: public function next()
178: {
179: if ($this->_it_mode & self::IT_MODE_LIFO) {
180: if ($this->_it_mode & self::IT_MODE_DELETE) {
181: $this->pop();
182: }
183: $this->_it_pos--;
184: } else {
185: if ($this->_it_mode & self::IT_MODE_DELETE) {
186: $this->shift();
187: } else {
188: $this->_it_pos++;
189: }
190: }
191: }
192:
193: /** @return whether a certain offset exists in the DLL
194: *
195: * @param $offset The offset
196: * @throw OutOfRangeException If the offset is either invalid or out of
197: * range.
198: */
199: public function offsetExists($offset)
200: {
201: if (!is_numeric($offset)) {
202: throw new OutOfRangeException("Offset invalid or out of range");
203: } else {
204: return array_key_exists($offset, $this->_llist);
205: }
206: }
207:
208: /** @return the data at a certain offset in the DLL
209: *
210: * @param $offset The offset
211: * @throw OutOfRangeException If the offset is either invalid or out of
212: * range.
213: */
214: public function offsetGet($offset)
215: {
216: if ($this->_it_mode & self::IT_MODE_LIFO) {
217: $realOffset = count($this->_llist)-$offset;
218: } else {
219: $realOffset = $offset;
220: }
221:
222: if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
223: throw new OutOfRangeException("Offset invalid or out of range");
224: } else {
225: return $this->_llist[$realOffset];
226: }
227: }
228:
229: /** Defines the data at a certain offset in the DLL
230: *
231: * @param $offset The offset
232: * @param $value New value
233: * @throw OutOfRangeException If the offset is either invalid or out of
234: * range.
235: */
236: public function offsetSet($offset, $value)
237: {
238: if ($offset === null) {
239: return $this->push($value);
240: }
241:
242: if ($this->_it_mode & self::IT_MODE_LIFO) {
243: $realOffset = count($this->_llist)-$offset;
244: } else {
245: $realOffset = $offset;
246: }
247:
248: if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
249: throw new OutOfRangeException("Offset invalid or out of range");
250: } else {
251: $this->_llist[$realOffset] = $value;
252: }
253: }
254:
255: /** Unsets the element at a certain offset in the DLL
256: *
257: * @param $offset The offset
258: * @throw OutOfRangeException If the offset is either invalid or out of
259: * range.
260: */
261: public function offsetUnset($offset)
262: {
263: if ($this->_it_mode & self::IT_MODE_LIFO) {
264: $realOffset = count($this->_llist)-$offset;
265: } else {
266: $realOffset = $offset;
267: }
268:
269: if (!is_numeric($offset) || !array_key_exists($realOffset, $this->_llist)) {
270: throw new OutOfRangeException("Offset invalid or out of range");
271: } else {
272: array_splice($this->_llist, $realOffset, 1);
273: }
274: }
275: }
276:
277: ?>
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>