Index: sdk/lib/core/list.dart |
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart |
index 062a0d9cfa7e947082ddd57d44ce5daa3ee54887..f5ef21867ffd56890486183934e08ad88821b21c 100644 |
--- a/sdk/lib/core/list.dart |
+++ b/sdk/lib/core/list.dart |
@@ -85,6 +85,15 @@ abstract class List<E> implements Collection<E> { |
void addAll(Iterable<E> iterable); |
/** |
+ * Returns a reversed fixed-length view of this [List]. |
+ * |
+ * The reversed list has elements in the opposite order of this list. |
+ * It is backed by this list, but will stop working if this list |
+ * becomes shorter than its current length. |
+ */ |
+ List<T> get reversed => new ReversedList(this, 0, length); |
+ |
+ /** |
* Sorts the list according to the order specified by the [compare] function. |
* |
* The [compare] function must act as a [Comparator]. |
@@ -192,11 +201,12 @@ abstract class List<E> implements Collection<E> { |
} |
/** |
- * An unmodifiable [List]. |
+ * Class implementing the read-operations on [List]. |
+ * |
+ * Implements all operations except [:operator[]:] and [:length:] that does not |
+ * modify the list in terms of those two. |
*/ |
-abstract class NonExtensibleListMixin<E> |
- extends Iterable<E> implements List<E> { |
- |
+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.
|
Iterator<E> get iterator => new ListIterator(this); |
void forEach(f(E element)) { |
@@ -278,6 +288,98 @@ abstract class NonExtensibleListMixin<E> |
} |
return result; |
} |
+} |
+ |
+/** |
+ * Abstract class implementing the non-length changing operations of [List]. |
+ */ |
+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
|
+ void operator[]=(int index, E value); |
+ |
+ List<E> get reversed => new ReversedList<E>(this, 0, length); |
+ |
+ void sort([Comparator<E> compare]) { |
+ coreSort(this, compare); |
+ } |
+ |
+ void setRange(int start, int length, List<E> from, [int startFrom]) { |
+ if (length < 0) throw new ArgumentError("length: $length"); |
+ if (startFrom == null) startFrom = 0; |
+ for (int i = 0; i < length; i++) { |
+ this[from + i] = from[startFrom + i]; |
+ } |
+ } |
+ |
+ void set length(int newLength) { |
+ throw new UnsupportedError( |
+ "Cannot change the length of a fixed-length list"); |
+ } |
+ |
+ void add(E value) { |
+ throw new UnsupportedError( |
+ "Cannot add to a fixed-length list"); |
+ } |
+ |
+ void addLast(E value) { |
+ throw new UnsupportedError( |
+ "Cannot add to a fixed-length list"); |
+ } |
+ |
+ void addAll(Iterable<E> iterable) { |
+ throw new UnsupportedError( |
+ "Cannot add to a fixed-length list"); |
+ } |
+ |
+ void remove(E element) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void removeAll(Iterable elements) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void retainAll(Iterable elements) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void removeMatching(bool test(E element)) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void clear() { |
+ throw new UnsupportedError( |
+ "Cannot clear a fixed-length list"); |
+ } |
+ |
+ E removeAt(int index) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ E removeLast() { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void removeRange(int start, int length) { |
+ throw new UnsupportedError( |
+ "Cannot remove from a fixed-length list"); |
+ } |
+ |
+ void insertRange(int start, int length, [E initialValue]) { |
+ throw new UnsupportedError( |
+ "Cannot insert range in a fixed-length list"); |
+ } |
+} |
+ |
+/** |
+ * An unmodifiable [List]. |
+ */ |
+abstract class UnmodifiableListMixin<E> extends BaseListMixin<E> { |
void operator []=(int index, E value) { |
throw new UnsupportedError( |
@@ -385,7 +487,7 @@ class ListIterator<E> implements Iterator<E> { |
E get current => _current; |
} |
-class MappedList<S, T> extends NonExtensibleListMixin<T> { |
+class MappedList<S, T> extends UnmodifiableListMixin<T> { |
final List<S> _list; |
// TODO(ahe): Restore type when feature is implemented in dart2js |
// checked mode. http://dartbug.com/7733 |
@@ -397,10 +499,17 @@ class MappedList<S, T> extends NonExtensibleListMixin<T> { |
int get length => _list.length; |
} |
+/** An empty fixed-length list. */ |
+class EmptyList<E> extends FixedLengthListMixin<E> { |
+ int get length => 0; |
+ 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.
|
+ void operator[]=(int index, E value) { throw new ArgumentError(index); } |
+} |
+ |
/** |
- * An immutable view of a [List]. |
+ * An unmodifiable view of a [List]. |
*/ |
-class ListView<E> extends NonExtensibleListMixin<E> { |
+class ListView<E> extends UnmodifiableListMixin<E> { |
final List<E> _list; |
final int _offset; |
final int _length; |
@@ -452,4 +561,98 @@ class ListView<E> extends NonExtensibleListMixin<E> { |
if (_length != null && takeCount > _length) newLength = _length; |
return new ListView(_list, _offset, newLength); |
} |
+ |
+ List<E> get reversed => new ReversedList(_list, _offset, _offset + _length); |
+ |
+ String toString() => Collections.collectionToString(this); |
+} |
+ |
+/** |
+ * Reversed view of a [List], or a slice of a list. |
+ * |
+ * The view is fixed-length and becomes invalid if the underlying |
+ * 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?
|
+ */ |
+class ReversedList<E> extends FixedLengthListMixin<E> { |
+ final List<E> _list; |
+ final int _start; |
+ final int _end; |
+ ReversedList(List<E> list, int start, int end) |
+ : _list = list, _start = start, _end = end; |
+ |
+ int get length => _end - _start; |
+ |
+ E operator[](int index) { |
+ if (_list.length < _end) throw new StateError("Concurrent modification"); |
+ int length = _end - _start; |
+ if (index < 0 || index > length) { |
+ throw new RangeError("$index not in range 0..$length"); |
+ } |
+ return _list[_end - index - 1]; |
+ } |
+ |
+ void operator[]=(int index, E value) { |
+ if (_list.length < _end) throw new StateError("Concurrent modification"); |
+ int length = _end - _start; |
+ if (index < 0 || index > length) { |
+ throw new RangeError("$index not in range 0..$length"); |
+ } |
+ _list[_end - index - 1] = value; |
+ } |
+ |
+ Iterable<E> get iterator => new ReverseListIterator<E>(_list, _start, _end); |
+ |
+ List<E> take(int count) { |
+ if (count is! int || count < 0) { |
+ throw new ArgumentError(count); |
+ } |
+ int length = _end - _start; |
+ if (count > length) count = length; |
+ return new ReversedList(_list, _end - count, _end); |
+ } |
+ |
+ List<E> skip(int count) { |
+ if (count is! int || count < 0) { |
+ throw new ArgumentError(count); |
+ } |
+ int length = _end - _start; |
+ if (count >= length) return new EmptyList(); |
+ return new ReversedList(_list, _start, _end - count); |
+ } |
+ |
+ void sort([int compare(E first, E second)]) { |
+ if (compare == null) compare = Comparable.compare; |
+ // TODO(lrn): Make a way to sort a slice of a list using core sort. |
+ List<E> slice = _list.getRange(_start, _end); |
+ slice.sort((E a, E b) => compare(b, a)); |
+ _list.setRange(_start, slice.length, slice); |
+ } |
+ |
+ List<E> get reversed { |
+ return new ListView(_list, _start, _end - _start); |
+ } |
+ |
+ String toString() => Collections.collectionToString(this); |
+} |
+ |
+/** |
+ * An [Iterator] over a slice of a list that access elements in reverse order. |
+ */ |
+class ReverseListIterator<E> implements Iterator<E> { |
+ final List<E> _list; |
+ final int _start; |
+ int _index; |
+ E _current; |
+ |
+ ReverseListIterator(List<E> list, int start, int end) |
+ : _list = list, _start = start, _index = end; |
+ |
+ bool moveNext() { |
+ if (_index <= _start) return false; |
+ _index -= 1; |
+ _current = _list[_index]; |
+ return true; |
+ } |
+ |
+ E get current => _current; |
} |