OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of util_implementation; | |
6 | |
7 class LinkIterator<T> implements Iterator<T> { | |
8 T _current; | |
9 Link<T> _link; | |
10 | |
11 LinkIterator(Link<T> this._link); | |
12 | |
13 T get current => _current; | |
14 | |
15 bool moveNext() { | |
16 if (_link.isEmpty) { | |
17 _current = null; | |
18 return false; | |
19 } | |
20 _current = _link.head; | |
21 _link = _link.tail; | |
22 return true; | |
23 } | |
24 } | |
25 | |
26 typedef T Transformation<S, T>(S input); | |
27 | |
28 class MappedLinkIterator<S, T> extends Iterator<T> { | |
29 Transformation<S, T> _transformation; | |
30 Link<S> _link; | |
31 T _current; | |
32 | |
33 MappedLinkIterator(this._link, this._transformation); | |
34 | |
35 T get current => _current; | |
36 | |
37 bool moveNext() { | |
38 if (_link.isEmpty) { | |
39 _current = null; | |
40 return false; | |
41 } | |
42 _current = _transformation(_link.head); | |
43 _link = _link.tail; | |
44 return true; | |
45 } | |
46 } | |
47 | |
48 class MappedLinkIterable<S, T> extends IterableBase<T> { | |
49 Transformation<S, T> _transformation; | |
50 Link<S> _link; | |
51 | |
52 MappedLinkIterable(this._link, this._transformation); | |
53 | |
54 Iterator<T> get iterator { | |
55 return new MappedLinkIterator<S,T>(_link, _transformation); | |
56 } | |
57 } | |
58 | |
59 class LinkEntry<T> extends Link<T> { | |
60 final T head; | |
61 Link<T> tail; | |
62 | |
63 LinkEntry(T this.head, [Link<T> tail]) | |
64 : this.tail = ((tail == null) ? new Link<T>() : tail); | |
65 | |
66 Link<T> prepend(T element) { | |
67 // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM. | |
68 return new LinkEntry<T>(element, this); | |
69 } | |
70 | |
71 void printOn(StringBuffer buffer, [separatedBy]) { | |
72 buffer.write(head); | |
73 if (separatedBy == null) separatedBy = ''; | |
74 for (Link link = tail; !link.isEmpty; link = link.tail) { | |
75 buffer.write(separatedBy); | |
76 buffer.write(link.head); | |
77 } | |
78 } | |
79 | |
80 String toString() { | |
81 StringBuffer buffer = new StringBuffer(); | |
82 buffer.write('[ '); | |
83 printOn(buffer, ', '); | |
84 buffer.write(' ]'); | |
85 return buffer.toString(); | |
86 } | |
87 | |
88 Link<T> reverse() { | |
89 Link<T> result = const Link(); | |
90 for (Link<T> link = this; !link.isEmpty; link = link.tail) { | |
91 result = result.prepend(link.head); | |
92 } | |
93 return result; | |
94 } | |
95 | |
96 Link<T> reversePrependAll(Link<T> from) { | |
97 Link<T> result; | |
98 for (result = this; !from.isEmpty; from = from.tail) { | |
99 result = result.prepend(from.head); | |
100 } | |
101 return result; | |
102 } | |
103 | |
104 Link<T> skip(int n) { | |
105 Link<T> link = this; | |
106 for (int i = 0 ; i < n ; i++) { | |
107 if (link.isEmpty) { | |
108 throw new RangeError('Index $n out of range'); | |
109 } | |
110 link = link.tail; | |
111 } | |
112 return link; | |
113 } | |
114 | |
115 bool get isEmpty => false; | |
116 | |
117 void forEach(void f(T element)) { | |
118 for (Link<T> link = this; !link.isEmpty; link = link.tail) { | |
119 f(link.head); | |
120 } | |
121 } | |
122 | |
123 bool operator ==(other) { | |
124 if (other is !Link<T>) return false; | |
125 Link<T> myElements = this; | |
126 while (!myElements.isEmpty && !other.isEmpty) { | |
127 if (myElements.head != other.head) { | |
128 return false; | |
129 } | |
130 myElements = myElements.tail; | |
131 other = other.tail; | |
132 } | |
133 return myElements.isEmpty && other.isEmpty; | |
134 } | |
135 | |
136 int get hashCode => throw new UnsupportedError('LinkEntry.hashCode'); | |
137 | |
138 int slowLength() => 1 + tail.slowLength(); | |
139 } | |
140 | |
141 class LinkBuilderImplementation<T> implements LinkBuilder<T> { | |
142 LinkEntry<T> head = null; | |
143 LinkEntry<T> lastLink = null; | |
144 int length = 0; | |
145 | |
146 LinkBuilderImplementation(); | |
147 | |
148 Link<T> toLink([Link<T> tail = const Link()]) { | |
149 if (head == null) return tail; | |
150 lastLink.tail = tail; | |
151 Link<T> link = head; | |
152 lastLink = null; | |
153 head = null; | |
154 return link; | |
155 } | |
156 | |
157 List<T> toList() { | |
158 if (length == 0) return new List<T>(0); | |
159 List<T> list = new List<T>(length); | |
160 int index = 0; | |
161 Link<T> link = head; | |
162 while (!link.isEmpty) { | |
163 list[index] = link.head; | |
164 link = link.tail; | |
165 index++; | |
166 } | |
167 lastLink = null; | |
168 head = null; | |
169 return list; | |
170 } | |
171 | |
172 void addLast(T t) { | |
173 length++; | |
174 LinkEntry<T> entry = new LinkEntry<T>(t, null); | |
175 if (head == null) { | |
176 head = entry; | |
177 } else { | |
178 lastLink.tail = entry; | |
179 } | |
180 lastLink = entry; | |
181 } | |
182 | |
183 bool get isEmpty => length == 0; | |
184 } | |
OLD | NEW |