OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 [List] is an indexable collection with a length. It can be of | 8 * A [List] is an indexable collection with a length. It can be of |
9 * fixed size or extendable. | 9 * fixed size or extendable. |
10 */ | 10 */ |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 void addLast(E value); | 78 void addLast(E value); |
79 | 79 |
80 /** | 80 /** |
81 * Appends all elements of the [iterable] to the end of this list. | 81 * Appends all elements of the [iterable] to the end of this list. |
82 * Extends the length of the list by the number of elements in [iterable]. | 82 * Extends the length of the list by the number of elements in [iterable]. |
83 * Throws an [UnsupportedError] if this list is not extensible. | 83 * Throws an [UnsupportedError] if this list is not extensible. |
84 */ | 84 */ |
85 void addAll(Iterable<E> iterable); | 85 void addAll(Iterable<E> iterable); |
86 | 86 |
87 /** | 87 /** |
88 * Returns a reversed fixed-length view of this [List]. | |
89 * | |
90 * The reversed list has elements in the opposite order of this list. | |
91 * It is backed by this list, but will stop working if this list | |
92 * becomes shorter than its current length. | |
93 */ | |
94 List<T> get reversed => new ReversedList(this, 0, length); | |
95 | |
96 /** | |
88 * Sorts the list according to the order specified by the [compare] function. | 97 * Sorts the list according to the order specified by the [compare] function. |
89 * | 98 * |
90 * The [compare] function must act as a [Comparator]. | 99 * The [compare] function must act as a [Comparator]. |
91 * The default [List] implementations use [Comparable.compare] if | 100 * The default [List] implementations use [Comparable.compare] if |
92 * [compare] is omitted. | 101 * [compare] is omitted. |
93 */ | 102 */ |
94 void sort([int compare(E a, E b)]); | 103 void sort([int compare(E a, E b)]); |
95 | 104 |
96 /** | 105 /** |
97 * Returns the first index of [element] in the list. | 106 * Returns the first index of [element] in the list. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 * If [start] is the length of the list, this method inserts the | 194 * If [start] is the length of the list, this method inserts the |
186 * range at the end of the list. | 195 * range at the end of the list. |
187 * Throws an [ArgumentError] if [length] is negative. | 196 * Throws an [ArgumentError] if [length] is negative. |
188 * Throws an [RangeError] if [start] is negative or if | 197 * Throws an [RangeError] if [start] is negative or if |
189 * [start] is greater than the length of the list. | 198 * [start] is greater than the length of the list. |
190 */ | 199 */ |
191 void insertRange(int start, int length, [E fill]); | 200 void insertRange(int start, int length, [E fill]); |
192 } | 201 } |
193 | 202 |
194 /** | 203 /** |
195 * An unmodifiable [List]. | 204 * Class implementing the read-operations on [List]. |
205 * | |
206 * Implements all operations except [:operator[]:] and [:length:] that does not | |
207 * modify the list in terms of those two. | |
196 */ | 208 */ |
197 abstract class NonExtensibleListMixin<E> | 209 abstract class BaseListMixin<E> extends Iterable<E> implements List<E> { |
floitsch
2013/01/21 14:38:06
These classes are no longer in core.
Lasse Reichstein Nielsen
2013/01/22 10:18:52
Moved to collection-dev.
| |
198 extends Iterable<E> implements List<E> { | |
199 | |
200 Iterator<E> get iterator => new ListIterator(this); | 210 Iterator<E> get iterator => new ListIterator(this); |
201 | 211 |
202 void forEach(f(E element)) { | 212 void forEach(f(E element)) { |
203 for (int i = 0; i < this.length; i++) f(this[i]); | 213 for (int i = 0; i < this.length; i++) f(this[i]); |
204 } | 214 } |
205 | 215 |
206 bool contains(E value) { | 216 bool contains(E value) { |
207 for (int i = 0; i < length; i++) { | 217 for (int i = 0; i < length; i++) { |
208 if (this[i] == value) return true; | 218 if (this[i] == value) return true; |
209 } | 219 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 throw new StateError("More than one element"); | 281 throw new StateError("More than one element"); |
272 } | 282 } |
273 | 283 |
274 List<E> getRange(int start, int length) { | 284 List<E> getRange(int start, int length) { |
275 List<E> result = <E>[]; | 285 List<E> result = <E>[]; |
276 for (int i = 0; i < length; i++) { | 286 for (int i = 0; i < length; i++) { |
277 result.add(this[start + i]); | 287 result.add(this[start + i]); |
278 } | 288 } |
279 return result; | 289 return result; |
280 } | 290 } |
291 } | |
292 | |
293 /** | |
294 * Abstract class implementing the non-length changing operations of [List]. | |
295 */ | |
296 abstract class FixedLengthListMixin<E> extends BaseListMixin<E> { | |
floitsch
2013/01/21 14:38:06
Can't be a mixin, since it extends (or mixins) Bas
Lasse Reichstein Nielsen
2013/01/22 10:18:52
True, so it needs a better name.
Just FixedLengthL
| |
297 void operator[]=(int index, E value); | |
298 | |
299 List<E> get reversed => new ReversedList<E>(this, 0, length); | |
300 | |
301 void sort([Comparator<E> compare]) { | |
302 coreSort(this, compare); | |
303 } | |
304 | |
305 void setRange(int start, int length, List<E> from, [int startFrom]) { | |
306 if (length < 0) throw new ArgumentError("length: $length"); | |
307 if (startFrom == null) startFrom = 0; | |
308 for (int i = 0; i < length; i++) { | |
309 this[from + i] = from[startFrom + i]; | |
310 } | |
311 } | |
312 | |
313 void set length(int newLength) { | |
314 throw new UnsupportedError( | |
315 "Cannot change the length of a fixed-length list"); | |
316 } | |
317 | |
318 void add(E value) { | |
319 throw new UnsupportedError( | |
320 "Cannot add to a fixed-length list"); | |
321 } | |
322 | |
323 void addLast(E value) { | |
324 throw new UnsupportedError( | |
325 "Cannot add to a fixed-length list"); | |
326 } | |
327 | |
328 void addAll(Iterable<E> iterable) { | |
329 throw new UnsupportedError( | |
330 "Cannot add to a fixed-length list"); | |
331 } | |
332 | |
333 void remove(E element) { | |
334 throw new UnsupportedError( | |
335 "Cannot remove from a fixed-length list"); | |
336 } | |
337 | |
338 void removeAll(Iterable elements) { | |
339 throw new UnsupportedError( | |
340 "Cannot remove from a fixed-length list"); | |
341 } | |
342 | |
343 void retainAll(Iterable elements) { | |
344 throw new UnsupportedError( | |
345 "Cannot remove from a fixed-length list"); | |
346 } | |
347 | |
348 void removeMatching(bool test(E element)) { | |
349 throw new UnsupportedError( | |
350 "Cannot remove from a fixed-length list"); | |
351 } | |
352 | |
353 void clear() { | |
354 throw new UnsupportedError( | |
355 "Cannot clear a fixed-length list"); | |
356 } | |
357 | |
358 E removeAt(int index) { | |
359 throw new UnsupportedError( | |
360 "Cannot remove from a fixed-length list"); | |
361 } | |
362 | |
363 E removeLast() { | |
364 throw new UnsupportedError( | |
365 "Cannot remove from a fixed-length list"); | |
366 } | |
367 | |
368 void removeRange(int start, int length) { | |
369 throw new UnsupportedError( | |
370 "Cannot remove from a fixed-length list"); | |
371 } | |
372 | |
373 void insertRange(int start, int length, [E initialValue]) { | |
374 throw new UnsupportedError( | |
375 "Cannot insert range in a fixed-length list"); | |
376 } | |
377 } | |
378 | |
379 /** | |
380 * An unmodifiable [List]. | |
381 */ | |
382 abstract class UnmodifiableListMixin<E> extends BaseListMixin<E> { | |
281 | 383 |
282 void operator []=(int index, E value) { | 384 void operator []=(int index, E value) { |
283 throw new UnsupportedError( | 385 throw new UnsupportedError( |
284 "Cannot modify an unmodifiable list"); | 386 "Cannot modify an unmodifiable list"); |
285 } | 387 } |
286 | 388 |
287 void set length(int newLength) { | 389 void set length(int newLength) { |
288 throw new UnsupportedError( | 390 throw new UnsupportedError( |
289 "Cannot change the length of an unmodifiable list"); | 391 "Cannot change the length of an unmodifiable list"); |
290 } | 392 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 return true; | 480 return true; |
379 } | 481 } |
380 _position = _list.length; | 482 _position = _list.length; |
381 _current = null; | 483 _current = null; |
382 return false; | 484 return false; |
383 } | 485 } |
384 | 486 |
385 E get current => _current; | 487 E get current => _current; |
386 } | 488 } |
387 | 489 |
388 class MappedList<S, T> extends NonExtensibleListMixin<T> { | 490 class MappedList<S, T> extends UnmodifiableListMixin<T> { |
389 final List<S> _list; | 491 final List<S> _list; |
390 // TODO(ahe): Restore type when feature is implemented in dart2js | 492 // TODO(ahe): Restore type when feature is implemented in dart2js |
391 // checked mode. http://dartbug.com/7733 | 493 // checked mode. http://dartbug.com/7733 |
392 final /* _Transformation<S, T> */ _f; | 494 final /* _Transformation<S, T> */ _f; |
393 | 495 |
394 MappedList(this._list, T this._f(S element)); | 496 MappedList(this._list, T this._f(S element)); |
395 | 497 |
396 T operator[](int index) => _f(_list[index]); | 498 T operator[](int index) => _f(_list[index]); |
397 int get length => _list.length; | 499 int get length => _list.length; |
398 } | 500 } |
399 | 501 |
502 /** An empty fixed-length list. */ | |
503 class EmptyList<E> extends FixedLengthListMixin<E> { | |
504 int get length => 0; | |
505 E operator[](int index) { throw new ArgumentError(index); } | |
floitsch
2013/01/21 14:38:06
RangeError
Lasse Reichstein Nielsen
2013/01/22 10:18:52
Done.
| |
506 void operator[]=(int index, E value) { throw new ArgumentError(index); } | |
507 } | |
508 | |
400 /** | 509 /** |
401 * An immutable view of a [List]. | 510 * An unmodifiable view of a [List]. |
402 */ | 511 */ |
403 class ListView<E> extends NonExtensibleListMixin<E> { | 512 class ListView<E> extends UnmodifiableListMixin<E> { |
404 final List<E> _list; | 513 final List<E> _list; |
405 final int _offset; | 514 final int _offset; |
406 final int _length; | 515 final int _length; |
407 | 516 |
408 /** | 517 /** |
409 * If the given length is `null` then the ListView's length is bound by | 518 * If the given length is `null` then the ListView's length is bound by |
410 * the backed [list]. | 519 * the backed [list]. |
411 */ | 520 */ |
412 ListView(List<E> list, this._offset, this._length) : _list = list { | 521 ListView(List<E> list, this._offset, this._length) : _list = list { |
413 if (_offset is! int || _offset < 0) { | 522 if (_offset is! int || _offset < 0) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 } | 554 } |
446 | 555 |
447 ListView<E> take(int takeCount) { | 556 ListView<E> take(int takeCount) { |
448 if (takeCount is! int || takeCount < 0) { | 557 if (takeCount is! int || takeCount < 0) { |
449 throw new ArgumentError(takeCount); | 558 throw new ArgumentError(takeCount); |
450 } | 559 } |
451 int newLength = takeCount; | 560 int newLength = takeCount; |
452 if (_length != null && takeCount > _length) newLength = _length; | 561 if (_length != null && takeCount > _length) newLength = _length; |
453 return new ListView(_list, _offset, newLength); | 562 return new ListView(_list, _offset, newLength); |
454 } | 563 } |
564 | |
565 List<E> get reversed => new ReversedList(_list, _offset, _offset + _length); | |
566 | |
567 String toString() => Collections.collectionToString(this); | |
455 } | 568 } |
569 | |
570 /** | |
571 * Reversed view of a [List], or a slice of a list. | |
572 * | |
573 * The view is fixed-length and becomes invalid if the underlying | |
574 * list changes its length below the slice used by this reversed list. | |
floitsch
2013/01/21 14:38:06
That's now how iterables work. And ReversedList (l
Lasse Reichstein Nielsen
2013/01/21 14:43:40
So what should it do?
| |
575 */ | |
576 class ReversedList<E> extends FixedLengthListMixin<E> { | |
577 final List<E> _list; | |
578 final int _start; | |
579 final int _end; | |
580 ReversedList(List<E> list, int start, int end) | |
581 : _list = list, _start = start, _end = end; | |
582 | |
583 int get length => _end - _start; | |
584 | |
585 E operator[](int index) { | |
586 if (_list.length < _end) throw new StateError("Concurrent modification"); | |
587 int length = _end - _start; | |
588 if (index < 0 || index > length) { | |
589 throw new RangeError("$index not in range 0..$length"); | |
590 } | |
591 return _list[_end - index - 1]; | |
592 } | |
593 | |
594 void operator[]=(int index, E value) { | |
595 if (_list.length < _end) throw new StateError("Concurrent modification"); | |
596 int length = _end - _start; | |
597 if (index < 0 || index > length) { | |
598 throw new RangeError("$index not in range 0..$length"); | |
599 } | |
600 _list[_end - index - 1] = value; | |
601 } | |
602 | |
603 Iterable<E> get iterator => new ReverseListIterator<E>(_list, _start, _end); | |
604 | |
605 List<E> take(int count) { | |
606 if (count is! int || count < 0) { | |
607 throw new ArgumentError(count); | |
608 } | |
609 int length = _end - _start; | |
610 if (count > length) count = length; | |
611 return new ReversedList(_list, _end - count, _end); | |
612 } | |
613 | |
614 List<E> skip(int count) { | |
615 if (count is! int || count < 0) { | |
616 throw new ArgumentError(count); | |
617 } | |
618 int length = _end - _start; | |
619 if (count >= length) return new EmptyList(); | |
620 return new ReversedList(_list, _start, _end - count); | |
621 } | |
622 | |
623 void sort([int compare(E first, E second)]) { | |
624 if (compare == null) compare = Comparable.compare; | |
625 // TODO(lrn): Make a way to sort a slice of a list using core sort. | |
626 List<E> slice = _list.getRange(_start, _end); | |
627 slice.sort((E a, E b) => compare(b, a)); | |
628 _list.setRange(_start, slice.length, slice); | |
629 } | |
630 | |
631 List<E> get reversed { | |
632 return new ListView(_list, _start, _end - _start); | |
633 } | |
634 | |
635 String toString() => Collections.collectionToString(this); | |
636 } | |
637 | |
638 /** | |
639 * An [Iterator] over a slice of a list that access elements in reverse order. | |
640 */ | |
641 class ReverseListIterator<E> implements Iterator<E> { | |
642 final List<E> _list; | |
643 final int _start; | |
644 int _index; | |
645 E _current; | |
646 | |
647 ReverseListIterator(List<E> list, int start, int end) | |
648 : _list = list, _start = start, _index = end; | |
649 | |
650 bool moveNext() { | |
651 if (_index <= _start) return false; | |
652 _index -= 1; | |
653 _current = _list[_index]; | |
654 return true; | |
655 } | |
656 | |
657 E get current => _current; | |
658 } | |
OLD | NEW |