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