Chromium Code Reviews| 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 { | 99 class _DoubleLink<E extends _DoubleLink> { |
| 100 _DoubleLink _previousLink; | 100 E _previousLink; |
| 101 _DoubleLink _nextLink; | 101 E _nextLink; |
| 102 | 102 |
| 103 void _link(_DoubleLink previous, | 103 void _link(E previous, E next) { |
| 104 _DoubleLink next) { | |
| 105 _nextLink = next; | 104 _nextLink = next; |
| 106 _previousLink = previous; | 105 _previousLink = previous; |
| 107 if (previous != null) previous._nextLink = this; | 106 if (previous != null) previous._nextLink = this; |
| 108 if (next != null) next._previousLink = this; | 107 if (next != null) next._previousLink = this; |
| 109 } | 108 } |
| 110 | 109 |
| 111 void _unlink() { | 110 void _unlink() { |
| 112 if (_previousLink != null) _previousLink._nextLink = _nextLink; | 111 if (_previousLink != null) _previousLink._nextLink = _nextLink; |
| 113 if (_nextLink != null) _nextLink._previousLink = _previousLink; | 112 if (_nextLink != null) _nextLink._previousLink = _previousLink; |
| 114 _nextLink = null; | 113 _nextLink = null; |
| 115 _previousLink = null; | 114 _previousLink = null; |
| 116 } | 115 } |
| 117 } | 116 } |
| 118 | 117 |
| 119 /** | 118 /** |
| 120 * 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 |
| 121 * entry, the previous entry, and the boxed element. | 120 * entry, the previous entry, and the boxed element. |
| 122 */ | 121 */ |
| 123 class DoubleLinkedQueueEntry<E> extends _DoubleLink { | 122 abstract class DoubleLinkedQueueEntry<E> { |
| 123 factory DoubleLinkedQueueEntry(E element) = _UserDoubleLinkedQueueEntry<E>; | |
|
Lasse Reichstein Nielsen
2016/05/13 05:31:09
This changes a generative constructor to a factory
floitsch
2016/05/13 17:12:01
Fixed in https://codereview.chromium.org/197390300
| |
| 124 | |
| 125 /// The element in the queue. | |
| 126 E get element; | |
| 127 | |
| 128 /// Appends the given [e] as entry just after this entry. | |
| 129 void append(E e); | |
| 130 | |
| 131 /// 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 } | |
|
sra1
2016/05/13 03:00:13
This is a breaking change since DoubleLinkedQueueE
floitsch
2016/05/13 17:12:01
Argh. Missed the 'remove' function.
Fixing in http
| |
| 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> { | |
| 124 E element; | 149 E element; |
| 125 | 150 |
| 126 DoubleLinkedQueueEntry(this.element); | 151 _UserDoubleLinkedQueueEntry(this.element); |
| 127 | 152 |
| 128 void append(E e) { | 153 void append(E e) { |
| 129 new DoubleLinkedQueueEntry<E>(e)._link(this, _nextLink); | 154 new _UserDoubleLinkedQueueEntry<E>(e)._link(this, _nextLink); |
| 130 } | 155 } |
| 131 | 156 |
| 132 void prepend(E e) { | 157 void prepend(E e) { |
| 133 new DoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); | 158 new _UserDoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); |
| 134 } | 159 } |
| 135 | 160 |
| 136 E remove() { | 161 E remove() { |
| 137 _unlink(); | 162 _unlink(); |
| 138 return element; | 163 return element; |
| 139 } | 164 } |
| 140 | 165 |
| 141 DoubleLinkedQueueEntry<E> previousEntry() { | 166 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink; |
| 142 return _previousLink; | |
| 143 } | |
| 144 | 167 |
| 145 DoubleLinkedQueueEntry<E> nextEntry() { | 168 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink; |
| 146 return _nextLink; | |
| 147 } | |
| 148 } | 169 } |
| 149 | 170 |
| 150 /** | 171 /** |
| 151 * Interface for the link classes used by [DoubleLinkedQueue]. | 172 * Interface for the link classes used by [DoubleLinkedQueue]. |
| 152 * | 173 * |
| 153 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] | 174 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] |
| 154 * implements this interface. | 175 * implement this interface. |
| 155 * The entry contains a link back to the queue, so calling `append` | 176 * The entry contains a link back to the queue, so calling `append` |
| 156 * or `prepend` can correctly update the element count. | 177 * or `prepend` can correctly update the element count. |
| 157 */ | 178 */ |
| 158 abstract class _DoubleLinkedQueueEntry<E> extends _DoubleLink { | 179 abstract class _DoubleLinkedQueueEntry<E> |
| 180 extends _DoubleLink<_DoubleLinkedQueueEntry<E>> { | |
| 159 DoubleLinkedQueue<E> _queue; | 181 DoubleLinkedQueue<E> _queue; |
| 160 _DoubleLinkedQueueEntry(this._queue); | 182 _DoubleLinkedQueueEntry(this._queue); |
| 161 | 183 |
| 162 _DoubleLinkedQueueElement _asNonSentinelEntry(); | 184 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); |
| 163 | 185 |
| 164 void _append(E e) { | 186 void _append(E e) { |
| 165 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); | 187 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); |
| 166 } | 188 } |
| 167 | 189 |
| 168 void _prepend(E e) { | 190 void _prepend(E e) { |
| 169 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); | 191 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); |
| 170 } | 192 } |
| 171 | 193 |
| 172 E _remove(); | 194 E _remove(); |
| 173 | 195 |
| 174 E get element; | 196 E get element; |
| 175 | 197 |
| 176 DoubleLinkedQueueEntry<E> nextEntry() { | 198 DoubleLinkedQueueEntry<E> nextEntry() { |
| 177 _DoubleLinkedQueueEntry next = _nextLink; | 199 return _nextLink._asNonSentinelEntry(); |
| 178 return next._asNonSentinelEntry(); | |
| 179 } | 200 } |
| 180 | 201 |
| 181 DoubleLinkedQueueEntry<E> previousEntry() { | 202 DoubleLinkedQueueEntry<E> previousEntry() { |
| 182 _DoubleLinkedQueueEntry previous = _previousLink; | 203 return _previousLink._asNonSentinelEntry(); |
| 183 return previous._asNonSentinelEntry(); | |
| 184 } | 204 } |
| 185 } | 205 } |
| 186 | 206 |
| 187 /** | 207 /** |
| 188 * The actual entry type used by the [DoubleLinkedQueue]. | 208 * The actual entry type used by the [DoubleLinkedQueue]. |
| 189 * | 209 * |
| 190 * The entry contains a reference to the queue, allowing | 210 * The entry contains a reference to the queue, allowing |
| 191 * [append]/[prepend] to update the list length. | 211 * [append]/[prepend] to update the list length. |
| 192 */ | 212 */ |
| 193 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> | 213 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 210 _queue = null; | 230 _queue = null; |
| 211 _unlink(); | 231 _unlink(); |
| 212 return element; | 232 return element; |
| 213 } | 233 } |
| 214 | 234 |
| 215 E remove() { | 235 E remove() { |
| 216 if (_queue != null) _queue._elementCount--; | 236 if (_queue != null) _queue._elementCount--; |
| 217 return _remove(); | 237 return _remove(); |
| 218 } | 238 } |
| 219 | 239 |
| 220 _DoubleLinkedQueueElement _asNonSentinelEntry() { | 240 _DoubleLinkedQueueElement<E> _asNonSentinelEntry() { |
| 221 return this; | 241 return this; |
| 222 } | 242 } |
| 223 } | 243 } |
| 224 | 244 |
| 225 /** | 245 /** |
| 226 * A sentinel in a double linked list is used to manipulate the list | 246 * A sentinel in a double linked list is used to manipulate the list |
| 227 * at both ends. | 247 * at both ends. |
| 228 * A double linked list has exactly one sentinel, | 248 * A double linked list has exactly one sentinel, |
| 229 * which is the only entry when the list is constructed. | 249 * which is the only entry when the list is constructed. |
| 230 * Initially, a sentinel has its next and previous entry point to itself. | 250 * Initially, a sentinel has its next and previous entry point to itself. |
| 231 * A sentinel does not box any user element. | 251 * A sentinel does not box any user element. |
| 232 */ | 252 */ |
| 233 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { | 253 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { |
| 234 _DoubleLinkedQueueSentinel(DoubleLinkedQueue queue) : super(queue) { | 254 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(queue) { |
| 235 _previousLink = this; | 255 _previousLink = this; |
| 236 _nextLink = this; | 256 _nextLink = this; |
| 237 } | 257 } |
| 238 | 258 |
| 239 _DoubleLinkedQueueElement _asNonSentinelEntry() { | 259 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { |
| 240 return null; | 260 return null; |
| 241 } | 261 } |
| 242 | 262 |
| 243 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ | 263 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ |
| 244 E _remove() { | 264 E _remove() { |
| 245 throw IterableElementError.noElement(); | 265 throw IterableElementError.noElement(); |
| 246 } | 266 } |
| 247 | 267 |
| 248 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ | 268 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ |
| 249 E get element { | 269 E get element { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 265 } | 285 } |
| 266 | 286 |
| 267 /** | 287 /** |
| 268 * Creates a double-linked queue containing all [elements]. | 288 * Creates a double-linked queue containing all [elements]. |
| 269 * | 289 * |
| 270 * The element order in the queue is as if the elements were added using | 290 * The element order in the queue is as if the elements were added using |
| 271 * [addLast] in the order provided by [elements.iterator]. | 291 * [addLast] in the order provided by [elements.iterator]. |
| 272 */ | 292 */ |
| 273 factory DoubleLinkedQueue.from(Iterable elements) { | 293 factory DoubleLinkedQueue.from(Iterable elements) { |
| 274 Queue<E> list = new DoubleLinkedQueue<E>(); | 294 Queue<E> list = new DoubleLinkedQueue<E>(); |
| 275 for (final E e in elements) { | 295 for (final e in elements) { |
| 276 list.addLast(e); | 296 E element = e as Object/*=E*/; |
| 297 list.addLast(element); | |
| 277 } | 298 } |
| 278 return list; | 299 return list; |
| 279 } | 300 } |
| 280 | 301 |
| 281 int get length => _elementCount; | 302 int get length => _elementCount; |
| 282 | 303 |
| 283 void addLast(E value) { | 304 void addLast(E value) { |
| 284 _sentinel._prepend(value); | 305 _sentinel._prepend(value); |
| 285 _elementCount++; | 306 _elementCount++; |
| 286 } | 307 } |
| 287 | 308 |
| 288 void addFirst(E value) { | 309 void addFirst(E value) { |
| 289 _sentinel._append(value); | 310 _sentinel._append(value); |
| 290 _elementCount++; | 311 _elementCount++; |
| 291 } | 312 } |
| 292 | 313 |
| 293 void add(E value) { | 314 void add(E value) { |
| 294 _sentinel._prepend(value); | 315 _sentinel._prepend(value); |
| 295 _elementCount++; | 316 _elementCount++; |
| 296 } | 317 } |
| 297 | 318 |
| 298 void addAll(Iterable<E> iterable) { | 319 void addAll(Iterable<E> iterable) { |
| 299 for (final E value in iterable) { | 320 for (final E value in iterable) { |
| 300 _sentinel._prepend(value); | 321 _sentinel._prepend(value); |
| 301 _elementCount++; | 322 _elementCount++; |
| 302 } | 323 } |
| 303 } | 324 } |
| 304 | 325 |
| 305 E removeLast() { | 326 E removeLast() { |
| 306 _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; | 327 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
| 307 E result = lastEntry._remove(); | 328 E result = lastEntry._remove(); |
| 308 _elementCount--; | 329 _elementCount--; |
| 309 return result; | 330 return result; |
| 310 } | 331 } |
| 311 | 332 |
| 312 E removeFirst() { | 333 E removeFirst() { |
| 313 _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; | 334 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
| 314 E result = firstEntry._remove(); | 335 E result = firstEntry._remove(); |
| 315 _elementCount--; | 336 _elementCount--; |
| 316 return result; | 337 return result; |
| 317 } | 338 } |
| 318 | 339 |
| 319 bool remove(Object o) { | 340 bool remove(Object o) { |
| 320 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 341 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
| 321 while (!identical(entry, _sentinel)) { | 342 while (!identical(entry, _sentinel)) { |
| 322 if (entry.element == o) { | 343 if (entry.element == o) { |
| 323 entry._remove(); | 344 entry._remove(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 343 | 364 |
| 344 void removeWhere(bool test(E element)) { | 365 void removeWhere(bool test(E element)) { |
| 345 _filter(test, true); | 366 _filter(test, true); |
| 346 } | 367 } |
| 347 | 368 |
| 348 void retainWhere(bool test(E element)) { | 369 void retainWhere(bool test(E element)) { |
| 349 _filter(test, false); | 370 _filter(test, false); |
| 350 } | 371 } |
| 351 | 372 |
| 352 E get first { | 373 E get first { |
| 353 _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; | 374 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
| 354 return firstEntry.element; | 375 return firstEntry.element; |
| 355 } | 376 } |
| 356 | 377 |
| 357 E get last { | 378 E get last { |
| 358 _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; | 379 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
| 359 return lastEntry.element; | 380 return lastEntry.element; |
| 360 } | 381 } |
| 361 | 382 |
| 362 E get single { | 383 E get single { |
| 363 // Note that this throws correctly if the queue is empty | 384 // Note that this throws correctly if the queue is empty |
| 364 // because reading element on the sentinel throws. | 385 // because reading element on the sentinel throws. |
| 365 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { | 386 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { |
| 366 _DoubleLinkedQueueEntry entry = _sentinel._nextLink; | 387 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
| 367 return entry.element; | 388 return entry.element; |
| 368 } | 389 } |
| 369 throw IterableElementError.tooMany(); | 390 throw IterableElementError.tooMany(); |
| 370 } | 391 } |
| 371 | 392 |
| 372 DoubleLinkedQueueEntry<E> lastEntry() { | 393 DoubleLinkedQueueEntry<E> lastEntry() { |
| 373 return _sentinel.previousEntry(); | 394 return _sentinel.previousEntry(); |
| 374 } | 395 } |
| 375 | 396 |
| 376 DoubleLinkedQueueEntry<E> firstEntry() { | 397 DoubleLinkedQueueEntry<E> firstEntry() { |
| 377 return _sentinel.nextEntry(); | 398 return _sentinel.nextEntry(); |
| 378 } | 399 } |
| 379 | 400 |
| 380 bool get isEmpty { | 401 bool get isEmpty { |
| 381 return (identical(_sentinel._nextLink, _sentinel)); | 402 return (identical(_sentinel._nextLink, _sentinel)); |
| 382 } | 403 } |
| 383 | 404 |
| 384 void clear() { | 405 void clear() { |
| 385 _sentinel._nextLink = _sentinel; | 406 _sentinel._nextLink = _sentinel; |
| 386 _sentinel._previousLink = _sentinel; | 407 _sentinel._previousLink = _sentinel; |
| 387 _elementCount = 0; | 408 _elementCount = 0; |
| 388 } | 409 } |
| 389 | 410 |
| 390 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | 411 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { |
| 391 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 412 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
| 392 while (!identical(entry, _sentinel)) { | 413 while (!identical(entry, _sentinel)) { |
| 393 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; | 414 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; |
| 394 _DoubleLinkedQueueElement element = entry; | 415 _DoubleLinkedQueueElement<E> element = entry; |
| 395 f(element); | 416 f(element); |
| 396 entry = nextEntry; | 417 entry = nextEntry; |
| 397 } | 418 } |
| 398 } | 419 } |
| 399 | 420 |
| 400 _DoubleLinkedQueueIterator<E> get iterator { | 421 _DoubleLinkedQueueIterator<E> get iterator { |
| 401 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 422 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
| 402 } | 423 } |
| 403 | 424 |
| 404 String toString() => IterableBase.iterableToFullString(this, '{', '}'); | 425 String toString() => IterableBase.iterableToFullString(this, '{', '}'); |
| 405 } | 426 } |
| 406 | 427 |
| 407 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 428 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
| 408 _DoubleLinkedQueueSentinel<E> _sentinel; | 429 _DoubleLinkedQueueSentinel<E> _sentinel; |
| 409 _DoubleLinkedQueueEntry<E> _nextEntry = null; | 430 _DoubleLinkedQueueEntry<E> _nextEntry = null; |
| 410 E _current; | 431 E _current; |
| 411 | 432 |
| 412 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) | 433 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) |
| 413 : _sentinel = sentinel, _nextEntry = sentinel._nextLink; | 434 : _sentinel = sentinel, |
| 435 _nextEntry = sentinel._nextLink; | |
| 414 | 436 |
| 415 bool moveNext() { | 437 bool moveNext() { |
| 416 if (identical(_nextEntry, _sentinel)) { | 438 if (identical(_nextEntry, _sentinel)) { |
| 417 _current = null; | 439 _current = null; |
| 418 _nextEntry = null; | 440 _nextEntry = null; |
| 419 _sentinel = null; | 441 _sentinel = null; |
| 420 return false; | 442 return false; |
| 421 } | 443 } |
| 422 _DoubleLinkedQueueElement elementEntry = _nextEntry; | 444 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; |
| 423 if (elementEntry._queue == null) { | 445 if (elementEntry._queue == null) { |
| 424 throw new ConcurrentModificationError(_sentinel._queue); | 446 throw new ConcurrentModificationError(_sentinel._queue); |
| 425 } | 447 } |
| 426 _current = elementEntry.element; | 448 _current = elementEntry.element; |
| 427 _nextEntry = elementEntry._nextLink; | 449 _nextEntry = elementEntry._nextLink; |
| 428 return true; | 450 return true; |
| 429 } | 451 } |
| 430 | 452 |
| 431 E get current => _current; | 453 E get current => _current; |
| 432 } | 454 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 * The elements are added to the queue, as by [addLast], in the order given by | 491 * The elements are added to the queue, as by [addLast], in the order given by |
| 470 * `elements.iterator`. | 492 * `elements.iterator`. |
| 471 * | 493 * |
| 472 * All `elements` should be assignable to [E]. | 494 * All `elements` should be assignable to [E]. |
| 473 */ | 495 */ |
| 474 factory ListQueue.from(Iterable elements) { | 496 factory ListQueue.from(Iterable elements) { |
| 475 if (elements is List) { | 497 if (elements is List) { |
| 476 int length = elements.length; | 498 int length = elements.length; |
| 477 ListQueue<E> queue = new ListQueue(length + 1); | 499 ListQueue<E> queue = new ListQueue(length + 1); |
| 478 assert(queue._table.length > length); | 500 assert(queue._table.length > length); |
| 479 List sourceList = elements; | 501 for (int i = 0; i < length; i++) { |
| 480 queue._table.setRange(0, length, sourceList, 0); | 502 queue._table[i] = elements[i] as Object/*=E*/; |
| 503 } | |
| 481 queue._tail = length; | 504 queue._tail = length; |
| 482 return queue; | 505 return queue; |
| 483 } else { | 506 } else { |
| 484 int capacity = _INITIAL_CAPACITY; | 507 int capacity = _INITIAL_CAPACITY; |
| 485 if (elements is EfficientLength) { | 508 if (elements is EfficientLength) { |
| 486 capacity = elements.length; | 509 capacity = elements.length; |
| 487 } | 510 } |
| 488 ListQueue<E> result = new ListQueue<E>(capacity); | 511 ListQueue<E> result = new ListQueue<E>(capacity); |
| 489 for (final E element in elements) { | 512 for (final element in elements) { |
| 490 result.addLast(element); | 513 result.addLast(element as Object/*=E*/); |
| 491 } | 514 } |
| 492 return result; | 515 return result; |
| 493 } | 516 } |
| 494 } | 517 } |
| 495 | 518 |
| 496 // Iterable interface. | 519 // Iterable interface. |
| 497 | 520 |
| 498 Iterator<E> get iterator => new _ListQueueIterator<E>(this); | 521 Iterator<E> get iterator => new _ListQueueIterator<E>(this); |
| 499 | 522 |
| 500 void forEach(void action (E element)) { | 523 void forEach(void action (E element)) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 return list; | 564 return list; |
| 542 } | 565 } |
| 543 | 566 |
| 544 // Collection interface. | 567 // Collection interface. |
| 545 | 568 |
| 546 void add(E value) { | 569 void add(E value) { |
| 547 _add(value); | 570 _add(value); |
| 548 } | 571 } |
| 549 | 572 |
| 550 void addAll(Iterable<E> elements) { | 573 void addAll(Iterable<E> elements) { |
| 551 if (elements is List) { | 574 if (elements is List/*<E>*/) { |
| 552 List list = elements; | 575 List<E> list = elements; |
| 553 int addCount = list.length; | 576 int addCount = list.length; |
| 554 int length = this.length; | 577 int length = this.length; |
| 555 if (length + addCount >= _table.length) { | 578 if (length + addCount >= _table.length) { |
| 556 _preGrow(length + addCount); | 579 _preGrow(length + addCount); |
| 557 // After preGrow, all elements are at the start of the list. | 580 // After preGrow, all elements are at the start of the list. |
| 558 _table.setRange(length, length + addCount, list, 0); | 581 _table.setRange(length, length + addCount, list, 0); |
| 559 _tail += addCount; | 582 _tail += addCount; |
| 560 } else { | 583 } else { |
| 561 // Adding addCount elements won't reach _head. | 584 // Adding addCount elements won't reach _head. |
| 562 int endSpace = _table.length - _tail; | 585 int endSpace = _table.length - _tail; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 _head = 0; | 808 _head = 0; |
| 786 } | 809 } |
| 787 } | 810 } |
| 788 | 811 |
| 789 /** | 812 /** |
| 790 * Iterator for a [ListQueue]. | 813 * Iterator for a [ListQueue]. |
| 791 * | 814 * |
| 792 * Considers any add or remove operation a concurrent modification. | 815 * Considers any add or remove operation a concurrent modification. |
| 793 */ | 816 */ |
| 794 class _ListQueueIterator<E> implements Iterator<E> { | 817 class _ListQueueIterator<E> implements Iterator<E> { |
| 795 final ListQueue _queue; | 818 final ListQueue<E> _queue; |
| 796 final int _end; | 819 final int _end; |
| 797 final int _modificationCount; | 820 final int _modificationCount; |
| 798 int _position; | 821 int _position; |
| 799 E _current; | 822 E _current; |
| 800 | 823 |
| 801 _ListQueueIterator(ListQueue queue) | 824 _ListQueueIterator(ListQueue<E> queue) |
| 802 : _queue = queue, | 825 : _queue = queue, |
| 803 _end = queue._tail, | 826 _end = queue._tail, |
| 804 _modificationCount = queue._modificationCount, | 827 _modificationCount = queue._modificationCount, |
| 805 _position = queue._head; | 828 _position = queue._head; |
| 806 | 829 |
| 807 E get current => _current; | 830 E get current => _current; |
| 808 | 831 |
| 809 bool moveNext() { | 832 bool moveNext() { |
| 810 _queue._checkModification(_modificationCount); | 833 _queue._checkModification(_modificationCount); |
| 811 if (_position == _end) { | 834 if (_position == _end) { |
| 812 _current = null; | 835 _current = null; |
| 813 return false; | 836 return false; |
| 814 } | 837 } |
| 815 _current = _queue._table[_position]; | 838 _current = _queue._table[_position]; |
| 816 _position = (_position + 1) & (_queue._table.length - 1); | 839 _position = (_position + 1) & (_queue._table.length - 1); |
| 817 return true; | 840 return true; |
| 818 } | 841 } |
| 819 } | 842 } |
| OLD | NEW |