| 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 |