| 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 |