|  | // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | part of dart.collection; | 
|  |  | 
|  | /// Helper interface to hide [EfficientLengthIterable] from the public | 
|  | /// declaration of [Queue]. | 
|  | abstract class _QueueIterable<E> | 
|  | implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {} | 
|  |  | 
|  | /// A [Queue] is a collection that can be manipulated at both ends. One | 
|  | /// can iterate over the elements of a queue through [forEach] or with | 
|  | /// an [Iterator]. | 
|  | /// | 
|  | /// It is generally not allowed to modify the queue (add or remove entries) | 
|  | /// while an operation in the queue is being performed, for example during a | 
|  | /// call to [forEach]. | 
|  | /// Modifying the queue while it is being iterated will most likely break the | 
|  | /// iteration. | 
|  | /// This goes both for using the [iterator] directly, or for iterating an | 
|  | /// `Iterable` returned by a method like [map] or [where]. | 
|  | /// | 
|  | /// Example: | 
|  | /// ```dart | 
|  | /// final queue = Queue<int>(); // ListQueue() by default | 
|  | /// print(queue.runtimeType); // ListQueue | 
|  | /// | 
|  | /// // Adding items to queue | 
|  | /// queue.addAll([1, 2, 3]); | 
|  | /// queue.addFirst(0); | 
|  | /// queue.addLast(10); | 
|  | /// print(queue); // {0, 1, 2, 3, 10} | 
|  | /// | 
|  | /// // Removing items from queue | 
|  | /// queue.removeFirst(); | 
|  | /// queue.removeLast(); | 
|  | /// print(queue); // {1, 2, 3} | 
|  | /// ``` | 
|  | abstract interface class Queue<E> implements Iterable<E>, _QueueIterable<E> { | 
|  | /// Creates a queue. | 
|  | factory Queue() = ListQueue<E>; | 
|  |  | 
|  | /// Creates a queue containing all [elements]. | 
|  | /// | 
|  | /// The element order in the queue is as if the elements were added using | 
|  | /// [addLast] in the order provided by [elements].iterator. | 
|  | /// | 
|  | /// All the [elements] should be instances of [E]. | 
|  | /// The `elements` iterable itself may have any element type, so this | 
|  | /// constructor can be used to down-cast a `Queue`, for example as: | 
|  | /// ```dart | 
|  | /// Queue<SuperType> superQueue = ...; | 
|  | /// Queue<SubType> subQueue = | 
|  | ///     Queue<SubType>.from(superQueue.whereType<SubType>()); | 
|  | /// ``` | 
|  | factory Queue.from(Iterable elements) = ListQueue<E>.from; | 
|  |  | 
|  | /// Creates a queue from [elements]. | 
|  | /// | 
|  | /// The element order in the queue is as if the elements were added using | 
|  | /// [addLast] in the order provided by [elements].iterator. | 
|  | factory Queue.of(Iterable<E> elements) = ListQueue<E>.of; | 
|  |  | 
|  | /// Adapts [source] to be a `Queue<T>`. | 
|  | /// | 
|  | /// Any time the queue would produce an element that is not a [T], | 
|  | /// the element access will throw. | 
|  | /// | 
|  | /// When a [T] value is stored into the adapted queue, | 
|  | /// the operation will throw unless the value is also an instance of [S]. | 
|  | /// | 
|  | /// If all accessed elements of [source] are actually instances of [T], | 
|  | /// and if all elements stored into the returned queue are actually instances | 
|  | /// of [S], | 
|  | /// then the returned queue can be used as a `Queue<T>`. | 
|  | /// | 
|  | /// Methods which accept `Object?` as argument, like [contains] and [remove], | 
|  | /// will pass the argument directly to this queue's method | 
|  | /// without any checks. | 
|  | static Queue<T> castFrom<S, T>(Queue<S> source) => CastQueue<S, T>(source); | 
|  |  | 
|  | /// Provides a view of this queue as a queue of [R] instances, if necessary. | 
|  | /// | 
|  | /// If this queue contains only instances of [R], all read operations | 
|  | /// will work correctly. If any operation tries to access an element | 
|  | /// that is not an instance of [R], the access will throw instead. | 
|  | /// | 
|  | /// Elements added to the queue (e.g., by using [addFirst] or [addAll]) | 
|  | /// must be instances of [R] to be valid arguments to the adding function, | 
|  | /// and they must also be instances of [E] to be accepted by | 
|  | /// this queue as well. | 
|  | /// | 
|  | /// Methods which accept `Object?` as argument, like [contains] and [remove], | 
|  | /// will pass the argument directly to the this queue's method | 
|  | /// without any checks. | 
|  | /// That means that you can do `queueOfStrings.cast<int>().remove("a")` | 
|  | /// successfully, even if it looks like it shouldn't have any effect. | 
|  | Queue<R> cast<R>(); | 
|  |  | 
|  | /// Removes and returns the first element of this queue. | 
|  | /// | 
|  | /// The queue must not be empty when this method is called. | 
|  | E removeFirst(); | 
|  |  | 
|  | /// Removes and returns the last element of the queue. | 
|  | /// | 
|  | /// The queue must not be empty when this method is called. | 
|  | E removeLast(); | 
|  |  | 
|  | /// Adds [value] at the beginning of the queue. | 
|  | void addFirst(E value); | 
|  |  | 
|  | /// Adds [value] at the end of the queue. | 
|  | void addLast(E value); | 
|  |  | 
|  | /// Adds [value] at the end of the queue. | 
|  | void add(E value); | 
|  |  | 
|  | /// Removes a single instance of [value] from the queue. | 
|  | /// | 
|  | /// Returns `true` if a value was removed, or `false` if the queue | 
|  | /// contained no element equal to [value]. | 
|  | bool remove(Object? value); | 
|  |  | 
|  | /// Adds all elements of [iterable] at the end of the queue. The | 
|  | /// length of the queue is extended by the length of [iterable]. | 
|  | void addAll(Iterable<E> iterable); | 
|  |  | 
|  | /// Removes all elements matched by [test] from the queue. | 
|  | /// | 
|  | /// The `test` function must not throw or modify the queue. | 
|  | void removeWhere(bool test(E element)); | 
|  |  | 
|  | /// Removes all elements not matched by [test] from the queue. | 
|  | /// | 
|  | /// The `test` function must not throw or modify the queue. | 
|  | void retainWhere(bool test(E element)); | 
|  |  | 
|  | /// Removes all elements in the queue. The size of the queue becomes zero. | 
|  | void clear(); | 
|  | } | 
|  |  | 
|  | /// Interface and base class for the link classes used by [DoubleLinkedQueue]. | 
|  | /// | 
|  | /// Both the [_DoubleLinkedQueueElement] and [_DoubleLinkedQueueSentinel] | 
|  | /// implement this interface. | 
|  | abstract class _DoubleLinkedQueueEntry<E> { | 
|  | _DoubleLinkedQueueEntry<E>? _previousLink; | 
|  | _DoubleLinkedQueueEntry<E>? _nextLink; | 
|  |  | 
|  | void _link( | 
|  | _DoubleLinkedQueueEntry<E>? previous, | 
|  | _DoubleLinkedQueueEntry<E>? next, | 
|  | ) { | 
|  | _nextLink = next; | 
|  | _previousLink = previous; | 
|  | previous?._nextLink = this; | 
|  | next?._previousLink = this; | 
|  | } | 
|  |  | 
|  | void _unlink() { | 
|  | _previousLink?._nextLink = _nextLink; | 
|  | _nextLink?._previousLink = _previousLink; | 
|  | _previousLink = _nextLink = null; | 
|  | } | 
|  |  | 
|  | _DoubleLinkedQueueElement<E>? _asNonSentinelEntry(); | 
|  |  | 
|  | void _append(E element, DoubleLinkedQueue<E>? queue) { | 
|  | _DoubleLinkedQueueElement<E>(element, queue)._link(this, _nextLink); | 
|  | } | 
|  |  | 
|  | void _prepend(E element, DoubleLinkedQueue<E>? queue) { | 
|  | _DoubleLinkedQueueElement<E>(element, queue)._link(_previousLink, this); | 
|  | } | 
|  |  | 
|  | E _remove(); | 
|  |  | 
|  | E get element; | 
|  | } | 
|  |  | 
|  | /// Linked list entry used by the [DoubleLinkedQueue] to hold an element. | 
|  | /// | 
|  | /// These entry objects are also exposed by [DoubleLinkedQueue.firstEntry], | 
|  | /// [DoubleLinkedQueue.lastEntry] and [DoubleLinkedQueue.forEachEntry]. | 
|  | /// | 
|  | /// The entry contains both the [element] (which is mutable to anyone with | 
|  | /// access to the entry object) and a reference to the queue, allowing | 
|  | /// [append]/[prepend] to update the list length. | 
|  | /// | 
|  | /// When an entry is removed from its queue, the [_queue] is set to `null` | 
|  | /// and will never change again. You can still use the unlinked entry | 
|  | /// to create a new list, by calling [append] and [prepend], but it won't | 
|  | /// be part of any [DoubleLinkedQueue]. | 
|  | class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> | 
|  | implements DoubleLinkedQueueEntry<E> { | 
|  | DoubleLinkedQueue<E>? _queue; | 
|  | E element; | 
|  |  | 
|  | _DoubleLinkedQueueElement(this.element, this._queue); | 
|  |  | 
|  | void append(E e) { | 
|  | _append(e, _queue); | 
|  | _queue?._elementCount++; | 
|  | } | 
|  |  | 
|  | void prepend(E e) { | 
|  | _prepend(e, _queue); | 
|  | _queue?._elementCount++; | 
|  | } | 
|  |  | 
|  | E _remove() { | 
|  | _queue = null; | 
|  | _unlink(); | 
|  | return element; | 
|  | } | 
|  |  | 
|  | E remove() { | 
|  | _queue?._elementCount--; | 
|  | return _remove(); | 
|  | } | 
|  |  | 
|  | _DoubleLinkedQueueElement<E> _asNonSentinelEntry() => this; | 
|  |  | 
|  | DoubleLinkedQueueEntry<E>? previousEntry() => | 
|  | _previousLink?._asNonSentinelEntry(); | 
|  |  | 
|  | DoubleLinkedQueueEntry<E>? nextEntry() => _nextLink?._asNonSentinelEntry(); | 
|  | } | 
|  |  | 
|  | /// A header object used to hold the two ends of a double linked queue. | 
|  | /// | 
|  | /// A [DoubleLinkedQueue] has exactly one sentinel, | 
|  | /// which is the only entry when the list is constructed. | 
|  | /// | 
|  | /// Initially, a sentinel has its next and previous entries point to itself. | 
|  | /// Its next and previous links are never `null` after creation, and | 
|  | /// the entries linked always form a circular structure with the next link | 
|  | /// pointing to the first element of the queue, and the previous link | 
|  | /// pointing to the last element of the queue, or both pointing to itself | 
|  | /// again if the queue becomes empty. | 
|  | /// | 
|  | /// Implements [_DoubleLinkedQueueEntry._remove] and | 
|  | /// [_DoubleLinkedQueueEntry.element] as throwing because | 
|  | /// it makes it simple to implement members like [Queue.removeFirst] | 
|  | /// or [Queue.first] as throwing on an empty queue. | 
|  | /// | 
|  | /// A sentinel does not contain any user element. | 
|  | class _DoubleLinkedQueueSentinel<E> extends _DoubleLinkedQueueEntry<E> { | 
|  | _DoubleLinkedQueueSentinel() { | 
|  | _previousLink = this; | 
|  | _nextLink = this; | 
|  | } | 
|  |  | 
|  | Null _asNonSentinelEntry() => null; | 
|  |  | 
|  | /// Hit by, e.g., [DoubleLinkedQueue.removeFirst] if the queue is empty. | 
|  | E _remove() { | 
|  | throw IterableElementError.noElement(); | 
|  | } | 
|  |  | 
|  | /// Hit by, e.g., [DoubleLinkedQueue.first] if the queue is empty. | 
|  | E get element { | 
|  | throw IterableElementError.noElement(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// A [Queue] implementation based on a double-linked list. | 
|  | /// | 
|  | /// Allows constant time add, remove-at-ends and peek operations. | 
|  | final class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { | 
|  | final _DoubleLinkedQueueSentinel<E> _sentinel = | 
|  | _DoubleLinkedQueueSentinel<E>(); | 
|  |  | 
|  | int _elementCount = 0; | 
|  |  | 
|  | DoubleLinkedQueue(); | 
|  |  | 
|  | /// Creates a double-linked queue containing all [elements]. | 
|  | /// | 
|  | /// The element order in the queue is as if the elements were added using | 
|  | /// [addLast] in the order provided by [elements].iterator. | 
|  | /// | 
|  | /// All the [elements] should be instances of [E]. | 
|  | /// The [elements] iterable itself may have any element type, so this | 
|  | /// constructor can be used to down-cast a [Queue], for example as: | 
|  | /// ```dart | 
|  | /// Queue<SuperType> superQueue = ...; | 
|  | /// Queue<SubType> subQueue = | 
|  | ///     DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>()); | 
|  | /// ``` | 
|  | factory DoubleLinkedQueue.from(Iterable<dynamic> elements) { | 
|  | DoubleLinkedQueue<E> list = DoubleLinkedQueue<E>(); | 
|  | for (final e in elements) { | 
|  | list.addLast(e as E); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | /// Creates a double-linked queue from [elements]. | 
|  | /// | 
|  | /// The element order in the queue is as if the elements were added using | 
|  | /// [addLast] in the order provided by [elements].iterator. | 
|  | factory DoubleLinkedQueue.of(Iterable<E> elements) => | 
|  | DoubleLinkedQueue<E>()..addAll(elements); | 
|  |  | 
|  | Queue<R> cast<R>() => Queue.castFrom<E, R>(this); | 
|  |  | 
|  | int get length => _elementCount; | 
|  |  | 
|  | void addLast(E value) { | 
|  | _sentinel._prepend(value, this); | 
|  | _elementCount++; | 
|  | } | 
|  |  | 
|  | void addFirst(E value) { | 
|  | _sentinel._append(value, this); | 
|  | _elementCount++; | 
|  | } | 
|  |  | 
|  | void add(E value) { | 
|  | _sentinel._prepend(value, this); | 
|  | _elementCount++; | 
|  | } | 
|  |  | 
|  | void addAll(Iterable<E> iterable) { | 
|  | for (final E value in iterable) { | 
|  | _sentinel._prepend(value, this); | 
|  | _elementCount++; | 
|  | } | 
|  | } | 
|  |  | 
|  | E removeLast() { | 
|  | // Hits sentinel's `_remove` if queue is empty. | 
|  | E result = _sentinel._previousLink!._remove(); | 
|  | _elementCount--; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | E removeFirst() { | 
|  | // Hits sentinel's `_remove` if queue is empty. | 
|  | E result = _sentinel._nextLink!._remove(); | 
|  | _elementCount--; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | bool remove(Object? o) { | 
|  | _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink!; | 
|  | while (true) { | 
|  | var elementEntry = entry._asNonSentinelEntry(); | 
|  | if (elementEntry == null) return false; | 
|  | bool equals = (elementEntry.element == o); | 
|  | if (!identical(this, elementEntry._queue)) { | 
|  | // Entry must still be in the queue. | 
|  | throw ConcurrentModificationError(this); | 
|  | } | 
|  | if (equals) { | 
|  | entry._remove(); | 
|  | _elementCount--; | 
|  | return true; | 
|  | } | 
|  | entry = entry._nextLink!; | 
|  | } | 
|  | } | 
|  |  | 
|  | void _filter(bool test(E element), bool removeMatching) { | 
|  | _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink!; | 
|  | while (true) { | 
|  | var elementEntry = entry._asNonSentinelEntry(); | 
|  | if (elementEntry == null) return; | 
|  | bool matches = test(elementEntry.element); | 
|  | if (!identical(this, elementEntry._queue)) { | 
|  | // Entry must still be in the queue. | 
|  | throw ConcurrentModificationError(this); | 
|  | } | 
|  | var next = entry._nextLink!; // Cannot be null while entry is in queue. | 
|  | if (identical(removeMatching, matches)) { | 
|  | elementEntry._remove(); | 
|  | _elementCount--; | 
|  | } | 
|  | entry = next; | 
|  | } | 
|  | } | 
|  |  | 
|  | void removeWhere(bool test(E element)) { | 
|  | _filter(test, true); | 
|  | } | 
|  |  | 
|  | void retainWhere(bool test(E element)) { | 
|  | _filter(test, false); | 
|  | } | 
|  |  | 
|  | // Hits sentinel's `get element` if no element in queue. | 
|  | E get first => _sentinel._nextLink!.element; | 
|  |  | 
|  | // Hits sentinel's `get element` if no element in queue. | 
|  | E get last => _sentinel._previousLink!.element; | 
|  |  | 
|  | E get single { | 
|  | // Note that this throws correctly if the queue is empty | 
|  | // because reading the element of the sentinel throws. | 
|  | if (identical(_sentinel._nextLink, _sentinel._previousLink)) { | 
|  | return _sentinel._nextLink!.element; | 
|  | } | 
|  | throw IterableElementError.tooMany(); | 
|  | } | 
|  |  | 
|  | /// The entry object of the first element in the queue. | 
|  | /// | 
|  | /// Each element of the queue has an associated [DoubleLinkedQueueEntry]. | 
|  | /// | 
|  | /// Returns the entry object corresponding to the first element of the queue, | 
|  | /// or `null` if the queue is empty. | 
|  | /// | 
|  | /// The entry objects can also be accessed using [lastEntry], | 
|  | /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and | 
|  | /// [DoubleLinkedQueueEntry.previousEntry]. | 
|  | DoubleLinkedQueueEntry<E>? firstEntry() => | 
|  | _sentinel._nextLink!._asNonSentinelEntry(); | 
|  |  | 
|  | /// The entry object of the last element in the queue. | 
|  | /// | 
|  | /// Each element of the queue has an associated [DoubleLinkedQueueEntry]. | 
|  | /// | 
|  | /// Returns the entry object corresponding to the last element of the queue, | 
|  | /// or `null` if the queue is empty. | 
|  | /// | 
|  | /// The entry objects can also be accessed using [firstEntry], | 
|  | /// and they can be iterated using [DoubleLinkedQueueEntry.nextEntry] and | 
|  | /// [DoubleLinkedQueueEntry.previousEntry]. | 
|  | DoubleLinkedQueueEntry<E>? lastEntry() => | 
|  | _sentinel._previousLink!._asNonSentinelEntry(); | 
|  |  | 
|  | bool get isEmpty => identical(_sentinel._nextLink, _sentinel); | 
|  |  | 
|  | void clear() { | 
|  | var cursor = _sentinel._nextLink!; | 
|  | while (true) { | 
|  | var entry = cursor._asNonSentinelEntry(); | 
|  | if (entry == null) break; | 
|  | cursor = cursor._nextLink!; | 
|  | entry | 
|  | .._nextLink = null | 
|  | .._previousLink = null | 
|  | .._queue = null; | 
|  | } | 
|  | _sentinel._nextLink = _sentinel; | 
|  | _sentinel._previousLink = _sentinel; | 
|  | _elementCount = 0; | 
|  | } | 
|  |  | 
|  | /// Calls [action] for each entry object of this double-linked queue. | 
|  | /// | 
|  | /// Each element of the queue has an associated [DoubleLinkedQueueEntry]. | 
|  | /// This method iterates the entry objects from first to last and calls | 
|  | /// [action] with each object in turn. | 
|  | /// | 
|  | /// The entry objects can also be accessed using [firstEntry] and [lastEntry], | 
|  | /// and iterated using [DoubleLinkedQueueEntry.nextEntry()] and | 
|  | /// [DoubleLinkedQueueEntry.previousEntry()]. | 
|  | /// | 
|  | /// The [action] function can use methods on [DoubleLinkedQueueEntry] to | 
|  | /// remove the entry or it can insert elements before or after the entry. | 
|  | /// If the current entry is removed, iteration continues with the entry that | 
|  | /// was following the current entry when [action] was called. Any elements | 
|  | /// inserted after the current element before it is removed will not be | 
|  | /// visited by the iteration. | 
|  | void forEachEntry(void action(DoubleLinkedQueueEntry<E> element)) { | 
|  | var cursor = _sentinel._nextLink!; | 
|  | while (true) { | 
|  | var element = cursor._asNonSentinelEntry(); | 
|  | if (element == null) break; | 
|  | if (!identical(element._queue, this)) { | 
|  | throw ConcurrentModificationError(this); | 
|  | } | 
|  | cursor = cursor._nextLink!; | 
|  | // Remember both element and element._nextLink (as cursor). | 
|  | // If someone calls `element.remove()` we continue from `next`. | 
|  | // Otherwise we use the value of element._nextLink which may have been | 
|  | // updated. | 
|  | action(element); | 
|  | if (identical(this, element._queue)) { | 
|  | cursor = element._nextLink!; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | _DoubleLinkedQueueIterator<E> get iterator { | 
|  | return _DoubleLinkedQueueIterator<E>(this); | 
|  | } | 
|  |  | 
|  | String toString() => Iterable.iterableToFullString(this, '{', '}'); | 
|  | } | 
|  |  | 
|  | class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 
|  | /// Queue being iterated. Used for concurrent modification checks. | 
|  | DoubleLinkedQueue<E>? _queue; | 
|  |  | 
|  | /// Next entry to visit. Set to null when hitting the sentinel. | 
|  | _DoubleLinkedQueueEntry<E>? _nextEntry; | 
|  |  | 
|  | /// Current element value, when valid. | 
|  | E? _current; | 
|  |  | 
|  | _DoubleLinkedQueueIterator(DoubleLinkedQueue<E> this._queue) | 
|  | : _nextEntry = _queue._sentinel._nextLink; | 
|  |  | 
|  | bool moveNext() { | 
|  | var nextElement = _nextEntry?._asNonSentinelEntry(); | 
|  | if (nextElement == null) { | 
|  | // Clear everything to not unnecessarily keep values alive. | 
|  | _current = null; | 
|  | _nextEntry = null; | 
|  | _queue = null; | 
|  | return false; | 
|  | } | 
|  | if (!identical(_queue, nextElement._queue)) { | 
|  | throw ConcurrentModificationError(_queue); | 
|  | } | 
|  | _current = nextElement.element; | 
|  | _nextEntry = nextElement._nextLink; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | E get current => _current as E; | 
|  | } | 
|  |  | 
|  | /// List based [Queue]. | 
|  | /// | 
|  | /// Keeps a cyclic buffer of elements, and grows to a larger buffer when | 
|  | /// it fills up. This guarantees constant time peek and remove operations, and | 
|  | /// amortized constant time add operations. | 
|  | /// | 
|  | /// The structure is efficient for any queue or stack usage. | 
|  | /// | 
|  | /// Example: | 
|  | /// ```dart | 
|  | /// final queue = ListQueue<int>(); | 
|  | /// ``` | 
|  | /// To add objects to a queue, use [add], [addAll], [addFirst] or[addLast]. | 
|  | /// ```dart continued | 
|  | /// queue.add(5); | 
|  | /// queue.addFirst(0); | 
|  | /// queue.addLast(10); | 
|  | /// queue.addAll([1, 2, 3]); | 
|  | /// print(queue); // {0, 5, 10, 1, 2, 3} | 
|  | /// ``` | 
|  | /// To check if the queue is empty, use [isEmpty] or [isNotEmpty]. | 
|  | /// To find the number of queue entries, use [length]. | 
|  | /// ```dart continued | 
|  | /// final isEmpty = queue.isEmpty; // false | 
|  | /// final queueSize = queue.length; // 6 | 
|  | /// ``` | 
|  | /// To get first or last item from queue, use [first] or [last]. | 
|  | /// ```dart continued | 
|  | /// final first = queue.first; // 0 | 
|  | /// final last = queue.last; // 3 | 
|  | /// ``` | 
|  | /// To get item value using index, use [elementAt]. | 
|  | /// ```dart continued | 
|  | /// final itemAt = queue.elementAt(2); // 10 | 
|  | /// ``` | 
|  | /// To convert queue to list, call [toList]. | 
|  | /// ```dart continued | 
|  | /// final numbers = queue.toList(); | 
|  | /// print(numbers); // [0, 5, 10, 1, 2, 3] | 
|  | /// ``` | 
|  | /// To remove item from queue, call [remove], [removeFirst] or [removeLast]. | 
|  | /// ```dart continued | 
|  | /// queue.remove(10); | 
|  | /// queue.removeFirst(); | 
|  | /// queue.removeLast(); | 
|  | /// print(queue); // {5, 1, 2} | 
|  | /// ``` | 
|  | /// To remove multiple elements at the same time, use [removeWhere]. | 
|  | /// ```dart continued | 
|  | /// queue.removeWhere((element) => element == 1); | 
|  | /// print(queue); // {5, 2} | 
|  | /// ``` | 
|  | /// To remove all elements in this queue that do not meet a condition, | 
|  | /// use [retainWhere]. | 
|  | /// ```dart continued | 
|  | /// queue.retainWhere((element) => element < 4); | 
|  | /// print(queue); // {2} | 
|  | /// ``` | 
|  | /// To remove all items and empty the set, use [clear]. | 
|  | /// ```dart continued | 
|  | /// queue.clear(); | 
|  | /// print(queue.isEmpty); // true | 
|  | /// print(queue); // {} | 
|  | /// ``` | 
|  | final class ListQueue<E> extends ListIterable<E> implements Queue<E> { | 
|  | static const int _INITIAL_CAPACITY = 8; | 
|  | List<E?> _table; | 
|  | int _head; | 
|  | int _tail; | 
|  | int _modificationCount = 0; | 
|  |  | 
|  | /// Create an empty queue. | 
|  | /// | 
|  | /// If [initialCapacity] is given, prepare the queue for at least that many | 
|  | /// elements. | 
|  | ListQueue([int? initialCapacity]) | 
|  | : _head = 0, | 
|  | _tail = 0, | 
|  | _table = List<E?>.filled(_calculateCapacity(initialCapacity), null); | 
|  |  | 
|  | static int _calculateCapacity(int? initialCapacity) { | 
|  | if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { | 
|  | return _INITIAL_CAPACITY; | 
|  | } else if (!_isPowerOf2(initialCapacity)) { | 
|  | return _nextPowerOf2(initialCapacity); | 
|  | } | 
|  | assert(_isPowerOf2(initialCapacity)); | 
|  | return initialCapacity; | 
|  | } | 
|  |  | 
|  | /// Create a `ListQueue` containing all [elements]. | 
|  | /// | 
|  | /// The elements are added to the queue, as by [addLast], in the order given | 
|  | /// by `elements.iterator`. | 
|  | /// | 
|  | /// All the [elements] should be instances of [E]. | 
|  | /// The `elements` iterable itself may have any element type, so this | 
|  | /// constructor can be used to down-cast a `Queue`, for example as: | 
|  | /// ```dart | 
|  | /// Queue<SuperType> superQueue = ...; | 
|  | /// Queue<SubType> subQueue = | 
|  | ///     ListQueue<SubType>.from(superQueue.whereType<SubType>()); | 
|  | /// ``` | 
|  | /// Example: | 
|  | /// ```dart | 
|  | /// final numbers = <num>[10, 20, 30]; | 
|  | /// final queue = ListQueue<int>.from(numbers); | 
|  | /// print(queue); // {10, 20, 30} | 
|  | /// ``` | 
|  | factory ListQueue.from(Iterable<dynamic> elements) { | 
|  | if (elements is List<dynamic>) { | 
|  | int length = elements.length; | 
|  | ListQueue<E> queue = ListQueue<E>(length + 1); | 
|  | assert(queue._table.length > length); | 
|  | for (int i = 0; i < length; i++) { | 
|  | queue._table[i] = elements[i] as E; | 
|  | } | 
|  | queue._tail = length; | 
|  | return queue; | 
|  | } else { | 
|  | int capacity = _INITIAL_CAPACITY; | 
|  | if (elements is EfficientLengthIterable) { | 
|  | capacity = elements.length; | 
|  | } | 
|  | ListQueue<E> result = ListQueue<E>(capacity); | 
|  | for (final element in elements) { | 
|  | result.addLast(element as E); | 
|  | } | 
|  | return result; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Create a `ListQueue` from [elements]. | 
|  | /// | 
|  | /// The elements are added to the queue, as by [addLast], in the order given | 
|  | /// by `elements.iterator`. | 
|  | /// Example: | 
|  | /// ```dart | 
|  | /// final baseQueue = ListQueue.of([1.0, 2.0, 3.0]); // A ListQueue<double> | 
|  | /// final numQueue = ListQueue<num>.of(baseQueue); | 
|  | /// print(numQueue); // {1.0, 2.0, 3.0} | 
|  | /// ``` | 
|  | factory ListQueue.of(Iterable<E> elements) => | 
|  | ListQueue<E>()..addAll(elements); | 
|  |  | 
|  | // Iterable interface. | 
|  |  | 
|  | Queue<R> cast<R>() => Queue.castFrom<E, R>(this); | 
|  | Iterator<E> get iterator => _ListQueueIterator<E>(this); | 
|  |  | 
|  | void forEach(void f(E element)) { | 
|  | int modificationCount = _modificationCount; | 
|  | for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { | 
|  | f(_table[i] as E); | 
|  | _checkModification(modificationCount); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool get isEmpty => _head == _tail; | 
|  |  | 
|  | int get length => (_tail - _head) & (_table.length - 1); | 
|  |  | 
|  | E get first { | 
|  | if (_head == _tail) throw IterableElementError.noElement(); | 
|  | return _table[_head] as E; | 
|  | } | 
|  |  | 
|  | E get last { | 
|  | if (_head == _tail) throw IterableElementError.noElement(); | 
|  | return _table[(_tail - 1) & (_table.length - 1)] as E; | 
|  | } | 
|  |  | 
|  | E get single { | 
|  | if (_head == _tail) throw IterableElementError.noElement(); | 
|  | if (length > 1) throw IterableElementError.tooMany(); | 
|  | return _table[_head] as E; | 
|  | } | 
|  |  | 
|  | E elementAt(int index) { | 
|  | IndexError.check(index, length, indexable: this); | 
|  | return _table[(_head + index) & (_table.length - 1)] as E; | 
|  | } | 
|  |  | 
|  | List<E> toList({bool growable = true}) { | 
|  | int mask = _table.length - 1; | 
|  | int length = (_tail - _head) & mask; | 
|  | if (length == 0) return List<E>.empty(growable: growable); | 
|  |  | 
|  | var list = List<E>.filled(length, first, growable: growable); | 
|  | for (int i = 0; i < length; i++) { | 
|  | list[i] = _table[(_head + i) & mask] as E; | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | // Collection interface. | 
|  |  | 
|  | void add(E value) { | 
|  | _add(value); | 
|  | } | 
|  |  | 
|  | void addAll(Iterable<E> elements) { | 
|  | if (elements is List<E>) { | 
|  | List<E> list = elements; | 
|  | int addCount = list.length; | 
|  | int length = this.length; | 
|  | if (length + addCount >= _table.length) { | 
|  | _preGrow(length + addCount); | 
|  | // After preGrow, all elements are at the start of the list. | 
|  | _table.setRange(length, length + addCount, list, 0); | 
|  | _tail += addCount; | 
|  | } else { | 
|  | // Adding addCount elements won't reach _head. | 
|  | int endSpace = _table.length - _tail; | 
|  | if (addCount < endSpace) { | 
|  | _table.setRange(_tail, _tail + addCount, list, 0); | 
|  | _tail += addCount; | 
|  | } else { | 
|  | int preSpace = addCount - endSpace; | 
|  | _table.setRange(_tail, _tail + endSpace, list, 0); | 
|  | _table.setRange(0, preSpace, list, endSpace); | 
|  | _tail = preSpace; | 
|  | } | 
|  | } | 
|  | _modificationCount++; | 
|  | } else { | 
|  | for (E element in elements) _add(element); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool remove(Object? value) { | 
|  | for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { | 
|  | E? element = _table[i]; | 
|  | if (element == value) { | 
|  | _remove(i); | 
|  | _modificationCount++; | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void _filterWhere(bool test(E element), bool removeMatching) { | 
|  | int modificationCount = _modificationCount; | 
|  | int i = _head; | 
|  | while (i != _tail) { | 
|  | E element = _table[i] as E; | 
|  | bool remove = identical(removeMatching, test(element)); | 
|  | _checkModification(modificationCount); | 
|  | if (remove) { | 
|  | i = _remove(i); | 
|  | modificationCount = ++_modificationCount; | 
|  | } else { | 
|  | i = (i + 1) & (_table.length - 1); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Remove all elements matched by [test]. | 
|  | /// | 
|  | /// This method is inefficient since it works by repeatedly removing single | 
|  | /// elements, each of which can take linear time. | 
|  | void removeWhere(bool test(E element)) { | 
|  | _filterWhere(test, true); | 
|  | } | 
|  |  | 
|  | /// Remove all elements not matched by [test]. | 
|  | /// | 
|  | /// This method is inefficient since it works by repeatedly removing single | 
|  | /// elements, each of which can take linear time. | 
|  | void retainWhere(bool test(E element)) { | 
|  | _filterWhere(test, false); | 
|  | } | 
|  |  | 
|  | void clear() { | 
|  | if (_head != _tail) { | 
|  | for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { | 
|  | _table[i] = null; | 
|  | } | 
|  | _head = _tail = 0; | 
|  | _modificationCount++; | 
|  | } | 
|  | } | 
|  |  | 
|  | String toString() => Iterable.iterableToFullString(this, "{", "}"); | 
|  |  | 
|  | // Queue interface. | 
|  |  | 
|  | void addLast(E value) { | 
|  | _add(value); | 
|  | } | 
|  |  | 
|  | void addFirst(E value) { | 
|  | _head = (_head - 1) & (_table.length - 1); | 
|  | _table[_head] = value; | 
|  | if (_head == _tail) _grow(); | 
|  | _modificationCount++; | 
|  | } | 
|  |  | 
|  | E removeFirst() { | 
|  | if (_head == _tail) throw IterableElementError.noElement(); | 
|  | _modificationCount++; | 
|  | E result = _table[_head] as E; | 
|  | _table[_head] = null; | 
|  | _head = (_head + 1) & (_table.length - 1); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | E removeLast() { | 
|  | if (_head == _tail) throw IterableElementError.noElement(); | 
|  | _modificationCount++; | 
|  | _tail = (_tail - 1) & (_table.length - 1); | 
|  | E result = _table[_tail] as E; | 
|  | _table[_tail] = null; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // Internal helper functions. | 
|  |  | 
|  | /// Whether [number] is a power of two. | 
|  | /// | 
|  | /// Only works for positive numbers. | 
|  | static bool _isPowerOf2(int number) => (number & (number - 1)) == 0; | 
|  |  | 
|  | /// Rounds [number] up to the nearest power of 2. | 
|  | /// | 
|  | /// If [number] is a power of 2 already, it is returned. | 
|  | /// | 
|  | /// Only works for positive numbers. | 
|  | static int _nextPowerOf2(int number) { | 
|  | assert(number > 0); | 
|  | number = (number << 1) - 1; | 
|  | for (;;) { | 
|  | int nextNumber = number & (number - 1); | 
|  | if (nextNumber == 0) return number; | 
|  | number = nextNumber; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Check if the queue has been modified during iteration. | 
|  | void _checkModification(int expectedModificationCount) { | 
|  | if (expectedModificationCount != _modificationCount) { | 
|  | throw ConcurrentModificationError(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Adds element at end of queue. Used by both [add] and [addAll]. | 
|  | void _add(E element) { | 
|  | _table[_tail] = element; | 
|  | _tail = (_tail + 1) & (_table.length - 1); | 
|  | if (_head == _tail) _grow(); | 
|  | _modificationCount++; | 
|  | } | 
|  |  | 
|  | /// Removes the element at [offset] into [_table]. | 
|  | /// | 
|  | /// Removal is performed by linearly moving elements either before or after | 
|  | /// [offset] by one position. | 
|  | /// | 
|  | /// Returns the new offset of the following element. This may be the same | 
|  | /// offset or the following offset depending on how elements are moved | 
|  | /// to fill the hole. | 
|  | int _remove(int offset) { | 
|  | int mask = _table.length - 1; | 
|  | int startDistance = (offset - _head) & mask; | 
|  | int endDistance = (_tail - offset) & mask; | 
|  | if (startDistance < endDistance) { | 
|  | // Closest to start. | 
|  | int i = offset; | 
|  | while (i != _head) { | 
|  | int prevOffset = (i - 1) & mask; | 
|  | _table[i] = _table[prevOffset]; | 
|  | i = prevOffset; | 
|  | } | 
|  | _table[_head] = null; | 
|  | _head = (_head + 1) & mask; | 
|  | return (offset + 1) & mask; | 
|  | } else { | 
|  | _tail = (_tail - 1) & mask; | 
|  | int i = offset; | 
|  | while (i != _tail) { | 
|  | int nextOffset = (i + 1) & mask; | 
|  | _table[i] = _table[nextOffset]; | 
|  | i = nextOffset; | 
|  | } | 
|  | _table[_tail] = null; | 
|  | return offset; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Grow the table when full. | 
|  | void _grow() { | 
|  | List<E?> newTable = List<E?>.filled(_table.length * 2, null); | 
|  | int split = _table.length - _head; | 
|  | newTable.setRange(0, split, _table, _head); | 
|  | newTable.setRange(split, split + _head, _table, 0); | 
|  | _head = 0; | 
|  | _tail = _table.length; | 
|  | _table = newTable; | 
|  | } | 
|  |  | 
|  | int _writeToList(List<E?> target) { | 
|  | assert(target.length >= length); | 
|  | if (_head <= _tail) { | 
|  | int length = _tail - _head; | 
|  | target.setRange(0, length, _table, _head); | 
|  | return length; | 
|  | } else { | 
|  | int firstPartSize = _table.length - _head; | 
|  | target.setRange(0, firstPartSize, _table, _head); | 
|  | target.setRange(firstPartSize, firstPartSize + _tail, _table, 0); | 
|  | return _tail + firstPartSize; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Grows the table even if it is not full. | 
|  | void _preGrow(int newElementCount) { | 
|  | assert(newElementCount >= length); | 
|  |  | 
|  | // Add some extra room to ensure that there's room for more elements after | 
|  | // expansion. | 
|  | newElementCount += newElementCount >> 1; | 
|  | int newCapacity = _nextPowerOf2(newElementCount); | 
|  | List<E?> newTable = List<E?>.filled(newCapacity, null); | 
|  | _tail = _writeToList(newTable); | 
|  | _table = newTable; | 
|  | _head = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Iterator for a [ListQueue]. | 
|  | /// | 
|  | /// Considers any add or remove operation a concurrent modification. | 
|  | class _ListQueueIterator<E> implements Iterator<E> { | 
|  | final ListQueue<E> _queue; | 
|  | final int _end; | 
|  | final int _modificationCount; | 
|  | int _position; | 
|  | E? _current; | 
|  |  | 
|  | _ListQueueIterator(ListQueue<E> queue) | 
|  | : _queue = queue, | 
|  | _end = queue._tail, | 
|  | _modificationCount = queue._modificationCount, | 
|  | _position = queue._head; | 
|  |  | 
|  | E get current => _current as E; | 
|  |  | 
|  | bool moveNext() { | 
|  | _queue._checkModification(_modificationCount); | 
|  | if (_position == _end) { | 
|  | _current = null; | 
|  | return false; | 
|  | } | 
|  | _current = _queue._table[_position]; | 
|  | _position = (_position + 1) & (_queue._table.length - 1); | 
|  | return true; | 
|  | } | 
|  | } |