| 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 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 var tmp = this[length]; | 318 var tmp = this[length]; |
| 319 this[length] = this[pos]; | 319 this[length] = this[pos]; |
| 320 this[pos] = tmp; | 320 this[pos] = tmp; |
| 321 } | 321 } |
| 322 } | 322 } |
| 323 | 323 |
| 324 Map<int, E> asMap() { | 324 Map<int, E> asMap() { |
| 325 return new ListMapView(this); | 325 return new ListMapView(this); |
| 326 } | 326 } |
| 327 | 327 |
| 328 void _rangeCheck(int start, int end) { | |
| 329 if (start < 0 || start > this.length) { | |
| 330 throw new RangeError.range(start, 0, this.length); | |
| 331 } | |
| 332 if (end < start || end > this.length) { | |
| 333 throw new RangeError.range(end, start, this.length); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 List<E> sublist(int start, [int end]) { | 328 List<E> sublist(int start, [int end]) { |
| 338 if (end == null) end = this.length; | 329 int listLength = this.length; |
| 339 _rangeCheck(start, end); | 330 if (end == null) end = listLength; |
| 331 RangeError.checkValidRange(start, end, listLength); |
| 340 int length = end - start; | 332 int length = end - start; |
| 341 List<E> result = new List<E>()..length = length; | 333 List<E> result = new List<E>()..length = length; |
| 342 for (int i = 0; i < length; i++) { | 334 for (int i = 0; i < length; i++) { |
| 343 result[i] = this[start + i]; | 335 result[i] = this[start + i]; |
| 344 } | 336 } |
| 345 return result; | 337 return result; |
| 346 } | 338 } |
| 347 | 339 |
| 348 Iterable<E> getRange(int start, int end) { | 340 Iterable<E> getRange(int start, int end) { |
| 349 _rangeCheck(start, end); | 341 RangeError.checkValidRange(start, end, this.length); |
| 350 return new SubListIterable<E>(this, start, end); | 342 return new SubListIterable<E>(this, start, end); |
| 351 } | 343 } |
| 352 | 344 |
| 353 void removeRange(int start, int end) { | 345 void removeRange(int start, int end) { |
| 354 _rangeCheck(start, end); | 346 RangeError.checkValidRange(start, end, this.length); |
| 355 int length = end - start; | 347 int length = end - start; |
| 356 setRange(start, this.length - length, this, end); | 348 setRange(start, this.length - length, this, end); |
| 357 this.length -= length; | 349 this.length -= length; |
| 358 } | 350 } |
| 359 | 351 |
| 360 void fillRange(int start, int end, [E fill]) { | 352 void fillRange(int start, int end, [E fill]) { |
| 361 _rangeCheck(start, end); | 353 RangeError.checkValidRange(start, end, this.length); |
| 362 for (int i = start; i < end; i++) { | 354 for (int i = start; i < end; i++) { |
| 363 this[i] = fill; | 355 this[i] = fill; |
| 364 } | 356 } |
| 365 } | 357 } |
| 366 | 358 |
| 367 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | 359 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
| 368 _rangeCheck(start, end); | 360 RangeError.checkValidRange(start, end, this.length); |
| 369 int length = end - start; | 361 int length = end - start; |
| 370 if (length == 0) return; | 362 if (length == 0) return; |
| 371 | 363 RangeError.checkNotNegative(skipCount, "skipCount"); |
| 372 if (skipCount < 0) throw new ArgumentError(skipCount); | |
| 373 | 364 |
| 374 List otherList; | 365 List otherList; |
| 375 int otherStart; | 366 int otherStart; |
| 376 // TODO(floitsch): Make this accept more. | 367 // TODO(floitsch): Make this accept more. |
| 377 if (iterable is List) { | 368 if (iterable is List) { |
| 378 otherList = iterable; | 369 otherList = iterable; |
| 379 otherStart = skipCount; | 370 otherStart = skipCount; |
| 380 } else { | 371 } else { |
| 381 otherList = iterable.skip(skipCount).toList(growable: false); | 372 otherList = iterable.skip(skipCount).toList(growable: false); |
| 382 otherStart = 0; | 373 otherStart = 0; |
| 383 } | 374 } |
| 384 if (otherStart + length > otherList.length) { | 375 if (otherStart + length > otherList.length) { |
| 385 throw IterableElementError.tooFew(); | 376 throw IterableElementError.tooFew(); |
| 386 } | 377 } |
| 387 if (otherStart < start) { | 378 if (otherStart < start) { |
| 388 // Copy backwards to ensure correct copy if [from] is this. | 379 // Copy backwards to ensure correct copy if [from] is this. |
| 389 for (int i = length - 1; i >= 0; i--) { | 380 for (int i = length - 1; i >= 0; i--) { |
| 390 this[start + i] = otherList[otherStart + i]; | 381 this[start + i] = otherList[otherStart + i]; |
| 391 } | 382 } |
| 392 } else { | 383 } else { |
| 393 for (int i = 0; i < length; i++) { | 384 for (int i = 0; i < length; i++) { |
| 394 this[start + i] = otherList[otherStart + i]; | 385 this[start + i] = otherList[otherStart + i]; |
| 395 } | 386 } |
| 396 } | 387 } |
| 397 } | 388 } |
| 398 | 389 |
| 399 void replaceRange(int start, int end, Iterable<E> newContents) { | 390 void replaceRange(int start, int end, Iterable<E> newContents) { |
| 400 _rangeCheck(start, end); | 391 RangeError.checkValidRange(start, end, this.length); |
| 401 if (newContents is! EfficientLength) { | 392 if (newContents is! EfficientLength) { |
| 402 newContents = newContents.toList(); | 393 newContents = newContents.toList(); |
| 403 } | 394 } |
| 404 int removeLength = end - start; | 395 int removeLength = end - start; |
| 405 int insertLength = newContents.length; | 396 int insertLength = newContents.length; |
| 406 if (removeLength >= insertLength) { | 397 if (removeLength >= insertLength) { |
| 407 int delta = removeLength - insertLength; | 398 int delta = removeLength - insertLength; |
| 408 int insertEnd = start + insertLength; | 399 int insertEnd = start + insertLength; |
| 409 int newLength = this.length - delta; | 400 int newLength = this.length - delta; |
| 410 this.setRange(start, insertEnd, newContents); | 401 this.setRange(start, insertEnd, newContents); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 } | 446 } |
| 456 for (int i = startIndex; i >= 0; i--) { | 447 for (int i = startIndex; i >= 0; i--) { |
| 457 if (this[i] == element) { | 448 if (this[i] == element) { |
| 458 return i; | 449 return i; |
| 459 } | 450 } |
| 460 } | 451 } |
| 461 return -1; | 452 return -1; |
| 462 } | 453 } |
| 463 | 454 |
| 464 void insert(int index, E element) { | 455 void insert(int index, E element) { |
| 465 if (index < 0 || index > length) { | 456 RangeError.checkValueInInterval(index, 0, length, "index"); |
| 466 throw new RangeError.range(index, 0, length); | |
| 467 } | |
| 468 if (index == this.length) { | 457 if (index == this.length) { |
| 469 add(element); | 458 add(element); |
| 470 return; | 459 return; |
| 471 } | 460 } |
| 472 // We are modifying the length just below the is-check. Without the check | 461 // We are modifying the length just below the is-check. Without the check |
| 473 // Array.copy could throw an exception, leaving the list in a bad state | 462 // 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). | 463 // (with a length that has been increased, but without a new element). |
| 475 if (index is! int) throw new ArgumentError(index); | 464 if (index is! int) throw new ArgumentError(index); |
| 476 this.length++; | 465 this.length++; |
| 477 setRange(index + 1, this.length, this, index); | 466 setRange(index + 1, this.length, this, index); |
| 478 this[index] = element; | 467 this[index] = element; |
| 479 } | 468 } |
| 480 | 469 |
| 481 E removeAt(int index) { | 470 E removeAt(int index) { |
| 482 E result = this[index]; | 471 E result = this[index]; |
| 483 setRange(index, this.length - 1, this, index + 1); | 472 setRange(index, this.length - 1, this, index + 1); |
| 484 length--; | 473 length--; |
| 485 return result; | 474 return result; |
| 486 } | 475 } |
| 487 | 476 |
| 488 void insertAll(int index, Iterable<E> iterable) { | 477 void insertAll(int index, Iterable<E> iterable) { |
| 489 if (index < 0 || index > length) { | 478 RangeError.checkValueInInterval(index, 0, length, "index"); |
| 490 throw new RangeError.range(index, 0, length); | |
| 491 } | |
| 492 if (iterable is EfficientLength) { | 479 if (iterable is EfficientLength) { |
| 493 iterable = iterable.toList(); | 480 iterable = iterable.toList(); |
| 494 } | 481 } |
| 495 int insertionLength = iterable.length; | 482 int insertionLength = iterable.length; |
| 496 // There might be errors after the length change, in which case the list | 483 // There might be errors after the length change, in which case the list |
| 497 // will end up being modified but the operation not complete. Unless we | 484 // will end up being modified but the operation not complete. Unless we |
| 498 // always go through a "toList" we can't really avoid that. | 485 // always go through a "toList" we can't really avoid that. |
| 499 this.length += insertionLength; | 486 this.length += insertionLength; |
| 500 setRange(index + insertionLength, this.length, this, index); | 487 setRange(index + insertionLength, this.length, this, index); |
| 501 setAll(index, iterable); | 488 setAll(index, iterable); |
| 502 } | 489 } |
| 503 | 490 |
| 504 void setAll(int index, Iterable<E> iterable) { | 491 void setAll(int index, Iterable<E> iterable) { |
| 505 if (iterable is List) { | 492 if (iterable is List) { |
| 506 setRange(index, index + iterable.length, iterable); | 493 setRange(index, index + iterable.length, iterable); |
| 507 } else { | 494 } else { |
| 508 for (E element in iterable) { | 495 for (E element in iterable) { |
| 509 this[index++] = element; | 496 this[index++] = element; |
| 510 } | 497 } |
| 511 } | 498 } |
| 512 } | 499 } |
| 513 | 500 |
| 514 Iterable<E> get reversed => new ReversedListIterable<E>(this); | 501 Iterable<E> get reversed => new ReversedListIterable<E>(this); |
| 515 | 502 |
| 516 String toString() => IterableBase.iterableToFullString(this, '[', ']'); | 503 String toString() => IterableBase.iterableToFullString(this, '[', ']'); |
| 517 } | 504 } |
| OLD | NEW |