Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Unified Diff: sdk/lib/collection_dev/list.dart

Issue 11896013: Add List.reversed to give a reverse fixed-length view of a list. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Moved some functionality to separate CL. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_array.dart ('k') | sdk/lib/core/errors.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/collection_dev/list.dart
diff --git a/sdk/lib/collection_dev/list.dart b/sdk/lib/collection_dev/list.dart
index 48b31fa93acf329afc66d820d258e5ad53925c23..cddc75a762baf32e1a11c10c169e6481cf8cb964 100644
--- a/sdk/lib/collection_dev/list.dart
+++ b/sdk/lib/collection_dev/list.dart
@@ -5,11 +5,12 @@
part of dart.collection.dev;
/**
- * Skeleton class for an unmodifiable [List].
+ * Class implementing the read-operations on [List].
+ *
+ * Implements all read-only operations, except [:operator[]:] and [:length:],
+ * in terms of those two operations.
*/
-abstract class NonExtensibleListMixin<E>
- extends Iterable<E> implements List<E> {
-
+abstract class ListBase<E> extends Iterable<E> implements List<E> {
Iterator<E> get iterator => new ListIterator(this);
void forEach(f(E element)) {
@@ -92,6 +93,100 @@ abstract class NonExtensibleListMixin<E>
return result;
}
+ String toString() => Collections.collectionToString(this);
+}
+
+/**
+ * Abstract class implementing the non-length changing operations of [List].
+ */
+abstract class FixedLengthListBase<E> extends ListBase<E> {
+ void operator[]=(int index, E value);
+
+ List<E> get reversed => new ReversedListView<E>(this, 0, null);
+
+ 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[start + 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 UnmodifiableListBase<E> extends ListBase<E> {
+
void operator []=(int index, E value) {
throw new UnsupportedError(
"Cannot modify an unmodifiable list");
@@ -136,6 +231,7 @@ abstract class NonExtensibleListMixin<E>
throw new UnsupportedError(
"Cannot remove from an unmodifiable list");
}
+
void sort([Comparator<E> compare]) {
throw new UnsupportedError(
"Cannot modify an unmodifiable list");
@@ -180,7 +276,7 @@ class ListIterator<E> implements Iterator<E> {
int _position;
E _current;
- ListIterator(this._list) : _position = -1;
+ ListIterator(List<E> list) : _list = list, _position = -1;
bool moveNext() {
int nextPosition = _position + 1;
@@ -197,7 +293,7 @@ class ListIterator<E> implements Iterator<E> {
E get current => _current;
}
-class MappedList<S, T> extends NonExtensibleListMixin<T> {
+class MappedList<S, T> extends UnmodifiableListBase<T> {
final List<S> _list;
// TODO(ahe): Restore type when feature is implemented in dart2js
// checked mode. http://dartbug.com/7733
@@ -209,59 +305,223 @@ class MappedList<S, T> extends NonExtensibleListMixin<T> {
int get length => _list.length;
}
+/** An empty fixed-length list. */
+class EmptyList<E> extends FixedLengthListBase<E> {
+ int get length => 0;
+ E operator[](int index) { throw new RangeError.value(index); }
+ void operator []=(int index, E value) { throw new RangeError.value(index); }
+ List<E> skip(int count) => this;
+ List<E> take(int count) => this;
+ List<E> get reversed => this;
+ void sort([int compare(E a, E b)]) {}
+}
+
/**
- * An immutable view of a [List].
+ * A fixed-length view of a sub-range of another [List].
+ *
+ * The range is described by start and end points relative
+ * to the other List's start or end.
+ *
+ * The range changes dynamically as the underlying list changes
+ * its length.
*/
-class ListView<E> extends NonExtensibleListMixin<E> {
+abstract class SubListView<E> extends UnmodifiableListBase<E> {
final List<E> _list;
- final int _offset;
- final int _length;
+ final int _start;
+ final int _end;
/**
- * If the given length is `null` then the ListView's length is bound by
- * the backed [list].
+ * Create a sub-list view.
+ *
+ * Both [_start] and [_end] can be given as positions
+ * relative to the start of [_list] (a non-negative integer)
+ * or relative to the end of [_list] (a negative integer or
+ * null, with null being at the end of the list).
*/
- ListView(List<E> list, this._offset, this._length) : _list = list {
- if (_offset is! int || _offset < 0) {
- throw new ArgumentError(_offset);
+ SubListView(this._list, this._start, this._end);
+
+ int _absoluteIndex(int relativeIndex) {
+ if (relativeIndex == null) return _list.length;
+ if (relativeIndex < 0) {
+ int result = _list.length + relativeIndex;
+ if (result < 0) return 0;
+ return result;
}
- if (_length != null &&
- (_length is! int || _length < 0)) {
- throw new ArgumentError(_length);
+ if (relativeIndex > _list.length) {
+ return _list.length;
}
+ return relativeIndex;
}
int get length {
- int originalLength = _list.length;
- int skipLength = originalLength - _offset;
- if (skipLength < 0) return 0;
- if (_length == null || _length > skipLength) return skipLength;
- return _length;
+ int result = _absoluteIndex(_end) - _absoluteIndex(_start);
+ if (result >= 0) return result;
+ return 0;
+ }
+
+ _createListView(int start, int end) {
+ if (start == null) return new EmptyList<E>();
+ if (end != null) {
+ if (start < 0) {
+ if (end <= start) return new EmptyList<E>();
+ } else {
+ if (end >= 0 && end <= start) return new EmptyList<E>();
+ }
+ }
+ return new ListView(_list, start, end);
+ }
+
+ _createReversedListView(int start, int end) {
+ if (start == null) return new EmptyList<E>();
+ if (end != null) {
+ if (start < 0) {
+ if (end <= start) return new EmptyList<E>();
+ } else {
+ if (end >= 0 && end <= start) return new EmptyList<E>();
+ }
+ }
+ return new ReversedListView(_list, start, end);
+ }
+}
+
+
+/**
+ * A fixed-length view of a sub-range of a [List].
+ */
+class ListView<E> extends SubListView<E> {
+
+ ListView(List<E> list, int start, int end) : super(list, start, end);
+
+ E operator[](int index) {
+ int start = _absoluteIndex(_start);
+ int end = _absoluteIndex(_end);
+ int length = end - start;
+ if (index < 0 || index >= length) {
+ throw new RangeError.range(index, 0, length);
+ }
+ return _list[start + index];
+ }
+
+ List<E> skip(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_start == null) {
+ return new EmptyList<E>();
+ }
+ int newStart = _start + count;
+ if (_start < 0 && newStart >= 0) {
+ return new EmptyList<E>();
+ }
+ return _createListView(newStart, _end);
}
+ List<E> take(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_start == null) {
+ return new EmptyList<E>();
+ }
+ int newEnd = _start + count;
+ if (_start < 0 && newEnd >= 0) {
+ newEnd = null;
+ }
+ return _createListView(_start, newEnd);
+ }
+
+ List<E> get reversed => new ReversedListView(_list, _start, _end);
+}
+
+/**
+ * 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.
+ *
+ * Start index and end index can be either positive, negative or null.
+ * Positive means an index relative to the start of the list,
+ * negative means an index relative to the end of the list, and null
+ * means at the end of the list (since there is no -0 integer).
+ */
+class ReversedListView<E> extends SubListView<E> {
+
+ ReversedListView(List<E> list, int start, int end)
+ : super(list, start, end);
+
E operator[](int index) {
- int skipIndex = index + _offset;
- if (index < 0 ||
- (_length != null && index >= _length) ||
- index + _offset >= _list.length) {
- throw new RangeError.value(index);
+ int start = _absoluteIndex(_start);
+ int end = _absoluteIndex(_end);
+ int length = end - start;
+ if (index < 0 || index >= length) {
+ throw new RangeError.range(index, 0, length);
}
- return _list[index + _offset];
+ return _list[end - index - 1];
}
- ListView<E> skip(int skipCount) {
- if (skipCount is! int || skipCount < 0) {
- throw new ArgumentError(skipCount);
+ List<E> skip(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ if (_end == null) {
+ return _createReversedListView(_start, -count);
}
- return new ListView(_list, _offset + skipCount, _length);
+ int newEnd = _end - count;
+ if (_end >= 0 && newEnd < 0) {
+ return new EmptyList<E>();
+ }
+ return _createReversedListView(_start, newEnd);
}
- ListView<E> take(int takeCount) {
- if (takeCount is! int || takeCount < 0) {
- throw new ArgumentError(takeCount);
+ List<E> take(int count) {
+ if (count is! int || count < 0) {
+ throw new ArgumentError(count);
+ }
+ int newStart;
+ if (_end == null) {
+ newStart = -count;
+ } else {
+ newStart = _end - count;
+ if (_end >= 0 && newStart < 0) {
+ return new EmptyList<E>();
+ }
}
- int newLength = takeCount;
- if (_length != null && takeCount > _length) newLength = _length;
- return new ListView(_list, _offset, newLength);
+ return _createReversedListView(newStart, _end);
}
+
+ Iterable<E> get iterator => new ReverseListIterator<E>(
+ _list, _absoluteIndex(_start), _absoluteIndex(_end));
+
+ List<E> get reversed {
+ return new ListView(_list, _start, _end);
+ }
+}
+
+/**
+ * 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;
+ final int _originalLength;
+ int _index;
+ E _current;
+
+ ReverseListIterator(List<E> list, int start, int end)
+ : _list = list,
+ _start = start,
+ _index = end,
+ _originalLength = list.length;
+
+ bool moveNext() {
+ if (list.length != _originalLength) {
+ throw new ConcurrentModificationError(list);
+ }
+ if (_index <= _start) return false;
+ _index -= 1;
+ _current = _list[_index];
+ return true;
+ }
+
+ E get current => _current;
}
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_array.dart ('k') | sdk/lib/core/errors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698