Index: sdk/lib/_collection_dev/list.dart |
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart |
index 1e40785f3a6540ab555979cb6cf7ba87fe7236d6..3ab841d71ba273d25b4fa41b0f79f06beeb08b3e 100644 |
--- a/sdk/lib/_collection_dev/list.dart |
+++ b/sdk/lib/_collection_dev/list.dart |
@@ -5,449 +5,6 @@ |
part of dart._collection.dev; |
/** |
- * Base implementation of a [List] class. |
- * |
- * This class can be used as a mixin. |
- * |
- * This implements all read operations using only the `length` and |
- * `operator[]` members. It implements write operations using those and |
- * `length=` and `operator[]=` |
- * |
- * A fixed-length list should mix this class in, and the [FixedLengthListMixin] |
- * as well, in that order, to overwrite the methods that modify the length. |
- * |
- * An unmodifiable list should mix [UnmodifiableListMixin] on top of this |
- * mixin to prevent all modifications. |
- */ |
-abstract class ListMixin<E> implements List<E> { |
- // Iterable interface. |
- Iterator<E> get iterator => new ListIterator<E>(this); |
- |
- E elementAt(int index) => this[index]; |
- |
- void forEach(void action(E element)) { |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- action(this[i]); |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- } |
- |
- bool get isEmpty => length == 0; |
- |
- E get first { |
- if (length == 0) throw new StateError("No elements"); |
- return this[0]; |
- } |
- |
- E get last { |
- if (length == 0) throw new StateError("No elements"); |
- return this[length - 1]; |
- } |
- |
- E get single { |
- if (length == 0) throw new StateError("No elements"); |
- if (length > 1) throw new StateError("Too many elements"); |
- return this[0]; |
- } |
- |
- bool contains(E element) { |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- if (this[i] == element) return true; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return false; |
- } |
- |
- bool every(bool test(E element)) { |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- if (!test(this[i])) return false; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return true; |
- } |
- |
- bool any(bool test(E element)) { |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- if (test(this[i])) return true; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return false; |
- } |
- |
- E firstWhere(bool test(E element), { E orElse() }) { |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- E element = this[i]; |
- if (test(element)) return element; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- if (orElse != null) return orElse(); |
- throw new StateError("No matching element"); |
- } |
- |
- E lastWhere(bool test(E element), { E orElse() }) { |
- int length = this.length; |
- for (int i = length - 1; i >= 0; i--) { |
- E element = this[i]; |
- if (test(element)) return element; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- if (orElse != null) return orElse(); |
- throw new StateError("No matching element"); |
- } |
- |
- E singleWhere(bool test(E element)) { |
- int length = this.length; |
- E match = null; |
- bool matchFound = false; |
- for (int i = 0; i < length; i++) { |
- E element = this[i]; |
- if (test(element)) { |
- if (matchFound) { |
- throw new StateError("More than one matching element"); |
- } |
- matchFound = true; |
- match = element; |
- } |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- if (matchFound) return match; |
- throw new StateError("No matching element"); |
- } |
- |
- E min([int compare(E a, E b)]) { |
- if (length == 0) return null; |
- if (compare == null) { |
- var defaultCompare = Comparable.compare; |
- compare = defaultCompare; |
- } |
- E min = this[0]; |
- int length = this.length; |
- for (int i = 1; i < length; i++) { |
- E element = this[i]; |
- if (compare(min, element) > 0) { |
- min = element; |
- } |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return min; |
- } |
- |
- E max([int compare(E a, E b)]) { |
- if (length == 0) return null; |
- if (compare == null) { |
- var defaultCompare = Comparable.compare; |
- compare = defaultCompare; |
- } |
- E max = this[0]; |
- int length = this.length; |
- for (int i = 1; i < length; i++) { |
- E element = this[i]; |
- if (compare(max, element) < 0) { |
- max = element; |
- } |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return max; |
- } |
- |
- String join([String separator]) { |
- int length = this.length; |
- if (separator != null && !separator.isEmpty) { |
- if (length == 0) return ""; |
- String first = "${this[0]}"; |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- StringBuffer buffer = new StringBuffer(first); |
- for (int i = 1; i < length; i++) { |
- buffer.write(separator); |
- buffer.write("${this[i]}"); |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return buffer.toString(); |
- } else { |
- StringBuffer buffer = new StringBuffer(); |
- for (int i = 0; i < length; i++) { |
- buffer.write("${this[i]}"); |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return buffer.toString(); |
- } |
- } |
- |
- Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); |
- |
- Iterable map(f(E element)) => new MappedListIterable(this, f); |
- |
- reduce(var initialValue, combine(var previousValue, E element)) { |
- return fold(initialValue, combine); |
- } |
- |
- fold(var initialValue, combine(var previousValue, E element)) { |
- var value = initialValue; |
- int length = this.length; |
- for (int i = 0; i < length; i++) { |
- value = combine(value, this[i]); |
- if (length != this.length) { |
- throw new ConcurrentModificationError(this); |
- } |
- } |
- return value; |
- } |
- |
- Iterable<E> skip(int count) => new SubListIterable(this, count, null); |
- |
- Iterable<E> skipWhile(bool test(E element)) { |
- return new SkipWhileIterable<E>(this, test); |
- } |
- |
- Iterable<E> take(int count) => new SubListIterable(this, 0, count); |
- |
- Iterable<E> takeWhile(bool test(E element)) { |
- return new TakeWhileIterable<E>(this, test); |
- } |
- |
- List<E> toList({ bool growable: true }) { |
- List<E> result; |
- if (growable) { |
- result = new List<E>()..length = length; |
- } else { |
- result = new List<E>(length); |
- } |
- for (int i = 0; i < length; i++) { |
- result[i] = this[i]; |
- } |
- return result; |
- } |
- |
- Set<E> toSet() { |
- Set<E> result = new Set<E>(); |
- for (int i = 0; i < length; i++) { |
- result.add(this[i]); |
- } |
- return result; |
- } |
- |
- // Collection interface. |
- void add(E element) { |
- this[this.length++] = element; |
- } |
- |
- void addAll(Iterable<E> iterable) { |
- for (E element in iterable) { |
- this[this.length++] = element; |
- } |
- } |
- |
- void remove(Object element) { |
- for (int i = 0; i < this.length; i++) { |
- if (this[i] == element) { |
- this.setRange(i, this.length - i - 1, this, i + 1); |
- this.length -= 1; |
- return; |
- } |
- } |
- } |
- |
- void removeAll(Iterable<Object> elements) { |
- if (elements is! Set) { |
- elements = elements.toSet(); |
- } |
- _filter(this, elements.contains, false); |
- } |
- |
- |
- void retainAll(Iterable<E> iterable) { |
- if (elements is! Set) { |
- elements = elements.toSet(); |
- } |
- _filter(this, elements.contains, true); |
- } |
- |
- void removeWhere(bool test(E element)) { |
- _filter(this, test, false); |
- } |
- |
- void retainWhere(bool test(E element)) { |
- _filter(this, test, true); |
- } |
- |
- static void _filter(List source, |
- bool test(var element), |
- bool retainMatching) { |
- List retained = []; |
- int length = source.length; |
- for (int i = 0; i < length; i++) { |
- var element = source[i]; |
- if (test(element) == retainMatching) { |
- retained.add(element); |
- } |
- if (length != source.length) { |
- throw new ConcurrentModificationError(source); |
- } |
- } |
- if (retained.length != source.length) { |
- source.setRange(0, retained.length, retained); |
- source.length = retained.length; |
- } |
- } |
- |
- // List interface. |
- |
- void sort([Comparator<E> compare]) { |
- Sort.sort(this, compare); |
- } |
- |
- Map<int, E> asMap() { |
- return new ListMapView(this); |
- } |
- |
- List<E> sublist(int start, [int end]) { |
- if (end == null) end = length; |
- if (start < 0 || start > this.length) { |
- throw new RangeError.range(start, 0, this.length); |
- } |
- if (end < start || end > this.length) { |
- throw new RangeError.range(end, start, this.length); |
- } |
- int length = end - start; |
- List<E> result = new List<E>()..length = length; |
- for (int i = 0; i < length; i++) { |
- result[i] = this[start + i]; |
- } |
- return result; |
- } |
- |
- List<E> getRange(int start, int length) => sublist(start, start + length); |
- |
- void insertRange(int start, int length, [E initialValue]) { |
- if (start < 0 || start > this.length) { |
- throw new RangeError.range(start, 0, this.length); |
- } |
- int oldLength = this.length; |
- int moveLength = oldLength - start; |
- this.length += length; |
- if (moveLength > 0) { |
- this.setRange(start + length, moveLength, this, start); |
- } |
- for (int i = 0; i < length; i++) { |
- this[start + i] = initialValue; |
- } |
- } |
- |
- void removeRange(int start, int length) { |
- if (start < 0 || start > this.length) { |
- throw new RangeError.range(start, 0, this.length); |
- } |
- if (length < 0 || start + length > this.length) { |
- throw new RangeError.range(length, 0, this.length - start); |
- } |
- int end = start + length; |
- setRange(start, this.length - end, this, end); |
- this.length -= length; |
- } |
- |
- void clearRange(int start, int length, [E fill]) { |
- for (int i = 0; i < length; i++) { |
- this[start + i] = fill; |
- } |
- } |
- |
- void setRange(int start, int length, List<E> from, [int startFrom]) { |
- if (start < 0 || start > this.length) { |
- throw new RangeError.range(start, 0, this.length); |
- } |
- if (length < 0 || start + length > this.length) { |
- throw new RangeError.range(length, 0, this.length - start); |
- } |
- if (startFrom == null) { |
- startFrom = 0; |
- } |
- if (startFrom < 0 || startFrom + length > from.length) { |
- throw new RangeError.range(startFrom, 0, from.length - length); |
- } |
- if (startFrom < start) { |
- // Copy backwards to ensure correct copy if [from] is this. |
- for (int i = length - 1; i >= 0; i--) { |
- this[start + i] = from[startFrom + i]; |
- } |
- } else { |
- for (int i = 0; i < length; i++) { |
- this[start + i] = from[startFrom + i]; |
- } |
- } |
- } |
- |
- int indexOf(E element, [int startIndex = 0]) { |
- if (startIndex >= this.length) { |
- return -1; |
- } |
- if (startIndex < 0) { |
- startIndex = 0; |
- } |
- for (int i = startIndex; i < this.length; i++) { |
- if (this[i] == element) { |
- return i; |
- } |
- } |
- return -1; |
- } |
- |
- /** |
- * Returns the last index in the list [a] of the given [element], starting |
- * the search at index [startIndex] to 0. |
- * Returns -1 if [element] is not found. |
- */ |
- int lastIndexOf(E element, [int startIndex]) { |
- if (startIndex == null) { |
- startIndex = this.length - 1; |
- } else { |
- if (startIndex < 0) { |
- return -1; |
- } |
- if (startIndex >= a.length) { |
- startIndex = a.length - 1; |
- } |
- } |
- for (int i = startIndex; i >= 0; i--) { |
- if (this[i] == element) { |
- return i; |
- } |
- } |
- return -1; |
- } |
- |
- Iterable<E> get reversed => new ReversedListIterable(this); |
-} |
- |
-/** |
* Mixin that throws on the length changing operations of [List]. |
* |
* Intended to mix-in on top of [ListMixin] for fixed-length lists. |
@@ -619,23 +176,13 @@ abstract class UnmodifiableListMixin<E> { |
} |
} |
- |
-/** |
- * Abstract implementation of a list. |
- * |
- * All operations are defined in terms of `length`, `operator[]`, |
- * `operator[]=` and `length=`, which need to be implemented. |
- */ |
-abstract class ListBase<E> extends ListMixin<E> implements List<E> {} |
- |
/** |
* Abstract implementation of a fixed-length list. |
* |
* All operations are defined in terms of `length`, `operator[]` and |
* `operator[]=`, which need to be implemented. |
*/ |
-abstract class FixedLengthListBase<E> extends ListBase<E> |
- with FixedLengthListMixin<E> {} |
+typedef FixedLengthListBase<E> = ListBase<E> with FixedLengthListMixin<E>; |
/** |
* Abstract implementation of an unmodifiable list. |
@@ -643,41 +190,7 @@ abstract class FixedLengthListBase<E> extends ListBase<E> |
* All operations are defined in terms of `length` and `operator[]`, |
* which need to be implemented. |
*/ |
-abstract class UnmodifiableListBase<E> extends ListBase<E> |
- with UnmodifiableListMixin<E> {} |
- |
-/** An empty fixed-length (and therefore unmodifiable) 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); } |
- Iterable<E> skip(int count) => const EmptyIterable(); |
- Iterable<E> take(int count) => const EmptyIterable(); |
- Iterable<E> get reversed => const EmptyIterable(); |
- void sort([int compare(E a, E b)]) {} |
-} |
- |
-class ReversedListIterable<E> extends ListIterable<E> { |
- Iterable<E> _source; |
- ReversedListIterable(this._source); |
- |
- int get length => _source.length; |
- |
- E elementAt(int index) => _source.elementAt(_source.length - 1 - index); |
-} |
- |
-/** |
- * An [Iterable] of the UTF-16 code units of a [String] in index order. |
- */ |
-class CodeUnits extends UnmodifiableListBase<int> { |
- /** The string that this is the code units of. */ |
- String _string; |
- |
- CodeUnits(this._string); |
- |
- int get length => _string.length; |
- int operator[](int i) => _string.codeUnitAt(i); |
-} |
+typedef UnmodifiableListBase<E> = ListBase<E> with UnmodifiableListMixin<E>; |
class _ListIndicesIterable extends ListIterable<int> { |
List _backedList; |
@@ -734,3 +247,12 @@ class ListMapView<E> implements Map<int, E> { |
throw new UnsupportedError("Cannot modify an unmodifiable map"); |
} |
} |
+ |
+class ReversedListIterable<E> extends ListIterable<E> { |
+ Iterable<E> _source; |
+ ReversedListIterable(this._source); |
+ |
+ int get length => _source.length; |
+ |
+ E elementAt(int index) => _source.elementAt(_source.length - 1 - index); |
+} |