OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * A [Queue] is a collection that can be manipulated at both ends. One | 8 * A [Queue] is a collection that can be manipulated at both ends. One |
9 * can iterate over the elements of a queue through [forEach] or with | 9 * can iterate over the elements of a queue through [forEach] or with |
10 * an [Iterator]. | 10 * an [Iterator]. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 * Adds [value] at the end of the queue. | 43 * Adds [value] at the end of the queue. |
44 */ | 44 */ |
45 void addLast(E value); | 45 void addLast(E value); |
46 | 46 |
47 /** | 47 /** |
48 * Adds [value] at the end of the queue. | 48 * Adds [value] at the end of the queue. |
49 */ | 49 */ |
50 void add(E value); | 50 void add(E value); |
51 | 51 |
52 /** | 52 /** |
53 * Adds all elements of [collection] at the end of the queue. The | 53 * Adds all elements of [iterable] at the end of the queue. The |
54 * length of the queue is extended by the length of [collection]. | 54 * length of the queue is extended by the length of [iterable]. |
55 */ | 55 */ |
56 void addAll(Collection<E> collection); | 56 void addAll(Iterable<E> iterable); |
57 | |
58 /** | |
59 * Returns the first element of the queue. Throws an | |
60 * [StateError] exception if this queue is empty. | |
61 */ | |
62 E get first; | |
63 | |
64 /** | |
65 * Returns the last element of the queue. Throws an | |
66 * [StateError] exception if this queue is empty. | |
67 */ | |
68 E get last; | |
69 | 57 |
70 /** | 58 /** |
71 * Removes all elements in the queue. The size of the queue becomes zero. | 59 * Removes all elements in the queue. The size of the queue becomes zero. |
72 */ | 60 */ |
73 void clear(); | 61 void clear(); |
74 } | 62 } |
75 | 63 |
76 | 64 |
77 /** | 65 /** |
78 * An entry in a doubly linked list. It contains a pointer to the next | 66 * An entry in a doubly linked list. It contains a pointer to the next |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 } | 153 } |
166 } | 154 } |
167 | 155 |
168 /** | 156 /** |
169 * Implementation of a double linked list that box list elements into | 157 * Implementation of a double linked list that box list elements into |
170 * DoubleLinkedQueueEntry objects. | 158 * DoubleLinkedQueueEntry objects. |
171 * | 159 * |
172 * WARNING: This class is temporary located in dart:core. It'll be removed | 160 * WARNING: This class is temporary located in dart:core. It'll be removed |
173 * at some point in the near future. | 161 * at some point in the near future. |
174 */ | 162 */ |
175 class DoubleLinkedQueue<E> implements Queue<E> { | 163 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> { |
176 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 164 _DoubleLinkedQueueEntrySentinel<E> _sentinel; |
177 | 165 |
178 DoubleLinkedQueue() { | 166 DoubleLinkedQueue() { |
179 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | 167 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); |
180 } | 168 } |
181 | 169 |
182 factory DoubleLinkedQueue.from(Iterable<E> other) { | 170 factory DoubleLinkedQueue.from(Iterable<E> other) { |
183 Queue<E> list = new DoubleLinkedQueue(); | 171 Queue<E> list = new DoubleLinkedQueue(); |
184 for (final e in other) { | 172 for (final e in other) { |
185 list.addLast(e); | 173 list.addLast(e); |
186 } | 174 } |
187 return list; | 175 return list; |
188 } | 176 } |
189 | 177 |
190 void addLast(E value) { | 178 void addLast(E value) { |
191 _sentinel.prepend(value); | 179 _sentinel.prepend(value); |
192 } | 180 } |
193 | 181 |
194 void addFirst(E value) { | 182 void addFirst(E value) { |
195 _sentinel.append(value); | 183 _sentinel.append(value); |
196 } | 184 } |
197 | 185 |
198 void add(E value) { | 186 void add(E value) { |
199 addLast(value); | 187 addLast(value); |
200 } | 188 } |
201 | 189 |
202 void addAll(Collection<E> collection) { | 190 void addAll(Iterable<E> iterable) { |
203 for (final e in collection) { | 191 for (final e in iterable) { |
204 add(e); | 192 add(e); |
205 } | 193 } |
206 } | 194 } |
207 | 195 |
208 E removeLast() { | 196 E removeLast() { |
209 return _sentinel._previous.remove(); | 197 return _sentinel._previous.remove(); |
210 } | 198 } |
211 | 199 |
212 E removeFirst() { | 200 E removeFirst() { |
213 return _sentinel._next.remove(); | 201 return _sentinel._next.remove(); |
214 } | 202 } |
215 | 203 |
216 E get first { | 204 E get first { |
217 return _sentinel._next.element; | 205 return _sentinel._next.element; |
218 } | 206 } |
219 | 207 |
220 E get last { | 208 E get last { |
221 return _sentinel._previous.element; | 209 return _sentinel._previous.element; |
222 } | 210 } |
223 | 211 |
| 212 E get single { |
| 213 // Note that this also covers the case where the queue is empty. |
| 214 if (identical(_sentinel._next, _sentinel._previous)) { |
| 215 return _sentinel._next.element; |
| 216 } |
| 217 throw new StateError("More than one element"); |
| 218 } |
| 219 |
224 DoubleLinkedQueueEntry<E> lastEntry() { | 220 DoubleLinkedQueueEntry<E> lastEntry() { |
225 return _sentinel.previousEntry(); | 221 return _sentinel.previousEntry(); |
226 } | 222 } |
227 | 223 |
228 DoubleLinkedQueueEntry<E> firstEntry() { | 224 DoubleLinkedQueueEntry<E> firstEntry() { |
229 return _sentinel.nextEntry(); | 225 return _sentinel.nextEntry(); |
230 } | 226 } |
231 | 227 |
232 int get length { | |
233 int counter = 0; | |
234 forEach((E element) { counter++; }); | |
235 return counter; | |
236 } | |
237 | |
238 bool get isEmpty { | 228 bool get isEmpty { |
239 return (identical(_sentinel._next, _sentinel)); | 229 return (identical(_sentinel._next, _sentinel)); |
240 } | 230 } |
241 | 231 |
242 void clear() { | 232 void clear() { |
243 _sentinel._next = _sentinel; | 233 _sentinel._next = _sentinel; |
244 _sentinel._previous = _sentinel; | 234 _sentinel._previous = _sentinel; |
245 } | 235 } |
246 | 236 |
247 void forEach(void f(E element)) { | |
248 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
249 while (!identical(entry, _sentinel)) { | |
250 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
251 f(entry._element); | |
252 entry = nextEntry; | |
253 } | |
254 } | |
255 | |
256 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | 237 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { |
257 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | 238 DoubleLinkedQueueEntry<E> entry = _sentinel._next; |
258 while (!identical(entry, _sentinel)) { | 239 while (!identical(entry, _sentinel)) { |
259 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | 240 DoubleLinkedQueueEntry<E> nextEntry = entry._next; |
260 f(entry); | 241 f(entry); |
261 entry = nextEntry; | 242 entry = nextEntry; |
262 } | 243 } |
263 } | 244 } |
264 | 245 |
265 bool every(bool f(E element)) { | 246 _DoubleLinkedQueueIterator<E> get iterator { |
266 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
267 while (!identical(entry, _sentinel)) { | |
268 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
269 if (!f(entry._element)) return false; | |
270 entry = nextEntry; | |
271 } | |
272 return true; | |
273 } | |
274 | |
275 bool some(bool f(E element)) { | |
276 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
277 while (!identical(entry, _sentinel)) { | |
278 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
279 if (f(entry._element)) return true; | |
280 entry = nextEntry; | |
281 } | |
282 return false; | |
283 } | |
284 | |
285 Queue map(f(E element)) { | |
286 Queue other = new Queue(); | |
287 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
288 while (!identical(entry, _sentinel)) { | |
289 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
290 other.addLast(f(entry._element)); | |
291 entry = nextEntry; | |
292 } | |
293 return other; | |
294 } | |
295 | |
296 dynamic reduce(dynamic initialValue, | |
297 dynamic combine(dynamic previousValue, E element)) { | |
298 return Collections.reduce(this, initialValue, combine); | |
299 } | |
300 | |
301 Queue<E> filter(bool f(E element)) { | |
302 Queue<E> other = new Queue<E>(); | |
303 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
304 while (!identical(entry, _sentinel)) { | |
305 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
306 if (f(entry._element)) other.addLast(entry._element); | |
307 entry = nextEntry; | |
308 } | |
309 return other; | |
310 } | |
311 | |
312 _DoubleLinkedQueueIterator<E> iterator() { | |
313 return new _DoubleLinkedQueueIterator<E>(_sentinel); | 247 return new _DoubleLinkedQueueIterator<E>(_sentinel); |
314 } | 248 } |
315 | 249 |
316 String toString() { | 250 String toString() { |
317 return Collections.collectionToString(this); | 251 return Collections.collectionToString(this); |
318 } | 252 } |
319 } | 253 } |
320 | 254 |
321 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | 255 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { |
322 final _DoubleLinkedQueueEntrySentinel<E> _sentinel; | 256 _DoubleLinkedQueueEntrySentinel<E> _sentinel; |
323 DoubleLinkedQueueEntry<E> _currentEntry; | 257 DoubleLinkedQueueEntry<E> _currentEntry = null; |
| 258 E _current; |
324 | 259 |
325 _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel this._sentinel) { | 260 _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel<E> sentinel) |
326 _currentEntry = _sentinel; | 261 : _sentinel = sentinel, _currentEntry = sentinel; |
| 262 |
| 263 bool moveNext() { |
| 264 // When [_currentEntry] it is set to [:null:] then it is at the end. |
| 265 if (_currentEntry == null) { |
| 266 assert(_current == null); |
| 267 return false; |
| 268 } |
| 269 _currentEntry = _currentEntry._next; |
| 270 if (identical(_currentEntry, _sentinel)) { |
| 271 _currentEntry = null; |
| 272 _current = null; |
| 273 _sentinel = null; |
| 274 return false; |
| 275 } |
| 276 _current = _currentEntry.element; |
| 277 return true; |
327 } | 278 } |
328 | 279 |
329 bool get hasNext { | 280 E get current => _current; |
330 return !identical(_currentEntry._next, _sentinel); | |
331 } | |
332 | |
333 E next() { | |
334 if (!hasNext) { | |
335 throw new StateError("No more elements"); | |
336 } | |
337 _currentEntry = _currentEntry._next; | |
338 return _currentEntry.element; | |
339 } | |
340 } | 281 } |
OLD | NEW |