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

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

Issue 11896013: Add List.reversed to give a reverse fixed-length view of a list. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.core; 5 part of dart.core;
6 6
7 /** 7 /**
8 * A [List] is an indexable collection with a length. It can be of 8 * A [List] is an indexable collection with a length. It can be of
9 * fixed size or extendable. 9 * fixed size or extendable.
10 */ 10 */
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 void addLast(E value); 78 void addLast(E value);
79 79
80 /** 80 /**
81 * Appends all elements of the [iterable] to the end of this list. 81 * Appends all elements of the [iterable] to the end of this list.
82 * Extends the length of the list by the number of elements in [iterable]. 82 * Extends the length of the list by the number of elements in [iterable].
83 * Throws an [UnsupportedError] if this list is not extensible. 83 * Throws an [UnsupportedError] if this list is not extensible.
84 */ 84 */
85 void addAll(Iterable<E> iterable); 85 void addAll(Iterable<E> iterable);
86 86
87 /** 87 /**
88 * Returns a reversed fixed-length view of this [List].
89 *
90 * The reversed list has elements in the opposite order of this list.
91 * It is backed by this list, but will stop working if this list
92 * becomes shorter than its current length.
93 */
94 List<T> get reversed => new ReversedList(this, 0, length);
95
96 /**
88 * Sorts the list according to the order specified by the [compare] function. 97 * Sorts the list according to the order specified by the [compare] function.
89 * 98 *
90 * The [compare] function must act as a [Comparator]. 99 * The [compare] function must act as a [Comparator].
91 * The default [List] implementations use [Comparable.compare] if 100 * The default [List] implementations use [Comparable.compare] if
92 * [compare] is omitted. 101 * [compare] is omitted.
93 */ 102 */
94 void sort([int compare(E a, E b)]); 103 void sort([int compare(E a, E b)]);
95 104
96 /** 105 /**
97 * Returns the first index of [element] in the list. 106 * Returns the first index of [element] in the list.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 * If [start] is the length of the list, this method inserts the 194 * If [start] is the length of the list, this method inserts the
186 * range at the end of the list. 195 * range at the end of the list.
187 * Throws an [ArgumentError] if [length] is negative. 196 * Throws an [ArgumentError] if [length] is negative.
188 * Throws an [RangeError] if [start] is negative or if 197 * Throws an [RangeError] if [start] is negative or if
189 * [start] is greater than the length of the list. 198 * [start] is greater than the length of the list.
190 */ 199 */
191 void insertRange(int start, int length, [E fill]); 200 void insertRange(int start, int length, [E fill]);
192 } 201 }
193 202
194 /** 203 /**
195 * An unmodifiable [List]. 204 * Class implementing the read-operations on [List].
205 *
206 * Implements all operations except [:operator[]:] and [:length:] that does not
207 * modify the list in terms of those two.
196 */ 208 */
197 abstract class NonExtensibleListMixin<E> 209 abstract class BaseListMixin<E> extends Iterable<E> implements List<E> {
floitsch 2013/01/21 14:38:06 These classes are no longer in core.
Lasse Reichstein Nielsen 2013/01/22 10:18:52 Moved to collection-dev.
198 extends Iterable<E> implements List<E> {
199
200 Iterator<E> get iterator => new ListIterator(this); 210 Iterator<E> get iterator => new ListIterator(this);
201 211
202 void forEach(f(E element)) { 212 void forEach(f(E element)) {
203 for (int i = 0; i < this.length; i++) f(this[i]); 213 for (int i = 0; i < this.length; i++) f(this[i]);
204 } 214 }
205 215
206 bool contains(E value) { 216 bool contains(E value) {
207 for (int i = 0; i < length; i++) { 217 for (int i = 0; i < length; i++) {
208 if (this[i] == value) return true; 218 if (this[i] == value) return true;
209 } 219 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 throw new StateError("More than one element"); 281 throw new StateError("More than one element");
272 } 282 }
273 283
274 List<E> getRange(int start, int length) { 284 List<E> getRange(int start, int length) {
275 List<E> result = <E>[]; 285 List<E> result = <E>[];
276 for (int i = 0; i < length; i++) { 286 for (int i = 0; i < length; i++) {
277 result.add(this[start + i]); 287 result.add(this[start + i]);
278 } 288 }
279 return result; 289 return result;
280 } 290 }
291 }
292
293 /**
294 * Abstract class implementing the non-length changing operations of [List].
295 */
296 abstract class FixedLengthListMixin<E> extends BaseListMixin<E> {
floitsch 2013/01/21 14:38:06 Can't be a mixin, since it extends (or mixins) Bas
Lasse Reichstein Nielsen 2013/01/22 10:18:52 True, so it needs a better name. Just FixedLengthL
297 void operator[]=(int index, E value);
298
299 List<E> get reversed => new ReversedList<E>(this, 0, length);
300
301 void sort([Comparator<E> compare]) {
302 coreSort(this, compare);
303 }
304
305 void setRange(int start, int length, List<E> from, [int startFrom]) {
306 if (length < 0) throw new ArgumentError("length: $length");
307 if (startFrom == null) startFrom = 0;
308 for (int i = 0; i < length; i++) {
309 this[from + i] = from[startFrom + i];
310 }
311 }
312
313 void set length(int newLength) {
314 throw new UnsupportedError(
315 "Cannot change the length of a fixed-length list");
316 }
317
318 void add(E value) {
319 throw new UnsupportedError(
320 "Cannot add to a fixed-length list");
321 }
322
323 void addLast(E value) {
324 throw new UnsupportedError(
325 "Cannot add to a fixed-length list");
326 }
327
328 void addAll(Iterable<E> iterable) {
329 throw new UnsupportedError(
330 "Cannot add to a fixed-length list");
331 }
332
333 void remove(E element) {
334 throw new UnsupportedError(
335 "Cannot remove from a fixed-length list");
336 }
337
338 void removeAll(Iterable elements) {
339 throw new UnsupportedError(
340 "Cannot remove from a fixed-length list");
341 }
342
343 void retainAll(Iterable elements) {
344 throw new UnsupportedError(
345 "Cannot remove from a fixed-length list");
346 }
347
348 void removeMatching(bool test(E element)) {
349 throw new UnsupportedError(
350 "Cannot remove from a fixed-length list");
351 }
352
353 void clear() {
354 throw new UnsupportedError(
355 "Cannot clear a fixed-length list");
356 }
357
358 E removeAt(int index) {
359 throw new UnsupportedError(
360 "Cannot remove from a fixed-length list");
361 }
362
363 E removeLast() {
364 throw new UnsupportedError(
365 "Cannot remove from a fixed-length list");
366 }
367
368 void removeRange(int start, int length) {
369 throw new UnsupportedError(
370 "Cannot remove from a fixed-length list");
371 }
372
373 void insertRange(int start, int length, [E initialValue]) {
374 throw new UnsupportedError(
375 "Cannot insert range in a fixed-length list");
376 }
377 }
378
379 /**
380 * An unmodifiable [List].
381 */
382 abstract class UnmodifiableListMixin<E> extends BaseListMixin<E> {
281 383
282 void operator []=(int index, E value) { 384 void operator []=(int index, E value) {
283 throw new UnsupportedError( 385 throw new UnsupportedError(
284 "Cannot modify an unmodifiable list"); 386 "Cannot modify an unmodifiable list");
285 } 387 }
286 388
287 void set length(int newLength) { 389 void set length(int newLength) {
288 throw new UnsupportedError( 390 throw new UnsupportedError(
289 "Cannot change the length of an unmodifiable list"); 391 "Cannot change the length of an unmodifiable list");
290 } 392 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 return true; 480 return true;
379 } 481 }
380 _position = _list.length; 482 _position = _list.length;
381 _current = null; 483 _current = null;
382 return false; 484 return false;
383 } 485 }
384 486
385 E get current => _current; 487 E get current => _current;
386 } 488 }
387 489
388 class MappedList<S, T> extends NonExtensibleListMixin<T> { 490 class MappedList<S, T> extends UnmodifiableListMixin<T> {
389 final List<S> _list; 491 final List<S> _list;
390 // TODO(ahe): Restore type when feature is implemented in dart2js 492 // TODO(ahe): Restore type when feature is implemented in dart2js
391 // checked mode. http://dartbug.com/7733 493 // checked mode. http://dartbug.com/7733
392 final /* _Transformation<S, T> */ _f; 494 final /* _Transformation<S, T> */ _f;
393 495
394 MappedList(this._list, T this._f(S element)); 496 MappedList(this._list, T this._f(S element));
395 497
396 T operator[](int index) => _f(_list[index]); 498 T operator[](int index) => _f(_list[index]);
397 int get length => _list.length; 499 int get length => _list.length;
398 } 500 }
399 501
502 /** An empty fixed-length list. */
503 class EmptyList<E> extends FixedLengthListMixin<E> {
504 int get length => 0;
505 E operator[](int index) { throw new ArgumentError(index); }
floitsch 2013/01/21 14:38:06 RangeError
Lasse Reichstein Nielsen 2013/01/22 10:18:52 Done.
506 void operator[]=(int index, E value) { throw new ArgumentError(index); }
507 }
508
400 /** 509 /**
401 * An immutable view of a [List]. 510 * An unmodifiable view of a [List].
402 */ 511 */
403 class ListView<E> extends NonExtensibleListMixin<E> { 512 class ListView<E> extends UnmodifiableListMixin<E> {
404 final List<E> _list; 513 final List<E> _list;
405 final int _offset; 514 final int _offset;
406 final int _length; 515 final int _length;
407 516
408 /** 517 /**
409 * If the given length is `null` then the ListView's length is bound by 518 * If the given length is `null` then the ListView's length is bound by
410 * the backed [list]. 519 * the backed [list].
411 */ 520 */
412 ListView(List<E> list, this._offset, this._length) : _list = list { 521 ListView(List<E> list, this._offset, this._length) : _list = list {
413 if (_offset is! int || _offset < 0) { 522 if (_offset is! int || _offset < 0) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 } 554 }
446 555
447 ListView<E> take(int takeCount) { 556 ListView<E> take(int takeCount) {
448 if (takeCount is! int || takeCount < 0) { 557 if (takeCount is! int || takeCount < 0) {
449 throw new ArgumentError(takeCount); 558 throw new ArgumentError(takeCount);
450 } 559 }
451 int newLength = takeCount; 560 int newLength = takeCount;
452 if (_length != null && takeCount > _length) newLength = _length; 561 if (_length != null && takeCount > _length) newLength = _length;
453 return new ListView(_list, _offset, newLength); 562 return new ListView(_list, _offset, newLength);
454 } 563 }
564
565 List<E> get reversed => new ReversedList(_list, _offset, _offset + _length);
566
567 String toString() => Collections.collectionToString(this);
455 } 568 }
569
570 /**
571 * Reversed view of a [List], or a slice of a list.
572 *
573 * The view is fixed-length and becomes invalid if the underlying
574 * list changes its length below the slice used by this reversed list.
floitsch 2013/01/21 14:38:06 That's now how iterables work. And ReversedList (l
Lasse Reichstein Nielsen 2013/01/21 14:43:40 So what should it do?
575 */
576 class ReversedList<E> extends FixedLengthListMixin<E> {
577 final List<E> _list;
578 final int _start;
579 final int _end;
580 ReversedList(List<E> list, int start, int end)
581 : _list = list, _start = start, _end = end;
582
583 int get length => _end - _start;
584
585 E operator[](int index) {
586 if (_list.length < _end) throw new StateError("Concurrent modification");
587 int length = _end - _start;
588 if (index < 0 || index > length) {
589 throw new RangeError("$index not in range 0..$length");
590 }
591 return _list[_end - index - 1];
592 }
593
594 void operator[]=(int index, E value) {
595 if (_list.length < _end) throw new StateError("Concurrent modification");
596 int length = _end - _start;
597 if (index < 0 || index > length) {
598 throw new RangeError("$index not in range 0..$length");
599 }
600 _list[_end - index - 1] = value;
601 }
602
603 Iterable<E> get iterator => new ReverseListIterator<E>(_list, _start, _end);
604
605 List<E> take(int count) {
606 if (count is! int || count < 0) {
607 throw new ArgumentError(count);
608 }
609 int length = _end - _start;
610 if (count > length) count = length;
611 return new ReversedList(_list, _end - count, _end);
612 }
613
614 List<E> skip(int count) {
615 if (count is! int || count < 0) {
616 throw new ArgumentError(count);
617 }
618 int length = _end - _start;
619 if (count >= length) return new EmptyList();
620 return new ReversedList(_list, _start, _end - count);
621 }
622
623 void sort([int compare(E first, E second)]) {
624 if (compare == null) compare = Comparable.compare;
625 // TODO(lrn): Make a way to sort a slice of a list using core sort.
626 List<E> slice = _list.getRange(_start, _end);
627 slice.sort((E a, E b) => compare(b, a));
628 _list.setRange(_start, slice.length, slice);
629 }
630
631 List<E> get reversed {
632 return new ListView(_list, _start, _end - _start);
633 }
634
635 String toString() => Collections.collectionToString(this);
636 }
637
638 /**
639 * An [Iterator] over a slice of a list that access elements in reverse order.
640 */
641 class ReverseListIterator<E> implements Iterator<E> {
642 final List<E> _list;
643 final int _start;
644 int _index;
645 E _current;
646
647 ReverseListIterator(List<E> list, int start, int end)
648 : _list = list, _start = start, _index = end;
649
650 bool moveNext() {
651 if (_index <= _start) return false;
652 _index -= 1;
653 _current = _list[_index];
654 return true;
655 }
656
657 E get current => _current;
658 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_array.dart ('k') | sdk/lib/html/html_common/filtered_element_list.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698