blob: a1f84922f6aaabcc8a84cc7b273ba032342e4978 [file] [log] [blame]
// 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.
class LinkIterator<T> implements Iterator<T> {
Link<T> current;
LinkIterator(Link<T> this.current);
bool hasNext() => !current.isEmpty();
T next() {
T result = current.head;
current = current.tail;
return result;
}
}
class LinkFactory<T> {
factory Link(T head, [Link<T> tail]) {
if (tail === null) {
tail = new LinkTail<T>();
}
return new LinkEntry<T>(head, tail);
}
factory Link.fromList(List<T> list) {
switch (list.length) {
case 0:
return new LinkTail<T>();
case 1:
return new Link<T>(list[0]);
case 2:
return new Link<T>(list[0], new Link<T>(list[1]));
case 3:
return new Link<T>(list[0], new Link<T>(list[1], new Link<T>(list[2])));
}
Link link = new Link<T>(list.last());
for (int i = list.length - 1; i > 0; i--) {
link = link.prepend(list[i - 1]);
}
return link;
}
}
class LinkTail<T> implements EmptyLink<T> {
T get head => null;
Link<T> get tail => null;
const LinkTail();
Link<T> prepend(T element) {
// TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
return new LinkEntry<T>(element, this);
}
Iterator<T> iterator() => new LinkIterator<T>(this);
void printOn(StringBuffer buffer, [separatedBy]) {
}
String toString() => "[]";
Link<T> reverse() => this;
Link<T> reversePrependAll(Link<T> from) {
if (from.isEmpty()) return this;
return this.prepend(from.head).reversePrependAll(from.tail);
}
List toList() => const [];
bool isEmpty() => true;
void forEach(void f(T element)) {}
bool operator ==(other) {
if (other is !Link<T>) return false;
return other.isEmpty();
}
}
class LinkEntry<T> implements Link<T> {
final T head;
Link<T> tail;
LinkEntry(T this.head, Link<T> this.tail);
Link<T> prepend(T element) {
// TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
return new LinkEntry<T>(element, this);
}
Iterator<T> iterator() => new LinkIterator<T>(this);
void printOn(StringBuffer buffer, [separatedBy]) {
buffer.add(head);
if (separatedBy === null) separatedBy = '';
for (Link link = tail; !link.isEmpty(); link = link.tail) {
buffer.add(separatedBy);
buffer.add(link.head);
}
}
String toString() {
StringBuffer buffer = new StringBuffer();
buffer.add('[ ');
printOn(buffer, ', ');
buffer.add(' ]');
return buffer.toString();
}
Link<T> reverse() {
Link<T> result = const LinkTail();
for (Link<T> link = this; !link.isEmpty(); link = link.tail) {
result = result.prepend(link.head);
}
return result;
}
Link<T> reversePrependAll(Link<T> from) {
Link<T> result;
for (result = this; !from.isEmpty(); from = from.tail) {
result = result.prepend(from.head);
}
return result;
}
bool isEmpty() => false;
List<T> toList() {
List<T> list = new List<T>();
for (Link<T> link = this; !link.isEmpty(); link = link.tail) {
list.addLast(link.head);
}
return list;
}
void forEach(void f(T element)) {
for (Link<T> link = this; !link.isEmpty(); link = link.tail) {
f(link.head);
}
}
bool operator ==(other) {
if (other is !Link<T>) return false;
Link<T> myElements = this;
while (!myElements.isEmpty() && !other.isEmpty()) {
if (myElements.head != other.head) {
return false;
}
myElements = myElements.tail;
other = other.tail;
}
return myElements.isEmpty() && other.isEmpty();
}
}
class LinkBuilderImplementation<T> implements LinkBuilder<T> {
LinkEntry<T> head = null;
LinkEntry<T> lastLink = null;
int length = 0;
LinkBuilderImplementation();
Link<T> toLink() {
if (head === null) return const LinkTail();
lastLink.tail = const LinkTail();
Link<T> link = head;
lastLink = null;
head = null;
return link;
}
void addLast(T t) {
length++;
LinkEntry<T> entry = new LinkEntry<T>(t, null);
if (head === null) {
head = entry;
} else {
lastLink.tail = entry;
}
lastLink = entry;
}
}