| // Copyright (c) 2012, 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. | |
| /** | |
| * An entry in a doubly linked list. It contains a pointer to the next | |
| * entry, the previous entry, and the boxed element. | |
| */ | |
| class DoubleLinkedQueueEntry<E> { | |
| DoubleLinkedQueueEntry<E> _previous; | |
| DoubleLinkedQueueEntry<E> _next; | |
| E _element; | |
| DoubleLinkedQueueEntry(E e) { | |
| _element = e; | |
| } | |
| void _link(DoubleLinkedQueueEntry<E> p, | |
| DoubleLinkedQueueEntry<E> n) { | |
| _next = n; | |
| _previous = p; | |
| p._next = this; | |
| n._previous = this; | |
| } | |
| void append(E e) { | |
| new DoubleLinkedQueueEntry<E>(e)._link(this, _next); | |
| } | |
| void prepend(E e) { | |
| new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); | |
| } | |
| E remove() { | |
| _previous._next = _next; | |
| _next._previous = _previous; | |
| _next = null; | |
| _previous = null; | |
| return _element; | |
| } | |
| DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | |
| return this; | |
| } | |
| DoubleLinkedQueueEntry<E> previousEntry() { | |
| return _previous._asNonSentinelEntry(); | |
| } | |
| DoubleLinkedQueueEntry<E> nextEntry() { | |
| return _next._asNonSentinelEntry(); | |
| } | |
| E get element { | |
| return _element; | |
| } | |
| void set element(E e) { | |
| _element = e; | |
| } | |
| } | |
| /** | |
| * A sentinel in a double linked list is used to manipulate the list | |
| * at both ends. A double linked list has exactly one sentinel, which | |
| * is the only entry when the list is constructed. Initially, a | |
| * sentinel has its next and previous entry point to itself. A | |
| * sentinel does not box any user element. | |
| */ | |
| class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { | |
| _DoubleLinkedQueueEntrySentinel() : super(null) { | |
| _link(this, this); | |
| } | |
| E remove() { | |
| throw const EmptyQueueException(); | |
| } | |
| DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | |
| return null; | |
| } | |
| void set element(E e) { | |
| // This setter is unreachable. | |
| assert(false); | |
| } | |
| E get element { | |
| throw const EmptyQueueException(); | |
| } | |
| } | |
| /** | |
| * Implementation of a double linked list that box list elements into | |
| * DoubleLinkedQueueEntry objects. | |
| */ | |
| class DoubleLinkedQueue<E> implements Queue<E> { | |
| _DoubleLinkedQueueEntrySentinel<E> _sentinel; | |
| DoubleLinkedQueue() { | |
| _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | |
| } | |
| factory DoubleLinkedQueue.from(Iterable<E> other) { | |
| Queue<E> list = new DoubleLinkedQueue(); | |
| for (final e in other) { | |
| list.addLast(e); | |
| } | |
| return list; | |
| } | |
| void addLast(E value) { | |
| _sentinel.prepend(value); | |
| } | |
| void addFirst(E value) { | |
| _sentinel.append(value); | |
| } | |
| void add(E value) { | |
| addLast(value); | |
| } | |
| void addAll(Collection<E> collection) { | |
| for (final e in collection) { | |
| add(e); | |
| } | |
| } | |
| E removeLast() { | |
| return _sentinel._previous.remove(); | |
| } | |
| E removeFirst() { | |
| return _sentinel._next.remove(); | |
| } | |
| E first() { | |
| return _sentinel._next.element; | |
| } | |
| E last() { | |
| return _sentinel._previous.element; | |
| } | |
| DoubleLinkedQueueEntry<E> lastEntry() { | |
| return _sentinel.previousEntry(); | |
| } | |
| DoubleLinkedQueueEntry<E> firstEntry() { | |
| return _sentinel.nextEntry(); | |
| } | |
| int get length { | |
| int counter = 0; | |
| forEach(void _(E element) { counter++; }); | |
| return counter; | |
| } | |
| bool isEmpty() { | |
| return (_sentinel._next === _sentinel); | |
| } | |
| void clear() { | |
| _sentinel._next = _sentinel; | |
| _sentinel._previous = _sentinel; | |
| } | |
| void forEach(void f(E element)) { | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| f(entry._element); | |
| entry = nextEntry; | |
| } | |
| } | |
| void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| f(entry); | |
| entry = nextEntry; | |
| } | |
| } | |
| bool every(bool f(E element)) { | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| if (!f(entry._element)) return false; | |
| entry = nextEntry; | |
| } | |
| return true; | |
| } | |
| bool some(bool f(E element)) { | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| if (f(entry._element)) return true; | |
| entry = nextEntry; | |
| } | |
| return false; | |
| } | |
| Queue map(f(E element)) { | |
| Queue other = new Queue(); | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| other.addLast(f(entry._element)); | |
| entry = nextEntry; | |
| } | |
| return other; | |
| } | |
| Dynamic reduce(Dynamic initialValue, | |
| Dynamic combine(Dynamic previousValue, E element)) { | |
| return Collections.reduce(this, initialValue, combine); | |
| } | |
| Queue<E> filter(bool f(E element)) { | |
| Queue<E> other = new Queue<E>(); | |
| DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| while (entry !== _sentinel) { | |
| DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| if (f(entry._element)) other.addLast(entry._element); | |
| entry = nextEntry; | |
| } | |
| return other; | |
| } | |
| _DoubleLinkedQueueIterator<E> iterator() { | |
| return new _DoubleLinkedQueueIterator<E>(_sentinel); | |
| } | |
| String toString() { | |
| return Collections.collectionToString(this); | |
| } | |
| } | |
| class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | |
| final _DoubleLinkedQueueEntrySentinel<E> _sentinel; | |
| DoubleLinkedQueueEntry<E> _currentEntry; | |
| _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel this._sentinel) { | |
| _currentEntry = _sentinel; | |
| } | |
| bool hasNext() { | |
| return _currentEntry._next !== _sentinel; | |
| } | |
| E next() { | |
| if (!hasNext()) { | |
| throw const NoMoreElementsException(); | |
| } | |
| _currentEntry = _currentEntry._next; | |
| return _currentEntry.element; | |
| } | |
| } |