| Index: sdk/lib/collection/linked_list.dart
|
| diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a653126d927566aad914dbb0608d9402127c76ea
|
| --- /dev/null
|
| +++ b/sdk/lib/collection/linked_list.dart
|
| @@ -0,0 +1,232 @@
|
| +// Copyright (c) 2013, 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;
|
| +
|
| +
|
| +/**
|
| + * A linked list implementation, providing O(1) removal(unlink) of elements and
|
| + * manual traversal through [next] and [previous].
|
| + *
|
| + * The list elements must extend [LinkedListEntry].
|
| + */
|
| +class LinkedList<E extends LinkedListEntry<E>>
|
| + extends IterableBase<E>
|
| + implements _LinkedListLink {
|
| + int _modificationCount = 0;
|
| + int _length = 0;
|
| + _LinkedListLink _next;
|
| + _LinkedListLink _previous;
|
| +
|
| + /**
|
| + * Construct a new empty linked list.
|
| + */
|
| + LinkedList() {
|
| + _next = _previous = this;
|
| + }
|
| +
|
| + /**
|
| + * Add [entry] to the beginning of the list.
|
| + */
|
| + void addFirst(E entry) {
|
| + _insertAfter(this, entry);
|
| + }
|
| +
|
| + /**
|
| + * Add [entry] to the end of the list.
|
| + */
|
| + void add(E entry) {
|
| + _insertAfter(_previous, entry);
|
| + }
|
| +
|
| + /**
|
| + * Add [entries] to the end of the list.
|
| + */
|
| + void addAll(Iterable<E> entries) {
|
| + entries.forEach((entry) => _insertAfter(_previous, entry));
|
| + }
|
| +
|
| + /**
|
| + * Remove [entry] from the list. This is the same as calling `entry.unlink()`.
|
| + *
|
| + * If [entry] is not in the list, `false` is returned.
|
| + */
|
| + bool remove(E entry) {
|
| + if (entry._list != this) return false;
|
| + _unlink(entry); // Unlink will decrement length.
|
| + return true;
|
| + }
|
| +
|
| + Iterator<E> get iterator => new _LinkedListIterator<E>(this);
|
| +
|
| + String toString() => ToString.iterableToString(this);
|
| +
|
| + int get length => _length;
|
| +
|
| + void clear() {
|
| + _modificationCount++;
|
| + _LinkedListLink next = _next;
|
| + while (!identical(next, this)) {
|
| + _LinkedListLink entry = next;
|
| + next = entry._next;
|
| + entry._next = entry._previous = entry._list = null;
|
| + }
|
| + _next = _previous = this;
|
| + _length = 0;
|
| + }
|
| +
|
| + E get first {
|
| + if (identical(_next, this)) {
|
| + throw new StateError('No such element');
|
| + }
|
| + return _next;
|
| + }
|
| +
|
| + E get last {
|
| + if (identical(_previous, this)) {
|
| + throw new StateError('No such element');
|
| + }
|
| + return _previous;
|
| + }
|
| +
|
| + E get single {
|
| + if (identical(_previous, this)) {
|
| + throw new StateError('No such element');
|
| + }
|
| + if (!identical(_previous, _next)) {
|
| + throw new StateError('Too many elements');
|
| + }
|
| + return _next;
|
| + }
|
| +
|
| + /**
|
| + * Call [action] with each entry in the list.
|
| + *
|
| + * It's an error if [action] modify the list.
|
| + */
|
| + void forEach(void action(E entry)) {
|
| + int modificationCount = _modificationCount;
|
| + _LinkedListLink current = _next;
|
| + while (!identical(current, this)) {
|
| + action(current);
|
| + if (modificationCount != _modificationCount) {
|
| + throw new ConcurrentModificationError(this);
|
| + }
|
| + current = current._next;
|
| + }
|
| + }
|
| +
|
| + bool get isEmpty => _length == 0;
|
| +
|
| + void _insertAfter(_LinkedListLink entry, E newEntry) {
|
| + if (newEntry.list != null) {
|
| + throw new StateError(
|
| + 'LinkedListEntry is already in a LinkedList');
|
| + }
|
| + _modificationCount++;
|
| + newEntry._list = this;
|
| + var predecessor = entry;
|
| + var successor = entry._next;
|
| + successor._previous = newEntry;
|
| + newEntry._previous = predecessor;
|
| + newEntry._next = successor;
|
| + predecessor._next = newEntry;
|
| + _length++;
|
| + }
|
| +
|
| + void _unlink(E entry) {
|
| + _modificationCount++;
|
| + entry._next._previous = entry._previous;
|
| + entry._previous._next = entry._next;
|
| + _length--;
|
| + entry._list = entry._next = entry._previous = null;
|
| + }
|
| +}
|
| +
|
| +
|
| +class _LinkedListIterator<E extends LinkedListEntry>
|
| + implements Iterator<E> {
|
| + final LinkedList<E> _list;
|
| + final int _modificationCount;
|
| + E _current;
|
| + _LinkedListLink _next;
|
| +
|
| + _LinkedListIterator(LinkedList<E> list)
|
| + : _list = list,
|
| + _modificationCount = list._modificationCount,
|
| + _next = list._next;
|
| +
|
| + E get current => _current;
|
| +
|
| + bool moveNext() {
|
| + if (identical(_next, _list)) {
|
| + _current = null;
|
| + return false;
|
| + }
|
| + if (_modificationCount != _list._modificationCount) {
|
| + throw new ConcurrentModificationError(this);
|
| + }
|
| + _current = _next;
|
| + _next = _next._next;
|
| + return true;
|
| + }
|
| +}
|
| +
|
| +
|
| +class _LinkedListLink {
|
| + _LinkedListLink _next;
|
| + _LinkedListLink _previous;
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Entry element for a [LinkedList]. Any entry must extend this class.
|
| + */
|
| +abstract class LinkedListEntry<E> implements _LinkedListLink {
|
| + LinkedList<E> _list;
|
| + _LinkedListLink _next;
|
| + _LinkedListLink _previous;
|
| +
|
| + /**
|
| + * Get the list containing this element.
|
| + */
|
| + LinkedList<E> get list => _list;
|
| +
|
| + /**
|
| + * Unlink the element from the list.
|
| + */
|
| + void unlink() {
|
| + _list._unlink(this);
|
| + }
|
| +
|
| + /**
|
| + * Return the succeeding element in the list.
|
| + */
|
| + E get next {
|
| + if (_next == _list) return null;
|
| + return _next;
|
| + }
|
| +
|
| + /**
|
| + * Return the preceeding element in the list.
|
| + */
|
| + E get previous {
|
| + if (_previous == _list) return null;
|
| + return _previous;
|
| + }
|
| +
|
| + /**
|
| + * insert an element after this.
|
| + */
|
| + void insertAfter(E entry) {
|
| + _list._insertAfter(this, entry);
|
| + }
|
| +
|
| + /**
|
| + * Insert an element before this.
|
| + */
|
| + void insertBefore(E entry) {
|
| + _list._insertAfter(_previous, entry);
|
| + }
|
| +}
|
|
|