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