| 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 */ |
| 11 abstract class EfficientLength { | 11 abstract class EfficientLengthIterable<T> extends Iterable<T> { |
| 12 const EfficientLengthIterable(); |
| 12 /** | 13 /** |
| 13 * Returns the number of elements in the iterable. | 14 * Returns the number of elements in the iterable. |
| 14 * | 15 * |
| 15 * This is an efficient operation that doesn't require iterating through | 16 * This is an efficient operation that doesn't require iterating through |
| 16 * the elements. | 17 * the elements. |
| 17 */ | 18 */ |
| 18 int get length; | 19 int get length; |
| 19 } | 20 } |
| 20 | 21 |
| 21 /** | 22 /** |
| 22 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 23 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
| 23 * | 24 * |
| 24 * All other methods are implemented in terms of [length] and [elementAt], | 25 * All other methods are implemented in terms of [length] and [elementAt], |
| 25 * including [iterator]. | 26 * including [iterator]. |
| 26 */ | 27 */ |
| 27 abstract class ListIterable<E> extends Iterable<E> | 28 abstract class ListIterable<E> extends EfficientLengthIterable<E> { |
| 28 implements EfficientLength { | |
| 29 int get length; | 29 int get length; |
| 30 E elementAt(int i); | 30 E elementAt(int i); |
| 31 | 31 |
| 32 const ListIterable(); | 32 const ListIterable(); |
| 33 | 33 |
| 34 Iterator<E> get iterator => new ListIterator<E>(this); | 34 Iterator<E> get iterator => new ListIterator<E>(this); |
| 35 | 35 |
| 36 void forEach(void action(E element)) { | 36 void forEach(void action(E element)) { |
| 37 int length = this.length; | 37 int length = this.length; |
| 38 for (int i = 0; i < length; i++) { | 38 for (int i = 0; i < length; i++) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 | 349 |
| 350 typedef T _Transformation<S, T>(S value); | 350 typedef T _Transformation<S, T>(S value); |
| 351 | 351 |
| 352 class MappedIterable<S, T> extends Iterable<T> { | 352 class MappedIterable<S, T> extends Iterable<T> { |
| 353 final Iterable<S> _iterable; | 353 final Iterable<S> _iterable; |
| 354 final _Transformation<S, T> _f; | 354 final _Transformation<S, T> _f; |
| 355 | 355 |
| 356 factory MappedIterable(Iterable<S> iterable, T function(S value)) { | 356 factory MappedIterable(Iterable<S> iterable, T function(S value)) { |
| 357 if (iterable is EfficientLength) { | 357 if (iterable is EfficientLengthIterable) { |
| 358 return new EfficientLengthMappedIterable<S, T>(iterable, function); | 358 return new EfficientLengthMappedIterable<S, T>(iterable, function); |
| 359 } | 359 } |
| 360 return new MappedIterable<S, T>._(iterable, function); | 360 return new MappedIterable<S, T>._(iterable, function); |
| 361 } | 361 } |
| 362 | 362 |
| 363 MappedIterable._(this._iterable, T this._f(S element)); | 363 MappedIterable._(this._iterable, T this._f(S element)); |
| 364 | 364 |
| 365 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); | 365 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); |
| 366 | 366 |
| 367 // Length related functions are independent of the mapping. | 367 // Length related functions are independent of the mapping. |
| 368 int get length => _iterable.length; | 368 int get length => _iterable.length; |
| 369 bool get isEmpty => _iterable.isEmpty; | 369 bool get isEmpty => _iterable.isEmpty; |
| 370 | 370 |
| 371 // Index based lookup can be done before transforming. | 371 // Index based lookup can be done before transforming. |
| 372 T get first => _f(_iterable.first); | 372 T get first => _f(_iterable.first); |
| 373 T get last => _f(_iterable.last); | 373 T get last => _f(_iterable.last); |
| 374 T get single => _f(_iterable.single); | 374 T get single => _f(_iterable.single); |
| 375 T elementAt(int index) => _f(_iterable.elementAt(index)); | 375 T elementAt(int index) => _f(_iterable.elementAt(index)); |
| 376 } | 376 } |
| 377 | 377 |
| 378 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> | 378 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> |
| 379 implements EfficientLength { | 379 implements EfficientLengthIterable<T> { |
| 380 EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value)) | 380 EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value)) |
| 381 : super._(iterable, function); | 381 : super._(iterable, function); |
| 382 } | 382 } |
| 383 | 383 |
| 384 class MappedIterator<S, T> extends Iterator<T> { | 384 class MappedIterator<S, T> extends Iterator<T> { |
| 385 T _current; | 385 T _current; |
| 386 final Iterator<S> _iterator; | 386 final Iterator<S> _iterator; |
| 387 final _Transformation<S, T> _f; | 387 final _Transformation<S, T> _f; |
| 388 | 388 |
| 389 MappedIterator(this._iterator, T this._f(S element)); | 389 MappedIterator(this._iterator, T this._f(S element)); |
| 390 | 390 |
| 391 bool moveNext() { | 391 bool moveNext() { |
| 392 if (_iterator.moveNext()) { | 392 if (_iterator.moveNext()) { |
| 393 _current = _f(_iterator.current); | 393 _current = _f(_iterator.current); |
| 394 return true; | 394 return true; |
| 395 } | 395 } |
| 396 _current = null; | 396 _current = null; |
| 397 return false; | 397 return false; |
| 398 } | 398 } |
| 399 | 399 |
| 400 T get current => _current; | 400 T get current => _current; |
| 401 } | 401 } |
| 402 | 402 |
| 403 /** | 403 /** |
| 404 * Specialized alternative to [MappedIterable] for mapped [List]s. | 404 * Specialized alternative to [MappedIterable] for mapped [List]s. |
| 405 * | 405 * |
| 406 * Expects efficient `length` and `elementAt` on the source iterable. | 406 * Expects efficient `length` and `elementAt` on the source iterable. |
| 407 */ | 407 */ |
| 408 class MappedListIterable<S, T> extends ListIterable<T> | 408 class MappedListIterable<S, T> extends ListIterable<T> |
| 409 implements EfficientLength { | 409 implements EfficientLengthIterable<T> { |
| 410 final Iterable<S> _source; | 410 final Iterable<S> _source; |
| 411 final _Transformation<S, T> _f; | 411 final _Transformation<S, T> _f; |
| 412 | 412 |
| 413 MappedListIterable(this._source, T this._f(S value)); | 413 MappedListIterable(this._source, T this._f(S value)); |
| 414 | 414 |
| 415 int get length => _source.length; | 415 int get length => _source.length; |
| 416 T elementAt(int index) => _f(_source.elementAt(index)); | 416 T elementAt(int index) => _f(_source.elementAt(index)); |
| 417 } | 417 } |
| 418 | 418 |
| 419 | 419 |
| 420 typedef bool _ElementPredicate<E>(E element); | 420 typedef bool _ElementPredicate<E>(E element); |
| 421 | 421 |
| 422 class WhereIterable<E> extends Iterable<E> { | 422 class WhereIterable<E> extends Iterable<E> { |
| 423 final Iterable<E> _iterable; | 423 final Iterable<E> _iterable; |
| 424 final _ElementPredicate<E> _f; | 424 final _ElementPredicate<E> _f; |
| 425 | 425 |
| 426 WhereIterable(this._iterable, bool this._f(E element)); | 426 WhereIterable(this._iterable, bool this._f(E element)); |
| 427 | 427 |
| 428 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); | 428 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f); |
| 429 | 429 |
| 430 // Specialization of [Iterable.map] to non-EfficientLength. | 430 // Specialization of [Iterable.map] to non-EfficientLengthIterable. |
| 431 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => | 431 Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => |
| 432 new MappedIterable<E, dynamic/*=T*/>._(this, f); | 432 new MappedIterable<E, dynamic/*=T*/>._(this, f); |
| 433 } | 433 } |
| 434 | 434 |
| 435 class WhereIterator<E> extends Iterator<E> { | 435 class WhereIterator<E> extends Iterator<E> { |
| 436 final Iterator<E> _iterator; | 436 final Iterator<E> _iterator; |
| 437 final _ElementPredicate _f; | 437 final _ElementPredicate _f; |
| 438 | 438 |
| 439 WhereIterator(this._iterator, bool this._f(E element)); | 439 WhereIterator(this._iterator, bool this._f(E element)); |
| 440 | 440 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 } | 493 } |
| 494 | 494 |
| 495 class TakeIterable<E> extends Iterable<E> { | 495 class TakeIterable<E> extends Iterable<E> { |
| 496 final Iterable<E> _iterable; | 496 final Iterable<E> _iterable; |
| 497 final int _takeCount; | 497 final int _takeCount; |
| 498 | 498 |
| 499 factory TakeIterable(Iterable<E> iterable, int takeCount) { | 499 factory TakeIterable(Iterable<E> iterable, int takeCount) { |
| 500 if (takeCount is! int || takeCount < 0) { | 500 if (takeCount is! int || takeCount < 0) { |
| 501 throw new ArgumentError(takeCount); | 501 throw new ArgumentError(takeCount); |
| 502 } | 502 } |
| 503 if (iterable is EfficientLength) { | 503 if (iterable is EfficientLengthIterable) { |
| 504 return new EfficientLengthTakeIterable<E>(iterable, takeCount); | 504 return new EfficientLengthTakeIterable<E>(iterable, takeCount); |
| 505 } | 505 } |
| 506 return new TakeIterable<E>._(iterable, takeCount); | 506 return new TakeIterable<E>._(iterable, takeCount); |
| 507 } | 507 } |
| 508 | 508 |
| 509 TakeIterable._(this._iterable, this._takeCount); | 509 TakeIterable._(this._iterable, this._takeCount); |
| 510 | 510 |
| 511 Iterator<E> get iterator { | 511 Iterator<E> get iterator { |
| 512 return new TakeIterator<E>(_iterable.iterator, _takeCount); | 512 return new TakeIterator<E>(_iterable.iterator, _takeCount); |
| 513 } | 513 } |
| 514 } | 514 } |
| 515 | 515 |
| 516 class EfficientLengthTakeIterable<E> extends TakeIterable<E> | 516 class EfficientLengthTakeIterable<E> extends TakeIterable<E> |
| 517 implements EfficientLength { | 517 implements EfficientLengthIterable<E> { |
| 518 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) | 518 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) |
| 519 : super._(iterable, takeCount); | 519 : super._(iterable, takeCount); |
| 520 | 520 |
| 521 int get length { | 521 int get length { |
| 522 int iterableLength = _iterable.length; | 522 int iterableLength = _iterable.length; |
| 523 if (iterableLength > _takeCount) return _takeCount; | 523 if (iterableLength > _takeCount) return _takeCount; |
| 524 return iterableLength; | 524 return iterableLength; |
| 525 } | 525 } |
| 526 } | 526 } |
| 527 | 527 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 if (_isFinished) return null; | 580 if (_isFinished) return null; |
| 581 return _iterator.current; | 581 return _iterator.current; |
| 582 } | 582 } |
| 583 } | 583 } |
| 584 | 584 |
| 585 class SkipIterable<E> extends Iterable<E> { | 585 class SkipIterable<E> extends Iterable<E> { |
| 586 final Iterable<E> _iterable; | 586 final Iterable<E> _iterable; |
| 587 final int _skipCount; | 587 final int _skipCount; |
| 588 | 588 |
| 589 factory SkipIterable(Iterable<E> iterable, int count) { | 589 factory SkipIterable(Iterable<E> iterable, int count) { |
| 590 if (iterable is EfficientLength) { | 590 if (iterable is EfficientLengthIterable) { |
| 591 return new EfficientLengthSkipIterable<E>(iterable, count); | 591 return new EfficientLengthSkipIterable<E>(iterable, count); |
| 592 } | 592 } |
| 593 return new SkipIterable<E>._(iterable, count); | 593 return new SkipIterable<E>._(iterable, count); |
| 594 } | 594 } |
| 595 | 595 |
| 596 SkipIterable._(this._iterable, this._skipCount) { | 596 SkipIterable._(this._iterable, this._skipCount) { |
| 597 if (_skipCount is! int) { | 597 if (_skipCount is! int) { |
| 598 throw new ArgumentError.value(_skipCount, "count is not an integer"); | 598 throw new ArgumentError.value(_skipCount, "count is not an integer"); |
| 599 } | 599 } |
| 600 RangeError.checkNotNegative(_skipCount, "count"); | 600 RangeError.checkNotNegative(_skipCount, "count"); |
| 601 } | 601 } |
| 602 | 602 |
| 603 Iterable<E> skip(int count) { | 603 Iterable<E> skip(int count) { |
| 604 if (_skipCount is! int) { | 604 if (_skipCount is! int) { |
| 605 throw new ArgumentError.value(_skipCount, "count is not an integer"); | 605 throw new ArgumentError.value(_skipCount, "count is not an integer"); |
| 606 } | 606 } |
| 607 RangeError.checkNotNegative(_skipCount, "count"); | 607 RangeError.checkNotNegative(_skipCount, "count"); |
| 608 return new SkipIterable<E>._(_iterable, _skipCount + count); | 608 return new SkipIterable<E>._(_iterable, _skipCount + count); |
| 609 } | 609 } |
| 610 | 610 |
| 611 Iterator<E> get iterator { | 611 Iterator<E> get iterator { |
| 612 return new SkipIterator<E>(_iterable.iterator, _skipCount); | 612 return new SkipIterator<E>(_iterable.iterator, _skipCount); |
| 613 } | 613 } |
| 614 } | 614 } |
| 615 | 615 |
| 616 class EfficientLengthSkipIterable<E> extends SkipIterable<E> | 616 class EfficientLengthSkipIterable<E> extends SkipIterable<E> |
| 617 implements EfficientLength { | 617 implements EfficientLengthIterable<E> { |
| 618 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) | 618 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) |
| 619 : super._(iterable, skipCount); | 619 : super._(iterable, skipCount); |
| 620 | 620 |
| 621 int get length { | 621 int get length { |
| 622 int length = _iterable.length - _skipCount; | 622 int length = _iterable.length - _skipCount; |
| 623 if (length >= 0) return length; | 623 if (length >= 0) return length; |
| 624 return 0; | 624 return 0; |
| 625 } | 625 } |
| 626 } | 626 } |
| 627 | 627 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 } | 669 } |
| 670 return _iterator.moveNext(); | 670 return _iterator.moveNext(); |
| 671 } | 671 } |
| 672 | 672 |
| 673 E get current => _iterator.current; | 673 E get current => _iterator.current; |
| 674 } | 674 } |
| 675 | 675 |
| 676 /** | 676 /** |
| 677 * The always empty [Iterable]. | 677 * The always empty [Iterable]. |
| 678 */ | 678 */ |
| 679 class EmptyIterable<E> extends Iterable<E> implements EfficientLength { | 679 class EmptyIterable<E> extends EfficientLengthIterable<E> { |
| 680 const EmptyIterable(); | 680 const EmptyIterable(); |
| 681 | 681 |
| 682 Iterator<E> get iterator => const EmptyIterator(); | 682 Iterator<E> get iterator => const EmptyIterator(); |
| 683 | 683 |
| 684 void forEach(void action(E element)) {} | 684 void forEach(void action(E element)) {} |
| 685 | 685 |
| 686 bool get isEmpty => true; | 686 bool get isEmpty => true; |
| 687 | 687 |
| 688 int get length => 0; | 688 int get length => 0; |
| 689 | 689 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 * Creates errors throw by [Iterable] when the element count is wrong. | 762 * Creates errors throw by [Iterable] when the element count is wrong. |
| 763 */ | 763 */ |
| 764 abstract class IterableElementError { | 764 abstract class IterableElementError { |
| 765 /** 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. */ |
| 766 static StateError noElement() => new StateError("No element"); | 766 static StateError noElement() => new StateError("No element"); |
| 767 /** 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. */ |
| 768 static StateError tooMany() => new StateError("Too many elements"); | 768 static StateError tooMany() => new StateError("Too many elements"); |
| 769 /** 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. */ |
| 770 static StateError tooFew() => new StateError("Too few elements"); | 770 static StateError tooFew() => new StateError("Too few elements"); |
| 771 } | 771 } |
| OLD | NEW |