Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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; | 5 part of dart.collection; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Abstract implementation of a list. | 8 * Abstract implementation of a list. |
| 9 * | 9 * |
| 10 * `ListBase` can be used as a base class for implementing the `List` interface. | 10 * `ListBase` can be used as a base class for implementing the `List` interface. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 throw new ConcurrentModificationError(this); | 65 throw new ConcurrentModificationError(this); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 bool get isEmpty => length == 0; | 70 bool get isEmpty => length == 0; |
| 71 | 71 |
| 72 bool get isNotEmpty => !isEmpty; | 72 bool get isNotEmpty => !isEmpty; |
| 73 | 73 |
| 74 E get first { | 74 E get first { |
| 75 if (length == 0) throw new StateError("No elements"); | 75 if (length == 0) throw IterableElementError.noElement(); |
| 76 return this[0]; | 76 return this[0]; |
| 77 } | 77 } |
| 78 | 78 |
| 79 E get last { | 79 E get last { |
| 80 if (length == 0) throw new StateError("No elements"); | 80 if (length == 0) throw IterableElementError.noElement(); |
| 81 return this[length - 1]; | 81 return this[length - 1]; |
| 82 } | 82 } |
| 83 | 83 |
| 84 E get single { | 84 E get single { |
| 85 if (length == 0) throw new StateError("No elements"); | 85 if (length == 0) throw IterableElementError.noElement(); |
| 86 if (length > 1) throw new StateError("Too many elements"); | 86 if (length > 1) throw IterableElementError.tooMany(); |
| 87 return this[0]; | 87 return this[0]; |
| 88 } | 88 } |
| 89 | 89 |
| 90 bool contains(Object element) { | 90 bool contains(Object element) { |
| 91 int length = this.length; | 91 int length = this.length; |
| 92 for (int i = 0; i < this.length; i++) { | 92 for (int i = 0; i < this.length; i++) { |
| 93 if (this[i] == element) return true; | 93 if (this[i] == element) return true; |
| 94 if (length != this.length) { | 94 if (length != this.length) { |
| 95 throw new ConcurrentModificationError(this); | 95 throw new ConcurrentModificationError(this); |
| 96 } | 96 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 123 dynamic firstWhere(bool test(E element), { Object orElse() }) { | 123 dynamic firstWhere(bool test(E element), { Object orElse() }) { |
| 124 int length = this.length; | 124 int length = this.length; |
| 125 for (int i = 0; i < length; i++) { | 125 for (int i = 0; i < length; i++) { |
| 126 E element = this[i]; | 126 E element = this[i]; |
| 127 if (test(element)) return element; | 127 if (test(element)) return element; |
| 128 if (length != this.length) { | 128 if (length != this.length) { |
| 129 throw new ConcurrentModificationError(this); | 129 throw new ConcurrentModificationError(this); |
| 130 } | 130 } |
| 131 } | 131 } |
| 132 if (orElse != null) return orElse(); | 132 if (orElse != null) return orElse(); |
| 133 throw new StateError("No matching element"); | 133 throw IterableElementError.noElement(); |
| 134 } | 134 } |
| 135 | 135 |
| 136 dynamic lastWhere(bool test(E element), { Object orElse() }) { | 136 dynamic lastWhere(bool test(E element), { Object orElse() }) { |
| 137 int length = this.length; | 137 int length = this.length; |
| 138 for (int i = length - 1; i >= 0; i--) { | 138 for (int i = length - 1; i >= 0; i--) { |
| 139 E element = this[i]; | 139 E element = this[i]; |
| 140 if (test(element)) return element; | 140 if (test(element)) return element; |
| 141 if (length != this.length) { | 141 if (length != this.length) { |
| 142 throw new ConcurrentModificationError(this); | 142 throw new ConcurrentModificationError(this); |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 if (orElse != null) return orElse(); | 145 if (orElse != null) return orElse(); |
| 146 throw new StateError("No matching element"); | 146 throw IterableElementError.noElement(); |
| 147 } | 147 } |
| 148 | 148 |
| 149 E singleWhere(bool test(E element)) { | 149 E singleWhere(bool test(E element)) { |
| 150 int length = this.length; | 150 int length = this.length; |
| 151 E match = null; | 151 E match = null; |
| 152 bool matchFound = false; | 152 bool matchFound = false; |
| 153 for (int i = 0; i < length; i++) { | 153 for (int i = 0; i < length; i++) { |
| 154 E element = this[i]; | 154 E element = this[i]; |
| 155 if (test(element)) { | 155 if (test(element)) { |
| 156 if (matchFound) { | 156 if (matchFound) { |
| 157 throw new StateError("More than one matching element"); | 157 throw IterableElementError.tooMany(); |
| 158 } | 158 } |
| 159 matchFound = true; | 159 matchFound = true; |
| 160 match = element; | 160 match = element; |
| 161 } | 161 } |
| 162 if (length != this.length) { | 162 if (length != this.length) { |
| 163 throw new ConcurrentModificationError(this); | 163 throw new ConcurrentModificationError(this); |
| 164 } | 164 } |
| 165 } | 165 } |
| 166 if (matchFound) return match; | 166 if (matchFound) return match; |
| 167 throw new StateError("No matching element"); | 167 throw IterableElementError.noElement(); |
| 168 } | 168 } |
| 169 | 169 |
| 170 String join([String separator = ""]) { | 170 String join([String separator = ""]) { |
| 171 if (length == 0) return ""; | 171 if (length == 0) return ""; |
| 172 StringBuffer buffer = new StringBuffer()..writeAll(this, separator); | 172 StringBuffer buffer = new StringBuffer()..writeAll(this, separator); |
| 173 return buffer.toString(); | 173 return buffer.toString(); |
| 174 } | 174 } |
| 175 | 175 |
| 176 Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); | 176 Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); |
| 177 | 177 |
| 178 Iterable map(f(E element)) => new MappedListIterable(this, f); | 178 Iterable map(f(E element)) => new MappedListIterable(this, f); |
| 179 | 179 |
| 180 Iterable expand(Iterable f(E element)) => | 180 Iterable expand(Iterable f(E element)) => |
| 181 new ExpandIterable<E, dynamic>(this, f); | 181 new ExpandIterable<E, dynamic>(this, f); |
| 182 | 182 |
| 183 E reduce(E combine(E previousValue, E element)) { | 183 E reduce(E combine(E previousValue, E element)) { |
| 184 if (length == 0) throw new StateError("No elements"); | 184 int length = this.length; |
| 185 if (length == 0) throw IterableElementError.noElement(); | |
| 185 E value = this[0]; | 186 E value = this[0]; |
| 186 for (int i = 1; i < length; i++) { | 187 for (int i = 1; i < length; i++) { |
| 187 value = combine(value, this[i]); | 188 value = combine(value, this[i]); |
| 189 if (length != this.length) { | |
|
Anders Johnsen
2014/10/14 09:08:24
Can this be changed to only check at end?
Lasse Reichstein Nielsen
2014/10/14 09:12:05
Not really. We check for non-change after each cal
| |
| 190 throw new ConcurrentModificationError(this); | |
| 191 } | |
| 188 } | 192 } |
| 189 return value; | 193 return value; |
| 190 } | 194 } |
| 191 | 195 |
| 192 fold(var initialValue, combine(var previousValue, E element)) { | 196 fold(var initialValue, combine(var previousValue, E element)) { |
| 193 var value = initialValue; | 197 var value = initialValue; |
| 194 int length = this.length; | 198 int length = this.length; |
| 195 for (int i = 0; i < length; i++) { | 199 for (int i = 0; i < length; i++) { |
| 196 value = combine(value, this[i]); | 200 value = combine(value, this[i]); |
| 197 if (length != this.length) { | 201 if (length != this.length) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 source.length = retained.length; | 287 source.length = retained.length; |
| 284 } | 288 } |
| 285 } | 289 } |
| 286 | 290 |
| 287 void clear() { this.length = 0; } | 291 void clear() { this.length = 0; } |
| 288 | 292 |
| 289 // List interface. | 293 // List interface. |
| 290 | 294 |
| 291 E removeLast() { | 295 E removeLast() { |
| 292 if (length == 0) { | 296 if (length == 0) { |
| 293 throw new StateError("No elements"); | 297 throw IterableElementError.noElement(); |
| 294 } | 298 } |
| 295 E result = this[length - 1]; | 299 E result = this[length - 1]; |
| 296 length--; | 300 length--; |
| 297 return result; | 301 return result; |
| 298 } | 302 } |
| 299 | 303 |
| 300 void sort([int compare(E a, E b)]) { | 304 void sort([int compare(E a, E b)]) { |
| 301 if (compare == null) { | 305 if (compare == null) { |
| 302 var defaultCompare = Comparable.compare; | 306 var defaultCompare = Comparable.compare; |
| 303 compare = defaultCompare; | 307 compare = defaultCompare; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 int otherStart; | 375 int otherStart; |
| 372 // TODO(floitsch): Make this accept more. | 376 // TODO(floitsch): Make this accept more. |
| 373 if (iterable is List) { | 377 if (iterable is List) { |
| 374 otherList = iterable; | 378 otherList = iterable; |
| 375 otherStart = skipCount; | 379 otherStart = skipCount; |
| 376 } else { | 380 } else { |
| 377 otherList = iterable.skip(skipCount).toList(growable: false); | 381 otherList = iterable.skip(skipCount).toList(growable: false); |
| 378 otherStart = 0; | 382 otherStart = 0; |
| 379 } | 383 } |
| 380 if (otherStart + length > otherList.length) { | 384 if (otherStart + length > otherList.length) { |
| 381 throw new StateError("Not enough elements"); | 385 throw IterableElementError.tooFew(); |
| 382 } | 386 } |
| 383 if (otherStart < start) { | 387 if (otherStart < start) { |
| 384 // Copy backwards to ensure correct copy if [from] is this. | 388 // Copy backwards to ensure correct copy if [from] is this. |
| 385 for (int i = length - 1; i >= 0; i--) { | 389 for (int i = length - 1; i >= 0; i--) { |
| 386 this[start + i] = otherList[otherStart + i]; | 390 this[start + i] = otherList[otherStart + i]; |
| 387 } | 391 } |
| 388 } else { | 392 } else { |
| 389 for (int i = 0; i < length; i++) { | 393 for (int i = 0; i < length; i++) { |
| 390 this[start + i] = otherList[otherStart + i]; | 394 this[start + i] = otherList[otherStart + i]; |
| 391 } | 395 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 for (E element in iterable) { | 508 for (E element in iterable) { |
| 505 this[index++] = element; | 509 this[index++] = element; |
| 506 } | 510 } |
| 507 } | 511 } |
| 508 } | 512 } |
| 509 | 513 |
| 510 Iterable<E> get reversed => new ReversedListIterable(this); | 514 Iterable<E> get reversed => new ReversedListIterable(this); |
| 511 | 515 |
| 512 String toString() => IterableBase.iterableToFullString(this, '[', ']'); | 516 String toString() => IterableBase.iterableToFullString(this, '[', ']'); |
| 513 } | 517 } |
| OLD | NEW |