| Index: sdk/lib/core/list.dart
|
| diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
|
| index e5230992f377b40d08ea3cea474cfae1f3536763..e86e5aa96c9fd183b11e0701d7fcbb4c7cade9fd 100644
|
| --- a/sdk/lib/core/list.dart
|
| +++ b/sdk/lib/core/list.dart
|
| @@ -8,21 +8,33 @@ part of dart.core;
|
| * A [List] is an indexable collection with a length. It can be of
|
| * fixed size or extendable.
|
| */
|
| -abstract class List<E> implements Collection<E>, Sequence<E> {
|
| +abstract class List<E> implements Collection<E> {
|
| /**
|
| * Creates a list of the given [length].
|
| *
|
| - * If no [length] argument is supplied an extendable list of
|
| - * length 0 is created.
|
| + * The length of the returned list is not fixed.
|
| + */
|
| + external factory List([int length = 0]);
|
| +
|
| + /**
|
| + * Creates a fixed-sized list of the given [length] where each entry is
|
| + * filled with [fill].
|
| + */
|
| + external factory List.fixedLength(int length, {E fill: null});
|
| +
|
| + /**
|
| + * Creates an list of the given [length] where each entry is
|
| + * filled with [fill].
|
| *
|
| - * If a [length] argument is supplied, a fixed size list of that
|
| - * length is created.
|
| + * The length of the returned list is not fixed.
|
| */
|
| - external factory List([int length]);
|
| + external factory List.filled(int length, E fill);
|
|
|
| /**
|
| - * Creates a list with the elements of [other]. The order in
|
| + * Creates an list with the elements of [other]. The order in
|
| * the list will be the order provided by the iterator of [other].
|
| + *
|
| + * The length of the returned list is not fixed.
|
| */
|
| factory List.from(Iterable<E> other) {
|
| var list = new List<E>();
|
| @@ -66,12 +78,11 @@ abstract class List<E> implements Collection<E>, Sequence<E> {
|
| void addLast(E value);
|
|
|
| /**
|
| - * Appends all elements of the [collection] to the end of this list.
|
| - * Extends the length of the list by the number of elements in [collection].
|
| - * Throws an [UnsupportedError] if this list is not
|
| - * extendable.
|
| + * Appends all elements of the [iterable] to the end of this list.
|
| + * Extends the length of the list by the number of elements in [iterable].
|
| + * Throws an [UnsupportedError] if this list is not extensible.
|
| */
|
| - void addAll(Collection<E> collection);
|
| + void addAll(Iterable<E> iterable);
|
|
|
| /**
|
| * Sorts the list according to the order specified by the [compare] function.
|
| @@ -134,18 +145,6 @@ abstract class List<E> implements Collection<E>, Sequence<E> {
|
| E removeLast();
|
|
|
| /**
|
| - * Returns the first element of the list, or throws an out of bounds
|
| - * exception if the list is empty.
|
| - */
|
| - E get first;
|
| -
|
| - /**
|
| - * Returns the last element of the list, or throws an out of bounds
|
| - * exception if the list is empty.
|
| - */
|
| - E get last;
|
| -
|
| - /**
|
| * Returns a new list containing [length] elements from the list,
|
| * starting at [start].
|
| * Returns an empty list if [length] is 0.
|
| @@ -179,7 +178,7 @@ abstract class List<E> implements Collection<E>, Sequence<E> {
|
|
|
| /**
|
| * Inserts a new range into the list, starting from [start] to
|
| - * [:start + length - 1:]. The entries are filled with [initialValue].
|
| + * [:start + length - 1:]. The entries are filled with [fill].
|
| * Throws an [UnsupportedError] if the list is
|
| * not extendable.
|
| * If [length] is 0, this method does not do anything.
|
| @@ -189,5 +188,246 @@ abstract class List<E> implements Collection<E>, Sequence<E> {
|
| * Throws an [RangeError] if [start] is negative or if
|
| * [start] is greater than the length of the list.
|
| */
|
| - void insertRange(int start, int length, [E initialValue]);
|
| + void insertRange(int start, int length, [E fill]);
|
| +}
|
| +
|
| +/**
|
| + * An unmodifiable [List].
|
| + */
|
| +abstract class NonExtensibleListMixin<E>
|
| + extends Iterable<E> implements List<E> {
|
| +
|
| + Iterator<E> get iterator => new ListIterator(this);
|
| +
|
| + void forEach(f(E element)) {
|
| + for (int i = 0; i < this.length; i++) f(this[i]);
|
| + }
|
| +
|
| + bool contains(E value) {
|
| + for (int i = 0; i < length; i++) {
|
| + if (this[i] == value) return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + reduce(initialValue, combine(previousValue, E element)) {
|
| + var value = initialValue;
|
| + for (int i = 0; i < this.length; i++) {
|
| + value = combine(value, this[i]);
|
| + }
|
| + return value;
|
| + }
|
| +
|
| + bool every(bool f(E element)) {
|
| + for (int i = 0; i < this.length; i++) {
|
| + if (!f(this[i])) return false;
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + bool any(bool f(E element)) {
|
| + for (int i = 0; i < this.length; i++) {
|
| + if (f(this[i])) return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool get isEmpty {
|
| + return this.length == 0;
|
| + }
|
| +
|
| + E elementAt(int index) {
|
| + return this[index];
|
| + }
|
| +
|
| + int indexOf(E value, [int start = 0]) {
|
| + for (int i = start; i < length; i++) {
|
| + if (this[i] == value) return i;
|
| + }
|
| + return -1;
|
| + }
|
| +
|
| + int lastIndexOf(E value, [int start]) {
|
| + if (start == null) start = length - 1;
|
| + for (int i = start; i >= 0; i--) {
|
| + if (this[i] == value) return i;
|
| + }
|
| + return -1;
|
| + }
|
| +
|
| + E get first {
|
| + if (length > 0) return this[0];
|
| + throw new StateError("No elements");
|
| + }
|
| +
|
| + E get last {
|
| + if (length > 0) return this[length - 1];
|
| + throw new StateError("No elements");
|
| + }
|
| +
|
| + E get single {
|
| + if (length == 1) return this[0];
|
| + if (length == 0) throw new StateError("No elements");
|
| + throw new StateError("More than one element");
|
| + }
|
| +
|
| + List<E> getRange(int start, int length) {
|
| + List<E> result = <E>[];
|
| + for (int i = 0; i < length; i++) {
|
| + result.add(this[start + i]);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + void operator []=(int index, E value) {
|
| + throw new UnsupportedError(
|
| + "Cannot modify an unmodifiable list");
|
| + }
|
| +
|
| + void set length(int newLength) {
|
| + throw new UnsupportedError(
|
| + "Cannot change the length of an unmodifiable list");
|
| + }
|
| +
|
| + void add(E value) {
|
| + throw new UnsupportedError(
|
| + "Cannot add to an unmodifiable list");
|
| + }
|
| +
|
| + void addLast(E value) {
|
| + throw new UnsupportedError(
|
| + "Cannot add to an unmodifiable list");
|
| + }
|
| +
|
| + void addAll(Iterable<E> iterable) {
|
| + throw new UnsupportedError(
|
| + "Cannot add to an unmodifiable list");
|
| + }
|
| +
|
| + void sort([Comparator<E> compare]) {
|
| + throw new UnsupportedError(
|
| + "Cannot modify an unmodifiable list");
|
| + }
|
| +
|
| + void clear() {
|
| + throw new UnsupportedError(
|
| + "Cannot clear an unmodifiable list");
|
| + }
|
| +
|
| + E removeAt(int index) {
|
| + throw new UnsupportedError(
|
| + "Cannot remove in an unmodifiable list");
|
| + }
|
| +
|
| + E removeLast() {
|
| + throw new UnsupportedError(
|
| + "Cannot remove in an unmodifiable list");
|
| + }
|
| +
|
| + void setRange(int start, int length, List<E> from, [int startFrom]) {
|
| + throw new UnsupportedError(
|
| + "Cannot modify an unmodifiable list");
|
| + }
|
| +
|
| + void removeRange(int start, int length) {
|
| + throw new UnsupportedError(
|
| + "Cannot remove in an unmodifiable list");
|
| + }
|
| +
|
| + void insertRange(int start, int length, [E initialValue]) {
|
| + throw new UnsupportedError(
|
| + "Cannot insert range in an unmodifiable list");
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Iterates over a [Sequence] in growing index order.
|
| + */
|
| +class ListIterator<E> implements Iterator<E> {
|
| + final List<E> _list;
|
| + int _position;
|
| + E _current;
|
| +
|
| + ListIterator(this._list) : _position = -1;
|
| +
|
| + bool moveNext() {
|
| + int nextPosition = _position + 1;
|
| + if (nextPosition < _list.length) {
|
| + _current = _list[nextPosition];
|
| + _position = nextPosition;
|
| + return true;
|
| + }
|
| + _position = _list.length;
|
| + _current = null;
|
| + return false;
|
| + }
|
| +
|
| + E get current => _current;
|
| +}
|
| +
|
| +class MappedList<S, T> extends NonExtensibleListMixin<T> {
|
| + final List<S> _list;
|
| + final _Transformation<S, T> _f;
|
| +
|
| + MappedList(this._list, T this._f(S element));
|
| +
|
| + T operator[](int index) => _f(_list[index]);
|
| + int get length => _list.length;
|
| +}
|
| +
|
| +/**
|
| + * An immutable view of a [List].
|
| + */
|
| +class ListView<E> extends NonExtensibleListMixin<E> {
|
| + final List<E> _list;
|
| + final int _offset;
|
| + final int _length;
|
| +
|
| + /**
|
| + * If the given length is `null` then the ListView's length is bound by
|
| + * the backed [list].
|
| + */
|
| + ListView(List<E> list, this._offset, this._length) : _list = list {
|
| + if (_offset is! int || _offset < 0) {
|
| + throw new ArgumentError(_offset);
|
| + }
|
| + if (_length != null &&
|
| + (_length is! int || _length < 0)) {
|
| + throw new ArgumentError(_length);
|
| + }
|
| + }
|
| +
|
| + 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;
|
| + }
|
| +
|
| + E operator[](int index) {
|
| + int skipIndex = index + _offset;
|
| + if (index < 0 ||
|
| + (_length != null && index >= _length) ||
|
| + index + _offset >= _list.length) {
|
| + throw new RangeError.value(index);
|
| + }
|
| + return _list[index + _offset];
|
| + }
|
| +
|
| + ListView<E> skip(int skipCount) {
|
| + if (skipCount is! int || skipCount < 0) {
|
| + throw new ArgumentError(skipCount);
|
| + }
|
| + return new ListView(_list, _offset + skipCount, _length);
|
| + }
|
| +
|
| + ListView<E> take(int takeCount) {
|
| + if (takeCount is! int || takeCount < 0) {
|
| + throw new ArgumentError(takeCount);
|
| + }
|
| + int newLength = takeCount;
|
| + if (_length != null && takeCount > _length) newLength = _length;
|
| + return new ListView(_list, _offset, newLength);
|
| + }
|
| }
|
|
|