OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, 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 dart.collection.dev; | |
6 | |
7 /** | |
8 * Class implementing the read-operations on [List]. | |
9 * | |
10 * Implements all read-only operations, except [:operator[]:] and [:length:], | |
11 * in terms of those two operations. | |
12 */ | |
13 abstract class ListBase<E> extends Collection<E> implements List<E> { | |
14 Iterator<E> get iterator => new ListIterator(this); | |
15 | |
16 void forEach(f(E element)) { | |
17 for (int i = 0; i < this.length; i++) f(this[i]); | |
18 } | |
19 | |
20 bool contains(E value) { | |
21 for (int i = 0; i < length; i++) { | |
22 if (this[i] == value) return true; | |
23 } | |
24 return false; | |
25 } | |
26 | |
27 reduce(initialValue, combine(previousValue, E element)) { | |
28 var value = initialValue; | |
29 for (int i = 0; i < this.length; i++) { | |
30 value = combine(value, this[i]); | |
31 } | |
32 return value; | |
33 } | |
34 | |
35 bool every(bool f(E element)) { | |
36 for (int i = 0; i < this.length; i++) { | |
37 if (!f(this[i])) return false; | |
38 } | |
39 return true; | |
40 } | |
41 | |
42 bool any(bool f(E element)) { | |
43 for (int i = 0; i < this.length; i++) { | |
44 if (f(this[i])) return true; | |
45 } | |
46 return false; | |
47 } | |
48 | |
49 bool get isEmpty { | |
50 return this.length == 0; | |
51 } | |
52 | |
53 E elementAt(int index) { | |
54 return this[index]; | |
55 } | |
56 | |
57 int indexOf(E value, [int start = 0]) { | |
58 for (int i = start; i < length; i++) { | |
59 if (this[i] == value) return i; | |
60 } | |
61 return -1; | |
62 } | |
63 | |
64 int lastIndexOf(E value, [int start]) { | |
65 if (start == null) start = length - 1; | |
66 for (int i = start; i >= 0; i--) { | |
67 if (this[i] == value) return i; | |
68 } | |
69 return -1; | |
70 } | |
71 | |
72 E get first { | |
73 if (length > 0) return this[0]; | |
74 throw new StateError("No elements"); | |
75 } | |
76 | |
77 E get last { | |
78 if (length > 0) return this[length - 1]; | |
79 throw new StateError("No elements"); | |
80 } | |
81 | |
82 E get single { | |
83 if (length == 1) return this[0]; | |
84 if (length == 0) throw new StateError("No elements"); | |
85 throw new StateError("More than one element"); | |
86 } | |
87 | |
88 List<E> getRange(int start, int length) { | |
89 List<E> result = <E>[]; | |
90 for (int i = 0; i < length; i++) { | |
91 result.add(this[start + i]); | |
92 } | |
93 return result; | |
94 } | |
95 | |
96 List mappedBy(f(E element)) { | |
97 return new MappedList(this, f); | |
98 } | |
99 | |
100 List<E> take(int n) { | |
101 return new ListView(this, 0, n); | |
102 } | |
103 | |
104 List<E> skip(int n) { | |
105 return new ListView(this, n, null); | |
106 } | |
107 | |
108 String toString() => ToString.collectionToString(this); | |
109 | |
110 List<E> get reversed { | |
111 return new ReversedListView(this, 0, null); | |
112 } | |
113 } | |
114 | |
115 /** | |
116 * Abstract class implementing the non-length changing operations of [List]. | |
117 */ | |
118 abstract class FixedLengthListBase<E> extends ListBase<E> { | |
119 void operator[]=(int index, E value); | |
120 | |
121 void sort([Comparator<E> compare]) { | |
122 Sort.sort(this, compare); | |
123 } | |
124 | |
125 void setRange(int start, int length, List<E> from, [int startFrom]) { | |
126 if (length < 0) throw new ArgumentError("length: $length"); | |
127 if (startFrom == null) startFrom = 0; | |
128 for (int i = 0; i < length; i++) { | |
129 this[start + i] = from[startFrom + i]; | |
130 } | |
131 } | |
132 | |
133 void set length(int newLength) { | |
134 throw new UnsupportedError( | |
135 "Cannot change the length of a fixed-length list"); | |
136 } | |
137 | |
138 void add(E value) { | |
139 throw new UnsupportedError( | |
140 "Cannot add to a fixed-length list"); | |
141 } | |
142 | |
143 void addLast(E value) { | |
144 throw new UnsupportedError( | |
145 "Cannot add to a fixed-length list"); | |
146 } | |
147 | |
148 void addAll(Iterable<E> iterable) { | |
149 throw new UnsupportedError( | |
150 "Cannot add to a fixed-length list"); | |
151 } | |
152 | |
153 void remove(E element) { | |
154 throw new UnsupportedError( | |
155 "Cannot remove from a fixed-length list"); | |
156 } | |
157 | |
158 void removeAll(Iterable elements) { | |
159 throw new UnsupportedError( | |
160 "Cannot remove from a fixed-length list"); | |
161 } | |
162 | |
163 void retainAll(Iterable elements) { | |
164 throw new UnsupportedError( | |
165 "Cannot remove from a fixed-length list"); | |
166 } | |
167 | |
168 void removeMatching(bool test(E element)) { | |
169 throw new UnsupportedError( | |
170 "Cannot remove from a fixed-length list"); | |
171 } | |
172 | |
173 void clear() { | |
174 throw new UnsupportedError( | |
175 "Cannot clear a fixed-length list"); | |
176 } | |
177 | |
178 E removeAt(int index) { | |
179 throw new UnsupportedError( | |
180 "Cannot remove from a fixed-length list"); | |
181 } | |
182 | |
183 E removeLast() { | |
184 throw new UnsupportedError( | |
185 "Cannot remove from a fixed-length list"); | |
186 } | |
187 | |
188 void removeRange(int start, int length) { | |
189 throw new UnsupportedError( | |
190 "Cannot remove from a fixed-length list"); | |
191 } | |
192 | |
193 void insertRange(int start, int length, [E initialValue]) { | |
194 throw new UnsupportedError( | |
195 "Cannot insert range in a fixed-length list"); | |
196 } | |
197 } | |
198 | |
199 /** | |
200 * An unmodifiable [List]. | |
201 */ | |
202 abstract class UnmodifiableListBase<E> extends ListBase<E> { | |
203 | |
204 void operator []=(int index, E value) { | |
205 throw new UnsupportedError( | |
206 "Cannot modify an unmodifiable list"); | |
207 } | |
208 | |
209 void set length(int newLength) { | |
210 throw new UnsupportedError( | |
211 "Cannot change the length of an unmodifiable list"); | |
212 } | |
213 | |
214 void add(E value) { | |
215 throw new UnsupportedError( | |
216 "Cannot add to an unmodifiable list"); | |
217 } | |
218 | |
219 void addLast(E value) { | |
220 throw new UnsupportedError( | |
221 "Cannot add to an unmodifiable list"); | |
222 } | |
223 | |
224 void addAll(Iterable<E> iterable) { | |
225 throw new UnsupportedError( | |
226 "Cannot add to an unmodifiable list"); | |
227 } | |
228 | |
229 void remove(E element) { | |
230 throw new UnsupportedError( | |
231 "Cannot remove from an unmodifiable list"); | |
232 } | |
233 | |
234 void removeAll(Iterable elements) { | |
235 throw new UnsupportedError( | |
236 "Cannot remove from an unmodifiable list"); | |
237 } | |
238 | |
239 void retainAll(Iterable elements) { | |
240 throw new UnsupportedError( | |
241 "Cannot remove from an unmodifiable list"); | |
242 } | |
243 | |
244 void removeMatching(bool test(E element)) { | |
245 throw new UnsupportedError( | |
246 "Cannot remove from an unmodifiable list"); | |
247 } | |
248 | |
249 void sort([Comparator<E> compare]) { | |
250 throw new UnsupportedError( | |
251 "Cannot modify an unmodifiable list"); | |
252 } | |
253 | |
254 void clear() { | |
255 throw new UnsupportedError( | |
256 "Cannot clear an unmodifiable list"); | |
257 } | |
258 | |
259 E removeAt(int index) { | |
260 throw new UnsupportedError( | |
261 "Cannot remove from an unmodifiable list"); | |
262 } | |
263 | |
264 E removeLast() { | |
265 throw new UnsupportedError( | |
266 "Cannot remove from an unmodifiable list"); | |
267 } | |
268 | |
269 void setRange(int start, int length, List<E> from, [int startFrom]) { | |
270 throw new UnsupportedError( | |
271 "Cannot modify an unmodifiable list"); | |
272 } | |
273 | |
274 void removeRange(int start, int length) { | |
275 throw new UnsupportedError( | |
276 "Cannot remove from an unmodifiable list"); | |
277 } | |
278 | |
279 void insertRange(int start, int length, [E initialValue]) { | |
280 throw new UnsupportedError( | |
281 "Cannot insert range in an unmodifiable list"); | |
282 } | |
283 } | |
284 | |
285 /** | |
286 * Iterates over a [List] in growing index order. | |
287 */ | |
288 class ListIterator<E> implements Iterator<E> { | |
289 final List<E> _list; | |
290 final int _length; | |
291 int _position; | |
292 E _current; | |
293 | |
294 ListIterator(List<E> list) | |
295 : _list = list, _position = -1, _length = list.length; | |
296 | |
297 bool moveNext() { | |
298 if (_list.length != _length) { | |
299 throw new ConcurrentModificationError(_list); | |
300 } | |
301 int nextPosition = _position + 1; | |
302 if (nextPosition < _length) { | |
303 _position = nextPosition; | |
304 _current = _list[nextPosition]; | |
305 return true; | |
306 } | |
307 _current = null; | |
308 return false; | |
309 } | |
310 | |
311 E get current => _current; | |
312 } | |
313 | |
314 class MappedList<S, T> extends UnmodifiableListBase<T> { | |
315 final List<S> _list; | |
316 // TODO(ahe): Restore type when feature is implemented in dart2js | |
317 // checked mode. http://dartbug.com/7733 | |
318 final /* _Transformation<S, T> */ _f; | |
319 | |
320 MappedList(this._list, T this._f(S element)); | |
321 | |
322 T operator[](int index) => _f(_list[index]); | |
323 int get length => _list.length; | |
324 } | |
325 | |
326 /** An empty fixed-length list. */ | |
327 class EmptyList<E> extends FixedLengthListBase<E> { | |
328 int get length => 0; | |
329 E operator[](int index) { throw new RangeError.value(index); } | |
330 void operator []=(int index, E value) { throw new RangeError.value(index); } | |
331 List<E> skip(int count) => this; | |
332 List<E> take(int count) => this; | |
333 List<E> get reversed => this; | |
334 void sort([int compare(E a, E b)]) {} | |
335 } | |
336 | |
337 /** | |
338 * A fixed-length view of a sub-range of another [List]. | |
339 * | |
340 * The range is described by start and end points relative | |
341 * to the other List's start or end. | |
342 * | |
343 * The range changes dynamically as the underlying list changes | |
344 * its length. | |
345 */ | |
346 abstract class SubListView<E> extends UnmodifiableListBase<E> { | |
347 final List<E> _list; | |
348 final int _start; | |
349 final int _end; | |
350 | |
351 /** | |
352 * Create a sub-list view. | |
353 * | |
354 * Both [_start] and [_end] can be given as positions | |
355 * relative to the start of [_list] (a non-negative integer) | |
356 * or relative to the end of [_list] (a negative integer or | |
357 * null, with null being at the end of the list). | |
358 */ | |
359 SubListView(this._list, this._start, this._end); | |
360 | |
361 int _absoluteIndex(int relativeIndex) { | |
362 if (relativeIndex == null) return _list.length; | |
363 if (relativeIndex < 0) { | |
364 int result = _list.length + relativeIndex; | |
365 if (result < 0) return 0; | |
366 return result; | |
367 } | |
368 if (relativeIndex > _list.length) { | |
369 return _list.length; | |
370 } | |
371 return relativeIndex; | |
372 } | |
373 | |
374 int get length { | |
375 int result = _absoluteIndex(_end) - _absoluteIndex(_start); | |
376 if (result >= 0) return result; | |
377 return 0; | |
378 } | |
379 | |
380 _createListView(int start, int end) { | |
381 if (start == null) return new EmptyList<E>(); | |
382 if (end != null) { | |
383 if (start < 0) { | |
384 if (end <= start) return new EmptyList<E>(); | |
385 } else { | |
386 if (end >= 0 && end <= start) return new EmptyList<E>(); | |
387 } | |
388 } | |
389 return new ListView(_list, start, end); | |
390 } | |
391 | |
392 _createReversedListView(int start, int end) { | |
393 if (start == null) return new EmptyList<E>(); | |
394 if (end != null) { | |
395 if (start < 0) { | |
396 if (end <= start) return new EmptyList<E>(); | |
397 } else { | |
398 if (end >= 0 && end <= start) return new EmptyList<E>(); | |
399 } | |
400 } | |
401 return new ReversedListView(_list, start, end); | |
402 } | |
403 } | |
404 | |
405 | |
406 /** | |
407 * A fixed-length view of a sub-range of a [List]. | |
408 */ | |
409 class ListView<E> extends SubListView<E> { | |
410 | |
411 ListView(List<E> list, int start, int end) : super(list, start, end); | |
412 | |
413 E operator[](int index) { | |
414 int start = _absoluteIndex(_start); | |
415 int end = _absoluteIndex(_end); | |
416 int length = end - start; | |
417 if (index < 0 || index >= length) { | |
418 throw new RangeError.range(index, 0, length); | |
419 } | |
420 return _list[start + index]; | |
421 } | |
422 | |
423 List<E> skip(int count) { | |
424 if (count is! int || count < 0) { | |
425 throw new ArgumentError(count); | |
426 } | |
427 if (_start == null) { | |
428 return new EmptyList<E>(); | |
429 } | |
430 int newStart = _start + count; | |
431 if (_start < 0 && newStart >= 0) { | |
432 return new EmptyList<E>(); | |
433 } | |
434 return _createListView(newStart, _end); | |
435 } | |
436 | |
437 List<E> take(int count) { | |
438 if (count is! int || count < 0) { | |
439 throw new ArgumentError(count); | |
440 } | |
441 if (_start == null) { | |
442 return new EmptyList<E>(); | |
443 } | |
444 int newEnd = _start + count; | |
445 if (_start < 0 && newEnd >= 0) { | |
446 newEnd = null; | |
447 } | |
448 return _createListView(_start, newEnd); | |
449 } | |
450 | |
451 List<E> get reversed => new ReversedListView(_list, _start, _end); | |
452 } | |
453 | |
454 /** | |
455 * Reversed view of a [List], or a slice of a list. | |
456 * | |
457 * The view is fixed-length and becomes invalid if the underlying | |
458 * list changes its length below the slice used by this reversed list. | |
459 * | |
460 * Start index and end index can be either positive, negative or null. | |
461 * Positive means an index relative to the start of the list, | |
462 * negative means an index relative to the end of the list, and null | |
463 * means at the end of the list (since there is no -0 integer). | |
464 */ | |
465 class ReversedListView<E> extends SubListView<E> { | |
466 | |
467 ReversedListView(List<E> list, int start, int end) | |
468 : super(list, start, end); | |
469 | |
470 E operator[](int index) { | |
471 int start = _absoluteIndex(_start); | |
472 int end = _absoluteIndex(_end); | |
473 int length = end - start; | |
474 if (index < 0 || index >= length) { | |
475 throw new RangeError.range(index, 0, length); | |
476 } | |
477 return _list[end - index - 1]; | |
478 } | |
479 | |
480 List<E> skip(int count) { | |
481 if (count is! int || count < 0) { | |
482 throw new ArgumentError(count); | |
483 } | |
484 if (_end == null) { | |
485 return _createReversedListView(_start, -count); | |
486 } | |
487 int newEnd = _end - count; | |
488 if (_end >= 0 && newEnd < 0) { | |
489 return new EmptyList<E>(); | |
490 } | |
491 return _createReversedListView(_start, newEnd); | |
492 } | |
493 | |
494 List<E> take(int count) { | |
495 if (count is! int || count < 0) { | |
496 throw new ArgumentError(count); | |
497 } | |
498 int newStart; | |
499 if (_end == null) { | |
500 newStart = -count; | |
501 } else { | |
502 newStart = _end - count; | |
503 if (_end >= 0 && newStart < 0) { | |
504 return new EmptyList<E>(); | |
505 } | |
506 } | |
507 return _createReversedListView(newStart, _end); | |
508 } | |
509 | |
510 Iterator<E> get iterator => new ReverseListIterator<E>( | |
511 _list, _absoluteIndex(_start), _absoluteIndex(_end)); | |
512 | |
513 List<E> get reversed { | |
514 return new ListView(_list, _start, _end); | |
515 } | |
516 } | |
517 | |
518 /** | |
519 * An [Iterator] over a slice of a list that access elements in reverse order. | |
520 */ | |
521 class ReverseListIterator<E> implements Iterator<E> { | |
522 final List<E> _list; | |
523 final int _start; | |
524 final int _originalLength; | |
525 int _index; | |
526 E _current; | |
527 | |
528 ReverseListIterator(List<E> list, int start, int end) | |
529 : _list = list, | |
530 _start = start, | |
531 _index = end, | |
532 _originalLength = list.length; | |
533 | |
534 bool moveNext() { | |
535 if (_list.length != _originalLength) { | |
536 throw new ConcurrentModificationError(_list); | |
537 } | |
538 if (_index <= _start) return false; | |
539 _index -= 1; | |
540 _current = _list[_index]; | |
541 return true; | |
542 } | |
543 | |
544 E get current => _current; | |
545 } | |
OLD | NEW |