| 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 */ |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 action(elementAt(i)); | 39 action(elementAt(i)); |
| 40 if (length != this.length) { | 40 if (length != this.length) { |
| 41 throw new ConcurrentModificationError(this); | 41 throw new ConcurrentModificationError(this); |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool get isEmpty => length == 0; | 46 bool get isEmpty => length == 0; |
| 47 | 47 |
| 48 E get first { | 48 E get first { |
| 49 if (length == 0) throw new StateError("No elements"); | 49 if (length == 0) throw IterableElementError.noElement(); |
| 50 return elementAt(0); | 50 return elementAt(0); |
| 51 } | 51 } |
| 52 | 52 |
| 53 E get last { | 53 E get last { |
| 54 if (length == 0) throw new StateError("No elements"); | 54 if (length == 0) throw IterableElementError.noElement(); |
| 55 return elementAt(length - 1); | 55 return elementAt(length - 1); |
| 56 } | 56 } |
| 57 | 57 |
| 58 E get single { | 58 E get single { |
| 59 if (length == 0) throw new StateError("No elements"); | 59 if (length == 0) throw IterableElementError.noElement(); |
| 60 if (length > 1) throw new StateError("Too many elements"); | 60 if (length > 1) throw IterableElementError.tooMany(); |
| 61 return elementAt(0); | 61 return elementAt(0); |
| 62 } | 62 } |
| 63 | 63 |
| 64 bool contains(Object element) { | 64 bool contains(Object element) { |
| 65 int length = this.length; | 65 int length = this.length; |
| 66 for (int i = 0; i < length; i++) { | 66 for (int i = 0; i < length; i++) { |
| 67 if (elementAt(i) == element) return true; | 67 if (elementAt(i) == element) return true; |
| 68 if (length != this.length) { | 68 if (length != this.length) { |
| 69 throw new ConcurrentModificationError(this); | 69 throw new ConcurrentModificationError(this); |
| 70 } | 70 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 97 dynamic firstWhere(bool test(E element), { Object orElse() }) { | 97 dynamic firstWhere(bool test(E element), { Object orElse() }) { |
| 98 int length = this.length; | 98 int length = this.length; |
| 99 for (int i = 0; i < length; i++) { | 99 for (int i = 0; i < length; i++) { |
| 100 E element = elementAt(i); | 100 E element = elementAt(i); |
| 101 if (test(element)) return element; | 101 if (test(element)) return element; |
| 102 if (length != this.length) { | 102 if (length != this.length) { |
| 103 throw new ConcurrentModificationError(this); | 103 throw new ConcurrentModificationError(this); |
| 104 } | 104 } |
| 105 } | 105 } |
| 106 if (orElse != null) return orElse(); | 106 if (orElse != null) return orElse(); |
| 107 throw new StateError("No matching element"); | 107 throw IterableElementError.noElement(); |
| 108 } | 108 } |
| 109 | 109 |
| 110 dynamic lastWhere(bool test(E element), { Object orElse() }) { | 110 dynamic lastWhere(bool test(E element), { Object orElse() }) { |
| 111 int length = this.length; | 111 int length = this.length; |
| 112 for (int i = length - 1; i >= 0; i--) { | 112 for (int i = length - 1; i >= 0; i--) { |
| 113 E element = elementAt(i); | 113 E element = elementAt(i); |
| 114 if (test(element)) return element; | 114 if (test(element)) return element; |
| 115 if (length != this.length) { | 115 if (length != this.length) { |
| 116 throw new ConcurrentModificationError(this); | 116 throw new ConcurrentModificationError(this); |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 if (orElse != null) return orElse(); | 119 if (orElse != null) return orElse(); |
| 120 throw new StateError("No matching element"); | 120 throw IterableElementError.noElement(); |
| 121 } | 121 } |
| 122 | 122 |
| 123 E singleWhere(bool test(E element)) { | 123 E singleWhere(bool test(E element)) { |
| 124 int length = this.length; | 124 int length = this.length; |
| 125 E match = null; | 125 E match = null; |
| 126 bool matchFound = false; | 126 bool matchFound = false; |
| 127 for (int i = 0; i < length; i++) { | 127 for (int i = 0; i < length; i++) { |
| 128 E element = elementAt(i); | 128 E element = elementAt(i); |
| 129 if (test(element)) { | 129 if (test(element)) { |
| 130 if (matchFound) { | 130 if (matchFound) { |
| 131 throw new StateError("More than one matching element"); | 131 throw IterableElementError.tooMany(); |
| 132 } | 132 } |
| 133 matchFound = true; | 133 matchFound = true; |
| 134 match = element; | 134 match = element; |
| 135 } | 135 } |
| 136 if (length != this.length) { | 136 if (length != this.length) { |
| 137 throw new ConcurrentModificationError(this); | 137 throw new ConcurrentModificationError(this); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 if (matchFound) return match; | 140 if (matchFound) return match; |
| 141 throw new StateError("No matching element"); | 141 throw IterableElementError.noElement(); |
| 142 } | 142 } |
| 143 | 143 |
| 144 String join([String separator = ""]) { | 144 String join([String separator = ""]) { |
| 145 int length = this.length; | 145 int length = this.length; |
| 146 if (!separator.isEmpty) { | 146 if (!separator.isEmpty) { |
| 147 if (length == 0) return ""; | 147 if (length == 0) return ""; |
| 148 String first = "${elementAt(0)}"; | 148 String first = "${elementAt(0)}"; |
| 149 if (length != this.length) { | 149 if (length != this.length) { |
| 150 throw new ConcurrentModificationError(this); | 150 throw new ConcurrentModificationError(this); |
| 151 } | 151 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 168 } | 168 } |
| 169 return buffer.toString(); | 169 return buffer.toString(); |
| 170 } | 170 } |
| 171 } | 171 } |
| 172 | 172 |
| 173 Iterable<E> where(bool test(E element)) => super.where(test); | 173 Iterable<E> where(bool test(E element)) => super.where(test); |
| 174 | 174 |
| 175 Iterable map(f(E element)) => new MappedListIterable(this, f); | 175 Iterable map(f(E element)) => new MappedListIterable(this, f); |
| 176 | 176 |
| 177 E reduce(E combine(var value, E element)) { | 177 E reduce(E combine(var value, E element)) { |
| 178 if (length == 0) throw new StateError("No elements"); | 178 if (length == 0) throw IterableElementError.noElement(); |
| 179 E value = elementAt(0); | 179 E value = elementAt(0); |
| 180 for (int i = 1; i < length; i++) { | 180 for (int i = 1; i < length; i++) { |
| 181 value = combine(value, elementAt(i)); | 181 value = combine(value, elementAt(i)); |
| 182 } | 182 } |
| 183 return value; | 183 return value; |
| 184 } | 184 } |
| 185 | 185 |
| 186 fold(var initialValue, combine(var previousValue, E element)) { | 186 fold(var initialValue, combine(var previousValue, E element)) { |
| 187 var value = initialValue; | 187 var value = initialValue; |
| 188 int length = this.length; | 188 int length = this.length; |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 const EmptyIterable(); | 654 const EmptyIterable(); |
| 655 | 655 |
| 656 Iterator<E> get iterator => const EmptyIterator(); | 656 Iterator<E> get iterator => const EmptyIterator(); |
| 657 | 657 |
| 658 void forEach(void action(E element)) {} | 658 void forEach(void action(E element)) {} |
| 659 | 659 |
| 660 bool get isEmpty => true; | 660 bool get isEmpty => true; |
| 661 | 661 |
| 662 int get length => 0; | 662 int get length => 0; |
| 663 | 663 |
| 664 E get first { throw new StateError("No elements"); } | 664 E get first { throw IterableElementError.noElement(); } |
| 665 | 665 |
| 666 E get last { throw new StateError("No elements"); } | 666 E get last { throw IterableElementError.noElement(); } |
| 667 | 667 |
| 668 E get single { throw new StateError("No elements"); } | 668 E get single { throw IterableElementError.noElement(); } |
| 669 | 669 |
| 670 E elementAt(int index) { throw new RangeError.value(index); } | 670 E elementAt(int index) { throw new RangeError.value(index); } |
| 671 | 671 |
| 672 bool contains(Object element) => false; | 672 bool contains(Object element) => false; |
| 673 | 673 |
| 674 bool every(bool test(E element)) => true; | 674 bool every(bool test(E element)) => true; |
| 675 | 675 |
| 676 bool any(bool test(E element)) => false; | 676 bool any(bool test(E element)) => false; |
| 677 | 677 |
| 678 E firstWhere(bool test(E element), { E orElse() }) { | 678 E firstWhere(bool test(E element), { E orElse() }) { |
| 679 if (orElse != null) return orElse(); | 679 if (orElse != null) return orElse(); |
| 680 throw new StateError("No matching element"); | 680 throw IterableElementError.noElement(); |
| 681 } | 681 } |
| 682 | 682 |
| 683 E lastWhere(bool test(E element), { E orElse() }) { | 683 E lastWhere(bool test(E element), { E orElse() }) { |
| 684 if (orElse != null) return orElse(); | 684 if (orElse != null) return orElse(); |
| 685 throw new StateError("No matching element"); | 685 throw IterableElementError.noElement(); |
| 686 } | 686 } |
| 687 | 687 |
| 688 E singleWhere(bool test(E element), { E orElse() }) { | 688 E singleWhere(bool test(E element), { E orElse() }) { |
| 689 if (orElse != null) return orElse(); | 689 if (orElse != null) return orElse(); |
| 690 throw new StateError("No matching element"); | 690 throw IterableElementError.noElement(); |
| 691 } | 691 } |
| 692 | 692 |
| 693 String join([String separator = ""]) => ""; | 693 String join([String separator = ""]) => ""; |
| 694 | 694 |
| 695 Iterable<E> where(bool test(E element)) => this; | 695 Iterable<E> where(bool test(E element)) => this; |
| 696 | 696 |
| 697 Iterable map(f(E element)) => const EmptyIterable(); | 697 Iterable map(f(E element)) => const EmptyIterable(); |
| 698 | 698 |
| 699 E reduce(E combine(E value, E element)) { | 699 E reduce(E combine(E value, E element)) { |
| 700 throw new StateError("No elements"); | 700 throw IterableElementError.noElement(); |
| 701 } | 701 } |
| 702 | 702 |
| 703 fold(var initialValue, combine(var previousValue, E element)) { | 703 fold(var initialValue, combine(var previousValue, E element)) { |
| 704 return initialValue; | 704 return initialValue; |
| 705 } | 705 } |
| 706 | 706 |
| 707 Iterable<E> skip(int count) { | 707 Iterable<E> skip(int count) { |
| 708 if (count < 0) throw new RangeError.value(count); | 708 if (count < 0) throw new RangeError.value(count); |
| 709 return this; | 709 return this; |
| 710 } | 710 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 static bool every(Iterable iterable, bool f(o)) { | 767 static bool every(Iterable iterable, bool f(o)) { |
| 768 for (final e in iterable) { | 768 for (final e in iterable) { |
| 769 if (!f(e)) return false; | 769 if (!f(e)) return false; |
| 770 } | 770 } |
| 771 return true; | 771 return true; |
| 772 } | 772 } |
| 773 | 773 |
| 774 static dynamic reduce(Iterable iterable, | 774 static dynamic reduce(Iterable iterable, |
| 775 dynamic combine(previousValue, element)) { | 775 dynamic combine(previousValue, element)) { |
| 776 Iterator iterator = iterable.iterator; | 776 Iterator iterator = iterable.iterator; |
| 777 if (!iterator.moveNext()) throw new StateError("No elements"); | 777 if (!iterator.moveNext()) throw IterableElementError.noElement(); |
| 778 var value = iterator.current; | 778 var value = iterator.current; |
| 779 while (iterator.moveNext()) { | 779 while (iterator.moveNext()) { |
| 780 value = combine(value, iterator.current); | 780 value = combine(value, iterator.current); |
| 781 } | 781 } |
| 782 return value; | 782 return value; |
| 783 } | 783 } |
| 784 | 784 |
| 785 static dynamic fold(Iterable iterable, | 785 static dynamic fold(Iterable iterable, |
| 786 dynamic initialValue, | 786 dynamic initialValue, |
| 787 dynamic combine(dynamic previousValue, element)) { | 787 dynamic combine(dynamic previousValue, element)) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 817 } | 817 } |
| 818 } | 818 } |
| 819 | 819 |
| 820 static bool isEmpty(Iterable iterable) { | 820 static bool isEmpty(Iterable iterable) { |
| 821 return !iterable.iterator.moveNext(); | 821 return !iterable.iterator.moveNext(); |
| 822 } | 822 } |
| 823 | 823 |
| 824 static dynamic first(Iterable iterable) { | 824 static dynamic first(Iterable iterable) { |
| 825 Iterator it = iterable.iterator; | 825 Iterator it = iterable.iterator; |
| 826 if (!it.moveNext()) { | 826 if (!it.moveNext()) { |
| 827 throw new StateError("No elements"); | 827 throw IterableElementError.noElement(); |
| 828 } | 828 } |
| 829 return it.current; | 829 return it.current; |
| 830 } | 830 } |
| 831 | 831 |
| 832 static dynamic last(Iterable iterable) { | 832 static dynamic last(Iterable iterable) { |
| 833 Iterator it = iterable.iterator; | 833 Iterator it = iterable.iterator; |
| 834 if (!it.moveNext()) { | 834 if (!it.moveNext()) { |
| 835 throw new StateError("No elements"); | 835 throw IterableElementError.noElement(); |
| 836 } | 836 } |
| 837 dynamic result; | 837 dynamic result; |
| 838 do { | 838 do { |
| 839 result = it.current; | 839 result = it.current; |
| 840 } while(it.moveNext()); | 840 } while(it.moveNext()); |
| 841 return result; | 841 return result; |
| 842 } | 842 } |
| 843 | 843 |
| 844 static dynamic single(Iterable iterable) { | 844 static dynamic single(Iterable iterable) { |
| 845 Iterator it = iterable.iterator; | 845 Iterator it = iterable.iterator; |
| 846 if (!it.moveNext()) throw new StateError("No elements"); | 846 if (!it.moveNext()) throw IterableElementError.noElement(); |
| 847 dynamic result = it.current; | 847 dynamic result = it.current; |
| 848 if (it.moveNext()) throw new StateError("More than one element"); | 848 if (it.moveNext()) throw IterableElementError.tooMany(); |
| 849 return result; | 849 return result; |
| 850 } | 850 } |
| 851 | 851 |
| 852 static dynamic firstWhere(Iterable iterable, | 852 static dynamic firstWhere(Iterable iterable, |
| 853 bool test(dynamic value), | 853 bool test(dynamic value), |
| 854 dynamic orElse()) { | 854 dynamic orElse()) { |
| 855 for (dynamic element in iterable) { | 855 for (dynamic element in iterable) { |
| 856 if (test(element)) return element; | 856 if (test(element)) return element; |
| 857 } | 857 } |
| 858 if (orElse != null) return orElse(); | 858 if (orElse != null) return orElse(); |
| 859 throw new StateError("No matching element"); | 859 throw IterableElementError.noElement(); |
| 860 } | 860 } |
| 861 | 861 |
| 862 static dynamic lastWhere(Iterable iterable, | 862 static dynamic lastWhere(Iterable iterable, |
| 863 bool test(dynamic value), | 863 bool test(dynamic value), |
| 864 dynamic orElse()) { | 864 dynamic orElse()) { |
| 865 dynamic result = null; | 865 dynamic result = null; |
| 866 bool foundMatching = false; | 866 bool foundMatching = false; |
| 867 for (dynamic element in iterable) { | 867 for (dynamic element in iterable) { |
| 868 if (test(element)) { | 868 if (test(element)) { |
| 869 result = element; | 869 result = element; |
| 870 foundMatching = true; | 870 foundMatching = true; |
| 871 } | 871 } |
| 872 } | 872 } |
| 873 if (foundMatching) return result; | 873 if (foundMatching) return result; |
| 874 if (orElse != null) return orElse(); | 874 if (orElse != null) return orElse(); |
| 875 throw new StateError("No matching element"); | 875 throw IterableElementError.noElement(); |
| 876 } | 876 } |
| 877 | 877 |
| 878 static dynamic lastWhereList(List list, | 878 static dynamic lastWhereList(List list, |
| 879 bool test(dynamic value), | 879 bool test(dynamic value), |
| 880 dynamic orElse()) { | 880 dynamic orElse()) { |
| 881 // TODO(floitsch): check that arguments are of correct type? | 881 // TODO(floitsch): check that arguments are of correct type? |
| 882 for (int i = list.length - 1; i >= 0; i--) { | 882 for (int i = list.length - 1; i >= 0; i--) { |
| 883 dynamic element = list[i]; | 883 dynamic element = list[i]; |
| 884 if (test(element)) return element; | 884 if (test(element)) return element; |
| 885 } | 885 } |
| 886 if (orElse != null) return orElse(); | 886 if (orElse != null) return orElse(); |
| 887 throw new StateError("No matching element"); | 887 throw IterableElementError.noElement(); |
| 888 } | 888 } |
| 889 | 889 |
| 890 static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) { | 890 static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) { |
| 891 dynamic result = null; | 891 dynamic result = null; |
| 892 bool foundMatching = false; | 892 bool foundMatching = false; |
| 893 for (dynamic element in iterable) { | 893 for (dynamic element in iterable) { |
| 894 if (test(element)) { | 894 if (test(element)) { |
| 895 if (foundMatching) { | 895 if (foundMatching) { |
| 896 throw new StateError("More than one matching element"); | 896 throw IterableElementError.tooMany(); |
| 897 } | 897 } |
| 898 result = element; | 898 result = element; |
| 899 foundMatching = true; | 899 foundMatching = true; |
| 900 } | 900 } |
| 901 } | 901 } |
| 902 if (foundMatching) return result; | 902 if (foundMatching) return result; |
| 903 throw new StateError("No matching element"); | 903 throw IterableElementError.noElement(); |
| 904 } | 904 } |
| 905 | 905 |
| 906 static dynamic elementAt(Iterable iterable, int index) { | 906 static dynamic elementAt(Iterable iterable, int index) { |
| 907 if (index is! int || index < 0) throw new RangeError.value(index); | 907 if (index is! int || index < 0) throw new RangeError.value(index); |
| 908 int remaining = index; | 908 int remaining = index; |
| 909 for (dynamic element in iterable) { | 909 for (dynamic element in iterable) { |
| 910 if (remaining == 0) return element; | 910 if (remaining == 0) return element; |
| 911 remaining--; | 911 remaining--; |
| 912 } | 912 } |
| 913 throw new RangeError.value(index); | 913 throw new RangeError.value(index); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 List otherList; | 1051 List otherList; |
| 1052 int otherStart; | 1052 int otherStart; |
| 1053 if (from is List) { | 1053 if (from is List) { |
| 1054 otherList = from; | 1054 otherList = from; |
| 1055 otherStart = skipCount; | 1055 otherStart = skipCount; |
| 1056 } else { | 1056 } else { |
| 1057 otherList = from.skip(skipCount).toList(growable: false); | 1057 otherList = from.skip(skipCount).toList(growable: false); |
| 1058 otherStart = 0; | 1058 otherStart = 0; |
| 1059 } | 1059 } |
| 1060 if (otherStart + length > otherList.length) { | 1060 if (otherStart + length > otherList.length) { |
| 1061 throw new StateError("Not enough elements"); | 1061 throw IterableElementError.tooFew(); |
| 1062 } | 1062 } |
| 1063 Lists.copy(otherList, otherStart, list, start, length); | 1063 Lists.copy(otherList, otherStart, list, start, length); |
| 1064 } | 1064 } |
| 1065 | 1065 |
| 1066 static void replaceRangeList(List list, int start, int end, | 1066 static void replaceRangeList(List list, int start, int end, |
| 1067 Iterable iterable) { | 1067 Iterable iterable) { |
| 1068 _rangeCheck(list, start, end); | 1068 _rangeCheck(list, start, end); |
| 1069 if (iterable is! EfficientLength) { | 1069 if (iterable is! EfficientLength) { |
| 1070 iterable = iterable.toList(); | 1070 iterable = iterable.toList(); |
| 1071 } | 1071 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 | 1158 |
| 1159 static Set setDifference(Set set, Set other, Set result) { | 1159 static Set setDifference(Set set, Set other, Set result) { |
| 1160 for (var element in set) { | 1160 for (var element in set) { |
| 1161 if (!other.contains(element)) { | 1161 if (!other.contains(element)) { |
| 1162 result.add(element); | 1162 result.add(element); |
| 1163 } | 1163 } |
| 1164 } | 1164 } |
| 1165 return result; | 1165 return result; |
| 1166 } | 1166 } |
| 1167 } | 1167 } |
| 1168 |
| 1169 /** |
| 1170 * Creates errors throw by [Iterable] when the element count is wrong. |
| 1171 */ |
| 1172 abstract class IterableElementError { |
| 1173 /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ |
| 1174 static StateError noElement() => new StateError("No element"); |
| 1175 /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ |
| 1176 static StateError tooMany() => new StateError("Too many elements"); |
| 1177 /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ |
| 1178 static StateError tooFew() => new StateError("Too few elements"); |
| 1179 } |
| OLD | NEW |