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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 * Adds [value] at the end of the queue. | 60 * Adds [value] at the end of the queue. |
61 */ | 61 */ |
62 void add(E value); | 62 void add(E value); |
63 | 63 |
64 /** | 64 /** |
65 * Remove a single instance of [value] from the queue. | 65 * Remove a single instance of [value] from the queue. |
66 * | 66 * |
67 * Returns `true` if a value was removed, or `false` if the queue | 67 * Returns `true` if a value was removed, or `false` if the queue |
68 * contained no element equal to [value]. | 68 * contained no element equal to [value]. |
69 */ | 69 */ |
70 bool remove(Object object); | 70 bool remove(Object value); |
71 | 71 |
72 /** | 72 /** |
73 * Adds all elements of [iterable] at the end of the queue. The | 73 * Adds all elements of [iterable] at the end of the queue. The |
74 * length of the queue is extended by the length of [iterable]. | 74 * length of the queue is extended by the length of [iterable]. |
75 */ | 75 */ |
76 void addAll(Iterable<E> iterable); | 76 void addAll(Iterable<E> iterable); |
77 | 77 |
78 /** | 78 /** |
79 * Removes all elements matched by [test] from the queue. | 79 * Removes all elements matched by [test] from the queue. |
80 * | 80 * |
81 * The `test` function must not throw or modify the queue. | 81 * The `test` function must not throw or modify the queue. |
82 */ | 82 */ |
83 void removeWhere(bool test(E element)); | 83 void removeWhere(bool test(E element)); |
84 | 84 |
85 /** | 85 /** |
86 * Removes all elements not matched by [test] from the queue. | 86 * Removes all elements not matched by [test] from the queue. |
87 * | 87 * |
88 * The `test` function must not throw or modify the queue. | 88 * The `test` function must not throw or modify the queue. |
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> { |
| 100 E _previousLink; |
| 101 E _nextLink; |
| 102 |
| 103 void _link(E previous, E next) { |
| 104 _nextLink = next; |
| 105 _previousLink = previous; |
| 106 if (previous != null) previous._nextLink = this; |
| 107 if (next != null) next._previousLink = this; |
| 108 } |
| 109 |
| 110 void _unlink() { |
| 111 if (_previousLink != null) _previousLink._nextLink = _nextLink; |
| 112 if (_nextLink != null) _nextLink._previousLink = _previousLink; |
| 113 _nextLink = null; |
| 114 _previousLink = null; |
| 115 } |
| 116 } |
| 117 |
99 /** | 118 /** |
100 * 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 |
101 * entry, the previous entry, and the boxed element. | 120 * entry, the previous entry, and the boxed element. |
102 */ | 121 */ |
103 class DoubleLinkedQueueEntry<E> { | 122 abstract class DoubleLinkedQueueEntry<E> { |
104 DoubleLinkedQueueEntry<E> _previous; | 123 factory DoubleLinkedQueueEntry(E element) = _UserDoubleLinkedQueueEntry<E>; |
105 DoubleLinkedQueueEntry<E> _next; | |
106 E _element; | |
107 | 124 |
108 DoubleLinkedQueueEntry(E e) : _element = e; | 125 /// The element in the queue. |
| 126 E get element; |
109 | 127 |
110 void _link(DoubleLinkedQueueEntry<E> previous, | 128 /// Appends the given [e] as entry just after this entry. |
111 DoubleLinkedQueueEntry<E> next) { | 129 void append(E e); |
112 _next = next; | 130 |
113 _previous = previous; | 131 /// Prepends the given [e] as entry just before this entry. |
114 previous._next = this; | 132 void prepend(E e); |
115 next._previous = this; | 133 |
116 } | 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); |
117 | 152 |
118 void append(E e) { | 153 void append(E e) { |
119 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); | 154 new _UserDoubleLinkedQueueEntry<E>(e)._link(this, _nextLink); |
120 } | 155 } |
121 | 156 |
122 void prepend(E e) { | 157 void prepend(E e) { |
123 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); | 158 new _UserDoubleLinkedQueueEntry<E>(e)._link(_previousLink, this); |
124 } | 159 } |
125 | 160 |
126 E remove() { | 161 E remove() { |
127 _previous._next = _next; | 162 _unlink(); |
128 _next._previous = _previous; | 163 return element; |
129 _next = null; | |
130 _previous = null; | |
131 return _element; | |
132 } | 164 } |
133 | 165 |
134 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 166 DoubleLinkedQueueEntry<E> previousEntry() => _previousLink; |
135 return this; | 167 |
| 168 DoubleLinkedQueueEntry<E> nextEntry() => _nextLink; |
| 169 } |
| 170 |
| 171 /** |
| 172 * Interface for the link classes used by [DoubleLinkedQueue]. |
| 173 * |
| 174 * Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] |
| 175 * implement this interface. |
| 176 * The entry contains a link back to the queue, so calling `append` |
| 177 * or `prepend` can correctly update the element count. |
| 178 */ |
| 179 abstract class _DoubleLinkedQueueEntry<E> |
| 180 extends _DoubleLink<_DoubleLinkedQueueEntry<E>> { |
| 181 DoubleLinkedQueue<E> _queue; |
| 182 _DoubleLinkedQueueEntry(this._queue); |
| 183 |
| 184 DoubleLinkedQueueEntry<E> _asNonSentinelEntry(); |
| 185 |
| 186 void _append(E e) { |
| 187 new _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink); |
| 188 } |
| 189 |
| 190 void _prepend(E e) { |
| 191 new _DoubleLinkedQueueElement<E>(e, _queue)._link(_previousLink, this); |
| 192 } |
| 193 |
| 194 E _remove(); |
| 195 |
| 196 E get element; |
| 197 |
| 198 DoubleLinkedQueueEntry<E> nextEntry() { |
| 199 return _nextLink._asNonSentinelEntry(); |
136 } | 200 } |
137 | 201 |
138 DoubleLinkedQueueEntry<E> previousEntry() { | 202 DoubleLinkedQueueEntry<E> previousEntry() { |
139 return _previous._asNonSentinelEntry(); | 203 return _previousLink._asNonSentinelEntry(); |
140 } | |
141 | |
142 DoubleLinkedQueueEntry<E> nextEntry() { | |
143 return _next._asNonSentinelEntry(); | |
144 } | |
145 | |
146 E get element { | |
147 return _element; | |
148 } | |
149 | |
150 void set element(E e) { | |
151 _element = e; | |
152 } | 204 } |
153 } | 205 } |
154 | 206 |
| 207 /** |
| 208 * The actual entry type used by the [DoubleLinkedQueue]. |
| 209 * |
| 210 * The entry contains a reference to the queue, allowing |
| 211 * [append]/[prepend] to update the list length. |
| 212 */ |
| 213 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> |
| 214 implements DoubleLinkedQueueEntry<E> { |
| 215 E element; |
| 216 _DoubleLinkedQueueElement(this.element, DoubleLinkedQueue<E> queue) |
| 217 : super(queue); |
| 218 |
| 219 void append(E e) { |
| 220 _append(e); |
| 221 if (_queue != null) _queue._elementCount++; |
| 222 } |
| 223 |
| 224 void prepend(E e) { |
| 225 _prepend(e); |
| 226 if (_queue != null) _queue._elementCount++; |
| 227 } |
| 228 |
| 229 E _remove() { |
| 230 _queue = null; |
| 231 _unlink(); |
| 232 return element; |
| 233 } |
| 234 |
| 235 E remove() { |
| 236 if (_queue != null) _queue._elementCount--; |
| 237 return _remove(); |
| 238 } |
| 239 |
| 240 _DoubleLinkedQueueElement<E> _asNonSentinelEntry() { |
| 241 return this; |
| 242 } |
| 243 } |
| 244 |
155 /** | 245 /** |
156 * 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 |
157 * at both ends. | 247 * at both ends. |
158 * A double linked list has exactly one sentinel, | 248 * A double linked list has exactly one sentinel, |
159 * which is the only entry when the list is constructed. | 249 * which is the only entry when the list is constructed. |
160 * 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. |
161 * A sentinel does not box any user element. | 251 * A sentinel does not box any user element. |
162 */ | 252 */ |
163 class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { | 253 class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { |
164 _DoubleLinkedQueueEntrySentinel() : super(null) { | 254 _DoubleLinkedQueueSentinel(DoubleLinkedQueue<E> queue) : super(queue) { |
165 _link(this, this); | 255 _previousLink = this; |
166 } | 256 _nextLink = this; |
167 | |
168 E remove() { | |
169 throw IterableElementError.noElement(); | |
170 } | 257 } |
171 | 258 |
172 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | 259 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { |
173 return null; | 260 return null; |
174 } | 261 } |
175 | 262 |
176 void set element(E e) { | 263 /** Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. */ |
177 // This setter is unreachable. | 264 E _remove() { |
178 // TODO(lrn): Don't inherit the field if we don't use it. | 265 throw IterableElementError.noElement(); |
179 assert(false); | |
180 } | 266 } |
181 | 267 |
| 268 /** Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. */ |
182 E get element { | 269 E get element { |
183 throw IterableElementError.noElement(); | 270 throw IterableElementError.noElement(); |
184 } | 271 } |
185 } | 272 } |
186 | 273 |
187 /** | 274 /** |
188 * A [Queue] implementation based on a double-linked list. | 275 * A [Queue] implementation based on a double-linked list. |
189 * | 276 * |
190 * Allows constant time add, remove-at-ends and peek operations. | 277 * Allows constant time add, remove-at-ends and peek operations. |
191 */ | 278 */ |
192 class DoubleLinkedQueue<E> extends IterableBase<E> implements Queue<E> { | 279 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { |
193 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 280 _DoubleLinkedQueueSentinel<E> _sentinel; |
194 int _elementCount = 0; | 281 int _elementCount = 0; |
195 | 282 |
196 DoubleLinkedQueue() { | 283 DoubleLinkedQueue() { |
197 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | 284 _sentinel = new _DoubleLinkedQueueSentinel<E>(this); |
198 } | 285 } |
199 | 286 |
200 /** | 287 /** |
201 * Creates a double-linked queue containing all [elements]. | 288 * Creates a double-linked queue containing all [elements]. |
202 * | 289 * |
203 * 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 |
204 * [addLast] in the order provided by [elements.iterator]. | 291 * [addLast] in the order provided by [elements.iterator]. |
205 */ | 292 */ |
206 factory DoubleLinkedQueue.from(Iterable elements) { | 293 factory DoubleLinkedQueue.from(Iterable elements) { |
207 Queue<E> list = new DoubleLinkedQueue(); | 294 Queue<E> list = new DoubleLinkedQueue<E>(); |
208 for (final E e in elements) { | 295 for (final e in elements) { |
209 list.addLast(e); | 296 list.addLast(e as E); |
210 } | 297 } |
211 return list; | 298 return list; |
212 } | 299 } |
213 | 300 |
214 int get length => _elementCount; | 301 int get length => _elementCount; |
215 | 302 |
216 void addLast(E value) { | 303 void addLast(E value) { |
217 _sentinel.prepend(value); | 304 _sentinel._prepend(value); |
218 _elementCount++; | 305 _elementCount++; |
219 } | 306 } |
220 | 307 |
221 void addFirst(E value) { | 308 void addFirst(E value) { |
222 _sentinel.append(value); | 309 _sentinel._append(value); |
223 _elementCount++; | 310 _elementCount++; |
224 } | 311 } |
225 | 312 |
226 void add(E value) { | 313 void add(E value) { |
227 _sentinel.prepend(value); | 314 _sentinel._prepend(value); |
228 _elementCount++; | 315 _elementCount++; |
229 } | 316 } |
230 | 317 |
231 void addAll(Iterable<E> iterable) { | 318 void addAll(Iterable<E> iterable) { |
232 for (final E value in iterable) { | 319 for (final E value in iterable) { |
233 _sentinel.prepend(value); | 320 _sentinel._prepend(value); |
234 _elementCount++; | 321 _elementCount++; |
235 } | 322 } |
236 } | 323 } |
237 | 324 |
238 E removeLast() { | 325 E removeLast() { |
239 E result = _sentinel._previous.remove(); | 326 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
| 327 E result = lastEntry._remove(); |
240 _elementCount--; | 328 _elementCount--; |
241 return result; | 329 return result; |
242 } | 330 } |
243 | 331 |
244 E removeFirst() { | 332 E removeFirst() { |
245 E result = _sentinel._next.remove(); | 333 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
| 334 E result = firstEntry._remove(); |
246 _elementCount--; | 335 _elementCount--; |
247 return result; | 336 return result; |
248 } | 337 } |
249 | 338 |
250 bool remove(Object o) { | 339 bool remove(Object o) { |
251 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 340 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
252 while (!identical(entry, _sentinel)) { | 341 while (!identical(entry, _sentinel)) { |
253 if (entry.element == o) { | 342 if (entry.element == o) { |
254 entry.remove(); | 343 entry._remove(); |
255 _elementCount--; | 344 _elementCount--; |
256 return true; | 345 return true; |
257 } | 346 } |
258 entry = entry._next; | 347 entry = entry._nextLink; |
259 } | 348 } |
260 return false; | 349 return false; |
261 } | 350 } |
262 | 351 |
263 void _filter(bool test(E element), bool removeMatching) { | 352 void _filter(bool test(E element), bool removeMatching) { |
264 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 353 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
265 while (!identical(entry, _sentinel)) { | 354 while (!identical(entry, _sentinel)) { |
266 DoubleLinkedQueueEntry<E> next = entry._next; | 355 _DoubleLinkedQueueEntry<E> next = entry._nextLink; |
267 if (identical(removeMatching, test(entry.element))) { | 356 if (identical(removeMatching, test(entry.element))) { |
268 entry.remove(); | 357 entry._remove(); |
269 _elementCount--; | 358 _elementCount--; |
270 } | 359 } |
271 entry = next; | 360 entry = next; |
272 } | 361 } |
273 } | 362 } |
274 | 363 |
275 void removeWhere(bool test(E element)) { | 364 void removeWhere(bool test(E element)) { |
276 _filter(test, true); | 365 _filter(test, true); |
277 } | 366 } |
278 | 367 |
279 void retainWhere(bool test(E element)) { | 368 void retainWhere(bool test(E element)) { |
280 _filter(test, false); | 369 _filter(test, false); |
281 } | 370 } |
282 | 371 |
283 E get first { | 372 E get first { |
284 return _sentinel._next.element; | 373 _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink; |
| 374 return firstEntry.element; |
285 } | 375 } |
286 | 376 |
287 E get last { | 377 E get last { |
288 return _sentinel._previous.element; | 378 _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink; |
| 379 return lastEntry.element; |
289 } | 380 } |
290 | 381 |
291 E get single { | 382 E get single { |
292 // Note that this throws correctly if the queue is empty. | 383 // Note that this throws correctly if the queue is empty |
293 if (identical(_sentinel._next, _sentinel._previous)) { | 384 // because reading element on the sentinel throws. |
294 return _sentinel._next.element; | 385 if (identical(_sentinel._nextLink, _sentinel._previousLink)) { |
| 386 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
| 387 return entry.element; |
295 } | 388 } |
296 throw IterableElementError.tooMany(); | 389 throw IterableElementError.tooMany(); |
297 } | 390 } |
298 | 391 |
299 DoubleLinkedQueueEntry<E> lastEntry() { | 392 DoubleLinkedQueueEntry<E> lastEntry() { |
300 return _sentinel.previousEntry(); | 393 return _sentinel.previousEntry(); |
301 } | 394 } |
302 | 395 |
303 DoubleLinkedQueueEntry<E> firstEntry() { | 396 DoubleLinkedQueueEntry<E> firstEntry() { |
304 return _sentinel.nextEntry(); | 397 return _sentinel.nextEntry(); |
305 } | 398 } |
306 | 399 |
307 bool get isEmpty { | 400 bool get isEmpty { |
308 return (identical(_sentinel._next, _sentinel)); | 401 return (identical(_sentinel._nextLink, _sentinel)); |
309 } | 402 } |
310 | 403 |
311 void clear() { | 404 void clear() { |
312 _sentinel._next = _sentinel; | 405 _sentinel._nextLink = _sentinel; |
313 _sentinel._previous = _sentinel; | 406 _sentinel._previousLink = _sentinel; |
314 _elementCount = 0; | 407 _elementCount = 0; |
315 } | 408 } |
316 | 409 |
317 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | 410 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { |
318 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 411 _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink; |
319 while (!identical(entry, _sentinel)) { | 412 while (!identical(entry, _sentinel)) { |
320 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | 413 _DoubleLinkedQueueEntry<E> nextEntry = entry._nextLink; |
321 f(entry); | 414 _DoubleLinkedQueueElement<E> element = entry; |
| 415 f(element); |
322 entry = nextEntry; | 416 entry = nextEntry; |
323 } | 417 } |
324 } | 418 } |
325 | 419 |
326 _DoubleLinkedQueueIterator<E> get iterator { | 420 _DoubleLinkedQueueIterator<E> get iterator { |
327 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 421 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
328 } | 422 } |
329 | 423 |
330 String toString() => IterableBase.iterableToFullString(this, '{', '}'); | 424 String toString() => IterableBase.iterableToFullString(this, '{', '}'); |
331 } | 425 } |
332 | 426 |
333 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 427 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
334 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 428 _DoubleLinkedQueueSentinel<E> _sentinel; |
335 DoubleLinkedQueueEntry<E> _nextEntry = null; | 429 _DoubleLinkedQueueEntry<E> _nextEntry = null; |
336 E _current; | 430 E _current; |
337 | 431 |
338 _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel<E> sentinel) | 432 _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel) |
339 : _sentinel = sentinel, _nextEntry = sentinel._next; | 433 : _sentinel = sentinel, |
| 434 _nextEntry = sentinel._nextLink; |
340 | 435 |
341 bool moveNext() { | 436 bool moveNext() { |
342 // When [_currentEntry] it is set to [:null:] then it is at the end. | 437 if (identical(_nextEntry, _sentinel)) { |
343 if (!identical(_nextEntry, _sentinel)) { | 438 _current = null; |
344 _current = _nextEntry._element; | 439 _nextEntry = null; |
345 _nextEntry = _nextEntry._next; | 440 _sentinel = null; |
346 return true; | 441 return false; |
347 } | 442 } |
348 _current = null; | 443 _DoubleLinkedQueueElement<E> elementEntry = _nextEntry; |
349 _nextEntry = _sentinel = null; // Still identical. | 444 if (elementEntry._queue == null) { |
350 return false; | 445 throw new ConcurrentModificationError(_sentinel._queue); |
| 446 } |
| 447 _current = elementEntry.element; |
| 448 _nextEntry = elementEntry._nextLink; |
| 449 return true; |
351 } | 450 } |
352 | 451 |
353 E get current => _current; | 452 E get current => _current; |
354 } | 453 } |
355 | 454 |
356 /** | 455 /** |
357 * List based [Queue]. | 456 * List based [Queue]. |
358 * | 457 * |
359 * Keeps a cyclic buffer of elements, and grows to a larger buffer when | 458 * 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 | 459 * it fills up. This guarantees constant time peek and remove operations, and |
361 * amortized constant time add operations. | 460 * amortized constant time add operations. |
362 * | 461 * |
363 * The structure is efficient for any queue or stack usage. | 462 * The structure is efficient for any queue or stack usage. |
364 */ | 463 */ |
365 class ListQueue<E> extends IterableBase<E> implements Queue<E> { | 464 class ListQueue<E> extends Iterable<E> implements Queue<E> { |
366 static const int _INITIAL_CAPACITY = 8; | 465 static const int _INITIAL_CAPACITY = 8; |
367 List<E> _table; | 466 List<E> _table; |
368 int _head; | 467 int _head; |
369 int _tail; | 468 int _tail; |
370 int _modificationCount = 0; | 469 int _modificationCount = 0; |
371 | 470 |
372 /** | 471 /** |
373 * Create an empty queue. | 472 * Create an empty queue. |
374 * | 473 * |
375 * If [initialCapacity] is given, prepare the queue for at least that many | 474 * If [initialCapacity] is given, prepare the queue for at least that many |
(...skipping 15 matching lines...) Expand all Loading... |
391 * 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 |
392 * `elements.iterator`. | 491 * `elements.iterator`. |
393 * | 492 * |
394 * All `elements` should be assignable to [E]. | 493 * All `elements` should be assignable to [E]. |
395 */ | 494 */ |
396 factory ListQueue.from(Iterable elements) { | 495 factory ListQueue.from(Iterable elements) { |
397 if (elements is List) { | 496 if (elements is List) { |
398 int length = elements.length; | 497 int length = elements.length; |
399 ListQueue<E> queue = new ListQueue(length + 1); | 498 ListQueue<E> queue = new ListQueue(length + 1); |
400 assert(queue._table.length > length); | 499 assert(queue._table.length > length); |
401 List sourceList = elements; | 500 for (int i = 0; i < length; i++) { |
402 queue._table.setRange(0, length, sourceList, 0); | 501 queue._table[i] = elements[i] as E; |
| 502 } |
403 queue._tail = length; | 503 queue._tail = length; |
404 return queue; | 504 return queue; |
405 } else { | 505 } else { |
406 int capacity = _INITIAL_CAPACITY; | 506 int capacity = _INITIAL_CAPACITY; |
407 if (elements is EfficientLength) { | 507 if (elements is EfficientLength) { |
408 capacity = elements.length; | 508 capacity = elements.length; |
409 } | 509 } |
410 ListQueue<E> result = new ListQueue<E>(capacity); | 510 ListQueue<E> result = new ListQueue<E>(capacity); |
411 for (final E element in elements) { | 511 for (final element in elements) { |
412 result.addLast(element); | 512 result.addLast(element as E); |
413 } | 513 } |
414 return result; | 514 return result; |
415 } | 515 } |
416 } | 516 } |
417 | 517 |
418 // Iterable interface. | 518 // Iterable interface. |
419 | 519 |
420 Iterator<E> get iterator => new _ListQueueIterator<E>(this); | 520 Iterator<E> get iterator => new _ListQueueIterator<E>(this); |
421 | 521 |
422 void forEach(void action (E element)) { | 522 void forEach(void action (E element)) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 list = new List<E>()..length = length; | 558 list = new List<E>()..length = length; |
459 } else { | 559 } else { |
460 list = new List<E>(length); | 560 list = new List<E>(length); |
461 } | 561 } |
462 _writeToList(list); | 562 _writeToList(list); |
463 return list; | 563 return list; |
464 } | 564 } |
465 | 565 |
466 // Collection interface. | 566 // Collection interface. |
467 | 567 |
468 void add(E element) { | 568 void add(E value) { |
469 _add(element); | 569 _add(value); |
470 } | 570 } |
471 | 571 |
472 void addAll(Iterable<E> elements) { | 572 void addAll(Iterable<E> elements) { |
473 if (elements is List) { | 573 if (elements is List/*<E>*/) { |
474 List list = elements; | 574 List<E> list = elements; |
475 int addCount = list.length; | 575 int addCount = list.length; |
476 int length = this.length; | 576 int length = this.length; |
477 if (length + addCount >= _table.length) { | 577 if (length + addCount >= _table.length) { |
478 _preGrow(length + addCount); | 578 _preGrow(length + addCount); |
479 // After preGrow, all elements are at the start of the list. | 579 // After preGrow, all elements are at the start of the list. |
480 _table.setRange(length, length + addCount, list, 0); | 580 _table.setRange(length, length + addCount, list, 0); |
481 _tail += addCount; | 581 _tail += addCount; |
482 } else { | 582 } else { |
483 // Adding addCount elements won't reach _head. | 583 // Adding addCount elements won't reach _head. |
484 int endSpace = _table.length - _tail; | 584 int endSpace = _table.length - _tail; |
485 if (addCount < endSpace) { | 585 if (addCount < endSpace) { |
486 _table.setRange(_tail, _tail + addCount, list, 0); | 586 _table.setRange(_tail, _tail + addCount, list, 0); |
487 _tail += addCount; | 587 _tail += addCount; |
488 } else { | 588 } else { |
489 int preSpace = addCount - endSpace; | 589 int preSpace = addCount - endSpace; |
490 _table.setRange(_tail, _tail + endSpace, list, 0); | 590 _table.setRange(_tail, _tail + endSpace, list, 0); |
491 _table.setRange(0, preSpace, list, endSpace); | 591 _table.setRange(0, preSpace, list, endSpace); |
492 _tail = preSpace; | 592 _tail = preSpace; |
493 } | 593 } |
494 } | 594 } |
495 _modificationCount++; | 595 _modificationCount++; |
496 } else { | 596 } else { |
497 for (E element in elements) _add(element); | 597 for (E element in elements) _add(element); |
498 } | 598 } |
499 } | 599 } |
500 | 600 |
501 bool remove(Object object) { | 601 bool remove(Object value) { |
502 for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { | 602 for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { |
503 E element = _table[i]; | 603 E element = _table[i]; |
504 if (element == object) { | 604 if (element == value) { |
505 _remove(i); | 605 _remove(i); |
506 _modificationCount++; | 606 _modificationCount++; |
507 return true; | 607 return true; |
508 } | 608 } |
509 } | 609 } |
510 return false; | 610 return false; |
511 } | 611 } |
512 | 612 |
513 void _filterWhere(bool test(E element), bool removeMatching) { | 613 void _filterWhere(bool test(E element), bool removeMatching) { |
514 int index = _head; | |
515 int modificationCount = _modificationCount; | 614 int modificationCount = _modificationCount; |
516 int i = _head; | 615 int i = _head; |
517 while (i != _tail) { | 616 while (i != _tail) { |
518 E element = _table[i]; | 617 E element = _table[i]; |
519 bool remove = identical(removeMatching, test(element)); | 618 bool remove = identical(removeMatching, test(element)); |
520 _checkModification(modificationCount); | 619 _checkModification(modificationCount); |
521 if (remove) { | 620 if (remove) { |
522 i = _remove(i); | 621 i = _remove(i); |
523 modificationCount = ++_modificationCount; | 622 modificationCount = ++_modificationCount; |
524 } else { | 623 } else { |
(...skipping 29 matching lines...) Expand all Loading... |
554 } | 653 } |
555 _head = _tail = 0; | 654 _head = _tail = 0; |
556 _modificationCount++; | 655 _modificationCount++; |
557 } | 656 } |
558 } | 657 } |
559 | 658 |
560 String toString() => IterableBase.iterableToFullString(this, "{", "}"); | 659 String toString() => IterableBase.iterableToFullString(this, "{", "}"); |
561 | 660 |
562 // Queue interface. | 661 // Queue interface. |
563 | 662 |
564 void addLast(E element) { _add(element); } | 663 void addLast(E value) { _add(value); } |
565 | 664 |
566 void addFirst(E element) { | 665 void addFirst(E value) { |
567 _head = (_head - 1) & (_table.length - 1); | 666 _head = (_head - 1) & (_table.length - 1); |
568 _table[_head] = element; | 667 _table[_head] = value; |
569 if (_head == _tail) _grow(); | 668 if (_head == _tail) _grow(); |
570 _modificationCount++; | 669 _modificationCount++; |
571 } | 670 } |
572 | 671 |
573 E removeFirst() { | 672 E removeFirst() { |
574 if (_head == _tail) throw IterableElementError.noElement(); | 673 if (_head == _tail) throw IterableElementError.noElement(); |
575 _modificationCount++; | 674 _modificationCount++; |
576 E result = _table[_head]; | 675 E result = _table[_head]; |
577 _table[_head] = null; | 676 _table[_head] = null; |
578 _head = (_head + 1) & (_table.length - 1); | 677 _head = (_head + 1) & (_table.length - 1); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 _head = 0; | 807 _head = 0; |
709 } | 808 } |
710 } | 809 } |
711 | 810 |
712 /** | 811 /** |
713 * Iterator for a [ListQueue]. | 812 * Iterator for a [ListQueue]. |
714 * | 813 * |
715 * Considers any add or remove operation a concurrent modification. | 814 * Considers any add or remove operation a concurrent modification. |
716 */ | 815 */ |
717 class _ListQueueIterator<E> implements Iterator<E> { | 816 class _ListQueueIterator<E> implements Iterator<E> { |
718 final ListQueue _queue; | 817 final ListQueue<E> _queue; |
719 final int _end; | 818 final int _end; |
720 final int _modificationCount; | 819 final int _modificationCount; |
721 int _position; | 820 int _position; |
722 E _current; | 821 E _current; |
723 | 822 |
724 _ListQueueIterator(ListQueue queue) | 823 _ListQueueIterator(ListQueue<E> queue) |
725 : _queue = queue, | 824 : _queue = queue, |
726 _end = queue._tail, | 825 _end = queue._tail, |
727 _modificationCount = queue._modificationCount, | 826 _modificationCount = queue._modificationCount, |
728 _position = queue._head; | 827 _position = queue._head; |
729 | 828 |
730 E get current => _current; | 829 E get current => _current; |
731 | 830 |
732 bool moveNext() { | 831 bool moveNext() { |
733 _queue._checkModification(_modificationCount); | 832 _queue._checkModification(_modificationCount); |
734 if (_position == _end) { | 833 if (_position == _end) { |
735 _current = null; | 834 _current = null; |
736 return false; | 835 return false; |
737 } | 836 } |
738 _current = _queue._table[_position]; | 837 _current = _queue._table[_position]; |
739 _position = (_position + 1) & (_queue._table.length - 1); | 838 _position = (_position + 1) & (_queue._table.length - 1); |
740 return true; | 839 return true; |
741 } | 840 } |
742 } | 841 } |
OLD | NEW |