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