blob: 31a6c01cab8b5666840de4d04e7088f2395b18ef [file] [log] [blame]
// Copyright (c) 2017, 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._internal;
/// A rudimentary linked list.
class LinkedList<T extends LinkedListEntry<T>> extends IterableBase<T> {
T first;
T last;
int length = 0;
bool get isEmpty => length == 0;
/**
* Adds [newLast] to the end of this linked list.
*/
void add(T newLast) {
assert(newLast._next == null && newLast._previous == null);
if (last != null) {
assert(last._next == null);
last._next = newLast;
} else {
first = newLast;
}
newLast._previous = last;
last = newLast;
last._list = this;
length++;
}
/**
* Adds [newFirst] to the beginning of this linked list.
*/
void addFirst(T newFirst) {
if (first != null) {
assert(first._previous == null);
first._previous = newFirst;
} else {
last = newFirst;
}
newFirst._next = first;
first = newFirst;
first._list = this;
length++;
}
/**
* Removes the given [node] from this list.
*
* If the entry is not in this linked list nothing happens.
*
* Also see [LinkedListEntry.unlink].
*/
void remove(T node) {
if (node._list != this) return;
length--;
if (node._previous == null) {
assert(identical(node, first));
first = node._next;
} else {
node._previous._next = node._next;
}
if (node._next == null) {
assert(identical(node, last));
last = node._previous;
} else {
node._next._previous = node._previous;
}
node._next = node._previous = null;
node._list = null;
}
Iterator<T> get iterator => new _LinkedListIterator<T>(this);
}
class LinkedListEntry<T extends LinkedListEntry<T>> {
T _next;
T _previous;
LinkedList<T> _list;
/**
* Unlinks the element from its linked list.
*
* If the entry is not in a linked list, does nothing. Otherwise, this
* is equivalent to calling [LinkedList.remove] on the list this entry
* is currently in.
*/
void unlink() {
if (_list == null) return;
_list.remove(this);
}
}
class _LinkedListIterator<T extends LinkedListEntry<T>> implements Iterator<T> {
/// The current element of the iterator.
// This field is writeable, but should only read by users of this class.
T current;
/// The list the iterator iterates over.
///
/// Set to [null] if the provided list was empty (indicating that there were
/// no entries to iterate over).
///
/// Set to [null] as soon as [moveNext] was invoked (indicating that the
/// iterator has to work with [current] from now on.
LinkedList<T> _list;
_LinkedListIterator(this._list) {
if (_list.length == 0) _list = null;
}
bool moveNext() {
// current is null if the iterator hasn't started iterating, or if the
// iteration is finished. In the first case, the [_list] field is not null.
if (current == null) {
if (_list == null) return false;
assert(_list.length > 0);
current = _list.first;
_list = null;
return true;
}
current = current._next;
return current != null;
}
}