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) ? const Link() : 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.isNotEmpty; 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.isNotEmpty; 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.isNotEmpty; 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 bool get isNotEmpty => true; | |
117 | |
118 void forEach(void f(T element)) { | |
119 for (Link<T> link = this; link.isNotEmpty; link = link.tail) { | |
120 f(link.head); | |
121 } | |
122 } | |
123 | |
124 bool operator ==(other) { | |
125 if (other is! Link<T>) return false; | |
126 Link<T> myElements = this; | |
127 while (myElements.isNotEmpty && other.isNotEmpty) { | |
128 if (myElements.head != other.head) { | |
129 return false; | |
130 } | |
131 myElements = myElements.tail; | |
132 other = other.tail; | |
133 } | |
134 return myElements.isEmpty && other.isEmpty; | |
135 } | |
136 | |
137 int get hashCode => throw new UnsupportedError('LinkEntry.hashCode'); | |
138 | |
139 int slowLength() { | |
140 int length = 0; | |
141 for (Link current = this; current.isNotEmpty; current = current.tail) { | |
142 ++length; | |
143 } | |
144 return length; | |
145 } | |
146 | |
147 Link copyWithout(e) { | |
148 LinkBuilder copy = new LinkBuilder(); | |
149 Link link = this; | |
150 for (; link.isNotEmpty; link = link.tail) { | |
151 if (link.head != e) { | |
152 copy.addLast(link.head); | |
153 } | |
154 } | |
155 return copy.toLink(link); | |
156 } | |
157 } | |
158 | |
159 class LinkBuilderImplementation<T> implements LinkBuilder<T> { | |
160 LinkEntry<T> head = null; | |
161 LinkEntry<T> lastLink = null; | |
162 int length = 0; | |
163 | |
164 LinkBuilderImplementation(); | |
165 | |
166 Link<T> toLink([Link<T> tail = const Link()]) { | |
167 if (head == null) return tail; | |
168 lastLink.tail = tail; | |
169 Link<T> link = head; | |
170 lastLink = null; | |
171 head = null; | |
172 length = 0; | |
173 return link; | |
174 } | |
175 | |
176 List<T> toList() { | |
177 if (length == 0) return new List<T>(0); | |
178 List<T> list = new List<T>(length); | |
179 int index = 0; | |
180 Link<T> link = head; | |
181 while (link.isNotEmpty) { | |
182 list[index] = link.head; | |
183 link = link.tail; | |
184 index++; | |
185 } | |
186 lastLink = null; | |
187 head = null; | |
188 length = 0; | |
189 return list; | |
190 } | |
191 | |
192 Link<T> addLast(T t) { | |
193 length++; | |
194 LinkEntry<T> entry = new LinkEntry<T>(t, null); | |
195 if (head == null) { | |
196 head = entry; | |
197 } else { | |
198 lastLink.tail = entry; | |
199 } | |
200 lastLink = entry; | |
201 return entry; | |
202 } | |
203 | |
204 bool get isEmpty => length == 0; | |
205 | |
206 T get first { | |
207 if (head != null) { | |
208 return head.head; | |
209 } | |
210 throw new StateError("no elements"); | |
211 } | |
212 | |
213 void clear() { | |
214 head = null; | |
215 lastLink = null; | |
216 length = 0; | |
217 } | |
218 } | |
OLD | NEW |