OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.collection; | 5 part of dart.collection; |
6 | 6 |
7 /** | 7 /** |
8 * A [Queue] is a collection that can be manipulated at both ends. One | 8 * A [Queue] is a collection that can be manipulated at both ends. One |
9 * can iterate over the elements of a queue through [forEach] or with | 9 * can iterate over the elements of a queue through [forEach] or with |
10 * an [Iterator]. | 10 * an [Iterator]. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 */ | 89 */ |
90 void retainWhere(bool test(E element)); | 90 void retainWhere(bool test(E element)); |
91 | 91 |
92 /** | 92 /** |
93 * Removes all elements in the queue. The size of the queue becomes zero. | 93 * Removes all elements in the queue. The size of the queue becomes zero. |
94 */ | 94 */ |
95 void clear(); | 95 void clear(); |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 class _DoubleLink<E extends _DoubleLink> { | 99 class _DoubleLink<Link extends _DoubleLink> { |
100 E _previousLink; | 100 Link _previousLink; |
101 E _nextLink; | 101 Link _nextLink; |
102 | 102 |
103 void _link(E previous, E next) { | 103 void _link(Link previous, Link next) { |
104 _nextLink = next; | 104 _nextLink = next; |
105 _previousLink = previous; | 105 _previousLink = previous; |
106 if (previous != null) previous._nextLink = this; | 106 if (previous != null) previous._nextLink = this; |
107 if (next != null) next._previousLink = this; | 107 if (next != null) next._previousLink = this; |
108 } | 108 } |
109 | 109 |
110 void _unlink() { | 110 void _unlink() { |
111 if (_previousLink != null) _previousLink._nextLink = _nextLink; | 111 if (_previousLink != null) _previousLink._nextLink = _nextLink; |
112 if (_nextLink != null) _nextLink._previousLink = _previousLink; | 112 if (_nextLink != null) _nextLink._previousLink = _previousLink; |
113 _nextLink = null; | 113 _nextLink = null; |
114 _previousLink = null; | 114 _previousLink = null; |
115 } | 115 } |
116 } | 116 } |
117 | 117 |
118 /** | 118 /** |
119 * An entry in a doubly linked list. It contains a pointer to the next | 119 * An entry in a doubly linked list. It contains a pointer to the next |
120 * entry, the previous entry, and the boxed element. | 120 * entry, the previous entry, and the boxed element. |
121 */ | 121 */ |
122 abstract class DoubleLinkedQueueEntry<E> { | 122 class DoubleLinkedQueueEntry<E> extends _DoubleLink<DoubleLinkedQueueEntry<E>> { |
123 factory DoubleLinkedQueueEntry(E element) = _UserDoubleLinkedQueueEntry<E>; | 123 /// The element in the queue. |
| 124 E element; |
124 | 125 |
125 /// The element in the queue. | 126 DoubleLinkedQueueEntry(this.element); |
126 E get element; | |
127 | 127 |
128 /// Appends the given [e] as entry just after this entry. | 128 /// Appends the given [e] as entry just after this entry. |
129 void append(E e); | 129 void append(E e) { |
| 130 new DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink); |
| 131 } |
130 | 132 |
131 /// Prepends the given [e] as entry just before this entry. | 133 /// Prepends the given [e] as entry just before this entry. |
132 void prepend(E e); | |
133 | |
134 /// Returns the previous entry or `null` if there is none. | |
135 DoubleLinkedQueueEntry<E> previousEntry(); | |
136 | |
137 /// Returns the next entry or `null` if there is none. | |
138 DoubleLinkedQueueEntry<E> nextEntry(); | |
139 } | |
140 | |
141 /// Default implementation of a doubly linked queue entry. | |
142 /// | |
143 /// This implementation is only used if a user instantiates a | |
144 /// [DoubleLinkedQueueEntry] directly. The internal implementations don't use | |
145 /// this class. | |
146 class _UserDoubleLinkedQueueEntry<E> | |
147 extends _DoubleLink<_UserDoubleLinkedQueueEntry<E>> | |
148 implements DoubleLinkedQueueEntry<E> { | |
149 E element; | |
150 | |
151 _UserDoubleLinkedQueueEntry(this.element); | |
152 | |
153 void append(E e) { | |
154 new _UserDoubleLinkedQueueEntry<E>(e)._link(this, _nextLink); | |
155 } | |
156 | |
157 void prepend(E e) { | 134 void prepend(E e) { |
158 new _UserDoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); | 135 new DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); |
159 } | 136 } |
160 | 137 |
161 E remove() { | 138 E remove() { |
162 _unlink(); | 139 _unlink(); |
163 return element; | 140 return element; |
164 } | 141 } |
165 | 142 |
| 143 /// Returns the previous entry or `null` if there is none. |
166 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink; | 144 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink; |
167 | 145 |
| 146 /// Returns the next entry or `null` if there is none. |
168 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink; | 147 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink; |
169 } | 148 } |
170 | 149 |
171 /** | 150 /** |
172 * Interface for the link classes used by [DoubleLinkedQueue]. | 151 * Interface for the link classes used by [DoubleLinkedQueue]. |
173 * | 152 * |
174 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] | 153 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] |
175 * implement this interface. | 154 * implement this interface. |
176 * The entry contains a link back to the queue, so calling `append` | 155 * The entry contains a link back to the queue, so calling `append` |
177 * or `prepend` can correctly update the element count. | 156 * or `prepend` can correctly update the element count. |
178 */ | 157 */ |
179 abstract class _DoubleLinkedQueueEntry<E> | 158 abstract class _DoubleLinkedQueueEntry<E> |
180 extends _DoubleLink<_DoubleLinkedQueueEntry<E>> { | 159 extends DoubleLinkedQueueEntry<E> { |
181 DoubleLinkedQueue<E> _queue; | 160 DoubleLinkedQueue<E> _queue; |
182 _DoubleLinkedQueueEntry(this._queue); | 161 _DoubleLinkedQueueEntry(E element, this._queue) : super(element); |
183 | 162 |
184 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); | 163 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); |
185 | 164 |
186 void _append(E e) { | 165 void _append(E e) { |
187 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); | 166 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); |
188 } | 167 } |
189 | 168 |
190 void _prepend(E e) { | 169 void _prepend(E e) { |
191 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); | 170 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); |
192 } | 171 } |
193 | 172 |
194 E _remove(); | 173 E _remove(); |
195 | 174 |
196 E get element; | 175 E get _element => element; |
197 | 176 |
198 DoubleLinkedQueueEntry<E> nextEntry() { | 177 DoubleLinkedQueueEntry<E> nextEntry() { |
199 return _nextLink._asNonSentinelEntry(); | 178 _DoubleLinkedQueueEntry<E> entry = |
| 179 _nextLink as dynamic/*=DoubleLinkedQueueEntry<E>*/; |
| 180 return entry._asNonSentinelEntry(); |
200 } | 181 } |
201 | 182 |
202 DoubleLinkedQueueEntry<E> previousEntry() { | 183 DoubleLinkedQueueEntry<E> previousEntry() { |
203 return _previousLink._asNonSentinelEntry(); | 184 _DoubleLinkedQueueEntry<E> entry = |
| 185 _previousLink as dynamic/*=DoubleLinkedQueueEntry<E>*/; |
| 186 return entry._asNonSentinelEntry(); |
204 } | 187 } |
205 } | 188 } |
206 | 189 |
207 /** | 190 /** |
208 * The actual entry type used by the [DoubleLinkedQueue]. | 191 * The actual entry type used by the [DoubleLinkedQueue]. |
209 * | 192 * |
210 * The entry contains a reference to the queue, allowing | 193 * The entry contains a reference to the queue, allowing |
211 * [append]/[prepend] to update the list length. | 194 * [append]/[prepend] to update the list length. |
212 */ | 195 */ |
213 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> | 196 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> { |
214 implements DoubleLinkedQueueEntry<E> { | 197 _DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E> queue) |
215 E element; | 198 : super(element, queue); |
216 _DoubleLinkedQueueElement(this.element, DoubleLinkedQueue<E> queue) | |
217 : super(queue); | |
218 | 199 |
219 void append(E e) { | 200 void append(E e) { |
220 _append(e); | 201 _append(e); |
221 if (_queue != null) _queue._elementCount++; | 202 if (_queue != null) _queue._elementCount++; |
222 } | 203 } |
223 | 204 |
224 void prepend(E e) { | 205 void prepend(E e) { |
225 _prepend(e); | 206 _prepend(e); |
226 if (_queue != null) _queue._elementCount++; | 207 if (_queue != null) _queue._elementCount++; |
227 } | 208 } |
(...skipping 16 matching lines...) Expand all Loading... |
244 | 225 |
245 /** | 226 /** |
246 * A sentinel in a double linked list is used to manipulate the list | 227 * A sentinel in a double linked list is used to manipulate the list |
247 * at both ends. | 228 * at both ends. |
248 * A double linked list has exactly one sentinel, | 229 * A double linked list has exactly one sentinel, |
249 * which is the only entry when the list is constructed. | 230 * which is the only entry when the list is constructed. |
250 * Initially, a sentinel has its next and previous entry point to itself. | 231 * Initially, a sentinel has its next and previous entry point to itself. |
251 * A sentinel does not box any user element. | 232 * A sentinel does not box any user element. |
252 */ | 233 */ |
253 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { | 234 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { |
254 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(queue) { | 235 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) |
| 236 : super(null, queue) { |
255 _previousLink = this; | 237 _previousLink = this; |
256 _nextLink = this; | 238 _nextLink = this; |
257 } | 239 } |
258 | 240 |
259 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 241 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { |
260 return null; | 242 return null; |
261 } | 243 } |
262 | 244 |
263 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ | 245 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ |
264 E _remove() { | 246 E _remove() { |
265 throw IterableElementError.noElement(); | 247 throw IterableElementError.noElement(); |
266 } | 248 } |
267 | 249 |
268 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ | 250 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ |
269 E get element { | 251 E get _element { |
270 throw IterableElementError.noElement(); | 252 throw IterableElementError.noElement(); |
271 } | 253 } |
272 } | 254 } |
273 | 255 |
274 /** | 256 /** |
275 * A [Queue] implementation based on a double-linked list. | 257 * A [Queue] implementation based on a double-linked list. |
276 * | 258 * |
277 * Allows constant time add, remove-at-ends and peek operations. | 259 * Allows constant time add, remove-at-ends and peek operations. |
278 */ | 260 */ |
279 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { | 261 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 E removeFirst() { | 315 E removeFirst() { |
334 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; | 316 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
335 E result = firstEntry._remove(); | 317 E result = firstEntry._remove(); |
336 _elementCount--; | 318 _elementCount--; |
337 return result; | 319 return result; |
338 } | 320 } |
339 | 321 |
340 bool remove(Object o) { | 322 bool remove(Object o) { |
341 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 323 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
342 while (!identical(entry, _sentinel)) { | 324 while (!identical(entry, _sentinel)) { |
343 if (entry.element == o) { | 325 if (entry._element == o) { |
344 entry._remove(); | 326 entry._remove(); |
345 _elementCount--; | 327 _elementCount--; |
346 return true; | 328 return true; |
347 } | 329 } |
348 entry = entry._nextLink; | 330 entry = entry._nextLink; |
349 } | 331 } |
350 return false; | 332 return false; |
351 } | 333 } |
352 | 334 |
353 void _filter(bool test(E element), bool removeMatching) { | 335 void _filter(bool test(E element), bool removeMatching) { |
354 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 336 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
355 while (!identical(entry, _sentinel)) { | 337 while (!identical(entry, _sentinel)) { |
356 _DoubleLinkedQueueEntry<E> next = entry._nextLink; | 338 _DoubleLinkedQueueEntry<E> next = entry._nextLink; |
357 if (identical(removeMatching, test(entry.element))) { | 339 if (identical(removeMatching, test(entry._element))) { |
358 entry._remove(); | 340 entry._remove(); |
359 _elementCount--; | 341 _elementCount--; |
360 } | 342 } |
361 entry = next; | 343 entry = next; |
362 } | 344 } |
363 } | 345 } |
364 | 346 |
365 void removeWhere(bool test(E element)) { | 347 void removeWhere(bool test(E element)) { |
366 _filter(test, true); | 348 _filter(test, true); |
367 } | 349 } |
368 | 350 |
369 void retainWhere(bool test(E element)) { | 351 void retainWhere(bool test(E element)) { |
370 _filter(test, false); | 352 _filter(test, false); |
371 } | 353 } |
372 | 354 |
373 E get first { | 355 E get first { |
374 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; | 356 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
375 return firstEntry.element; | 357 return firstEntry._element; |
376 } | 358 } |
377 | 359 |
378 E get last { | 360 E get last { |
379 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; | 361 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
380 return lastEntry.element; | 362 return lastEntry._element; |
381 } | 363 } |
382 | 364 |
383 E get single { | 365 E get single { |
384 // Note that this throws correctly if the queue is empty | 366 // Note that this throws correctly if the queue is empty |
385 // because reading element on the sentinel throws. | 367 // because reading element on the sentinel throws. |
386 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { | 368 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { |
387 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 369 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
388 return entry.element; | 370 return entry._element; |
389 } | 371 } |
390 throw IterableElementError.tooMany(); | 372 throw IterableElementError.tooMany(); |
391 } | 373 } |
392 | 374 |
393 DoubleLinkedQueueEntry<E> lastEntry() { | 375 DoubleLinkedQueueEntry<E> lastEntry() { |
394 return _sentinel.previousEntry(); | 376 return _sentinel.previousEntry(); |
395 } | 377 } |
396 | 378 |
397 DoubleLinkedQueueEntry<E> firstEntry() { | 379 DoubleLinkedQueueEntry<E> firstEntry() { |
398 return _sentinel.nextEntry(); | 380 return _sentinel.nextEntry(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 if (identical(_nextEntry, _sentinel)) { | 420 if (identical(_nextEntry, _sentinel)) { |
439 _current = null; | 421 _current = null; |
440 _nextEntry = null; | 422 _nextEntry = null; |
441 _sentinel = null; | 423 _sentinel = null; |
442 return false; | 424 return false; |
443 } | 425 } |
444 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; | 426 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; |
445 if (elementEntry._queue == null) { | 427 if (elementEntry._queue == null) { |
446 throw new ConcurrentModificationError(_sentinel._queue); | 428 throw new ConcurrentModificationError(_sentinel._queue); |
447 } | 429 } |
448 _current = elementEntry.element; | 430 _current = elementEntry._element; |
449 _nextEntry = elementEntry._nextLink; | 431 _nextEntry = elementEntry._nextLink; |
450 return true; | 432 return true; |
451 } | 433 } |
452 | 434 |
453 E get current => _current; | 435 E get current => _current; |
454 } | 436 } |
455 | 437 |
456 /** | 438 /** |
457 * List based [Queue]. | 439 * List based [Queue]. |
458 * | 440 * |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 _queue._checkModification(_modificationCount); | 815 _queue._checkModification(_modificationCount); |
834 if (_position == _end) { | 816 if (_position == _end) { |
835 _current = null; | 817 _current = null; |
836 return false; | 818 return false; |
837 } | 819 } |
838 _current = _queue._table[_position]; | 820 _current = _queue._table[_position]; |
839 _position = (_position + 1) & (_queue._table.length - 1); | 821 _position = (_position + 1) & (_queue._table.length - 1); |
840 return true; | 822 return true; |
841 } | 823 } |
842 } | 824 } |
OLD | NEW |