| 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 { |
| 100 _DoubleLink _previous; |
| 101 _DoubleLink _next; |
| 102 |
| 103 void _link(_DoubleLink previous, |
| 104 _DoubleLink next) { |
| 105 _next = next; |
| 106 _previous = previous; |
| 107 if (previous != null) previous._next = this; |
| 108 if (next != null) next._previous = this; |
| 109 } |
| 110 |
| 111 void _unlink() { |
| 112 if (_previous != null) _previous._next = _next; |
| 113 if (_next != null) _next._previous = _previous; |
| 114 _next = null; |
| 115 _previous = null; |
| 116 } |
| 117 } |
| 118 |
| 99 /** | 119 /** |
| 100 * An entry in a doubly linked list. It contains a pointer to the next | 120 * An entry in a doubly linked list. It contains a pointer to the next |
| 101 * entry, the previous entry, and the boxed element. | 121 * entry, the previous entry, and the boxed element. |
| 102 */ | 122 */ |
| 103 class DoubleLinkedQueueEntry<E> { | 123 class DoubleLinkedQueueEntry<E> extends _DoubleLink { |
| 104 DoubleLinkedQueueEntry<E> _previous; | 124 E element; |
| 105 DoubleLinkedQueueEntry<E> _next; | |
| 106 E _element; | |
| 107 | 125 |
| 108 DoubleLinkedQueueEntry(E e) : _element = e; | 126 DoubleLinkedQueueEntry(this.element); |
| 109 | |
| 110 void _link(DoubleLinkedQueueEntry<E> previous, | |
| 111 DoubleLinkedQueueEntry<E> next) { | |
| 112 _next = next; | |
| 113 _previous = previous; | |
| 114 previous._next = this; | |
| 115 next._previous = this; | |
| 116 } | |
| 117 | 127 |
| 118 void append(E e) { | 128 void append(E e) { |
| 119 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); | 129 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); |
| 120 } | 130 } |
| 121 | 131 |
| 122 void prepend(E e) { | 132 void prepend(E e) { |
| 123 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); | 133 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); |
| 124 } | 134 } |
| 125 | 135 |
| 126 E remove() { | 136 E remove() { |
| 127 _previous._next = _next; | 137 _unlink(); |
| 128 _next._previous = _previous; | 138 return element; |
| 129 _next = null; | |
| 130 _previous = null; | |
| 131 return _element; | |
| 132 } | |
| 133 | |
| 134 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | |
| 135 return this; | |
| 136 } | 139 } |
| 137 | 140 |
| 138 DoubleLinkedQueueEntry<E> previousEntry() { | 141 DoubleLinkedQueueEntry<E> previousEntry() { |
| 139 return _previous._asNonSentinelEntry(); | 142 return _previous; |
| 140 } | 143 } |
| 141 | 144 |
| 142 DoubleLinkedQueueEntry<E> nextEntry() { | 145 DoubleLinkedQueueEntry<E> nextEntry() { |
| 143 return _next._asNonSentinelEntry(); | 146 return _next; |
| 144 } | |
| 145 | |
| 146 E get element { | |
| 147 return _element; | |
| 148 } | |
| 149 | |
| 150 void set element(E e) { | |
| 151 _element = e; | |
| 152 } | 147 } |
| 153 } | 148 } |
| 154 | 149 |
| 150 /** |
| 151 * Interface for the link classes used by [DoubleLinkedQueue]. |
| 152 * |
| 153 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] |
| 154 * implements this interface. |
| 155 * The entry contains a link back to the queue, so calling `append` |
| 156 * or `prepend` can correctly update the element count. |
| 157 */ |
| 158 abstract class _DoubleLinkedQueueEntry<E> extends _DoubleLink { |
| 159 DoubleLinkedQueue<E> _queue; |
| 160 _DoubleLinkedQueueEntry(this._queue); |
| 161 |
| 162 _DoubleLinkedQueueElement _asNonSentinelEntry(); |
| 163 |
| 164 void _append(E e) { |
| 165 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _next); |
| 166 } |
| 167 |
| 168 void _prepend(E e) { |
| 169 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previous, this); |
| 170 } |
| 171 |
| 172 E _remove(); |
| 173 |
| 174 E get element; |
| 175 |
| 176 DoubleLinkedQueueEntry<E> nextEntry() { |
| 177 _DoubleLinkedQueueEntry next = _next; |
| 178 return next._asNonSentinelEntry(); |
| 179 } |
| 180 |
| 181 DoubleLinkedQueueEntry<E> previousEntry() { |
| 182 _DoubleLinkedQueueEntry previous = _previous; |
| 183 return previous._asNonSentinelEntry(); |
| 184 } |
| 185 } |
| 186 |
| 187 /** |
| 188 * The actual entry type used by the [DoubleLinkedQueue]. |
| 189 * |
| 190 * The entry contains a reference to the queue, allowing |
| 191 * [append]/[prepend] to update the list length. |
| 192 */ |
| 193 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> |
| 194 implements DoubleLinkedQueueEntry<E> { |
| 195 E element; |
| 196 _DoubleLinkedQueueElement(this.element, DoubleLinkedQueue<E> queue) |
| 197 : super(queue); |
| 198 |
| 199 void append(E e) { |
| 200 _append(e); |
| 201 if (_queue != null) _queue._elementCount++; |
| 202 } |
| 203 |
| 204 void prepend(E e) { |
| 205 _prepend(e); |
| 206 if (_queue != null) _queue._elementCount++; |
| 207 } |
| 208 |
| 209 E _remove() { |
| 210 _queue = null; |
| 211 _unlink(); |
| 212 return element; |
| 213 } |
| 214 |
| 215 E remove() { |
| 216 if (_queue != null) _queue._elementCount--; |
| 217 return _remove(); |
| 218 } |
| 219 |
| 220 _DoubleLinkedQueueElement _asNonSentinelEntry() { |
| 221 return this; |
| 222 } |
| 223 } |
| 224 |
| 155 /** | 225 /** |
| 156 * A sentinel in a double linked list is used to manipulate the list | 226 * A sentinel in a double linked list is used to manipulate the list |
| 157 * at both ends. | 227 * at both ends. |
| 158 * A double linked list has exactly one sentinel, | 228 * A double linked list has exactly one sentinel, |
| 159 * which is the only entry when the list is constructed. | 229 * which is the only entry when the list is constructed. |
| 160 * Initially, a sentinel has its next and previous entry point to itself. | 230 * Initially, a sentinel has its next and previous entry point to itself. |
| 161 * A sentinel does not box any user element. | 231 * A sentinel does not box any user element. |
| 162 */ | 232 */ |
| 163 class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { | 233 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { |
| 164 _DoubleLinkedQueueEntrySentinel() : super(null) { | 234 _DoubleLinkedQueueSentinel(DoubleLinkedQueue queue) : super(queue) { |
| 165 _link(this, this); | 235 _previous = this; |
| 236 _next = this; |
| 166 } | 237 } |
| 167 | 238 |
| 168 E remove() { | 239 _DoubleLinkedQueueElement _asNonSentinelEntry() { |
| 240 return null; |
| 241 } |
| 242 |
| 243 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ |
| 244 E _remove() { |
| 169 throw IterableElementError.noElement(); | 245 throw IterableElementError.noElement(); |
| 170 } | 246 } |
| 171 | 247 |
| 172 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 248 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ |
| 173 return null; | |
| 174 } | |
| 175 | |
| 176 void set element(E e) { | |
| 177 // This setter is unreachable. | |
| 178 // TODO(lrn): Don't inherit the field if we don't use it. | |
| 179 assert(false); | |
| 180 } | |
| 181 | |
| 182 E get element { | 249 E get element { |
| 183 throw IterableElementError.noElement(); | 250 throw IterableElementError.noElement(); |
| 184 } | 251 } |
| 185 } | 252 } |
| 186 | 253 |
| 187 /** | 254 /** |
| 188 * A [Queue] implementation based on a double-linked list. | 255 * A [Queue] implementation based on a double-linked list. |
| 189 * | 256 * |
| 190 * Allows constant time add, remove-at-ends and peek operations. | 257 * Allows constant time add, remove-at-ends and peek operations. |
| 191 */ | 258 */ |
| 192 class DoubleLinkedQueue<E> extends IterableBase<E> implements Queue<E> { | 259 class DoubleLinkedQueue<E> extends IterableBase<E> implements Queue<E> { |
| 193 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 260 _DoubleLinkedQueueSentinel<E> _sentinel; |
| 194 int _elementCount = 0; | 261 int _elementCount = 0; |
| 195 | 262 |
| 196 DoubleLinkedQueue() { | 263 DoubleLinkedQueue() { |
| 197 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | 264 _sentinel = new _DoubleLinkedQueueSentinel<E>(this); |
| 198 } | 265 } |
| 199 | 266 |
| 200 /** | 267 /** |
| 201 * Creates a double-linked queue containing all [elements]. | 268 * Creates a double-linked queue containing all [elements]. |
| 202 * | 269 * |
| 203 * The element order in the queue is as if the elements were added using | 270 * The element order in the queue is as if the elements were added using |
| 204 * [addLast] in the order provided by [elements.iterator]. | 271 * [addLast] in the order provided by [elements.iterator]. |
| 205 */ | 272 */ |
| 206 factory DoubleLinkedQueue.from(Iterable elements) { | 273 factory DoubleLinkedQueue.from(Iterable elements) { |
| 207 Queue<E> list = new DoubleLinkedQueue(); | 274 Queue<E> list = new DoubleLinkedQueue<E>(); |
| 208 for (final E e in elements) { | 275 for (final E e in elements) { |
| 209 list.addLast(e); | 276 list.addLast(e); |
| 210 } | 277 } |
| 211 return list; | 278 return list; |
| 212 } | 279 } |
| 213 | 280 |
| 214 int get length => _elementCount; | 281 int get length => _elementCount; |
| 215 | 282 |
| 216 void addLast(E value) { | 283 void addLast(E value) { |
| 217 _sentinel.prepend(value); | 284 _sentinel._prepend(value); |
| 218 _elementCount++; | 285 _elementCount++; |
| 219 } | 286 } |
| 220 | 287 |
| 221 void addFirst(E value) { | 288 void addFirst(E value) { |
| 222 _sentinel.append(value); | 289 _sentinel._append(value); |
| 223 _elementCount++; | 290 _elementCount++; |
| 224 } | 291 } |
| 225 | 292 |
| 226 void add(E value) { | 293 void add(E value) { |
| 227 _sentinel.prepend(value); | 294 _sentinel._prepend(value); |
| 228 _elementCount++; | 295 _elementCount++; |
| 229 } | 296 } |
| 230 | 297 |
| 231 void addAll(Iterable<E> iterable) { | 298 void addAll(Iterable<E> iterable) { |
| 232 for (final E value in iterable) { | 299 for (final E value in iterable) { |
| 233 _sentinel.prepend(value); | 300 _sentinel._prepend(value); |
| 234 _elementCount++; | 301 _elementCount++; |
| 235 } | 302 } |
| 236 } | 303 } |
| 237 | 304 |
| 238 E removeLast() { | 305 E removeLast() { |
| 239 E result = _sentinel._previous.remove(); | 306 _DoubleLinkedQueueEntry lastEntry = _sentinel._previous; |
| 307 E result = lastEntry._remove(); |
| 240 _elementCount--; | 308 _elementCount--; |
| 241 return result; | 309 return result; |
| 242 } | 310 } |
| 243 | 311 |
| 244 E removeFirst() { | 312 E removeFirst() { |
| 245 E result = _sentinel._next.remove(); | 313 _DoubleLinkedQueueEntry firstEntry = _sentinel._next; |
| 314 E result = firstEntry._remove(); |
| 246 _elementCount--; | 315 _elementCount--; |
| 247 return result; | 316 return result; |
| 248 } | 317 } |
| 249 | 318 |
| 250 bool remove(Object o) { | 319 bool remove(Object o) { |
| 251 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 320 _DoubleLinkedQueueEntry<E> entry = _sentinel._next; |
| 252 while (!identical(entry, _sentinel)) { | 321 while (!identical(entry, _sentinel)) { |
| 253 if (entry.element == o) { | 322 if (entry.element == o) { |
| 254 entry.remove(); | 323 entry._remove(); |
| 255 _elementCount--; | 324 _elementCount--; |
| 256 return true; | 325 return true; |
| 257 } | 326 } |
| 258 entry = entry._next; | 327 entry = entry._next; |
| 259 } | 328 } |
| 260 return false; | 329 return false; |
| 261 } | 330 } |
| 262 | 331 |
| 263 void _filter(bool test(E element), bool removeMatching) { | 332 void _filter(bool test(E element), bool removeMatching) { |
| 264 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 333 _DoubleLinkedQueueEntry<E> entry = _sentinel._next; |
| 265 while (!identical(entry, _sentinel)) { | 334 while (!identical(entry, _sentinel)) { |
| 266 DoubleLinkedQueueEntry<E> next = entry._next; | 335 _DoubleLinkedQueueEntry<E> next = entry._next; |
| 267 if (identical(removeMatching, test(entry.element))) { | 336 if (identical(removeMatching, test(entry.element))) { |
| 268 entry.remove(); | 337 entry._remove(); |
| 269 _elementCount--; | 338 _elementCount--; |
| 270 } | 339 } |
| 271 entry = next; | 340 entry = next; |
| 272 } | 341 } |
| 273 } | 342 } |
| 274 | 343 |
| 275 void removeWhere(bool test(E element)) { | 344 void removeWhere(bool test(E element)) { |
| 276 _filter(test, true); | 345 _filter(test, true); |
| 277 } | 346 } |
| 278 | 347 |
| 279 void retainWhere(bool test(E element)) { | 348 void retainWhere(bool test(E element)) { |
| 280 _filter(test, false); | 349 _filter(test, false); |
| 281 } | 350 } |
| 282 | 351 |
| 283 E get first { | 352 E get first { |
| 284 return _sentinel._next.element; | 353 _DoubleLinkedQueueEntry firstEntry = _sentinel._next; |
| 354 return firstEntry.element; |
| 285 } | 355 } |
| 286 | 356 |
| 287 E get last { | 357 E get last { |
| 288 return _sentinel._previous.element; | 358 _DoubleLinkedQueueEntry lastEntry = _sentinel._previous; |
| 359 return lastEntry.element; |
| 289 } | 360 } |
| 290 | 361 |
| 291 E get single { | 362 E get single { |
| 292 // Note that this throws correctly if the queue is empty. | 363 // Note that this throws correctly if the queue is empty |
| 364 // because reading element on the sentinel throws. |
| 293 if (identical(_sentinel._next, _sentinel._previous)) { | 365 if (identical(_sentinel._next, _sentinel._previous)) { |
| 294 return _sentinel._next.element; | 366 _DoubleLinkedQueueEntry entry = _sentinel._next; |
| 367 return entry.element; |
| 295 } | 368 } |
| 296 throw IterableElementError.tooMany(); | 369 throw IterableElementError.tooMany(); |
| 297 } | 370 } |
| 298 | 371 |
| 299 DoubleLinkedQueueEntry<E> lastEntry() { | 372 DoubleLinkedQueueEntry<E> lastEntry() { |
| 300 return _sentinel.previousEntry(); | 373 return _sentinel.previousEntry(); |
| 301 } | 374 } |
| 302 | 375 |
| 303 DoubleLinkedQueueEntry<E> firstEntry() { | 376 DoubleLinkedQueueEntry<E> firstEntry() { |
| 304 return _sentinel.nextEntry(); | 377 return _sentinel.nextEntry(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 324 } | 397 } |
| 325 | 398 |
| 326 _DoubleLinkedQueueIterator<E> get iterator { | 399 _DoubleLinkedQueueIterator<E> get iterator { |
| 327 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 400 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
| 328 } | 401 } |
| 329 | 402 |
| 330 String toString() => IterableBase.iterableToFullString(this, '{', '}'); | 403 String toString() => IterableBase.iterableToFullString(this, '{', '}'); |
| 331 } | 404 } |
| 332 | 405 |
| 333 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 406 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
| 334 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 407 _DoubleLinkedQueueSentinel<E> _sentinel; |
| 335 DoubleLinkedQueueEntry<E> _nextEntry = null; | 408 _DoubleLinkedQueueEntry<E> _nextEntry = null; |
| 336 E _current; | 409 E _current; |
| 337 | 410 |
| 338 _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel<E> sentinel) | 411 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) |
| 339 : _sentinel = sentinel, _nextEntry = sentinel._next; | 412 : _sentinel = sentinel, _nextEntry = sentinel._next; |
| 340 | 413 |
| 341 bool moveNext() { | 414 bool moveNext() { |
| 342 // When [_currentEntry] it is set to [:null:] then it is at the end. | 415 if (identical(_nextEntry, _sentinel)) { |
| 343 if (!identical(_nextEntry, _sentinel)) { | 416 _current = null; |
| 344 _current = _nextEntry._element; | 417 _nextEntry = null; |
| 345 _nextEntry = _nextEntry._next; | 418 _sentinel = null; |
| 346 return true; | 419 return false; |
| 347 } | 420 } |
| 348 _current = null; | 421 _DoubleLinkedQueueElement elementEntry = _nextEntry; |
| 349 _nextEntry = _sentinel = null; // Still identical. | 422 if (elementEntry._queue == null) { |
| 350 return false; | 423 throw new ConcurrentModificationError(_sentinel._queue); |
| 424 } |
| 425 _current = elementEntry.element; |
| 426 _nextEntry = elementEntry._next; |
| 427 return true; |
| 351 } | 428 } |
| 352 | 429 |
| 353 E get current => _current; | 430 E get current => _current; |
| 354 } | 431 } |
| 355 | 432 |
| 356 /** | 433 /** |
| 357 * List based [Queue]. | 434 * List based [Queue]. |
| 358 * | 435 * |
| 359 * Keeps a cyclic buffer of elements, and grows to a larger buffer when | 436 * Keeps a cyclic buffer of elements, and grows to a larger buffer when |
| 360 * it fills up. This guarantees constant time peek and remove operations, and | 437 * it fills up. This guarantees constant time peek and remove operations, and |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 _queue._checkModification(_modificationCount); | 810 _queue._checkModification(_modificationCount); |
| 734 if (_position == _end) { | 811 if (_position == _end) { |
| 735 _current = null; | 812 _current = null; |
| 736 return false; | 813 return false; |
| 737 } | 814 } |
| 738 _current = _queue._table[_position]; | 815 _current = _queue._table[_position]; |
| 739 _position = (_position + 1) & (_queue._table.length - 1); | 816 _position = (_position + 1) & (_queue._table.length - 1); |
| 740 return true; | 817 return true; |
| 741 } | 818 } |
| 742 } | 819 } |
| OLD | NEW |