| 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._collection.dev; | 5 part of dart._collection.dev; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 8 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
| 9 * | 9 * |
| 10 * All other methods are implemented in terms of [length] and [elementAt], | 10 * All other methods are implemented in terms of [length] and [elementAt], |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 475 } |
| 476 | 476 |
| 477 class TakeWhileIterable<E> extends Iterable<E> { | 477 class TakeWhileIterable<E> extends Iterable<E> { |
| 478 final Iterable<E> _iterable; | 478 final Iterable<E> _iterable; |
| 479 // TODO(ahe): Restore type when feature is implemented in dart2js | 479 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 480 // checked mode. http://dartbug.com/7733 | 480 // checked mode. http://dartbug.com/7733 |
| 481 final /* _ElementPredicate */ _f; | 481 final /* _ElementPredicate */ _f; |
| 482 | 482 |
| 483 TakeWhileIterable(this._iterable, bool this._f(E element)); | 483 TakeWhileIterable(this._iterable, bool this._f(E element)); |
| 484 | 484 |
| 485 Iterator<E> get iterator { | 485 Iterator<E> get iterator {collectionToString |
| 486 return new TakeWhileIterator<E>(_iterable.iterator, _f); | 486 return new TakeWhileIterator<E>(_iterable.iterator, _f); |
| 487 } | 487 } |
| 488 } | 488 } |
| 489 | 489 |
| 490 class TakeWhileIterator<E> extends Iterator<E> { | 490 class TakeWhileIterator<E> extends Iterator<E> { |
| 491 final Iterator<E> _iterator; | 491 final Iterator<E> _iterator; |
| 492 // TODO(ahe): Restore type when feature is implemented in dart2js | 492 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 493 // checked mode. http://dartbug.com/7733 | 493 // checked mode. http://dartbug.com/7733 |
| 494 final /* _ElementPredicate */ _f; | 494 final /* _ElementPredicate */ _f; |
| 495 bool _isFinished = false; | 495 bool _isFinished = false; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 class EmptyIterator<E> implements Iterator<E> { | 659 class EmptyIterator<E> implements Iterator<E> { |
| 660 const EmptyIterator(); | 660 const EmptyIterator(); |
| 661 bool moveNext() => false; | 661 bool moveNext() => false; |
| 662 E get current => null; | 662 E get current => null; |
| 663 } | 663 } |
| 664 | 664 |
| 665 /** An [Iterator] that can move in both directions. */ | 665 /** An [Iterator] that can move in both directions. */ |
| 666 abstract class BidirectionalIterator<T> implements Iterator<T> { | 666 abstract class BidirectionalIterator<T> implements Iterator<T> { |
| 667 bool movePrevious(); | 667 bool movePrevious(); |
| 668 } | 668 } |
| 669 |
| 670 /** |
| 671 * This class provides default implementations for Iterables (including Lists). |
| 672 * |
| 673 * The uses of this class will be replaced by mixins. |
| 674 */ |
| 675 class IterableMixinWorkaround { |
| 676 static bool contains(Iterable iterable, var element) { |
| 677 for (final e in iterable) { |
| 678 if (element == e) return true; |
| 679 } |
| 680 return false; |
| 681 } |
| 682 |
| 683 static void forEach(Iterable iterable, void f(o)) { |
| 684 for (final e in iterable) { |
| 685 f(e); |
| 686 } |
| 687 } |
| 688 |
| 689 static bool any(Iterable iterable, bool f(o)) { |
| 690 for (final e in iterable) { |
| 691 if (f(e)) return true; |
| 692 } |
| 693 return false; |
| 694 } |
| 695 |
| 696 static bool every(Iterable iterable, bool f(o)) { |
| 697 for (final e in iterable) { |
| 698 if (!f(e)) return false; |
| 699 } |
| 700 return true; |
| 701 } |
| 702 |
| 703 static dynamic reduce(Iterable iterable, |
| 704 dynamic combine(previousValue, element)) { |
| 705 Iterator iterator = iterable.iterator; |
| 706 if (!iterator.moveNext()) throw new StateError("No elements"); |
| 707 var value = iterator.current; |
| 708 while (iterator.moveNext()) { |
| 709 value = combine(value, iterator.current); |
| 710 } |
| 711 return value; |
| 712 } |
| 713 |
| 714 static dynamic fold(Iterable iterable, |
| 715 dynamic initialValue, |
| 716 dynamic combine(dynamic previousValue, element)) { |
| 717 for (final element in iterable) { |
| 718 initialValue = combine(initialValue, element); |
| 719 } |
| 720 return initialValue; |
| 721 } |
| 722 |
| 723 /** |
| 724 * Removes elements matching [test] from [list]. |
| 725 * |
| 726 * This is performed in two steps, to avoid exposing an inconsistent state |
| 727 * to the [test] function. First the elements to retain are found, and then |
| 728 * the original list is updated to contain those elements. |
| 729 */ |
| 730 static void removeWhereList(List list, bool test(var element)) { |
| 731 List retained = []; |
| 732 int length = list.length; |
| 733 for (int i = 0; i < length; i++) { |
| 734 var element = list[i]; |
| 735 if (!test(element)) { |
| 736 retained.add(element); |
| 737 } |
| 738 if (length != list.length) { |
| 739 throw new ConcurrentModificationError(list); |
| 740 } |
| 741 } |
| 742 if (retained.length == length) return; |
| 743 list.length = retained.length; |
| 744 for (int i = 0; i < retained.length; i++) { |
| 745 list[i] = retained[i]; |
| 746 } |
| 747 } |
| 748 |
| 749 static bool isEmpty(Iterable iterable) { |
| 750 return !iterable.iterator.moveNext(); |
| 751 } |
| 752 |
| 753 static dynamic first(Iterable iterable) { |
| 754 Iterator it = iterable.iterator; |
| 755 if (!it.moveNext()) { |
| 756 throw new StateError("No elements"); |
| 757 } |
| 758 return it.current; |
| 759 } |
| 760 |
| 761 static dynamic last(Iterable iterable) { |
| 762 Iterator it = iterable.iterator; |
| 763 if (!it.moveNext()) { |
| 764 throw new StateError("No elements"); |
| 765 } |
| 766 dynamic result; |
| 767 do { |
| 768 result = it.current; |
| 769 } while(it.moveNext()); |
| 770 return result; |
| 771 } |
| 772 |
| 773 static dynamic single(Iterable iterable) { |
| 774 Iterator it = iterable.iterator; |
| 775 if (!it.moveNext()) throw new StateError("No elements"); |
| 776 dynamic result = it.current; |
| 777 if (it.moveNext()) throw new StateError("More than one element"); |
| 778 return result; |
| 779 } |
| 780 |
| 781 static dynamic firstWhere(Iterable iterable, |
| 782 bool test(dynamic value), |
| 783 dynamic orElse()) { |
| 784 for (dynamic element in iterable) { |
| 785 if (test(element)) return element; |
| 786 } |
| 787 if (orElse != null) return orElse(); |
| 788 throw new StateError("No matching element"); |
| 789 } |
| 790 |
| 791 static dynamic lastWhere(Iterable iterable, |
| 792 bool test(dynamic value), |
| 793 dynamic orElse()) { |
| 794 dynamic result = null; |
| 795 bool foundMatching = false; |
| 796 for (dynamic element in iterable) { |
| 797 if (test(element)) { |
| 798 result = element; |
| 799 foundMatching = true; |
| 800 } |
| 801 } |
| 802 if (foundMatching) return result; |
| 803 if (orElse != null) return orElse(); |
| 804 throw new StateError("No matching element"); |
| 805 } |
| 806 |
| 807 static dynamic lastWhereList(List list, |
| 808 bool test(dynamic value), |
| 809 dynamic orElse()) { |
| 810 // TODO(floitsch): check that arguments are of correct type? |
| 811 for (int i = list.length - 1; i >= 0; i--) { |
| 812 dynamic element = list[i]; |
| 813 if (test(element)) return element; |
| 814 } |
| 815 if (orElse != null) return orElse(); |
| 816 throw new StateError("No matching element"); |
| 817 } |
| 818 |
| 819 static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) { |
| 820 dynamic result = null; |
| 821 bool foundMatching = false; |
| 822 for (dynamic element in iterable) { |
| 823 if (test(element)) { |
| 824 if (foundMatching) { |
| 825 throw new StateError("More than one matching element"); |
| 826 } |
| 827 result = element; |
| 828 foundMatching = true; |
| 829 } |
| 830 } |
| 831 if (foundMatching) return result; |
| 832 throw new StateError("No matching element"); |
| 833 } |
| 834 |
| 835 static dynamic elementAt(Iterable iterable, int index) { |
| 836 if (index is! int || index < 0) throw new RangeError.value(index); |
| 837 int remaining = index; |
| 838 for (dynamic element in iterable) { |
| 839 if (remaining == 0) return element; |
| 840 remaining--; |
| 841 } |
| 842 throw new RangeError.value(index); |
| 843 } |
| 844 |
| 845 static String join(Iterable iterable, [String separator]) { |
| 846 StringBuffer buffer = new StringBuffer(); |
| 847 buffer.writeAll(iterable, separator); |
| 848 return buffer.toString(); |
| 849 } |
| 850 |
| 851 static String joinList(List list, [String separator]) { |
| 852 if (list.isEmpty) return ""; |
| 853 if (list.length == 1) return "${list[0]}"; |
| 854 StringBuffer buffer = new StringBuffer(); |
| 855 if (separator.isEmpty) { |
| 856 for (int i = 0; i < list.length; i++) { |
| 857 buffer.write(list[i]); |
| 858 } |
| 859 } else { |
| 860 buffer.write(list[0]); |
| 861 for (int i = 1; i < list.length; i++) { |
| 862 buffer.write(separator); |
| 863 buffer.write(list[i]); |
| 864 } |
| 865 } |
| 866 return buffer.toString(); |
| 867 } |
| 868 |
| 869 static Iterable where(Iterable iterable, bool f(var element)) { |
| 870 return new WhereIterable(iterable, f); |
| 871 } |
| 872 |
| 873 static Iterable map(Iterable iterable, f(var element)) { |
| 874 return new MappedIterable(iterable, f); |
| 875 } |
| 876 |
| 877 static Iterable mapList(List list, f(var element)) { |
| 878 return new MappedListIterable(list, f); |
| 879 } |
| 880 |
| 881 static Iterable expand(Iterable iterable, Iterable f(var element)) { |
| 882 return new ExpandIterable(iterable, f); |
| 883 } |
| 884 |
| 885 static Iterable takeList(List list, int n) { |
| 886 // The generic type is currently lost. It will be fixed with mixins. |
| 887 return new SubListIterable(list, 0, n); |
| 888 } |
| 889 |
| 890 static Iterable takeWhile(Iterable iterable, bool test(var value)) { |
| 891 // The generic type is currently lost. It will be fixed with mixins. |
| 892 return new TakeWhileIterable(iterable, test); |
| 893 } |
| 894 |
| 895 static Iterable skipList(List list, int n) { |
| 896 // The generic type is currently lost. It will be fixed with mixins. |
| 897 return new SubListIterable(list, n, null); |
| 898 } |
| 899 |
| 900 static Iterable skipWhile(Iterable iterable, bool test(var value)) { |
| 901 // The generic type is currently lost. It will be fixed with mixins. |
| 902 return new SkipWhileIterable(iterable, test); |
| 903 } |
| 904 |
| 905 static Iterable reversedList(List list) { |
| 906 return new ReversedListIterable(list); |
| 907 } |
| 908 |
| 909 static void sortList(List list, int compare(a, b)) { |
| 910 if (compare == null) compare = Comparable.compare; |
| 911 Sort.sort(list, compare); |
| 912 } |
| 913 |
| 914 static int indexOfList(List list, var element, int start) { |
| 915 return Arrays.indexOf(list, element, start, list.length); |
| 916 } |
| 917 |
| 918 static int lastIndexOfList(List list, var element, int start) { |
| 919 if (start == null) start = list.length - 1; |
| 920 return Arrays.lastIndexOf(list, element, start); |
| 921 } |
| 922 |
| 923 static Iterable getRangeList(List list, int start, int end) { |
| 924 if (start < 0 || start > list.length) { |
| 925 throw new RangeError.range(start, 0, list.length); |
| 926 } |
| 927 if (end < start || end > list.length) { |
| 928 throw new RangeError.range(end, start, list.length); |
| 929 } |
| 930 // The generic type is currently lost. It will be fixed with mixins. |
| 931 return new SubListIterable(list, start, end); |
| 932 } |
| 933 |
| 934 static void setRangeList(List list, int start, int length, |
| 935 List from, int startFrom) { |
| 936 if (length == 0) return; |
| 937 |
| 938 if (length < 0) throw new ArgumentError(length); |
| 939 if (start < 0) throw new RangeError.value(start); |
| 940 if (start + length > list.length) { |
| 941 throw new RangeError.value(start + length); |
| 942 } |
| 943 |
| 944 Arrays.copy(from, startFrom, list, start, length); |
| 945 } |
| 946 |
| 947 static Map<int, dynamic> asMapList(List l) { |
| 948 return new ListMapView(l); |
| 949 } |
| 950 |
| 951 static bool setContainsAll(Set set, Iterable other) { |
| 952 for (var element in other) { |
| 953 if (!set.contains(element)) return false; |
| 954 } |
| 955 return true; |
| 956 } |
| 957 |
| 958 static Set setIntersection(Set set, Set other, Set result) { |
| 959 Set smaller; |
| 960 Set larger; |
| 961 if (set.length < other.length) { |
| 962 smaller = set; |
| 963 larger = other; |
| 964 } else { |
| 965 smaller = other; |
| 966 larger = set; |
| 967 } |
| 968 for (var element in smaller) { |
| 969 if (larger.contains(element)) { |
| 970 result.add(element); |
| 971 } |
| 972 } |
| 973 return result; |
| 974 } |
| 975 |
| 976 static Set setUnion(Set set, Set other, Set result) { |
| 977 result.addAll(set); |
| 978 result.addAll(other); |
| 979 return result; |
| 980 } |
| 981 |
| 982 static Set setDifference(Set set, Set other, Set result) { |
| 983 for (var element in set) { |
| 984 if (!other.contains(element)) { |
| 985 result.add(element); |
| 986 } |
| 987 } |
| 988 return result; |
| 989 } |
| 990 } |
| OLD | NEW |