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 |