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.dev; | 5 part of dart._collection.dev; |
6 | 6 |
7 /** | 7 /** |
8 * Class implementing the read-operations on [List]. | 8 * Class implementing the read-operations on [List]. |
9 * | 9 * |
10 * Implements all read-only operations, except [:operator[]:] and [:length:], | 10 * Implements all read-only operations, except [:operator[]:] and [:length:], |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 for (int i = 0; i < length; i++) { | 90 for (int i = 0; i < length; i++) { |
91 result.add(this[start + i]); | 91 result.add(this[start + i]); |
92 } | 92 } |
93 return result; | 93 return result; |
94 } | 94 } |
95 | 95 |
96 Iterable map(f(E element)) { | 96 Iterable map(f(E element)) { |
97 return new MappedIterable(this, f); | 97 return new MappedIterable(this, f); |
98 } | 98 } |
99 | 99 |
100 List mappedBy(f(E element)) { | 100 Iterable<E> take(int n) { |
101 return new MappedList(this, f); | 101 return new SubListIterable(this, 0, n); |
102 } | 102 } |
103 | 103 |
104 List<E> take(int n) { | 104 Iterable<E> skip(int n) { |
105 return new ListView(this, 0, n); | 105 return new SubListIterable(this, n, null); |
106 } | 106 } |
107 | 107 |
108 List<E> skip(int n) { | 108 Iterable<E> get reversed => new ReversedListIterable(this); |
109 return new ListView(this, n, null); | |
110 } | |
111 | 109 |
112 String toString() => ToString.collectionToString(this); | 110 String toString() => ToString.collectionToString(this); |
113 | |
114 List<E> get reversed { | |
115 return new ReversedListView(this, 0, null); | |
116 } | |
117 } | 111 } |
118 | 112 |
119 /** | 113 /** |
120 * Abstract class implementing the non-length changing operations of [List]. | 114 * Abstract class implementing the non-length changing operations of [List]. |
| 115 * |
| 116 * All modifications are performed using [[]=]. |
121 */ | 117 */ |
122 abstract class FixedLengthListBase<E> extends ListBase<E> { | 118 abstract class FixedLengthListBase<E> extends ListBase<E> { |
123 void operator[]=(int index, E value); | 119 void operator[]=(int index, E value); |
124 | 120 |
125 void sort([Comparator<E> compare]) { | 121 void sort([Comparator<E> compare]) { |
126 Sort.sort(this, compare); | 122 Sort.sort(this, compare); |
127 } | 123 } |
128 | 124 |
129 void setRange(int start, int length, List<E> from, [int startFrom]) { | 125 void setRange(int start, int length, List<E> from, [int startFrom]) { |
130 if (length < 0) throw new ArgumentError("length: $length"); | 126 if (length < 0) throw new ArgumentError("length: $length"); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 throw new UnsupportedError( | 275 throw new UnsupportedError( |
280 "Cannot remove from an unmodifiable list"); | 276 "Cannot remove from an unmodifiable list"); |
281 } | 277 } |
282 | 278 |
283 void insertRange(int start, int length, [E initialValue]) { | 279 void insertRange(int start, int length, [E initialValue]) { |
284 throw new UnsupportedError( | 280 throw new UnsupportedError( |
285 "Cannot insert range in an unmodifiable list"); | 281 "Cannot insert range in an unmodifiable list"); |
286 } | 282 } |
287 } | 283 } |
288 | 284 |
289 /** | |
290 * Iterates over a [List] in growing index order. | |
291 */ | |
292 class ListIterator<E> implements Iterator<E> { | |
293 final List<E> _list; | |
294 final int _length; | |
295 int _position; | |
296 E _current; | |
297 | |
298 ListIterator(List<E> list) | |
299 : _list = list, _position = -1, _length = list.length; | |
300 | |
301 bool moveNext() { | |
302 if (_list.length != _length) { | |
303 throw new ConcurrentModificationError(_list); | |
304 } | |
305 int nextPosition = _position + 1; | |
306 if (nextPosition < _length) { | |
307 _position = nextPosition; | |
308 _current = _list[nextPosition]; | |
309 return true; | |
310 } | |
311 _current = null; | |
312 return false; | |
313 } | |
314 | |
315 E get current => _current; | |
316 } | |
317 | |
318 class MappedList<S, T> extends UnmodifiableListBase<T> { | |
319 final List<S> _list; | |
320 // TODO(ahe): Restore type when feature is implemented in dart2js | |
321 // checked mode. http://dartbug.com/7733 | |
322 final /* _Transformation<S, T> */ _f; | |
323 | |
324 MappedList(this._list, T this._f(S element)); | |
325 | |
326 T operator[](int index) => _f(_list[index]); | |
327 int get length => _list.length; | |
328 } | |
329 | |
330 /** An empty fixed-length list. */ | 285 /** An empty fixed-length list. */ |
331 class EmptyList<E> extends FixedLengthListBase<E> { | 286 class EmptyList<E> extends FixedLengthListBase<E> { |
332 int get length => 0; | 287 int get length => 0; |
333 E operator[](int index) { throw new RangeError.value(index); } | 288 E operator[](int index) { throw new RangeError.value(index); } |
334 void operator []=(int index, E value) { throw new RangeError.value(index); } | 289 void operator []=(int index, E value) { throw new RangeError.value(index); } |
335 List<E> skip(int count) => this; | 290 Iterable<E> skip(int count) => const EmptyIterable(); |
336 List<E> take(int count) => this; | 291 Iterable<E> take(int count) => const EmptyIterable(); |
337 List<E> get reversed => this; | 292 Iterable<E> get reversed => const EmptyIterable(); |
338 void sort([int compare(E a, E b)]) {} | 293 void sort([int compare(E a, E b)]) {} |
339 } | 294 } |
340 | 295 |
341 /** | 296 class ReversedListIterable<E> extends ListIterable<E> { |
342 * A fixed-length view of a sub-range of another [List]. | 297 Iterable<E> _source; |
343 * | 298 ReversedListIterable(this._source); |
344 * The range is described by start and end points relative | |
345 * to the other List's start or end. | |
346 * | |
347 * The range changes dynamically as the underlying list changes | |
348 * its length. | |
349 */ | |
350 abstract class SubListView<E> extends UnmodifiableListBase<E> { | |
351 final List<E> _list; | |
352 final int _start; | |
353 final int _end; | |
354 | 299 |
355 /** | 300 int get length => _source.length; |
356 * Create a sub-list view. | |
357 * | |
358 * Both [_start] and [_end] can be given as positions | |
359 * relative to the start of [_list] (a non-negative integer) | |
360 * or relative to the end of [_list] (a negative integer or | |
361 * null, with null being at the end of the list). | |
362 */ | |
363 SubListView(this._list, this._start, this._end); | |
364 | 301 |
365 int _absoluteIndex(int relativeIndex) { | 302 E elementAt(int index) => _source.elementAt(_source.length - 1 - index); |
366 if (relativeIndex == null) return _list.length; | |
367 if (relativeIndex < 0) { | |
368 int result = _list.length + relativeIndex; | |
369 if (result < 0) return 0; | |
370 return result; | |
371 } | |
372 if (relativeIndex > _list.length) { | |
373 return _list.length; | |
374 } | |
375 return relativeIndex; | |
376 } | |
377 | |
378 int get length { | |
379 int result = _absoluteIndex(_end) - _absoluteIndex(_start); | |
380 if (result >= 0) return result; | |
381 return 0; | |
382 } | |
383 | |
384 _createListView(int start, int end) { | |
385 if (start == null) return new EmptyList<E>(); | |
386 if (end != null) { | |
387 if (start < 0) { | |
388 if (end <= start) return new EmptyList<E>(); | |
389 } else { | |
390 if (end >= 0 && end <= start) return new EmptyList<E>(); | |
391 } | |
392 } | |
393 return new ListView(_list, start, end); | |
394 } | |
395 | |
396 _createReversedListView(int start, int end) { | |
397 if (start == null) return new EmptyList<E>(); | |
398 if (end != null) { | |
399 if (start < 0) { | |
400 if (end <= start) return new EmptyList<E>(); | |
401 } else { | |
402 if (end >= 0 && end <= start) return new EmptyList<E>(); | |
403 } | |
404 } | |
405 return new ReversedListView(_list, start, end); | |
406 } | |
407 } | 303 } |
408 | |
409 | |
410 /** | |
411 * A fixed-length view of a sub-range of a [List]. | |
412 */ | |
413 class ListView<E> extends SubListView<E> { | |
414 | |
415 ListView(List<E> list, int start, int end) : super(list, start, end); | |
416 | |
417 E operator[](int index) { | |
418 int start = _absoluteIndex(_start); | |
419 int end = _absoluteIndex(_end); | |
420 int length = end - start; | |
421 if (index < 0 || index >= length) { | |
422 throw new RangeError.range(index, 0, length); | |
423 } | |
424 return _list[start + index]; | |
425 } | |
426 | |
427 List<E> skip(int count) { | |
428 if (count is! int || count < 0) { | |
429 throw new ArgumentError(count); | |
430 } | |
431 if (_start == null) { | |
432 return new EmptyList<E>(); | |
433 } | |
434 int newStart = _start + count; | |
435 if (_start < 0 && newStart >= 0) { | |
436 return new EmptyList<E>(); | |
437 } | |
438 return _createListView(newStart, _end); | |
439 } | |
440 | |
441 List<E> take(int count) { | |
442 if (count is! int || count < 0) { | |
443 throw new ArgumentError(count); | |
444 } | |
445 if (_start == null) { | |
446 return new EmptyList<E>(); | |
447 } | |
448 int newEnd = _start + count; | |
449 if (_start < 0 && newEnd >= 0) { | |
450 newEnd = null; | |
451 } | |
452 return _createListView(_start, newEnd); | |
453 } | |
454 | |
455 List<E> get reversed => new ReversedListView(_list, _start, _end); | |
456 } | |
457 | |
458 /** | |
459 * Reversed view of a [List], or a slice of a list. | |
460 * | |
461 * The view is fixed-length and becomes invalid if the underlying | |
462 * list changes its length below the slice used by this reversed list. | |
463 * | |
464 * Start index and end index can be either positive, negative or null. | |
465 * Positive means an index relative to the start of the list, | |
466 * negative means an index relative to the end of the list, and null | |
467 * means at the end of the list (since there is no -0 integer). | |
468 */ | |
469 class ReversedListView<E> extends SubListView<E> { | |
470 | |
471 ReversedListView(List<E> list, int start, int end) | |
472 : super(list, start, end); | |
473 | |
474 E operator[](int index) { | |
475 int start = _absoluteIndex(_start); | |
476 int end = _absoluteIndex(_end); | |
477 int length = end - start; | |
478 if (index < 0 || index >= length) { | |
479 throw new RangeError.range(index, 0, length); | |
480 } | |
481 return _list[end - index - 1]; | |
482 } | |
483 | |
484 List<E> skip(int count) { | |
485 if (count is! int || count < 0) { | |
486 throw new ArgumentError(count); | |
487 } | |
488 if (_end == null) { | |
489 return _createReversedListView(_start, -count); | |
490 } | |
491 int newEnd = _end - count; | |
492 if (_end >= 0 && newEnd < 0) { | |
493 return new EmptyList<E>(); | |
494 } | |
495 return _createReversedListView(_start, newEnd); | |
496 } | |
497 | |
498 List<E> take(int count) { | |
499 if (count is! int || count < 0) { | |
500 throw new ArgumentError(count); | |
501 } | |
502 int newStart; | |
503 if (_end == null) { | |
504 newStart = -count; | |
505 } else { | |
506 newStart = _end - count; | |
507 if (_end >= 0 && newStart < 0) { | |
508 return new EmptyList<E>(); | |
509 } | |
510 } | |
511 return _createReversedListView(newStart, _end); | |
512 } | |
513 | |
514 Iterator<E> get iterator => new ReverseListIterator<E>( | |
515 _list, _absoluteIndex(_start), _absoluteIndex(_end)); | |
516 | |
517 List<E> get reversed { | |
518 return new ListView(_list, _start, _end); | |
519 } | |
520 } | |
521 | |
522 /** | |
523 * An [Iterator] over a slice of a list that access elements in reverse order. | |
524 */ | |
525 class ReverseListIterator<E> implements Iterator<E> { | |
526 final List<E> _list; | |
527 final int _start; | |
528 final int _originalLength; | |
529 int _index; | |
530 E _current; | |
531 | |
532 ReverseListIterator(List<E> list, int start, int end) | |
533 : _list = list, | |
534 _start = start, | |
535 _index = end, | |
536 _originalLength = list.length; | |
537 | |
538 bool moveNext() { | |
539 if (_list.length != _originalLength) { | |
540 throw new ConcurrentModificationError(_list); | |
541 } | |
542 if (_index <= _start) return false; | |
543 _index -= 1; | |
544 _current = _list[_index]; | |
545 return true; | |
546 } | |
547 | |
548 E get current => _current; | |
549 } | |
OLD | NEW |