OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart._internal; | 5 part of dart._internal; |
6 | 6 |
7 /** | 7 /** |
8 * Marker interface for [Iterable] subclasses that have an efficient | 8 * Marker interface for [Iterable] subclasses that have an efficient |
9 * [length] implementation. | 9 * [length] implementation. |
10 */ | 10 */ |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 int length = this.length; | 87 int length = this.length; |
88 for (int i = 0; i < length; i++) { | 88 for (int i = 0; i < length; i++) { |
89 if (test(elementAt(i))) return true; | 89 if (test(elementAt(i))) return true; |
90 if (length != this.length) { | 90 if (length != this.length) { |
91 throw new ConcurrentModificationError(this); | 91 throw new ConcurrentModificationError(this); |
92 } | 92 } |
93 } | 93 } |
94 return false; | 94 return false; |
95 } | 95 } |
96 | 96 |
97 E firstWhere(bool test(E element), { E orElse() }) { | 97 E firstWhere(bool test(E element), {E orElse()}) { |
98 int length = this.length; | 98 int length = this.length; |
99 for (int i = 0; i < length; i++) { | 99 for (int i = 0; i < length; i++) { |
100 E element = elementAt(i); | 100 E element = elementAt(i); |
101 if (test(element)) return element; | 101 if (test(element)) return element; |
102 if (length != this.length) { | 102 if (length != this.length) { |
103 throw new ConcurrentModificationError(this); | 103 throw new ConcurrentModificationError(this); |
104 } | 104 } |
105 } | 105 } |
106 if (orElse != null) return orElse(); | 106 if (orElse != null) return orElse(); |
107 throw IterableElementError.noElement(); | 107 throw IterableElementError.noElement(); |
108 } | 108 } |
109 | 109 |
110 E lastWhere(bool test(E element), { E orElse() }) { | 110 E lastWhere(bool test(E element), {E orElse()}) { |
111 int length = this.length; | 111 int length = this.length; |
112 for (int i = length - 1; i >= 0; i--) { | 112 for (int i = length - 1; i >= 0; i--) { |
113 E element = elementAt(i); | 113 E element = elementAt(i); |
114 if (test(element)) return element; | 114 if (test(element)) return element; |
115 if (length != this.length) { | 115 if (length != this.length) { |
116 throw new ConcurrentModificationError(this); | 116 throw new ConcurrentModificationError(this); |
117 } | 117 } |
118 } | 118 } |
119 if (orElse != null) return orElse(); | 119 if (orElse != null) return orElse(); |
120 throw IterableElementError.noElement(); | 120 throw IterableElementError.noElement(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 | 176 |
177 E reduce(E combine(var value, E element)) { | 177 E reduce(E combine(var value, E element)) { |
178 int length = this.length; | 178 int length = this.length; |
179 if (length == 0) throw IterableElementError.noElement(); | 179 if (length == 0) throw IterableElementError.noElement(); |
180 E value = elementAt(0); | 180 E value = elementAt(0); |
181 for (int i = 1; i < length; i++) { | 181 for (int i = 1; i < length; i++) { |
182 value = combine(value, elementAt(i)); | 182 value = combine(value, elementAt(i)); |
183 if (length != this.length) { | 183 if (length != this.length) { |
184 throw new ConcurrentModificationError(this); | 184 throw new ConcurrentModificationError(this); |
185 } | 185 } |
186 | |
187 } | 186 } |
188 return value; | 187 return value; |
189 } | 188 } |
190 | 189 |
191 T fold<T>(T initialValue, T combine(T previousValue, E element)) { | 190 T fold<T>(T initialValue, T combine(T previousValue, E element)) { |
192 var value = initialValue; | 191 var value = initialValue; |
193 int length = this.length; | 192 int length = this.length; |
194 for (int i = 0; i < length; i++) { | 193 for (int i = 0; i < length; i++) { |
195 value = combine(value, elementAt(i)); | 194 value = combine(value, elementAt(i)); |
196 if (length != this.length) { | 195 if (length != this.length) { |
197 throw new ConcurrentModificationError(this); | 196 throw new ConcurrentModificationError(this); |
198 } | 197 } |
199 } | 198 } |
200 return value; | 199 return value; |
201 } | 200 } |
202 | 201 |
203 Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null); | 202 Iterable<E> skip(int count) => new SubListIterable<E>(this, count, null); |
204 | 203 |
205 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); | 204 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); |
206 | 205 |
207 Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count); | 206 Iterable<E> take(int count) => new SubListIterable<E>(this, 0, count); |
208 | 207 |
209 Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test); | 208 Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test); |
210 | 209 |
211 List<E> toList({ bool growable: true }) { | 210 List<E> toList({bool growable: true}) { |
212 List<E> result; | 211 List<E> result; |
213 if (growable) { | 212 if (growable) { |
214 result = new List<E>()..length = length; | 213 result = new List<E>()..length = length; |
215 } else { | 214 } else { |
216 result = new List<E>(length); | 215 result = new List<E>(length); |
217 } | 216 } |
218 for (int i = 0; i < length; i++) { | 217 for (int i = 0; i < length; i++) { |
219 result[i] = elementAt(i); | 218 result[i] = elementAt(i); |
220 } | 219 } |
221 return result; | 220 return result; |
222 } | 221 } |
223 | 222 |
224 Set<E> toSet() { | 223 Set<E> toSet() { |
225 Set<E> result = new Set<E>(); | 224 Set<E> result = new Set<E>(); |
226 for (int i = 0; i < length; i++) { | 225 for (int i = 0; i < length; i++) { |
227 result.add(elementAt(i)); | 226 result.add(elementAt(i)); |
228 } | 227 } |
229 return result; | 228 return result; |
230 } | 229 } |
231 } | 230 } |
232 | 231 |
233 class SubListIterable<E> extends ListIterable<E> { | 232 class SubListIterable<E> extends ListIterable<E> { |
234 final Iterable<E> _iterable; // Has efficient length and elementAt. | 233 final Iterable<E> _iterable; // Has efficient length and elementAt. |
235 final int _start; | 234 final int _start; |
236 /** If null, represents the length of the iterable. */ | 235 /** If null, represents the length of the iterable. */ |
237 final int _endOrLength; | 236 final int _endOrLength; |
238 | 237 |
239 SubListIterable(this._iterable, this._start, this._endOrLength) { | 238 SubListIterable(this._iterable, this._start, this._endOrLength) { |
240 RangeError.checkNotNegative(_start, "start"); | 239 RangeError.checkNotNegative(_start, "start"); |
241 if (_endOrLength != null) { | 240 if (_endOrLength != null) { |
242 RangeError.checkNotNegative(_endOrLength, "end"); | 241 RangeError.checkNotNegative(_endOrLength, "end"); |
243 if (_start > _endOrLength) { | 242 if (_start > _endOrLength) { |
244 throw new RangeError.range(_start, 0, _endOrLength, "start"); | 243 throw new RangeError.range(_start, 0, _endOrLength, "start"); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return new SubListIterable<E>(_iterable, _start, newEnd); | 293 return new SubListIterable<E>(_iterable, _start, newEnd); |
295 } | 294 } |
296 } | 295 } |
297 | 296 |
298 List<E> toList({bool growable: true}) { | 297 List<E> toList({bool growable: true}) { |
299 int start = _start; | 298 int start = _start; |
300 int end = _iterable.length; | 299 int end = _iterable.length; |
301 if (_endOrLength != null && _endOrLength < end) end = _endOrLength; | 300 if (_endOrLength != null && _endOrLength < end) end = _endOrLength; |
302 int length = end - start; | 301 int length = end - start; |
303 if (length < 0) length = 0; | 302 if (length < 0) length = 0; |
304 List<E> result = growable ? (new List<E>()..length = length) | 303 List<E> result = |
305 : new List<E>(length); | 304 growable ? (new List<E>()..length = length) : new List<E>(length); |
306 for (int i = 0; i < length; i++) { | 305 for (int i = 0; i < length; i++) { |
307 result[i] = _iterable.elementAt(start + i); | 306 result[i] = _iterable.elementAt(start + i); |
308 if (_iterable.length < end) throw new ConcurrentModificationError(this); | 307 if (_iterable.length < end) throw new ConcurrentModificationError(this); |
309 } | 308 } |
310 return result; | 309 return result; |
311 } | 310 } |
312 } | 311 } |
313 | 312 |
314 /** | 313 /** |
315 * An [Iterator] that iterates a list-like [Iterable]. | 314 * An [Iterator] that iterates a list-like [Iterable]. |
316 * | 315 * |
317 * All iterations is done in terms of [Iterable.length] and | 316 * All iterations is done in terms of [Iterable.length] and |
318 * [Iterable.elementAt]. These operations are fast for list-like | 317 * [Iterable.elementAt]. These operations are fast for list-like |
319 * iterables. | 318 * iterables. |
320 */ | 319 */ |
321 class ListIterator<E> implements Iterator<E> { | 320 class ListIterator<E> implements Iterator<E> { |
322 final Iterable<E> _iterable; | 321 final Iterable<E> _iterable; |
323 final int _length; | 322 final int _length; |
324 int _index; | 323 int _index; |
325 E _current; | 324 E _current; |
326 | 325 |
327 ListIterator(Iterable<E> iterable) | 326 ListIterator(Iterable<E> iterable) |
328 : _iterable = iterable, _length = iterable.length, _index = 0; | 327 : _iterable = iterable, |
| 328 _length = iterable.length, |
| 329 _index = 0; |
329 | 330 |
330 E get current => _current; | 331 E get current => _current; |
331 | 332 |
332 bool moveNext() { | 333 bool moveNext() { |
333 int length = _iterable.length; | 334 int length = _iterable.length; |
334 if (_length != length) { | 335 if (_length != length) { |
335 throw new ConcurrentModificationError(_iterable); | 336 throw new ConcurrentModificationError(_iterable); |
336 } | 337 } |
337 if (_index >= length) { | 338 if (_index >= length) { |
338 _current = null; | 339 _current = null; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 class MappedListIterable<S, T> extends ListIterable<T> { | 406 class MappedListIterable<S, T> extends ListIterable<T> { |
406 final Iterable<S> _source; | 407 final Iterable<S> _source; |
407 final _Transformation<S, T> _f; | 408 final _Transformation<S, T> _f; |
408 | 409 |
409 MappedListIterable(this._source, this._f); | 410 MappedListIterable(this._source, this._f); |
410 | 411 |
411 int get length => _source.length; | 412 int get length => _source.length; |
412 T elementAt(int index) => _f(_source.elementAt(index)); | 413 T elementAt(int index) => _f(_source.elementAt(index)); |
413 } | 414 } |
414 | 415 |
415 | |
416 typedef bool _ElementPredicate<E>(E element); | 416 typedef bool _ElementPredicate<E>(E element); |
417 | 417 |
418 class WhereIterable<E> extends Iterable<E> { | 418 class WhereIterable<E> extends Iterable<E> { |
419 final Iterable<E> _iterable; | 419 final Iterable<E> _iterable; |
420 final _ElementPredicate<E> _f; | 420 final _ElementPredicate<E> _f; |
421 | 421 |
422 WhereIterable(this._iterable, this._f); | 422 WhereIterable(this._iterable, this._f); |
423 | 423 |
424 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); | 424 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); |
425 | 425 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 } | 502 } |
503 | 503 |
504 TakeIterable._(this._iterable, this._takeCount); | 504 TakeIterable._(this._iterable, this._takeCount); |
505 | 505 |
506 Iterator<E> get iterator { | 506 Iterator<E> get iterator { |
507 return new TakeIterator<E>(_iterable.iterator, _takeCount); | 507 return new TakeIterator<E>(_iterable.iterator, _takeCount); |
508 } | 508 } |
509 } | 509 } |
510 | 510 |
511 class EfficientLengthTakeIterable<E> extends TakeIterable<E> | 511 class EfficientLengthTakeIterable<E> extends TakeIterable<E> |
512 implements EfficientLengthIterable<E> { | 512 implements EfficientLengthIterable<E> { |
513 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) | 513 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) |
514 : super._(iterable, takeCount); | 514 : super._(iterable, takeCount); |
515 | 515 |
516 int get length { | 516 int get length { |
517 int iterableLength = _iterable.length; | 517 int iterableLength = _iterable.length; |
518 if (iterableLength > _takeCount) return _takeCount; | 518 if (iterableLength > _takeCount) return _takeCount; |
519 return iterableLength; | 519 return iterableLength; |
520 } | 520 } |
521 } | 521 } |
522 | 522 |
523 | |
524 class TakeIterator<E> extends Iterator<E> { | 523 class TakeIterator<E> extends Iterator<E> { |
525 final Iterator<E> _iterator; | 524 final Iterator<E> _iterator; |
526 int _remaining; | 525 int _remaining; |
527 | 526 |
528 TakeIterator(this._iterator, this._remaining) { | 527 TakeIterator(this._iterator, this._remaining) { |
529 assert(_remaining is int && _remaining >= 0); | 528 assert(_remaining is int && _remaining >= 0); |
530 } | 529 } |
531 | 530 |
532 bool moveNext() { | 531 bool moveNext() { |
533 _remaining--; | 532 _remaining--; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 RangeError.checkNotNegative(_skipCount, "count"); | 601 RangeError.checkNotNegative(_skipCount, "count"); |
603 return new SkipIterable<E>._(_iterable, _skipCount + count); | 602 return new SkipIterable<E>._(_iterable, _skipCount + count); |
604 } | 603 } |
605 | 604 |
606 Iterator<E> get iterator { | 605 Iterator<E> get iterator { |
607 return new SkipIterator<E>(_iterable.iterator, _skipCount); | 606 return new SkipIterator<E>(_iterable.iterator, _skipCount); |
608 } | 607 } |
609 } | 608 } |
610 | 609 |
611 class EfficientLengthSkipIterable<E> extends SkipIterable<E> | 610 class EfficientLengthSkipIterable<E> extends SkipIterable<E> |
612 implements EfficientLengthIterable<E> { | 611 implements EfficientLengthIterable<E> { |
613 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) | 612 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) |
614 : super._(iterable, skipCount); | 613 : super._(iterable, skipCount); |
615 | 614 |
616 int get length { | 615 int get length { |
617 int length = _iterable.length - _skipCount; | 616 int length = _iterable.length - _skipCount; |
618 if (length >= 0) return length; | 617 if (length >= 0) return length; |
619 return 0; | 618 return 0; |
620 } | 619 } |
621 } | 620 } |
622 | 621 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 const EmptyIterable(); | 674 const EmptyIterable(); |
676 | 675 |
677 Iterator<E> get iterator => const EmptyIterator(); | 676 Iterator<E> get iterator => const EmptyIterator(); |
678 | 677 |
679 void forEach(void action(E element)) {} | 678 void forEach(void action(E element)) {} |
680 | 679 |
681 bool get isEmpty => true; | 680 bool get isEmpty => true; |
682 | 681 |
683 int get length => 0; | 682 int get length => 0; |
684 | 683 |
685 E get first { throw IterableElementError.noElement(); } | 684 E get first { |
| 685 throw IterableElementError.noElement(); |
| 686 } |
686 | 687 |
687 E get last { throw IterableElementError.noElement(); } | 688 E get last { |
| 689 throw IterableElementError.noElement(); |
| 690 } |
688 | 691 |
689 E get single { throw IterableElementError.noElement(); } | 692 E get single { |
| 693 throw IterableElementError.noElement(); |
| 694 } |
690 | 695 |
691 E elementAt(int index) { throw new RangeError.range(index, 0, 0, "index"); } | 696 E elementAt(int index) { |
| 697 throw new RangeError.range(index, 0, 0, "index"); |
| 698 } |
692 | 699 |
693 bool contains(Object element) => false; | 700 bool contains(Object element) => false; |
694 | 701 |
695 bool every(bool test(E element)) => true; | 702 bool every(bool test(E element)) => true; |
696 | 703 |
697 bool any(bool test(E element)) => false; | 704 bool any(bool test(E element)) => false; |
698 | 705 |
699 E firstWhere(bool test(E element), { E orElse() }) { | 706 E firstWhere(bool test(E element), {E orElse()}) { |
700 if (orElse != null) return orElse(); | 707 if (orElse != null) return orElse(); |
701 throw IterableElementError.noElement(); | 708 throw IterableElementError.noElement(); |
702 } | 709 } |
703 | 710 |
704 E lastWhere(bool test(E element), { E orElse() }) { | 711 E lastWhere(bool test(E element), {E orElse()}) { |
705 if (orElse != null) return orElse(); | 712 if (orElse != null) return orElse(); |
706 throw IterableElementError.noElement(); | 713 throw IterableElementError.noElement(); |
707 } | 714 } |
708 | 715 |
709 E singleWhere(bool test(E element), { E orElse() }) { | 716 E singleWhere(bool test(E element), {E orElse()}) { |
710 if (orElse != null) return orElse(); | 717 if (orElse != null) return orElse(); |
711 throw IterableElementError.noElement(); | 718 throw IterableElementError.noElement(); |
712 } | 719 } |
713 | 720 |
714 String join([String separator = ""]) => ""; | 721 String join([String separator = ""]) => ""; |
715 | 722 |
716 Iterable<E> where(bool test(E element)) => this; | 723 Iterable<E> where(bool test(E element)) => this; |
717 | 724 |
718 Iterable<T> map<T>(T f(E element)) => const EmptyIterable(); | 725 Iterable<T> map<T>(T f(E element)) => const EmptyIterable(); |
719 | 726 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 * Creates errors throw by [Iterable] when the element count is wrong. | 762 * Creates errors throw by [Iterable] when the element count is wrong. |
756 */ | 763 */ |
757 abstract class IterableElementError { | 764 abstract class IterableElementError { |
758 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ | 765 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ |
759 static StateError noElement() => new StateError("No element"); | 766 static StateError noElement() => new StateError("No element"); |
760 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ | 767 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ |
761 static StateError tooMany() => new StateError("Too many elements"); | 768 static StateError tooMany() => new StateError("Too many elements"); |
762 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ | 769 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ |
763 static StateError tooFew() => new StateError("Too few elements"); | 770 static StateError tooFew() => new StateError("Too few elements"); |
764 } | 771 } |
OLD | NEW |