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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 assert(this.length == i || (throw new ConcurrentModificationError(this))); | 249 assert(this.length == i || (throw new ConcurrentModificationError(this))); |
250 this.length = i + 1; | 250 this.length = i + 1; |
251 this[i] = element; | 251 this[i] = element; |
252 i++; | 252 i++; |
253 } | 253 } |
254 } | 254 } |
255 | 255 |
256 bool remove(Object element) { | 256 bool remove(Object element) { |
257 for (int i = 0; i < this.length; i++) { | 257 for (int i = 0; i < this.length; i++) { |
258 if (this[i] == element) { | 258 if (this[i] == element) { |
259 this._closeGap(i, i + 1); | 259 this.setRange(i, this.length - 1, this, i + 1); |
| 260 this.length -= 1; |
260 return true; | 261 return true; |
261 } | 262 } |
262 } | 263 } |
263 return false; | 264 return false; |
264 } | 265 } |
265 | 266 |
266 /// Removes elements from the list starting at [start] up to but not including | |
267 /// [end]. Arguments are pre-validated. | |
268 void _closeGap(int start, int end) { | |
269 int length = this.length; | |
270 assert(0 <= start); | |
271 assert(start < end); | |
272 assert(end <= length); | |
273 int size = end - start; | |
274 for (int i = end; i < length; i++) { | |
275 this[i - size] = this[i]; | |
276 } | |
277 this.length = length - size; | |
278 } | |
279 | |
280 void removeWhere(bool test(E element)) { | 267 void removeWhere(bool test(E element)) { |
281 _filter(test, false); | 268 _filter(test, false); |
282 } | 269 } |
283 | 270 |
284 void retainWhere(bool test(E element)) { | 271 void retainWhere(bool test(E element)) { |
285 _filter(test, true); | 272 _filter(test, true); |
286 } | 273 } |
287 | 274 |
288 void _filter(bool test(var element), bool retainMatching) { | 275 void _filter(bool test(var element), bool retainMatching) { |
289 List<E> retained = <E>[]; | 276 List<E> retained = <E>[]; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 return result; | 343 return result; |
357 } | 344 } |
358 | 345 |
359 Iterable<E> getRange(int start, int end) { | 346 Iterable<E> getRange(int start, int end) { |
360 RangeError.checkValidRange(start, end, this.length); | 347 RangeError.checkValidRange(start, end, this.length); |
361 return new SubListIterable<E>(this, start, end); | 348 return new SubListIterable<E>(this, start, end); |
362 } | 349 } |
363 | 350 |
364 void removeRange(int start, int end) { | 351 void removeRange(int start, int end) { |
365 RangeError.checkValidRange(start, end, this.length); | 352 RangeError.checkValidRange(start, end, this.length); |
366 if (end > start) { | 353 int length = end - start; |
367 _closeGap(start, end); | 354 setRange(start, this.length - length, this, end); |
368 } | 355 this.length -= length; |
369 } | 356 } |
370 | 357 |
371 void fillRange(int start, int end, [E fill]) { | 358 void fillRange(int start, int end, [E fill]) { |
372 RangeError.checkValidRange(start, end, this.length); | 359 RangeError.checkValidRange(start, end, this.length); |
373 for (int i = start; i < end; i++) { | 360 for (int i = start; i < end; i++) { |
374 this[i] = fill; | 361 this[i] = fill; |
375 } | 362 } |
376 } | 363 } |
377 | 364 |
378 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | 365 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
(...skipping 28 matching lines...) Expand all Loading... |
407 } | 394 } |
408 | 395 |
409 void replaceRange(int start, int end, Iterable<E> newContents) { | 396 void replaceRange(int start, int end, Iterable<E> newContents) { |
410 RangeError.checkValidRange(start, end, this.length); | 397 RangeError.checkValidRange(start, end, this.length); |
411 if (newContents is! EfficientLengthIterable) { | 398 if (newContents is! EfficientLengthIterable) { |
412 newContents = newContents.toList(); | 399 newContents = newContents.toList(); |
413 } | 400 } |
414 int removeLength = end - start; | 401 int removeLength = end - start; |
415 int insertLength = newContents.length; | 402 int insertLength = newContents.length; |
416 if (removeLength >= insertLength) { | 403 if (removeLength >= insertLength) { |
| 404 int delta = removeLength - insertLength; |
417 int insertEnd = start + insertLength; | 405 int insertEnd = start + insertLength; |
| 406 int newLength = this.length - delta; |
418 this.setRange(start, insertEnd, newContents); | 407 this.setRange(start, insertEnd, newContents); |
419 if (removeLength > insertLength) { | 408 if (delta != 0) { |
420 _closeGap(insertEnd, end); | 409 this.setRange(insertEnd, newLength, this, end); |
| 410 this.length = newLength; |
421 } | 411 } |
422 } else { | 412 } else { |
423 int delta = insertLength - removeLength; | 413 int delta = insertLength - removeLength; |
424 int newLength = this.length + delta; | 414 int newLength = this.length + delta; |
425 int insertEnd = start + insertLength; // aka. end + delta. | 415 int insertEnd = start + insertLength; // aka. end + delta. |
426 this.length = newLength; | 416 this.length = newLength; |
427 this.setRange(insertEnd, newLength, this, end); | 417 this.setRange(insertEnd, newLength, this, end); |
428 this.setRange(start, insertEnd, newContents); | 418 this.setRange(start, insertEnd, newContents); |
429 } | 419 } |
430 } | 420 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 // Array.copy could throw an exception, leaving the list in a bad state | 463 // Array.copy could throw an exception, leaving the list in a bad state |
474 // (with a length that has been increased, but without a new element). | 464 // (with a length that has been increased, but without a new element). |
475 if (index is! int) throw new ArgumentError(index); | 465 if (index is! int) throw new ArgumentError(index); |
476 this.length++; | 466 this.length++; |
477 setRange(index + 1, this.length, this, index); | 467 setRange(index + 1, this.length, this, index); |
478 this[index] = element; | 468 this[index] = element; |
479 } | 469 } |
480 | 470 |
481 E removeAt(int index) { | 471 E removeAt(int index) { |
482 E result = this[index]; | 472 E result = this[index]; |
483 _closeGap(index, index + 1); | 473 setRange(index, this.length - 1, this, index + 1); |
| 474 length--; |
484 return result; | 475 return result; |
485 } | 476 } |
486 | 477 |
487 void insertAll(int index, Iterable<E> iterable) { | 478 void insertAll(int index, Iterable<E> iterable) { |
488 RangeError.checkValueInInterval(index, 0, length, "index"); | 479 RangeError.checkValueInInterval(index, 0, length, "index"); |
489 if (iterable is! EfficientLengthIterable || identical(iterable, this)) { | 480 if (iterable is! EfficientLengthIterable || identical(iterable, this)) { |
490 iterable = iterable.toList(); | 481 iterable = iterable.toList(); |
491 } | 482 } |
492 int insertionLength = iterable.length; | 483 int insertionLength = iterable.length; |
493 // There might be errors after the length change, in which case the list | 484 // There might be errors after the length change, in which case the list |
(...skipping 17 matching lines...) Expand all Loading... |
511 for (E element in iterable) { | 502 for (E element in iterable) { |
512 this[index++] = element; | 503 this[index++] = element; |
513 } | 504 } |
514 } | 505 } |
515 } | 506 } |
516 | 507 |
517 Iterable<E> get reversed => new ReversedListIterable<E>(this); | 508 Iterable<E> get reversed => new ReversedListIterable<E>(this); |
518 | 509 |
519 String toString() => IterableBase.iterableToFullString(this, '[', ']'); | 510 String toString() => IterableBase.iterableToFullString(this, '[', ']'); |
520 } | 511 } |
OLD | NEW |