| 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 |
| 9 * [length] implementation. |
| 10 */ |
| 11 abstract class EfficientLength { |
| 12 /** |
| 13 * Returns the number of elements in the iterable. |
| 14 * |
| 15 * This is an efficient operation that doesn't require iterating through |
| 16 * the elements. |
| 17 */ |
| 18 int get length; |
| 19 } |
| 20 |
| 21 /** |
| 8 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 22 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
| 9 * | 23 * |
| 10 * All other methods are implemented in terms of [length] and [elementAt], | 24 * All other methods are implemented in terms of [length] and [elementAt], |
| 11 * including [iterator]. | 25 * including [iterator]. |
| 12 */ | 26 */ |
| 13 abstract class ListIterable<E> extends Iterable<E> | 27 abstract class ListIterable<E> extends Iterable<E> |
| 14 implements EfficientLengthIterable<E> { | 28 implements EfficientLength { |
| 15 int get length; | 29 int get length; |
| 16 E elementAt(int i); | 30 E elementAt(int i); |
| 17 | 31 |
| 18 const ListIterable(); | 32 const ListIterable(); |
| 19 | 33 |
| 20 Iterator<E> get iterator => new ListIterator<E>(this); | 34 Iterator<E> get iterator => new ListIterator<E>(this); |
| 21 | 35 |
| 22 void forEach(void action(E element)) { | 36 void forEach(void action(E element)) { |
| 23 int length = this.length; | 37 int length = this.length; |
| 24 for (int i = 0; i < length; i++) { | 38 for (int i = 0; i < length; i++) { |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 344 } |
| 331 } | 345 } |
| 332 | 346 |
| 333 typedef T _Transformation<S, T>(S value); | 347 typedef T _Transformation<S, T>(S value); |
| 334 | 348 |
| 335 class MappedIterable<S, T> extends Iterable<T> { | 349 class MappedIterable<S, T> extends Iterable<T> { |
| 336 final Iterable<S> _iterable; | 350 final Iterable<S> _iterable; |
| 337 final _Transformation<S, T> _f; | 351 final _Transformation<S, T> _f; |
| 338 | 352 |
| 339 factory MappedIterable(Iterable iterable, T function(S value)) { | 353 factory MappedIterable(Iterable iterable, T function(S value)) { |
| 340 if (iterable is EfficientLengthIterable) { | 354 if (iterable is EfficientLength) { |
| 341 return new EfficientLengthMappedIterable<S, T>(iterable, function); | 355 return new EfficientLengthMappedIterable<S, T>(iterable, function); |
| 342 } | 356 } |
| 343 return new MappedIterable<S, T>._(iterable, function); | 357 return new MappedIterable<S, T>._(iterable, function); |
| 344 } | 358 } |
| 345 | 359 |
| 346 MappedIterable._(this._iterable, T this._f(S element)); | 360 MappedIterable._(this._iterable, T this._f(S element)); |
| 347 | 361 |
| 348 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); | 362 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); |
| 349 | 363 |
| 350 // Length related functions are independent of the mapping. | 364 // Length related functions are independent of the mapping. |
| 351 int get length => _iterable.length; | 365 int get length => _iterable.length; |
| 352 bool get isEmpty => _iterable.isEmpty; | 366 bool get isEmpty => _iterable.isEmpty; |
| 353 | 367 |
| 354 // Index based lookup can be done before transforming. | 368 // Index based lookup can be done before transforming. |
| 355 T get first => _f(_iterable.first); | 369 T get first => _f(_iterable.first); |
| 356 T get last => _f(_iterable.last); | 370 T get last => _f(_iterable.last); |
| 357 T get single => _f(_iterable.single); | 371 T get single => _f(_iterable.single); |
| 358 T elementAt(int index) => _f(_iterable.elementAt(index)); | 372 T elementAt(int index) => _f(_iterable.elementAt(index)); |
| 359 } | 373 } |
| 360 | 374 |
| 361 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> | 375 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T> |
| 362 implements EfficientLengthIterable<T> { | 376 implements EfficientLength { |
| 363 EfficientLengthMappedIterable(Iterable iterable, T function(S value)) | 377 EfficientLengthMappedIterable(Iterable iterable, T function(S value)) |
| 364 : super._(iterable, function); | 378 : super._(iterable, function); |
| 365 } | 379 } |
| 366 | 380 |
| 367 class MappedIterator<S, T> extends Iterator<T> { | 381 class MappedIterator<S, T> extends Iterator<T> { |
| 368 T _current; | 382 T _current; |
| 369 final Iterator<S> _iterator; | 383 final Iterator<S> _iterator; |
| 370 final _Transformation<S, T> _f; | 384 final _Transformation<S, T> _f; |
| 371 | 385 |
| 372 MappedIterator(this._iterator, T this._f(S element)); | 386 MappedIterator(this._iterator, T this._f(S element)); |
| 373 | 387 |
| 374 bool moveNext() { | 388 bool moveNext() { |
| 375 if (_iterator.moveNext()) { | 389 if (_iterator.moveNext()) { |
| 376 _current = _f(_iterator.current); | 390 _current = _f(_iterator.current); |
| 377 return true; | 391 return true; |
| 378 } | 392 } |
| 379 _current = null; | 393 _current = null; |
| 380 return false; | 394 return false; |
| 381 } | 395 } |
| 382 | 396 |
| 383 T get current => _current; | 397 T get current => _current; |
| 384 } | 398 } |
| 385 | 399 |
| 386 /** | 400 /** |
| 387 * Specialized alternative to [MappedIterable] for mapped [List]s. | 401 * Specialized alternative to [MappedIterable] for mapped [List]s. |
| 388 * | 402 * |
| 389 * Expects efficient `length` and `elementAt` on the source iterable. | 403 * Expects efficient `length` and `elementAt` on the source iterable. |
| 390 */ | 404 */ |
| 391 class MappedListIterable<S, T> extends ListIterable<T> { | 405 class MappedListIterable<S, T> extends ListIterable<T> |
| 406 implements EfficientLength { |
| 392 final Iterable<S> _source; | 407 final Iterable<S> _source; |
| 393 final _Transformation<S, T> _f; | 408 final _Transformation<S, T> _f; |
| 394 | 409 |
| 395 MappedListIterable(this._source, T this._f(S value)); | 410 MappedListIterable(this._source, T this._f(S value)); |
| 396 | 411 |
| 397 int get length => _source.length; | 412 int get length => _source.length; |
| 398 T elementAt(int index) => _f(_source.elementAt(index)); | 413 T elementAt(int index) => _f(_source.elementAt(index)); |
| 399 } | 414 } |
| 400 | 415 |
| 401 | 416 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 489 } |
| 475 | 490 |
| 476 class TakeIterable<E> extends Iterable<E> { | 491 class TakeIterable<E> extends Iterable<E> { |
| 477 final Iterable<E> _iterable; | 492 final Iterable<E> _iterable; |
| 478 final int _takeCount; | 493 final int _takeCount; |
| 479 | 494 |
| 480 factory TakeIterable(Iterable<E> iterable, int takeCount) { | 495 factory TakeIterable(Iterable<E> iterable, int takeCount) { |
| 481 if (takeCount is! int || takeCount < 0) { | 496 if (takeCount is! int || takeCount < 0) { |
| 482 throw new ArgumentError(takeCount); | 497 throw new ArgumentError(takeCount); |
| 483 } | 498 } |
| 484 if (iterable is EfficientLengthIterable) { | 499 if (iterable is EfficientLength) { |
| 485 return new EfficientLengthTakeIterable<E>(iterable, takeCount); | 500 return new EfficientLengthTakeIterable<E>(iterable, takeCount); |
| 486 } | 501 } |
| 487 return new TakeIterable<E>._(iterable, takeCount); | 502 return new TakeIterable<E>._(iterable, takeCount); |
| 488 } | 503 } |
| 489 | 504 |
| 490 TakeIterable._(this._iterable, this._takeCount); | 505 TakeIterable._(this._iterable, this._takeCount); |
| 491 | 506 |
| 492 Iterator<E> get iterator { | 507 Iterator<E> get iterator { |
| 493 return new TakeIterator<E>(_iterable.iterator, _takeCount); | 508 return new TakeIterator<E>(_iterable.iterator, _takeCount); |
| 494 } | 509 } |
| 495 } | 510 } |
| 496 | 511 |
| 497 class EfficientLengthTakeIterable<E> extends TakeIterable<E> | 512 class EfficientLengthTakeIterable<E> extends TakeIterable<E> |
| 498 implements EfficientLengthIterable<E> { | 513 implements EfficientLength { |
| 499 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) | 514 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount) |
| 500 : super._(iterable, takeCount); | 515 : super._(iterable, takeCount); |
| 501 | 516 |
| 502 int get length { | 517 int get length { |
| 503 int iterableLength = _iterable.length; | 518 int iterableLength = _iterable.length; |
| 504 if (iterableLength > _takeCount) return _takeCount; | 519 if (iterableLength > _takeCount) return _takeCount; |
| 505 return iterableLength; | 520 return iterableLength; |
| 506 } | 521 } |
| 507 } | 522 } |
| 508 | 523 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 if (_isFinished) return null; | 576 if (_isFinished) return null; |
| 562 return _iterator.current; | 577 return _iterator.current; |
| 563 } | 578 } |
| 564 } | 579 } |
| 565 | 580 |
| 566 class SkipIterable<E> extends Iterable<E> { | 581 class SkipIterable<E> extends Iterable<E> { |
| 567 final Iterable<E> _iterable; | 582 final Iterable<E> _iterable; |
| 568 final int _skipCount; | 583 final int _skipCount; |
| 569 | 584 |
| 570 factory SkipIterable(Iterable<E> iterable, int count) { | 585 factory SkipIterable(Iterable<E> iterable, int count) { |
| 571 if (iterable is EfficientLengthIterable) { | 586 if (iterable is EfficientLength) { |
| 572 return new EfficientLengthSkipIterable<E>(iterable, count); | 587 return new EfficientLengthSkipIterable<E>(iterable, count); |
| 573 } | 588 } |
| 574 return new SkipIterable<E>._(iterable, count); | 589 return new SkipIterable<E>._(iterable, count); |
| 575 } | 590 } |
| 576 | 591 |
| 577 SkipIterable._(this._iterable, this._skipCount) { | 592 SkipIterable._(this._iterable, this._skipCount) { |
| 578 if (_skipCount is! int) { | 593 if (_skipCount is! int) { |
| 579 throw new ArgumentError.value(_skipCount, "count is not an integer"); | 594 throw new ArgumentError.value(_skipCount, "count is not an integer"); |
| 580 } | 595 } |
| 581 RangeError.checkNotNegative(_skipCount, "count"); | 596 RangeError.checkNotNegative(_skipCount, "count"); |
| 582 } | 597 } |
| 583 | 598 |
| 584 Iterable<E> skip(int count) { | 599 Iterable<E> skip(int count) { |
| 585 if (_skipCount is! int) { | 600 if (_skipCount is! int) { |
| 586 throw new ArgumentError.value(_skipCount, "count is not an integer"); | 601 throw new ArgumentError.value(_skipCount, "count is not an integer"); |
| 587 } | 602 } |
| 588 RangeError.checkNotNegative(_skipCount, "count"); | 603 RangeError.checkNotNegative(_skipCount, "count"); |
| 589 return new SkipIterable<E>._(_iterable, _skipCount + count); | 604 return new SkipIterable<E>._(_iterable, _skipCount + count); |
| 590 } | 605 } |
| 591 | 606 |
| 592 Iterator<E> get iterator { | 607 Iterator<E> get iterator { |
| 593 return new SkipIterator<E>(_iterable.iterator, _skipCount); | 608 return new SkipIterator<E>(_iterable.iterator, _skipCount); |
| 594 } | 609 } |
| 595 } | 610 } |
| 596 | 611 |
| 597 class EfficientLengthSkipIterable<E> extends SkipIterable<E> | 612 class EfficientLengthSkipIterable<E> extends SkipIterable<E> |
| 598 implements EfficientLengthIterable<E> { | 613 implements EfficientLength { |
| 599 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) | 614 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount) |
| 600 : super._(iterable, skipCount); | 615 : super._(iterable, skipCount); |
| 601 | 616 |
| 602 int get length { | 617 int get length { |
| 603 int length = _iterable.length - _skipCount; | 618 int length = _iterable.length - _skipCount; |
| 604 if (length >= 0) return length; | 619 if (length >= 0) return length; |
| 605 return 0; | 620 return 0; |
| 606 } | 621 } |
| 607 } | 622 } |
| 608 | 623 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 } | 665 } |
| 651 return _iterator.moveNext(); | 666 return _iterator.moveNext(); |
| 652 } | 667 } |
| 653 | 668 |
| 654 E get current => _iterator.current; | 669 E get current => _iterator.current; |
| 655 } | 670 } |
| 656 | 671 |
| 657 /** | 672 /** |
| 658 * The always empty [Iterable]. | 673 * The always empty [Iterable]. |
| 659 */ | 674 */ |
| 660 class EmptyIterable<E> extends Iterable<E> | 675 class EmptyIterable<E> extends Iterable<E> implements EfficientLength { |
| 661 implements EfficientLengthIterable<E> { | |
| 662 const EmptyIterable(); | 676 const EmptyIterable(); |
| 663 | 677 |
| 664 Iterator<E> get iterator => const EmptyIterator(); | 678 Iterator<E> get iterator => const EmptyIterator(); |
| 665 | 679 |
| 666 void forEach(void action(E element)) {} | 680 void forEach(void action(E element)) {} |
| 667 | 681 |
| 668 bool get isEmpty => true; | 682 bool get isEmpty => true; |
| 669 | 683 |
| 670 int get length => 0; | 684 int get length => 0; |
| 671 | 685 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 * Creates errors throw by [Iterable] when the element count is wrong. | 762 * Creates errors throw by [Iterable] when the element count is wrong. |
| 749 */ | 763 */ |
| 750 abstract class IterableElementError { | 764 abstract class IterableElementError { |
| 751 /** 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. */ |
| 752 static StateError noElement() => new StateError("No element"); | 766 static StateError noElement() => new StateError("No element"); |
| 753 /** 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. */ |
| 754 static StateError tooMany() => new StateError("Too many elements"); | 768 static StateError tooMany() => new StateError("Too many elements"); |
| 755 /** 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. */ |
| 756 static StateError tooFew() => new StateError("Too few elements"); | 770 static StateError tooFew() => new StateError("Too few elements"); |
| 757 } | 771 } |
| OLD | NEW |