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>; | |
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 } | |
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 list.addLast(e as E); |
sra1
2016/05/06 18:12:17
fix
floitsch
2016/05/10 14:12:31
Done.
| |
277 } | 297 } |
278 return list; | 298 return list; |
279 } | 299 } |
280 | 300 |
281 int get length => _elementCount; | 301 int get length => _elementCount; |
282 | 302 |
283 void addLast(E value) { | 303 void addLast(E value) { |
284 _sentinel._prepend(value); | 304 _sentinel._prepend(value); |
285 _elementCount++; | 305 _elementCount++; |
286 } | 306 } |
287 | 307 |
288 void addFirst(E value) { | 308 void addFirst(E value) { |
289 _sentinel._append(value); | 309 _sentinel._append(value); |
290 _elementCount++; | 310 _elementCount++; |
291 } | 311 } |
292 | 312 |
293 void add(E value) { | 313 void add(E value) { |
294 _sentinel._prepend(value); | 314 _sentinel._prepend(value); |
295 _elementCount++; | 315 _elementCount++; |
296 } | 316 } |
297 | 317 |
298 void addAll(Iterable<E> iterable) { | 318 void addAll(Iterable<E> iterable) { |
299 for (final E value in iterable) { | 319 for (final E value in iterable) { |
300 _sentinel._prepend(value); | 320 _sentinel._prepend(value); |
301 _elementCount++; | 321 _elementCount++; |
302 } | 322 } |
303 } | 323 } |
304 | 324 |
305 E removeLast() { | 325 E removeLast() { |
306 _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; | 326 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
307 E result = lastEntry._remove(); | 327 E result = lastEntry._remove(); |
308 _elementCount--; | 328 _elementCount--; |
309 return result; | 329 return result; |
310 } | 330 } |
311 | 331 |
312 E removeFirst() { | 332 E removeFirst() { |
313 _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; | 333 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
314 E result = firstEntry._remove(); | 334 E result = firstEntry._remove(); |
315 _elementCount--; | 335 _elementCount--; |
316 return result; | 336 return result; |
317 } | 337 } |
318 | 338 |
319 bool remove(Object o) { | 339 bool remove(Object o) { |
320 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 340 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
321 while (!identical(entry, _sentinel)) { | 341 while (!identical(entry, _sentinel)) { |
322 if (entry.element == o) { | 342 if (entry.element == o) { |
323 entry._remove(); | 343 entry._remove(); |
(...skipping 19 matching lines...) Expand all Loading... | |
343 | 363 |
344 void removeWhere(bool test(E element)) { | 364 void removeWhere(bool test(E element)) { |
345 _filter(test, true); | 365 _filter(test, true); |
346 } | 366 } |
347 | 367 |
348 void retainWhere(bool test(E element)) { | 368 void retainWhere(bool test(E element)) { |
349 _filter(test, false); | 369 _filter(test, false); |
350 } | 370 } |
351 | 371 |
352 E get first { | 372 E get first { |
353 _DoubleLinkedQueueEntry firstEntry = _sentinel._nextLink; | 373 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
354 return firstEntry.element; | 374 return firstEntry.element; |
355 } | 375 } |
356 | 376 |
357 E get last { | 377 E get last { |
358 _DoubleLinkedQueueEntry lastEntry = _sentinel._previousLink; | 378 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
359 return lastEntry.element; | 379 return lastEntry.element; |
360 } | 380 } |
361 | 381 |
362 E get single { | 382 E get single { |
363 // Note that this throws correctly if the queue is empty | 383 // Note that this throws correctly if the queue is empty |
364 // because reading element on the sentinel throws. | 384 // because reading element on the sentinel throws. |
365 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { | 385 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { |
366 _DoubleLinkedQueueEntry entry = _sentinel._nextLink; | 386 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
367 return entry.element; | 387 return entry.element; |
368 } | 388 } |
369 throw IterableElementError.tooMany(); | 389 throw IterableElementError.tooMany(); |
370 } | 390 } |
371 | 391 |
372 DoubleLinkedQueueEntry<E> lastEntry() { | 392 DoubleLinkedQueueEntry<E> lastEntry() { |
373 return _sentinel.previousEntry(); | 393 return _sentinel.previousEntry(); |
374 } | 394 } |
375 | 395 |
376 DoubleLinkedQueueEntry<E> firstEntry() { | 396 DoubleLinkedQueueEntry<E> firstEntry() { |
377 return _sentinel.nextEntry(); | 397 return _sentinel.nextEntry(); |
378 } | 398 } |
379 | 399 |
380 bool get isEmpty { | 400 bool get isEmpty { |
381 return (identical(_sentinel._nextLink, _sentinel)); | 401 return (identical(_sentinel._nextLink, _sentinel)); |
382 } | 402 } |
383 | 403 |
384 void clear() { | 404 void clear() { |
385 _sentinel._nextLink = _sentinel; | 405 _sentinel._nextLink = _sentinel; |
386 _sentinel._previousLink = _sentinel; | 406 _sentinel._previousLink = _sentinel; |
387 _elementCount = 0; | 407 _elementCount = 0; |
388 } | 408 } |
389 | 409 |
390 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | 410 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { |
391 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; | 411 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
392 while (!identical(entry, _sentinel)) { | 412 while (!identical(entry, _sentinel)) { |
393 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; | 413 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; |
394 _DoubleLinkedQueueElement element = entry; | 414 _DoubleLinkedQueueElement<E> element = entry; |
395 f(element); | 415 f(element); |
396 entry = nextEntry; | 416 entry = nextEntry; |
397 } | 417 } |
398 } | 418 } |
399 | 419 |
400 _DoubleLinkedQueueIterator<E> get iterator { | 420 _DoubleLinkedQueueIterator<E> get iterator { |
401 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 421 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
402 } | 422 } |
403 | 423 |
404 String toString() => IterableBase.iterableToFullString(this, '{', '}'); | 424 String toString() => IterableBase.iterableToFullString(this, '{', '}'); |
405 } | 425 } |
406 | 426 |
407 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 427 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
408 _DoubleLinkedQueueSentinel<E> _sentinel; | 428 _DoubleLinkedQueueSentinel<E> _sentinel; |
409 _DoubleLinkedQueueEntry<E> _nextEntry = null; | 429 _DoubleLinkedQueueEntry<E> _nextEntry = null; |
410 E _current; | 430 E _current; |
411 | 431 |
412 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) | 432 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) |
413 : _sentinel = sentinel, _nextEntry = sentinel._nextLink; | 433 : _sentinel = sentinel, |
434 _nextEntry = sentinel._nextLink; | |
414 | 435 |
415 bool moveNext() { | 436 bool moveNext() { |
416 if (identical(_nextEntry, _sentinel)) { | 437 if (identical(_nextEntry, _sentinel)) { |
417 _current = null; | 438 _current = null; |
418 _nextEntry = null; | 439 _nextEntry = null; |
419 _sentinel = null; | 440 _sentinel = null; |
420 return false; | 441 return false; |
421 } | 442 } |
422 _DoubleLinkedQueueElement elementEntry = _nextEntry; | 443 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; |
423 if (elementEntry._queue == null) { | 444 if (elementEntry._queue == null) { |
424 throw new ConcurrentModificationError(_sentinel._queue); | 445 throw new ConcurrentModificationError(_sentinel._queue); |
425 } | 446 } |
426 _current = elementEntry.element; | 447 _current = elementEntry.element; |
427 _nextEntry = elementEntry._nextLink; | 448 _nextEntry = elementEntry._nextLink; |
428 return true; | 449 return true; |
429 } | 450 } |
430 | 451 |
431 E get current => _current; | 452 E get current => _current; |
432 } | 453 } |
(...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 | 490 * The elements are added to the queue, as by [addLast], in the order given by |
470 * `elements.iterator`. | 491 * `elements.iterator`. |
471 * | 492 * |
472 * All `elements` should be assignable to [E]. | 493 * All `elements` should be assignable to [E]. |
473 */ | 494 */ |
474 factory ListQueue.from(Iterable elements) { | 495 factory ListQueue.from(Iterable elements) { |
475 if (elements is List) { | 496 if (elements is List) { |
476 int length = elements.length; | 497 int length = elements.length; |
477 ListQueue<E> queue = new ListQueue(length + 1); | 498 ListQueue<E> queue = new ListQueue(length + 1); |
478 assert(queue._table.length > length); | 499 assert(queue._table.length > length); |
479 List sourceList = elements; | 500 for (int i = 0; i < length; i++) { |
480 queue._table.setRange(0, length, sourceList, 0); | 501 queue._table[i] = elements[i] as E; |
sra1
2016/05/06 18:12:17
fix
floitsch
2016/05/10 14:12:31
Done.
| |
502 } | |
481 queue._tail = length; | 503 queue._tail = length; |
482 return queue; | 504 return queue; |
483 } else { | 505 } else { |
484 int capacity = _INITIAL_CAPACITY; | 506 int capacity = _INITIAL_CAPACITY; |
485 if (elements is EfficientLength) { | 507 if (elements is EfficientLength) { |
486 capacity = elements.length; | 508 capacity = elements.length; |
487 } | 509 } |
488 ListQueue<E> result = new ListQueue<E>(capacity); | 510 ListQueue<E> result = new ListQueue<E>(capacity); |
489 for (final E element in elements) { | 511 for (final element in elements) { |
490 result.addLast(element); | 512 result.addLast(element as E); |
sra1
2016/05/06 18:12:17
fix
floitsch
2016/05/10 14:12:31
Done.
| |
491 } | 513 } |
492 return result; | 514 return result; |
493 } | 515 } |
494 } | 516 } |
495 | 517 |
496 // Iterable interface. | 518 // Iterable interface. |
497 | 519 |
498 Iterator<E> get iterator => new _ListQueueIterator<E>(this); | 520 Iterator<E> get iterator => new _ListQueueIterator<E>(this); |
499 | 521 |
500 void forEach(void action (E element)) { | 522 void forEach(void action (E element)) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 return list; | 563 return list; |
542 } | 564 } |
543 | 565 |
544 // Collection interface. | 566 // Collection interface. |
545 | 567 |
546 void add(E value) { | 568 void add(E value) { |
547 _add(value); | 569 _add(value); |
548 } | 570 } |
549 | 571 |
550 void addAll(Iterable<E> elements) { | 572 void addAll(Iterable<E> elements) { |
551 if (elements is List) { | 573 if (elements is List/*<E>*/) { |
552 List list = elements; | 574 List<E> list = elements; |
553 int addCount = list.length; | 575 int addCount = list.length; |
554 int length = this.length; | 576 int length = this.length; |
555 if (length + addCount >= _table.length) { | 577 if (length + addCount >= _table.length) { |
556 _preGrow(length + addCount); | 578 _preGrow(length + addCount); |
557 // After preGrow, all elements are at the start of the list. | 579 // After preGrow, all elements are at the start of the list. |
558 _table.setRange(length, length + addCount, list, 0); | 580 _table.setRange(length, length + addCount, list, 0); |
559 _tail += addCount; | 581 _tail += addCount; |
560 } else { | 582 } else { |
561 // Adding addCount elements won't reach _head. | 583 // Adding addCount elements won't reach _head. |
562 int endSpace = _table.length - _tail; | 584 int endSpace = _table.length - _tail; |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
785 _head = 0; | 807 _head = 0; |
786 } | 808 } |
787 } | 809 } |
788 | 810 |
789 /** | 811 /** |
790 * Iterator for a [ListQueue]. | 812 * Iterator for a [ListQueue]. |
791 * | 813 * |
792 * Considers any add or remove operation a concurrent modification. | 814 * Considers any add or remove operation a concurrent modification. |
793 */ | 815 */ |
794 class _ListQueueIterator<E> implements Iterator<E> { | 816 class _ListQueueIterator<E> implements Iterator<E> { |
795 final ListQueue _queue; | 817 final ListQueue<E> _queue; |
796 final int _end; | 818 final int _end; |
797 final int _modificationCount; | 819 final int _modificationCount; |
798 int _position; | 820 int _position; |
799 E _current; | 821 E _current; |
800 | 822 |
801 _ListQueueIterator(ListQueue queue) | 823 _ListQueueIterator(ListQueue<E> queue) |
802 : _queue = queue, | 824 : _queue = queue, |
803 _end = queue._tail, | 825 _end = queue._tail, |
804 _modificationCount = queue._modificationCount, | 826 _modificationCount = queue._modificationCount, |
805 _position = queue._head; | 827 _position = queue._head; |
806 | 828 |
807 E get current => _current; | 829 E get current => _current; |
808 | 830 |
809 bool moveNext() { | 831 bool moveNext() { |
810 _queue._checkModification(_modificationCount); | 832 _queue._checkModification(_modificationCount); |
811 if (_position == _end) { | 833 if (_position == _end) { |
812 _current = null; | 834 _current = null; |
813 return false; | 835 return false; |
814 } | 836 } |
815 _current = _queue._table[_position]; | 837 _current = _queue._table[_position]; |
816 _position = (_position + 1) & (_queue._table.length - 1); | 838 _position = (_position + 1) & (_queue._table.length - 1); |
817 return true; | 839 return true; |
818 } | 840 } |
819 } | 841 } |
OLD | NEW |