| 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 // patch classes for Int8List ..... Float64List and ByteData implementations. | 5 // patch classes for Int8List ..... Float64List and ByteData implementations. |
| 6 | 6 |
| 7 import "dart:_internal"; | 7 import "dart:_internal"; |
| 8 import 'dart:math' show Random; | 8 import 'dart:math' show Random; |
| 9 | 9 |
| 10 patch class Int8List { | 10 patch class Int8List { |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 234 |
| 235 // Called directly from C code. | 235 // Called directly from C code. |
| 236 factory ByteData._view(TypedData typedData, int offsetInBytes, int length) { | 236 factory ByteData._view(TypedData typedData, int offsetInBytes, int length) { |
| 237 return new _ByteDataView(typedData, offsetInBytes, length); | 237 return new _ByteDataView(typedData, offsetInBytes, length); |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 | 240 |
| 241 | 241 |
| 242 // Based class for _TypedList that provides common methods for implementing | 242 // Based class for _TypedList that provides common methods for implementing |
| 243 // the collection and list interfaces. | 243 // the collection and list interfaces. |
| 244 // TODO(13647): Make this extends ListBase<T> | 244 // This class does not extend ListBase<T> since that would add type arguments |
| 245 // to instances of _TypeListBase. Instead the subclasses use type specific |
| 246 // mixins (like _IntListMixin, _DoubleListMixin) to implement ListBase<T>. |
| 245 abstract class _TypedListBase { | 247 abstract class _TypedListBase { |
| 246 | 248 |
| 247 // Method(s) implementing the Collection interface. | 249 // Method(s) implementing the Collection interface. |
| 248 bool contains(element) => IterableMixinWorkaround.contains(this, element); | 250 bool contains(element) { |
| 251 var len = this.length; |
| 252 for (var i = 0; i < len; ++i) { |
| 253 if (this[i] == element) return true; |
| 254 } |
| 255 return false; |
| 256 } |
| 249 | 257 |
| 250 void forEach(void f(element)) { | 258 void forEach(void f(element)) { |
| 251 var len = this.length; | 259 var len = this.length; |
| 252 for (var i = 0; i < len; i++) { | 260 for (var i = 0; i < len; i++) { |
| 253 f(this[i]); | 261 f(this[i]); |
| 254 } | 262 } |
| 255 } | 263 } |
| 256 | 264 |
| 257 String join([String separator = ""]) { | 265 String join([String separator = ""]) { |
| 258 return IterableMixinWorkaround.join(this, separator); | 266 StringBuffer buffer = new StringBuffer(); |
| 267 buffer.writeAll(this, separator); |
| 268 return buffer.toString(); |
| 259 } | 269 } |
| 260 | 270 |
| 261 dynamic reduce(dynamic combine(value, element)) { | 271 dynamic reduce(dynamic combine(value, element)) { |
| 262 return IterableMixinWorkaround.reduce(this, combine); | 272 var len = this.length; |
| 273 if (len == 0) throw IterableElementError.noElement(); |
| 274 var i = 0; |
| 275 var value = this[0]; |
| 276 for (var i = 1; i < len; ++i) { |
| 277 value = combine(value, this[i]); |
| 278 } |
| 279 return value; |
| 263 } | 280 } |
| 264 | 281 |
| 265 dynamic fold(dynamic initialValue, | 282 dynamic fold(dynamic initialValue, |
| 266 dynamic combine(dynamic initialValue, element)) { | 283 dynamic combine(dynamic initialValue, element)) { |
| 267 return IterableMixinWorkaround.fold(this, initialValue, combine); | 284 var len = this.length; |
| 285 for (var i = 0; i < len; ++i) { |
| 286 initialValue = combine(initialValue, this[i]); |
| 287 } |
| 288 return initialValue; |
| 268 } | 289 } |
| 269 | 290 |
| 270 Iterable map(f(element)) { | 291 Iterable map(f(element)) => new MappedIterable(this, f); |
| 271 return IterableMixinWorkaround.mapList(this, f); | |
| 272 } | |
| 273 | 292 |
| 274 Iterable expand(Iterable f(element)) { | 293 Iterable expand(Iterable f(element)) => new ExpandIterable(this, f); |
| 275 return IterableMixinWorkaround.expand(this, f); | |
| 276 } | |
| 277 | 294 |
| 278 bool every(bool f(element)) { | 295 bool every(bool f(element)) { |
| 279 return IterableMixinWorkaround.every(this, f); | 296 var len = this.length; |
| 297 for (var i = 0; i < len; ++i) { |
| 298 if (!f(this[i])) return false; |
| 299 } |
| 300 return true; |
| 280 } | 301 } |
| 281 | 302 |
| 282 bool any(bool f(element)) { | 303 bool any(bool f(element)) { |
| 283 return IterableMixinWorkaround.any(this, f); | 304 var len = this.length; |
| 305 for (var i = 0; i < len; ++i) { |
| 306 if (f(this[i])) return true; |
| 307 } |
| 308 return false; |
| 284 } | 309 } |
| 285 | 310 |
| 286 dynamic firstWhere(bool test(element), {orElse()}) { | 311 dynamic firstWhere(bool test(element), {orElse()}) { |
| 287 return IterableMixinWorkaround.firstWhere(this, test, orElse); | 312 var len = this.length; |
| 313 for (var i = 0; i < len; ++i) { |
| 314 var element = this[i]; |
| 315 if (test(element)) return element; |
| 316 } |
| 317 if (orElse != null) return orElse(); |
| 318 throw IterableElementError.noElement(); |
| 288 } | 319 } |
| 289 | 320 |
| 290 dynamic lastWhere(bool test(element), {orElse()}) { | 321 dynamic lastWhere(bool test(element), {orElse()}) { |
| 291 return IterableMixinWorkaround.lastWhereList(this, test, orElse); | 322 var result = null; |
| 323 var len = this.length; |
| 324 for (var i = len - 1; i >= 0; --i) { |
| 325 var element = this[i]; |
| 326 if (test(element)) { |
| 327 return element; |
| 328 } |
| 329 } |
| 330 if (orElse != null) return orElse(); |
| 331 throw IterableElementError.noElement(); |
| 292 } | 332 } |
| 293 | 333 |
| 294 dynamic singleWhere(bool test(element)) { | 334 dynamic singleWhere(bool test(element)) { |
| 295 return IterableMixinWorkaround.singleWhere(this, test); | 335 var result = null; |
| 336 bool foundMatching = false; |
| 337 var len = this.length; |
| 338 for (var i = 0; i < len; ++i) { |
| 339 var element = this[i]; |
| 340 if (test(element)) { |
| 341 if (foundMatching) { |
| 342 throw IterableElementError.tooMany(); |
| 343 } |
| 344 result = element; |
| 345 foundMatching = true; |
| 346 } |
| 347 } |
| 348 if (foundMatching) return result; |
| 349 throw IterableElementError.noElement(); |
| 296 } | 350 } |
| 297 | 351 |
| 298 dynamic elementAt(int index) { | 352 dynamic elementAt(int index) { |
| 299 return this[index]; | 353 return this[index]; |
| 300 } | 354 } |
| 301 | 355 |
| 302 bool get isEmpty { | 356 bool get isEmpty { |
| 303 return this.length == 0; | 357 return this.length == 0; |
| 304 } | 358 } |
| 305 | 359 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 326 throw new UnsupportedError( | 380 throw new UnsupportedError( |
| 327 "Cannot insert into a fixed-length list"); | 381 "Cannot insert into a fixed-length list"); |
| 328 } | 382 } |
| 329 | 383 |
| 330 void insertAll(int index, Iterable values) { | 384 void insertAll(int index, Iterable values) { |
| 331 throw new UnsupportedError( | 385 throw new UnsupportedError( |
| 332 "Cannot insert into a fixed-length list"); | 386 "Cannot insert into a fixed-length list"); |
| 333 } | 387 } |
| 334 | 388 |
| 335 void sort([int compare(a, b)]) { | 389 void sort([int compare(a, b)]) { |
| 336 IterableMixinWorkaround.sortList(this, compare); | 390 if (compare == null) compare = Comparable.compare; |
| 391 Sort.sort(this, compare); |
| 337 } | 392 } |
| 338 | 393 |
| 339 void shuffle([Random random]) { | 394 void shuffle([Random random]) { |
| 340 IterableMixinWorkaround.shuffleList(this, random); | 395 if (random == null) random = new Random(); |
| 396 var i = this.length; |
| 397 while (i > 1) { |
| 398 int pos = random.nextInt(i); |
| 399 i -= 1; |
| 400 var tmp = this[i]; |
| 401 this[i] = this[pos]; |
| 402 this[pos] = tmp; |
| 403 } |
| 341 } | 404 } |
| 342 | 405 |
| 343 int indexOf(element, [int start = 0]) { | 406 int indexOf(element, [int start = 0]) { |
| 344 return IterableMixinWorkaround.indexOfList(this, element, start); | 407 return Lists.indexOf(this, element, start, this.length); |
| 345 } | 408 } |
| 346 | 409 |
| 347 int lastIndexOf(element, [int start = null]) { | 410 int lastIndexOf(element, [int start = null]) { |
| 348 return IterableMixinWorkaround.lastIndexOfList(this, element, start); | 411 if (start == null) start = this.length - 1; |
| 412 return Lists.lastIndexOf(this, element, start); |
| 349 } | 413 } |
| 350 | 414 |
| 351 void clear() { | 415 void clear() { |
| 352 throw new UnsupportedError( | 416 throw new UnsupportedError( |
| 353 "Cannot remove from a fixed-length list"); | 417 "Cannot remove from a fixed-length list"); |
| 354 } | 418 } |
| 355 | 419 |
| 356 int removeLast() { | 420 int removeLast() { |
| 357 throw new UnsupportedError( | 421 throw new UnsupportedError( |
| 358 "Cannot remove from a fixed-length list"); | 422 "Cannot remove from a fixed-length list"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 373 "Cannot remove from a fixed-length list"); | 437 "Cannot remove from a fixed-length list"); |
| 374 } | 438 } |
| 375 | 439 |
| 376 void retainWhere(bool test(element)) { | 440 void retainWhere(bool test(element)) { |
| 377 throw new UnsupportedError( | 441 throw new UnsupportedError( |
| 378 "Cannot remove from a fixed-length list"); | 442 "Cannot remove from a fixed-length list"); |
| 379 } | 443 } |
| 380 | 444 |
| 381 dynamic get first { | 445 dynamic get first { |
| 382 if (length > 0) return this[0]; | 446 if (length > 0) return this[0]; |
| 383 throw new StateError("No elements"); | 447 throw IterableElementError.noElement(); |
| 384 } | 448 } |
| 385 | 449 |
| 386 dynamic get last { | 450 dynamic get last { |
| 387 if (length > 0) return this[length - 1]; | 451 if (length > 0) return this[length - 1]; |
| 388 throw new StateError("No elements"); | 452 throw IterableElementError.noElement(); |
| 389 } | 453 } |
| 390 | 454 |
| 391 dynamic get single { | 455 dynamic get single { |
| 392 if (length == 1) return this[0]; | 456 if (length == 1) return this[0]; |
| 393 if (length == 0) throw new StateError("No elements"); | 457 if (length == 0) throw IterableElementError.noElement(); |
| 394 throw new StateError("More than one element"); | 458 throw IterableElementError.tooMany(); |
| 395 } | 459 } |
| 396 | 460 |
| 397 void removeRange(int start, int end) { | 461 void removeRange(int start, int end) { |
| 398 throw new UnsupportedError( | 462 throw new UnsupportedError( |
| 399 "Cannot remove from a fixed-length list"); | 463 "Cannot remove from a fixed-length list"); |
| 400 } | 464 } |
| 401 | 465 |
| 402 void replaceRange(int start, int end, Iterable iterable) { | 466 void replaceRange(int start, int end, Iterable iterable) { |
| 403 throw new UnsupportedError( | 467 throw new UnsupportedError( |
| 404 "Cannot remove from a fixed-length list"); | 468 "Cannot remove from a fixed-length list"); |
| 405 } | 469 } |
| 406 | 470 |
| 407 List toList({bool growable: true}) { | 471 List toList({bool growable: true}) { |
| 408 return new List.from(this, growable: growable); | 472 return new List.from(this, growable: growable); |
| 409 } | 473 } |
| 410 | 474 |
| 411 Set toSet() { | 475 Set toSet() { |
| 412 return new Set.from(this); | 476 return new Set.from(this); |
| 413 } | 477 } |
| 414 | 478 |
| 415 List sublist(int start, [int end]) { | 479 List sublist(int start, [int end]) { |
| 416 if (end == null) end = this.length; | 480 if (end == null) end = this.length; |
| 417 int length = end - start; | 481 var length = end - start; |
| 418 _rangeCheck(this.length, start, length); | 482 _rangeCheck(this.length, start, length); |
| 419 List result = _createList(length); | 483 List result = _createList(length); |
| 420 result.setRange(0, length, this, start); | 484 result.setRange(0, length, this, start); |
| 421 return result; | 485 return result; |
| 422 } | 486 } |
| 423 | 487 |
| 424 void setRange(int start, int end, Iterable from, [int skipCount = 0]) { | 488 void setRange(int start, int end, Iterable from, [int skipCount = 0]) { |
| 425 // Check ranges. | 489 // Check ranges. |
| 426 if ((start < 0) || (start > length)) { | 490 if ((start < 0) || (start > length)) { |
| 427 throw _newRangeError(start, length + 1); | 491 throw _newRangeError(start, length + 1); |
| 428 } | 492 } |
| 429 if ((end < 0) || (end > length)) { | 493 if ((end < 0) || (end > length)) { |
| 430 throw _newRangeError(end, length + 1); | 494 throw _newRangeError(end, length + 1); |
| 431 } | 495 } |
| 432 if (start > end) { | 496 if (start > end) { |
| 433 throw _newRangeError(start, end + 1); | 497 throw _newRangeError(start, end + 1); |
| 434 } | 498 } |
| 435 if (skipCount < 0) { | 499 if (skipCount < 0) { |
| 436 throw new ArgumentError(skipCount); | 500 throw new ArgumentError(skipCount); |
| 437 } | 501 } |
| 438 | 502 |
| 439 final count = end - start; | 503 final count = end - start; |
| 440 if ((from.length - skipCount) < count) { | 504 if ((from.length - skipCount) < count) { |
| 441 throw new StateError("Not enough elements"); | 505 throw IterableElementError.tooFew(); |
| 442 } | 506 } |
| 443 | 507 |
| 444 if (from is _TypedListBase) { | 508 if (from is _TypedListBase) { |
| 445 if (this.elementSizeInBytes == from.elementSizeInBytes) { | 509 if (this.elementSizeInBytes == from.elementSizeInBytes) { |
| 446 if ((count < 10) && (from.buffer != this.buffer)) { | 510 if ((count < 10) && (from.buffer != this.buffer)) { |
| 447 Lists.copy(from, skipCount, this, start, count); | 511 Lists.copy(from, skipCount, this, start, count); |
| 448 return; | 512 return; |
| 449 } else if (this.buffer._data._setRange( | 513 } else if (this.buffer._data._setRange( |
| 450 start * elementSizeInBytes + this.offsetInBytes, | 514 start * elementSizeInBytes + this.offsetInBytes, |
| 451 count * elementSizeInBytes, | 515 count * elementSizeInBytes, |
| 452 from.buffer._data, | 516 from.buffer._data, |
| 453 skipCount * elementSizeInBytes + from.offsetInBytes, | 517 skipCount * elementSizeInBytes + from.offsetInBytes, |
| 454 ClassID.getID(this), ClassID.getID(from))) { | 518 ClassID.getID(this), ClassID.getID(from))) { |
| 455 return; | 519 return; |
| 456 } | 520 } |
| 457 } else if (from.buffer == this.buffer) { | 521 } else if (from.buffer == this.buffer) { |
| 458 // Different element sizes, but same buffer means that we need | 522 // Different element sizes, but same buffer means that we need |
| 459 // an intermediate structure. | 523 // an intermediate structure. |
| 460 // TODO(srdjan): Optimize to skip copying if the range does not overlap. | 524 // TODO(srdjan): Optimize to skip copying if the range does not overlap. |
| 461 final temp_buffer = new List(count); | 525 final temp_buffer = new List(count); |
| 462 for (int i = 0; i < count; i++) { | 526 for (var i = 0; i < count; i++) { |
| 463 temp_buffer[i] = from[skipCount + i]; | 527 temp_buffer[i] = from[skipCount + i]; |
| 464 } | 528 } |
| 465 for (int i = start; i < end; i++) { | 529 for (var i = start; i < end; i++) { |
| 466 this[i] = temp_buffer[i - start]; | 530 this[i] = temp_buffer[i - start]; |
| 467 } | 531 } |
| 468 return; | 532 return; |
| 469 } | 533 } |
| 470 } | 534 } |
| 471 IterableMixinWorkaround.setRangeList(this, start, | 535 |
| 472 end, from, skipCount); | 536 if (count == 0) return; |
| 537 List otherList; |
| 538 int otherStart; |
| 539 if (from is List) { |
| 540 otherList = from; |
| 541 otherStart = skipCount; |
| 542 } else { |
| 543 otherList = from.skip(skipCount).toList(growable: false); |
| 544 otherStart = 0; |
| 545 } |
| 546 if (otherStart + count > otherList.length) { |
| 547 throw IterableElementError.tooFew(); |
| 548 } |
| 549 Lists.copy(otherList, otherStart, this, start, count); |
| 473 } | 550 } |
| 474 | 551 |
| 475 void setAll(int index, Iterable iterable) { | 552 void setAll(int index, Iterable iterable) { |
| 476 final end = iterable.length + index; | 553 final end = iterable.length + index; |
| 477 setRange(index, end, iterable); | 554 setRange(index, end, iterable); |
| 478 } | 555 } |
| 479 | 556 |
| 480 void fillRange(int start, int end, [fillValue]) { | 557 void fillRange(int start, int end, [fillValue]) { |
| 481 IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); | 558 RangeError.checkValidRange(start, end, this.length); |
| 559 for (var i = start; i < end; ++i) { |
| 560 this[i] = fillValue; |
| 561 } |
| 482 } | 562 } |
| 483 | 563 |
| 484 | 564 |
| 485 // Method(s) implementing Object interface. | 565 // Method(s) implementing Object interface. |
| 486 | 566 |
| 487 String toString() => ListBase.listToString(this); | 567 String toString() => ListBase.listToString(this); |
| 488 | 568 |
| 489 | 569 |
| 490 // Internal utility methods. | 570 // Internal utility methods. |
| 491 | 571 |
| (...skipping 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3486 return value; | 3566 return value; |
| 3487 } | 3567 } |
| 3488 return object; | 3568 return object; |
| 3489 } | 3569 } |
| 3490 | 3570 |
| 3491 | 3571 |
| 3492 _newRangeError(int index, int length) { | 3572 _newRangeError(int index, int length) { |
| 3493 String message = "$index must be in the range [0..$length)"; | 3573 String message = "$index must be in the range [0..$length)"; |
| 3494 return new RangeError(message); | 3574 return new RangeError(message); |
| 3495 } | 3575 } |
| OLD | NEW |