Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(715)

Side by Side Diff: sdk/lib/_collection_dev/list.dart

Issue 13774006: Moving ListBase, FixedLengthListMixin and UmodifiableListMixin to collection. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Moved ReversedListIterable back to collection-dev Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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.dev; 5 part of dart._collection.dev;
6 6
7 /** 7 /**
8 * Base implementation of a [List] class.
9 *
10 * This class can be used as a mixin.
11 *
12 * This implements all read operations using only the `length` and
13 * `operator[]` members. It implements write operations using those and
14 * `length=` and `operator[]=`
15 *
16 * A fixed-length list should mix this class in, and the [FixedLengthListMixin]
17 * as well, in that order, to overwrite the methods that modify the length.
18 *
19 * An unmodifiable list should mix [UnmodifiableListMixin] on top of this
20 * mixin to prevent all modifications.
21 */
22 abstract class ListMixin<E> implements List<E> {
23 // Iterable interface.
24 Iterator<E> get iterator => new ListIterator<E>(this);
25
26 E elementAt(int index) => this[index];
27
28 void forEach(void action(E element)) {
29 int length = this.length;
30 for (int i = 0; i < length; i++) {
31 action(this[i]);
32 if (length != this.length) {
33 throw new ConcurrentModificationError(this);
34 }
35 }
36 }
37
38 bool get isEmpty => length == 0;
39
40 E get first {
41 if (length == 0) throw new StateError("No elements");
42 return this[0];
43 }
44
45 E get last {
46 if (length == 0) throw new StateError("No elements");
47 return this[length - 1];
48 }
49
50 E get single {
51 if (length == 0) throw new StateError("No elements");
52 if (length > 1) throw new StateError("Too many elements");
53 return this[0];
54 }
55
56 bool contains(E element) {
57 int length = this.length;
58 for (int i = 0; i < length; i++) {
59 if (this[i] == element) return true;
60 if (length != this.length) {
61 throw new ConcurrentModificationError(this);
62 }
63 }
64 return false;
65 }
66
67 bool every(bool test(E element)) {
68 int length = this.length;
69 for (int i = 0; i < length; i++) {
70 if (!test(this[i])) return false;
71 if (length != this.length) {
72 throw new ConcurrentModificationError(this);
73 }
74 }
75 return true;
76 }
77
78 bool any(bool test(E element)) {
79 int length = this.length;
80 for (int i = 0; i < length; i++) {
81 if (test(this[i])) return true;
82 if (length != this.length) {
83 throw new ConcurrentModificationError(this);
84 }
85 }
86 return false;
87 }
88
89 E firstWhere(bool test(E element), { E orElse() }) {
90 int length = this.length;
91 for (int i = 0; i < length; i++) {
92 E element = this[i];
93 if (test(element)) return element;
94 if (length != this.length) {
95 throw new ConcurrentModificationError(this);
96 }
97 }
98 if (orElse != null) return orElse();
99 throw new StateError("No matching element");
100 }
101
102 E lastWhere(bool test(E element), { E orElse() }) {
103 int length = this.length;
104 for (int i = length - 1; i >= 0; i--) {
105 E element = this[i];
106 if (test(element)) return element;
107 if (length != this.length) {
108 throw new ConcurrentModificationError(this);
109 }
110 }
111 if (orElse != null) return orElse();
112 throw new StateError("No matching element");
113 }
114
115 E singleWhere(bool test(E element)) {
116 int length = this.length;
117 E match = null;
118 bool matchFound = false;
119 for (int i = 0; i < length; i++) {
120 E element = this[i];
121 if (test(element)) {
122 if (matchFound) {
123 throw new StateError("More than one matching element");
124 }
125 matchFound = true;
126 match = element;
127 }
128 if (length != this.length) {
129 throw new ConcurrentModificationError(this);
130 }
131 }
132 if (matchFound) return match;
133 throw new StateError("No matching element");
134 }
135
136 E min([int compare(E a, E b)]) {
137 if (length == 0) return null;
138 if (compare == null) {
139 var defaultCompare = Comparable.compare;
140 compare = defaultCompare;
141 }
142 E min = this[0];
143 int length = this.length;
144 for (int i = 1; i < length; i++) {
145 E element = this[i];
146 if (compare(min, element) > 0) {
147 min = element;
148 }
149 if (length != this.length) {
150 throw new ConcurrentModificationError(this);
151 }
152 }
153 return min;
154 }
155
156 E max([int compare(E a, E b)]) {
157 if (length == 0) return null;
158 if (compare == null) {
159 var defaultCompare = Comparable.compare;
160 compare = defaultCompare;
161 }
162 E max = this[0];
163 int length = this.length;
164 for (int i = 1; i < length; i++) {
165 E element = this[i];
166 if (compare(max, element) < 0) {
167 max = element;
168 }
169 if (length != this.length) {
170 throw new ConcurrentModificationError(this);
171 }
172 }
173 return max;
174 }
175
176 String join([String separator]) {
177 int length = this.length;
178 if (separator != null && !separator.isEmpty) {
179 if (length == 0) return "";
180 String first = "${this[0]}";
181 if (length != this.length) {
182 throw new ConcurrentModificationError(this);
183 }
184 StringBuffer buffer = new StringBuffer(first);
185 for (int i = 1; i < length; i++) {
186 buffer.write(separator);
187 buffer.write("${this[i]}");
188 if (length != this.length) {
189 throw new ConcurrentModificationError(this);
190 }
191 }
192 return buffer.toString();
193 } else {
194 StringBuffer buffer = new StringBuffer();
195 for (int i = 0; i < length; i++) {
196 buffer.write("${this[i]}");
197 if (length != this.length) {
198 throw new ConcurrentModificationError(this);
199 }
200 }
201 return buffer.toString();
202 }
203 }
204
205 Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
206
207 Iterable map(f(E element)) => new MappedListIterable(this, f);
208
209 reduce(var initialValue, combine(var previousValue, E element)) {
210 return fold(initialValue, combine);
211 }
212
213 fold(var initialValue, combine(var previousValue, E element)) {
214 var value = initialValue;
215 int length = this.length;
216 for (int i = 0; i < length; i++) {
217 value = combine(value, this[i]);
218 if (length != this.length) {
219 throw new ConcurrentModificationError(this);
220 }
221 }
222 return value;
223 }
224
225 Iterable<E> skip(int count) => new SubListIterable(this, count, null);
226
227 Iterable<E> skipWhile(bool test(E element)) {
228 return new SkipWhileIterable<E>(this, test);
229 }
230
231 Iterable<E> take(int count) => new SubListIterable(this, 0, count);
232
233 Iterable<E> takeWhile(bool test(E element)) {
234 return new TakeWhileIterable<E>(this, test);
235 }
236
237 List<E> toList({ bool growable: true }) {
238 List<E> result;
239 if (growable) {
240 result = new List<E>()..length = length;
241 } else {
242 result = new List<E>(length);
243 }
244 for (int i = 0; i < length; i++) {
245 result[i] = this[i];
246 }
247 return result;
248 }
249
250 Set<E> toSet() {
251 Set<E> result = new Set<E>();
252 for (int i = 0; i < length; i++) {
253 result.add(this[i]);
254 }
255 return result;
256 }
257
258 // Collection interface.
259 void add(E element) {
260 this[this.length++] = element;
261 }
262
263 void addAll(Iterable<E> iterable) {
264 for (E element in iterable) {
265 this[this.length++] = element;
266 }
267 }
268
269 void remove(Object element) {
270 for (int i = 0; i < this.length; i++) {
271 if (this[i] == element) {
272 this.setRange(i, this.length - i - 1, this, i + 1);
273 this.length -= 1;
274 return;
275 }
276 }
277 }
278
279 void removeAll(Iterable<Object> elements) {
280 if (elements is! Set) {
281 elements = elements.toSet();
282 }
283 _filter(this, elements.contains, false);
284 }
285
286
287 void retainAll(Iterable<E> iterable) {
288 if (elements is! Set) {
289 elements = elements.toSet();
290 }
291 _filter(this, elements.contains, true);
292 }
293
294 void removeWhere(bool test(E element)) {
295 _filter(this, test, false);
296 }
297
298 void retainWhere(bool test(E element)) {
299 _filter(this, test, true);
300 }
301
302 static void _filter(List source,
303 bool test(var element),
304 bool retainMatching) {
305 List retained = [];
306 int length = source.length;
307 for (int i = 0; i < length; i++) {
308 var element = source[i];
309 if (test(element) == retainMatching) {
310 retained.add(element);
311 }
312 if (length != source.length) {
313 throw new ConcurrentModificationError(source);
314 }
315 }
316 if (retained.length != source.length) {
317 source.setRange(0, retained.length, retained);
318 source.length = retained.length;
319 }
320 }
321
322 // List interface.
323
324 void sort([Comparator<E> compare]) {
325 Sort.sort(this, compare);
326 }
327
328 Map<int, E> asMap() {
329 return new ListMapView(this);
330 }
331
332 List<E> sublist(int start, [int end]) {
333 if (end == null) end = length;
334 if (start < 0 || start > this.length) {
335 throw new RangeError.range(start, 0, this.length);
336 }
337 if (end < start || end > this.length) {
338 throw new RangeError.range(end, start, this.length);
339 }
340 int length = end - start;
341 List<E> result = new List<E>()..length = length;
342 for (int i = 0; i < length; i++) {
343 result[i] = this[start + i];
344 }
345 return result;
346 }
347
348 List<E> getRange(int start, int length) => sublist(start, start + length);
349
350 void insertRange(int start, int length, [E initialValue]) {
351 if (start < 0 || start > this.length) {
352 throw new RangeError.range(start, 0, this.length);
353 }
354 int oldLength = this.length;
355 int moveLength = oldLength - start;
356 this.length += length;
357 if (moveLength > 0) {
358 this.setRange(start + length, moveLength, this, start);
359 }
360 for (int i = 0; i < length; i++) {
361 this[start + i] = initialValue;
362 }
363 }
364
365 void removeRange(int start, int length) {
366 if (start < 0 || start > this.length) {
367 throw new RangeError.range(start, 0, this.length);
368 }
369 if (length < 0 || start + length > this.length) {
370 throw new RangeError.range(length, 0, this.length - start);
371 }
372 int end = start + length;
373 setRange(start, this.length - end, this, end);
374 this.length -= length;
375 }
376
377 void clearRange(int start, int length, [E fill]) {
378 for (int i = 0; i < length; i++) {
379 this[start + i] = fill;
380 }
381 }
382
383 void setRange(int start, int length, List<E> from, [int startFrom]) {
384 if (start < 0 || start > this.length) {
385 throw new RangeError.range(start, 0, this.length);
386 }
387 if (length < 0 || start + length > this.length) {
388 throw new RangeError.range(length, 0, this.length - start);
389 }
390 if (startFrom == null) {
391 startFrom = 0;
392 }
393 if (startFrom < 0 || startFrom + length > from.length) {
394 throw new RangeError.range(startFrom, 0, from.length - length);
395 }
396 if (startFrom < start) {
397 // Copy backwards to ensure correct copy if [from] is this.
398 for (int i = length - 1; i >= 0; i--) {
399 this[start + i] = from[startFrom + i];
400 }
401 } else {
402 for (int i = 0; i < length; i++) {
403 this[start + i] = from[startFrom + i];
404 }
405 }
406 }
407
408 int indexOf(E element, [int startIndex = 0]) {
409 if (startIndex >= this.length) {
410 return -1;
411 }
412 if (startIndex < 0) {
413 startIndex = 0;
414 }
415 for (int i = startIndex; i < this.length; i++) {
416 if (this[i] == element) {
417 return i;
418 }
419 }
420 return -1;
421 }
422
423 /**
424 * Returns the last index in the list [a] of the given [element], starting
425 * the search at index [startIndex] to 0.
426 * Returns -1 if [element] is not found.
427 */
428 int lastIndexOf(E element, [int startIndex]) {
429 if (startIndex == null) {
430 startIndex = this.length - 1;
431 } else {
432 if (startIndex < 0) {
433 return -1;
434 }
435 if (startIndex >= a.length) {
436 startIndex = a.length - 1;
437 }
438 }
439 for (int i = startIndex; i >= 0; i--) {
440 if (this[i] == element) {
441 return i;
442 }
443 }
444 return -1;
445 }
446
447 Iterable<E> get reversed => new ReversedListIterable(this);
448 }
449
450 /**
451 * Mixin that throws on the length changing operations of [List]. 8 * Mixin that throws on the length changing operations of [List].
452 * 9 *
453 * Intended to mix-in on top of [ListMixin] for fixed-length lists. 10 * Intended to mix-in on top of [ListMixin] for fixed-length lists.
454 */ 11 */
455 abstract class FixedLengthListMixin<E> { 12 abstract class FixedLengthListMixin<E> {
456 void set length(int newLength) { 13 void set length(int newLength) {
457 throw new UnsupportedError( 14 throw new UnsupportedError(
458 "Cannot change the length of a fixed-length list"); 15 "Cannot change the length of a fixed-length list");
459 } 16 }
460 17
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 throw new UnsupportedError( 169 throw new UnsupportedError(
613 "Cannot remove from an unmodifiable list"); 170 "Cannot remove from an unmodifiable list");
614 } 171 }
615 172
616 void insertRange(int start, int length, [E initialValue]) { 173 void insertRange(int start, int length, [E initialValue]) {
617 throw new UnsupportedError( 174 throw new UnsupportedError(
618 "Cannot insert range in an unmodifiable list"); 175 "Cannot insert range in an unmodifiable list");
619 } 176 }
620 } 177 }
621 178
622
623 /**
624 * Abstract implementation of a list.
625 *
626 * All operations are defined in terms of `length`, `operator[]`,
627 * `operator[]=` and `length=`, which need to be implemented.
628 */
629 abstract class ListBase<E> extends ListMixin<E> implements List<E> {}
630
631 /** 179 /**
632 * Abstract implementation of a fixed-length list. 180 * Abstract implementation of a fixed-length list.
633 * 181 *
634 * All operations are defined in terms of `length`, `operator[]` and 182 * All operations are defined in terms of `length`, `operator[]` and
635 * `operator[]=`, which need to be implemented. 183 * `operator[]=`, which need to be implemented.
636 */ 184 */
637 abstract class FixedLengthListBase<E> extends ListBase<E> 185 typedef FixedLengthListBase<E> = ListBase<E> with FixedLengthListMixin<E>;
638 with FixedLengthListMixin<E> {}
639 186
640 /** 187 /**
641 * Abstract implementation of an unmodifiable list. 188 * Abstract implementation of an unmodifiable list.
642 * 189 *
643 * All operations are defined in terms of `length` and `operator[]`, 190 * All operations are defined in terms of `length` and `operator[]`,
644 * which need to be implemented. 191 * which need to be implemented.
645 */ 192 */
646 abstract class UnmodifiableListBase<E> extends ListBase<E> 193 typedef UnmodifiableListBase<E> = ListBase<E> with UnmodifiableListMixin<E>;
647 with UnmodifiableListMixin<E> {}
648
649 /** An empty fixed-length (and therefore unmodifiable) list. */
650 class EmptyList<E> extends FixedLengthListBase<E> {
651 int get length => 0;
652 E operator[](int index) { throw new RangeError.value(index); }
653 void operator []=(int index, E value) { throw new RangeError.value(index); }
654 Iterable<E> skip(int count) => const EmptyIterable();
655 Iterable<E> take(int count) => const EmptyIterable();
656 Iterable<E> get reversed => const EmptyIterable();
657 void sort([int compare(E a, E b)]) {}
658 }
659
660 class ReversedListIterable<E> extends ListIterable<E> {
661 Iterable<E> _source;
662 ReversedListIterable(this._source);
663
664 int get length => _source.length;
665
666 E elementAt(int index) => _source.elementAt(_source.length - 1 - index);
667 }
668
669 /**
670 * An [Iterable] of the UTF-16 code units of a [String] in index order.
671 */
672 class CodeUnits extends UnmodifiableListBase<int> {
673 /** The string that this is the code units of. */
674 String _string;
675
676 CodeUnits(this._string);
677
678 int get length => _string.length;
679 int operator[](int i) => _string.codeUnitAt(i);
680 }
681 194
682 class _ListIndicesIterable extends ListIterable<int> { 195 class _ListIndicesIterable extends ListIterable<int> {
683 List _backedList; 196 List _backedList;
684 197
685 _ListIndicesIterable(this._backedList); 198 _ListIndicesIterable(this._backedList);
686 199
687 int get length => _backedList.length; 200 int get length => _backedList.length;
688 int elementAt(int index) { 201 int elementAt(int index) {
689 if (index < 0 || index >= length) { 202 if (index < 0 || index >= length) {
690 throw new RangeError.range(index, 0, length); 203 throw new RangeError.range(index, 0, length);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 } 240 }
728 241
729 E remove(int key) { 242 E remove(int key) {
730 throw new UnsupportedError("Cannot modify an unmodifiable map"); 243 throw new UnsupportedError("Cannot modify an unmodifiable map");
731 } 244 }
732 245
733 void clear() { 246 void clear() {
734 throw new UnsupportedError("Cannot modify an unmodifiable map"); 247 throw new UnsupportedError("Cannot modify an unmodifiable map");
735 } 248 }
736 } 249 }
250
251 class ReversedListIterable<E> extends ListIterable<E> {
252 Iterable<E> _source;
253 ReversedListIterable(this._source);
254
255 int get length => _source.length;
256
257 E elementAt(int index) => _source.elementAt(_source.length - 1 - index);
258 }
OLDNEW
« no previous file with comments | « sdk/lib/_collection_dev/collection_dev.dart ('k') | sdk/lib/_internal/compiler/implementation/lib/js_string.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698