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

Side by Side Diff: sdk/lib/collection_dev/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: Moved some functionality to separate CL. 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
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_array.dart ('k') | sdk/lib/core/errors.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 * Skeleton class for an unmodifiable [List]. 8 * Class implementing the read-operations on [List].
9 *
10 * Implements all read-only operations, except [:operator[]:] and [:length:],
11 * in terms of those two operations.
9 */ 12 */
10 abstract class NonExtensibleListMixin<E> 13 abstract class ListBase<E> extends Iterable<E> implements List<E> {
11 extends Iterable<E> implements List<E> {
12
13 Iterator<E> get iterator => new ListIterator(this); 14 Iterator<E> get iterator => new ListIterator(this);
14 15
15 void forEach(f(E element)) { 16 void forEach(f(E element)) {
16 for (int i = 0; i < this.length; i++) f(this[i]); 17 for (int i = 0; i < this.length; i++) f(this[i]);
17 } 18 }
18 19
19 bool contains(E value) { 20 bool contains(E value) {
20 for (int i = 0; i < length; i++) { 21 for (int i = 0; i < length; i++) {
21 if (this[i] == value) return true; 22 if (this[i] == value) return true;
22 } 23 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 86 }
86 87
87 List<E> getRange(int start, int length) { 88 List<E> getRange(int start, int length) {
88 List<E> result = <E>[]; 89 List<E> result = <E>[];
89 for (int i = 0; i < length; i++) { 90 for (int i = 0; i < length; i++) {
90 result.add(this[start + i]); 91 result.add(this[start + i]);
91 } 92 }
92 return result; 93 return result;
93 } 94 }
94 95
96 String toString() => Collections.collectionToString(this);
97 }
98
99 /**
100 * Abstract class implementing the non-length changing operations of [List].
101 */
102 abstract class FixedLengthListBase<E> extends ListBase<E> {
103 void operator[]=(int index, E value);
104
105 List<E> get reversed => new ReversedListView<E>(this, 0, null);
106
107 void sort([Comparator<E> compare]) {
108 coreSort(this, compare);
109 }
110
111 void setRange(int start, int length, List<E> from, [int startFrom]) {
112 if (length < 0) throw new ArgumentError("length: $length");
113 if (startFrom == null) startFrom = 0;
114 for (int i = 0; i < length; i++) {
115 this[start + i] = from[startFrom + i];
116 }
117 }
118
119 void set length(int newLength) {
120 throw new UnsupportedError(
121 "Cannot change the length of a fixed-length list");
122 }
123
124 void add(E value) {
125 throw new UnsupportedError(
126 "Cannot add to a fixed-length list");
127 }
128
129 void addLast(E value) {
130 throw new UnsupportedError(
131 "Cannot add to a fixed-length list");
132 }
133
134 void addAll(Iterable<E> iterable) {
135 throw new UnsupportedError(
136 "Cannot add to a fixed-length list");
137 }
138
139 void remove(E element) {
140 throw new UnsupportedError(
141 "Cannot remove from a fixed-length list");
142 }
143
144 void removeAll(Iterable elements) {
145 throw new UnsupportedError(
146 "Cannot remove from a fixed-length list");
147 }
148
149 void retainAll(Iterable elements) {
150 throw new UnsupportedError(
151 "Cannot remove from a fixed-length list");
152 }
153
154 void removeMatching(bool test(E element)) {
155 throw new UnsupportedError(
156 "Cannot remove from a fixed-length list");
157 }
158
159 void clear() {
160 throw new UnsupportedError(
161 "Cannot clear a fixed-length list");
162 }
163
164 E removeAt(int index) {
165 throw new UnsupportedError(
166 "Cannot remove from a fixed-length list");
167 }
168
169 E removeLast() {
170 throw new UnsupportedError(
171 "Cannot remove from a fixed-length list");
172 }
173
174 void removeRange(int start, int length) {
175 throw new UnsupportedError(
176 "Cannot remove from a fixed-length list");
177 }
178
179 void insertRange(int start, int length, [E initialValue]) {
180 throw new UnsupportedError(
181 "Cannot insert range in a fixed-length list");
182 }
183 }
184
185 /**
186 * An unmodifiable [List].
187 */
188 abstract class UnmodifiableListBase<E> extends ListBase<E> {
189
95 void operator []=(int index, E value) { 190 void operator []=(int index, E value) {
96 throw new UnsupportedError( 191 throw new UnsupportedError(
97 "Cannot modify an unmodifiable list"); 192 "Cannot modify an unmodifiable list");
98 } 193 }
99 194
100 void set length(int newLength) { 195 void set length(int newLength) {
101 throw new UnsupportedError( 196 throw new UnsupportedError(
102 "Cannot change the length of an unmodifiable list"); 197 "Cannot change the length of an unmodifiable list");
103 } 198 }
104 199
(...skipping 24 matching lines...) Expand all
129 224
130 void retainAll(Iterable elements) { 225 void retainAll(Iterable elements) {
131 throw new UnsupportedError( 226 throw new UnsupportedError(
132 "Cannot remove from an unmodifiable list"); 227 "Cannot remove from an unmodifiable list");
133 } 228 }
134 229
135 void removeMatching(bool test(E element)) { 230 void removeMatching(bool test(E element)) {
136 throw new UnsupportedError( 231 throw new UnsupportedError(
137 "Cannot remove from an unmodifiable list"); 232 "Cannot remove from an unmodifiable list");
138 } 233 }
234
139 void sort([Comparator<E> compare]) { 235 void sort([Comparator<E> compare]) {
140 throw new UnsupportedError( 236 throw new UnsupportedError(
141 "Cannot modify an unmodifiable list"); 237 "Cannot modify an unmodifiable list");
142 } 238 }
143 239
144 void clear() { 240 void clear() {
145 throw new UnsupportedError( 241 throw new UnsupportedError(
146 "Cannot clear an unmodifiable list"); 242 "Cannot clear an unmodifiable list");
147 } 243 }
148 244
(...skipping 24 matching lines...) Expand all
173 } 269 }
174 270
175 /** 271 /**
176 * Iterates over a [List] in growing index order. 272 * Iterates over a [List] in growing index order.
177 */ 273 */
178 class ListIterator<E> implements Iterator<E> { 274 class ListIterator<E> implements Iterator<E> {
179 final List<E> _list; 275 final List<E> _list;
180 int _position; 276 int _position;
181 E _current; 277 E _current;
182 278
183 ListIterator(this._list) : _position = -1; 279 ListIterator(List<E> list) : _list = list, _position = -1;
184 280
185 bool moveNext() { 281 bool moveNext() {
186 int nextPosition = _position + 1; 282 int nextPosition = _position + 1;
187 if (nextPosition < _list.length) { 283 if (nextPosition < _list.length) {
188 _current = _list[nextPosition]; 284 _current = _list[nextPosition];
189 _position = nextPosition; 285 _position = nextPosition;
190 return true; 286 return true;
191 } 287 }
192 _position = _list.length; 288 _position = _list.length;
193 _current = null; 289 _current = null;
194 return false; 290 return false;
195 } 291 }
196 292
197 E get current => _current; 293 E get current => _current;
198 } 294 }
199 295
200 class MappedList<S, T> extends NonExtensibleListMixin<T> { 296 class MappedList<S, T> extends UnmodifiableListBase<T> {
201 final List<S> _list; 297 final List<S> _list;
202 // TODO(ahe): Restore type when feature is implemented in dart2js 298 // TODO(ahe): Restore type when feature is implemented in dart2js
203 // checked mode. http://dartbug.com/7733 299 // checked mode. http://dartbug.com/7733
204 final /* _Transformation<S, T> */ _f; 300 final /* _Transformation<S, T> */ _f;
205 301
206 MappedList(this._list, T this._f(S element)); 302 MappedList(this._list, T this._f(S element));
207 303
208 T operator[](int index) => _f(_list[index]); 304 T operator[](int index) => _f(_list[index]);
209 int get length => _list.length; 305 int get length => _list.length;
210 } 306 }
211 307
212 /** 308 /** An empty fixed-length list. */
213 * An immutable view of a [List]. 309 class EmptyList<E> extends FixedLengthListBase<E> {
214 */ 310 int get length => 0;
215 class ListView<E> extends NonExtensibleListMixin<E> { 311 E operator[](int index) { throw new RangeError.value(index); }
312 void operator []=(int index, E value) { throw new RangeError.value(index); }
313 List<E> skip(int count) => this;
314 List<E> take(int count) => this;
315 List<E> get reversed => this;
316 void sort([int compare(E a, E b)]) {}
317 }
318
319 /**
320 * A fixed-length view of a sub-range of another [List].
321 *
322 * The range is described by start and end points relative
323 * to the other List's start or end.
324 *
325 * The range changes dynamically as the underlying list changes
326 * its length.
327 */
328 abstract class SubListView<E> extends UnmodifiableListBase<E> {
216 final List<E> _list; 329 final List<E> _list;
217 final int _offset; 330 final int _start;
218 final int _length; 331 final int _end;
219 332
220 /** 333 /**
221 * If the given length is `null` then the ListView's length is bound by 334 * Create a sub-list view.
222 * the backed [list]. 335 *
336 * Both [_start] and [_end] can be given as positions
337 * relative to the start of [_list] (a non-negative integer)
338 * or relative to the end of [_list] (a negative integer or
339 * null, with null being at the end of the list).
223 */ 340 */
224 ListView(List<E> list, this._offset, this._length) : _list = list { 341 SubListView(this._list, this._start, this._end);
225 if (_offset is! int || _offset < 0) { 342
226 throw new ArgumentError(_offset); 343 int _absoluteIndex(int relativeIndex) {
227 } 344 if (relativeIndex == null) return _list.length;
228 if (_length != null && 345 if (relativeIndex < 0) {
229 (_length is! int || _length < 0)) { 346 int result = _list.length + relativeIndex;
230 throw new ArgumentError(_length); 347 if (result < 0) return 0;
231 } 348 return result;
349 }
350 if (relativeIndex > _list.length) {
351 return _list.length;
352 }
353 return relativeIndex;
232 } 354 }
233 355
234 int get length { 356 int get length {
235 int originalLength = _list.length; 357 int result = _absoluteIndex(_end) - _absoluteIndex(_start);
236 int skipLength = originalLength - _offset; 358 if (result >= 0) return result;
237 if (skipLength < 0) return 0; 359 return 0;
238 if (_length == null || _length > skipLength) return skipLength; 360 }
239 return _length; 361
240 } 362 _createListView(int start, int end) {
363 if (start == null) return new EmptyList<E>();
364 if (end != null) {
365 if (start < 0) {
366 if (end <= start) return new EmptyList<E>();
367 } else {
368 if (end >= 0 && end <= start) return new EmptyList<E>();
369 }
370 }
371 return new ListView(_list, start, end);
372 }
373
374 _createReversedListView(int start, int end) {
375 if (start == null) return new EmptyList<E>();
376 if (end != null) {
377 if (start < 0) {
378 if (end <= start) return new EmptyList<E>();
379 } else {
380 if (end >= 0 && end <= start) return new EmptyList<E>();
381 }
382 }
383 return new ReversedListView(_list, start, end);
384 }
385 }
386
387
388 /**
389 * A fixed-length view of a sub-range of a [List].
390 */
391 class ListView<E> extends SubListView<E> {
392
393 ListView(List<E> list, int start, int end) : super(list, start, end);
241 394
242 E operator[](int index) { 395 E operator[](int index) {
243 int skipIndex = index + _offset; 396 int start = _absoluteIndex(_start);
244 if (index < 0 || 397 int end = _absoluteIndex(_end);
245 (_length != null && index >= _length) || 398 int length = end - start;
246 index + _offset >= _list.length) { 399 if (index < 0 || index >= length) {
247 throw new RangeError.value(index); 400 throw new RangeError.range(index, 0, length);
248 } 401 }
249 return _list[index + _offset]; 402 return _list[start + index];
250 } 403 }
251 404
252 ListView<E> skip(int skipCount) { 405 List<E> skip(int count) {
253 if (skipCount is! int || skipCount < 0) { 406 if (count is! int || count < 0) {
254 throw new ArgumentError(skipCount); 407 throw new ArgumentError(count);
255 } 408 }
256 return new ListView(_list, _offset + skipCount, _length); 409 if (_start == null) {
257 } 410 return new EmptyList<E>();
258 411 }
259 ListView<E> take(int takeCount) { 412 int newStart = _start + count;
260 if (takeCount is! int || takeCount < 0) { 413 if (_start < 0 && newStart >= 0) {
261 throw new ArgumentError(takeCount); 414 return new EmptyList<E>();
262 } 415 }
263 int newLength = takeCount; 416 return _createListView(newStart, _end);
264 if (_length != null && takeCount > _length) newLength = _length; 417 }
265 return new ListView(_list, _offset, newLength); 418
266 } 419 List<E> take(int count) {
267 } 420 if (count is! int || count < 0) {
421 throw new ArgumentError(count);
422 }
423 if (_start == null) {
424 return new EmptyList<E>();
425 }
426 int newEnd = _start + count;
427 if (_start < 0 && newEnd >= 0) {
428 newEnd = null;
429 }
430 return _createListView(_start, newEnd);
431 }
432
433 List<E> get reversed => new ReversedListView(_list, _start, _end);
434 }
435
436 /**
437 * Reversed view of a [List], or a slice of a list.
438 *
439 * The view is fixed-length and becomes invalid if the underlying
440 * list changes its length below the slice used by this reversed list.
441 *
442 * Start index and end index can be either positive, negative or null.
443 * Positive means an index relative to the start of the list,
444 * negative means an index relative to the end of the list, and null
445 * means at the end of the list (since there is no -0 integer).
446 */
447 class ReversedListView<E> extends SubListView<E> {
448
449 ReversedListView(List<E> list, int start, int end)
450 : super(list, start, end);
451
452 E operator[](int index) {
453 int start = _absoluteIndex(_start);
454 int end = _absoluteIndex(_end);
455 int length = end - start;
456 if (index < 0 || index >= length) {
457 throw new RangeError.range(index, 0, length);
458 }
459 return _list[end - index - 1];
460 }
461
462 List<E> skip(int count) {
463 if (count is! int || count < 0) {
464 throw new ArgumentError(count);
465 }
466 if (_end == null) {
467 return _createReversedListView(_start, -count);
468 }
469 int newEnd = _end - count;
470 if (_end >= 0 && newEnd < 0) {
471 return new EmptyList<E>();
472 }
473 return _createReversedListView(_start, newEnd);
474 }
475
476 List<E> take(int count) {
477 if (count is! int || count < 0) {
478 throw new ArgumentError(count);
479 }
480 int newStart;
481 if (_end == null) {
482 newStart = -count;
483 } else {
484 newStart = _end - count;
485 if (_end >= 0 && newStart < 0) {
486 return new EmptyList<E>();
487 }
488 }
489 return _createReversedListView(newStart, _end);
490 }
491
492 Iterable<E> get iterator => new ReverseListIterator<E>(
493 _list, _absoluteIndex(_start), _absoluteIndex(_end));
494
495 List<E> get reversed {
496 return new ListView(_list, _start, _end);
497 }
498 }
499
500 /**
501 * An [Iterator] over a slice of a list that access elements in reverse order.
502 */
503 class ReverseListIterator<E> implements Iterator<E> {
504 final List<E> _list;
505 final int _start;
506 final int _originalLength;
507 int _index;
508 E _current;
509
510 ReverseListIterator(List<E> list, int start, int end)
511 : _list = list,
512 _start = start,
513 _index = end,
514 _originalLength = list.length;
515
516 bool moveNext() {
517 if (list.length != _originalLength) {
518 throw new ConcurrentModificationError(list);
519 }
520 if (_index <= _start) return false;
521 _index -= 1;
522 _current = _list[_index];
523 return true;
524 }
525
526 E get current => _current;
527 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_array.dart ('k') | sdk/lib/core/errors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698