| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of dart.collection; |
| |
| /** |
| * This [Iterable] mixin implements all [Iterable] members except `iterator`. |
| * |
| * All other methods are implemented in terms of `iterator`. |
| */ |
| abstract class IterableMixin<E> implements Iterable<E> { |
| Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| |
| Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| |
| Iterable expand(Iterable f(E element)) => |
| new ExpandIterable<E, dynamic>(this, f); |
| |
| bool contains(Object element) { |
| for (E e in this) { |
| if (e == element) return true; |
| } |
| return false; |
| } |
| |
| void forEach(void f(E element)) { |
| for (E element in this) f(element); |
| } |
| |
| E reduce(E combine(E value, E element)) { |
| Iterator<E> iterator = this.iterator; |
| if (!iterator.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| E value = iterator.current; |
| while (iterator.moveNext()) { |
| value = combine(value, iterator.current); |
| } |
| return value; |
| } |
| |
| dynamic fold(var initialValue, |
| dynamic combine(var previousValue, E element)) { |
| var value = initialValue; |
| for (E element in this) value = combine(value, element); |
| return value; |
| } |
| |
| bool every(bool f(E element)) { |
| for (E element in this) { |
| if (!f(element)) return false; |
| } |
| return true; |
| } |
| |
| String join([String separator]) { |
| Iterator<E> iterator = this.iterator; |
| if (!iterator.moveNext()) return ""; |
| StringBuffer buffer = new StringBuffer(); |
| if (separator == null || separator == "") { |
| do { |
| buffer.write("${iterator.current}"); |
| } while (iterator.moveNext()); |
| } else { |
| buffer.write("${iterator.current}"); |
| while (iterator.moveNext()) { |
| buffer.write(separator); |
| buffer.write("${iterator.current}"); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| bool any(bool f(E element)) { |
| for (E element in this) { |
| if (f(element)) return true; |
| } |
| return false; |
| } |
| |
| List<E> toList({ bool growable: true }) => |
| new List<E>.from(this, growable: growable); |
| |
| Set<E> toSet() => new Set<E>.from(this); |
| |
| int get length { |
| int count = 0; |
| Iterator it = iterator; |
| while (it.moveNext()) { |
| count++; |
| } |
| return count; |
| } |
| |
| bool get isEmpty => !iterator.moveNext(); |
| |
| bool get isNotEmpty => !isEmpty; |
| |
| Iterable<E> take(int n) { |
| return new TakeIterable<E>(this, n); |
| } |
| |
| Iterable<E> takeWhile(bool test(E value)) { |
| return new TakeWhileIterable<E>(this, test); |
| } |
| |
| Iterable<E> skip(int n) { |
| return new SkipIterable<E>(this, n); |
| } |
| |
| Iterable<E> skipWhile(bool test(E value)) { |
| return new SkipWhileIterable<E>(this, test); |
| } |
| |
| E get first { |
| Iterator it = iterator; |
| if (!it.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| return it.current; |
| } |
| |
| E get last { |
| Iterator it = iterator; |
| if (!it.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| E result; |
| do { |
| result = it.current; |
| } while(it.moveNext()); |
| return result; |
| } |
| |
| E get single { |
| Iterator it = iterator; |
| if (!it.moveNext()) throw new StateError("No elements"); |
| E result = it.current; |
| if (it.moveNext()) throw new StateError("More than one element"); |
| return result; |
| } |
| |
| dynamic firstWhere(bool test(E value), { Object orElse() }) { |
| for (E element in this) { |
| if (test(element)) return element; |
| } |
| if (orElse != null) return orElse(); |
| throw new StateError("No matching element"); |
| } |
| |
| dynamic lastWhere(bool test(E value), { Object orElse() }) { |
| E result = null; |
| bool foundMatching = false; |
| for (E element in this) { |
| if (test(element)) { |
| result = element; |
| foundMatching = true; |
| } |
| } |
| if (foundMatching) return result; |
| if (orElse != null) return orElse(); |
| throw new StateError("No matching element"); |
| } |
| |
| E singleWhere(bool test(E value)) { |
| E result = null; |
| bool foundMatching = false; |
| for (E element in this) { |
| if (test(element)) { |
| if (foundMatching) { |
| throw new StateError("More than one matching element"); |
| } |
| result = element; |
| foundMatching = true; |
| } |
| } |
| if (foundMatching) return result; |
| throw new StateError("No matching element"); |
| } |
| |
| E elementAt(int index) { |
| if (index is! int || index < 0) throw new RangeError.value(index); |
| int remaining = index; |
| for (E element in this) { |
| if (remaining == 0) return element; |
| remaining--; |
| } |
| throw new RangeError.value(index); |
| } |
| } |
| |
| /** |
| * Base class for implementing [Iterable]. |
| * |
| * This class implements all methods of [Iterable] except [Iterable.iterator] |
| * in terms of `iterator`. |
| */ |
| abstract class IterableBase<E> implements Iterable<E> { |
| // TODO(lrn): Base this on IterableMixin if there ever becomes a way |
| // to combine const constructors and mixins. |
| const IterableBase(); |
| |
| Iterable map(f(E element)) => new MappedIterable<E, dynamic>(this, f); |
| |
| Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f); |
| |
| Iterable expand(Iterable f(E element)) => |
| new ExpandIterable<E, dynamic>(this, f); |
| |
| bool contains(Object element) { |
| for (E e in this) { |
| if (e == element) return true; |
| } |
| return false; |
| } |
| |
| void forEach(void f(E element)) { |
| for (E element in this) f(element); |
| } |
| |
| E reduce(E combine(E value, E element)) { |
| Iterator<E> iterator = this.iterator; |
| if (!iterator.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| E value = iterator.current; |
| while (iterator.moveNext()) { |
| value = combine(value, iterator.current); |
| } |
| return value; |
| } |
| |
| dynamic fold(var initialValue, |
| dynamic combine(var previousValue, E element)) { |
| var value = initialValue; |
| for (E element in this) value = combine(value, element); |
| return value; |
| } |
| |
| bool every(bool f(E element)) { |
| for (E element in this) { |
| if (!f(element)) return false; |
| } |
| return true; |
| } |
| |
| String join([String separator]) { |
| Iterator<E> iterator = this.iterator; |
| if (!iterator.moveNext()) return ""; |
| StringBuffer buffer = new StringBuffer(); |
| if (separator == null || separator == "") { |
| do { |
| buffer.write("${iterator.current}"); |
| } while (iterator.moveNext()); |
| } else { |
| buffer.write("${iterator.current}"); |
| while (iterator.moveNext()) { |
| buffer.write(separator); |
| buffer.write("${iterator.current}"); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| bool any(bool f(E element)) { |
| for (E element in this) { |
| if (f(element)) return true; |
| } |
| return false; |
| } |
| |
| List<E> toList({ bool growable: true }) => |
| new List<E>.from(this, growable: growable); |
| |
| Set<E> toSet() => new Set<E>.from(this); |
| |
| int get length { |
| int count = 0; |
| Iterator it = iterator; |
| while (it.moveNext()) { |
| count++; |
| } |
| return count; |
| } |
| |
| bool get isEmpty => !iterator.moveNext(); |
| |
| bool get isNotEmpty => !isEmpty; |
| |
| Iterable<E> take(int n) { |
| return new TakeIterable<E>(this, n); |
| } |
| |
| Iterable<E> takeWhile(bool test(E value)) { |
| return new TakeWhileIterable<E>(this, test); |
| } |
| |
| Iterable<E> skip(int n) { |
| return new SkipIterable<E>(this, n); |
| } |
| |
| Iterable<E> skipWhile(bool test(E value)) { |
| return new SkipWhileIterable<E>(this, test); |
| } |
| |
| E get first { |
| Iterator it = iterator; |
| if (!it.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| return it.current; |
| } |
| |
| E get last { |
| Iterator it = iterator; |
| if (!it.moveNext()) { |
| throw new StateError("No elements"); |
| } |
| E result; |
| do { |
| result = it.current; |
| } while(it.moveNext()); |
| return result; |
| } |
| |
| E get single { |
| Iterator it = iterator; |
| if (!it.moveNext()) throw new StateError("No elements"); |
| E result = it.current; |
| if (it.moveNext()) throw new StateError("More than one element"); |
| return result; |
| } |
| |
| dynamic firstWhere(bool test(E value), { Object orElse() }) { |
| for (E element in this) { |
| if (test(element)) return element; |
| } |
| if (orElse != null) return orElse(); |
| throw new StateError("No matching element"); |
| } |
| |
| dynamic lastWhere(bool test(E value), { Object orElse() }) { |
| E result = null; |
| bool foundMatching = false; |
| for (E element in this) { |
| if (test(element)) { |
| result = element; |
| foundMatching = true; |
| } |
| } |
| if (foundMatching) return result; |
| if (orElse != null) return orElse(); |
| throw new StateError("No matching element"); |
| } |
| |
| E singleWhere(bool test(E value)) { |
| E result = null; |
| bool foundMatching = false; |
| for (E element in this) { |
| if (test(element)) { |
| if (foundMatching) { |
| throw new StateError("More than one matching element"); |
| } |
| result = element; |
| foundMatching = true; |
| } |
| } |
| if (foundMatching) return result; |
| throw new StateError("No matching element"); |
| } |
| |
| E elementAt(int index) { |
| if (index is! int || index < 0) throw new RangeError.value(index); |
| int remaining = index; |
| for (E element in this) { |
| if (remaining == 0) return element; |
| remaining--; |
| } |
| throw new RangeError.value(index); |
| } |
| } |