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 |