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 |