b8b5632148
Review URL: https://codereview.chromium.org//11269045 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@14122 260f80e4-7a28-3924-810f-c04153c831b5
264 lines
6.0 KiB
Dart
264 lines
6.0 KiB
Dart
// 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 new StateError("Empty queue");
|
|
}
|
|
|
|
DoubleLinkedQueueEntry<E> _asNonSentinelEntry() {
|
|
return null;
|
|
}
|
|
|
|
void set element(E e) {
|
|
// This setter is unreachable.
|
|
assert(false);
|
|
}
|
|
|
|
E get element {
|
|
throw new StateError("Empty queue");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 get first {
|
|
return _sentinel._next.element;
|
|
}
|
|
|
|
E get 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 get 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 get hasNext {
|
|
return _currentEntry._next !== _sentinel;
|
|
}
|
|
|
|
E next() {
|
|
if (!hasNext) {
|
|
throw new StateError("No more elements");
|
|
}
|
|
_currentEntry = _currentEntry._next;
|
|
return _currentEntry.element;
|
|
}
|
|
}
|