Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: sdk/lib/_collection_dev/iterable.dart

Issue 26681002: Add EfficientLength marker interface to some iterabels. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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.dev; 5 part of dart._collection.dev;
6 6
7 7
8 // This is a hack to make @deprecated work in dart:io. Don't remove or use this, 8 // This is a hack to make @deprecated work in dart:io. Don't remove or use this,
9 // unless coordinated with either me or the core library team. Thanks! 9 // unless coordinated with either me or the core library team. Thanks!
10 // TODO(ajohnsen): Remove at the 11th of August 2013. 10 // TODO(ajohnsen): Remove at the 11th of August 2013.
(...skipping 18 matching lines...) Expand all
29 // This is, because we have a test that verifies that no metadata is included 29 // This is, because we have a test that verifies that no metadata is included
30 // in the output, when no mirrors need them. 30 // in the output, when no mirrors need them.
31 const deprecated = "qB2n4PYM"; 31 const deprecated = "qB2n4PYM";
32 32
33 /** 33 /**
34 * An [Iterable] for classes that have efficient [length] and [elementAt]. 34 * An [Iterable] for classes that have efficient [length] and [elementAt].
35 * 35 *
36 * All other methods are implemented in terms of [length] and [elementAt], 36 * All other methods are implemented in terms of [length] and [elementAt],
37 * including [iterator]. 37 * including [iterator].
38 */ 38 */
39 abstract class ListIterable<E> extends IterableBase<E> { 39 abstract class ListIterable<E> extends IterableBase<E>
40 implements EfficientLength {
40 int get length; 41 int get length;
41 E elementAt(int i); 42 E elementAt(int i);
42 43
43 const ListIterable(); 44 const ListIterable();
44 45
45 Iterator<E> get iterator => new ListIterator<E>(this); 46 Iterator<E> get iterator => new ListIterator<E>(this);
46 47
47 void forEach(void action(E element)) { 48 void forEach(void action(E element)) {
48 int length = this.length; 49 int length = this.length;
49 for (int i = 0; i < length; i++) { 50 for (int i = 0; i < length; i++) {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 return true; 335 return true;
335 } 336 }
336 } 337 }
337 338
338 typedef T _Transformation<S, T>(S value); 339 typedef T _Transformation<S, T>(S value);
339 340
340 class MappedIterable<S, T> extends IterableBase<T> { 341 class MappedIterable<S, T> extends IterableBase<T> {
341 final Iterable<S> _iterable; 342 final Iterable<S> _iterable;
342 final _Transformation<S, T> _f; 343 final _Transformation<S, T> _f;
343 344
344 MappedIterable(this._iterable, T this._f(S element)); 345 factory MappedIterable(Iterable iterable, T function(S value)) {
346 if (iterable is EfficientLength) {
347 return new EfficientLengthMappedIterable<S, T>(iterable, function);
348 }
349 return new MappedIterable<S, T>._(iterable, function);
350 }
351
352 MappedIterable._(this._iterable, T this._f(S element));
345 353
346 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); 354 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f);
347 355
348 // Length related functions are independent of the mapping. 356 // Length related functions are independent of the mapping.
349 int get length => _iterable.length; 357 int get length => _iterable.length;
350 bool get isEmpty => _iterable.isEmpty; 358 bool get isEmpty => _iterable.isEmpty;
351 359
352 // Index based lookup can be done before transforming. 360 // Index based lookup can be done before transforming.
353 T get first => _f(_iterable.first); 361 T get first => _f(_iterable.first);
354 T get last => _f(_iterable.last); 362 T get last => _f(_iterable.last);
355 T get single => _f(_iterable.single); 363 T get single => _f(_iterable.single);
356 T elementAt(int index) => _f(_iterable.elementAt(index)); 364 T elementAt(int index) => _f(_iterable.elementAt(index));
357 } 365 }
358 366
367 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
368 implements EfficientLength {
369 EfficientLengthMappedIterable(Iterable iterable, T function(S value))
370 : super._(iterable, function);
371 }
372
359 class MappedIterator<S, T> extends Iterator<T> { 373 class MappedIterator<S, T> extends Iterator<T> {
360 T _current; 374 T _current;
361 final Iterator<S> _iterator; 375 final Iterator<S> _iterator;
362 final _Transformation<S, T> _f; 376 final _Transformation<S, T> _f;
363 377
364 MappedIterator(this._iterator, T this._f(S element)); 378 MappedIterator(this._iterator, T this._f(S element));
365 379
366 bool moveNext() { 380 bool moveNext() {
367 if (_iterator.moveNext()) { 381 if (_iterator.moveNext()) {
368 _current = _f(_iterator.current); 382 _current = _f(_iterator.current);
369 return true; 383 return true;
370 } 384 }
371 _current = null; 385 _current = null;
372 return false; 386 return false;
373 } 387 }
374 388
375 T get current => _current; 389 T get current => _current;
376 } 390 }
377 391
378 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ 392 /**
379 class MappedListIterable<S, T> extends ListIterable<T> { 393 * Specialized alternative to [MappedIterable] for mapped [List]s.
394 *
395 * Expects efficient `length` and `elementAt` on the source iterable.
396 */
397 class MappedListIterable<S, T> extends ListIterable<T>
398 implements EfficientLength {
380 final Iterable<S> _source; 399 final Iterable<S> _source;
381 final _Transformation<S, T> _f; 400 final _Transformation<S, T> _f;
382 401
383 MappedListIterable(this._source, T this._f(S value)); 402 MappedListIterable(this._source, T this._f(S value));
384 403
385 int get length => _source.length; 404 int get length => _source.length;
386 T elementAt(int index) => _f(_source.elementAt(index)); 405 T elementAt(int index) => _f(_source.elementAt(index));
387 } 406 }
388 407
389 408
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 } 477 }
459 _current = _currentExpansion.current; 478 _current = _currentExpansion.current;
460 return true; 479 return true;
461 } 480 }
462 } 481 }
463 482
464 class TakeIterable<E> extends IterableBase<E> { 483 class TakeIterable<E> extends IterableBase<E> {
465 final Iterable<E> _iterable; 484 final Iterable<E> _iterable;
466 final int _takeCount; 485 final int _takeCount;
467 486
468 TakeIterable(this._iterable, this._takeCount) { 487 factory TakeIterable(Iterable<E> iterable, int takeCount) {
469 if (_takeCount is! int || _takeCount < 0) { 488 if (takeCount is! int || takeCount < 0) {
470 throw new ArgumentError(_takeCount); 489 throw new ArgumentError(takeCount);
471 } 490 }
491 if (iterable is EfficientLength) {
492 return new EfficientLengthTakeIterable<E>(iterable, takeCount);
493 }
494 return new TakeIterable<E>._(iterable, takeCount);
472 } 495 }
473 496
497 TakeIterable._(this._iterable, this._takeCount);
498
474 Iterator<E> get iterator { 499 Iterator<E> get iterator {
475 return new TakeIterator<E>(_iterable.iterator, _takeCount); 500 return new TakeIterator<E>(_iterable.iterator, _takeCount);
476 } 501 }
477 } 502 }
478 503
504 class EfficientLengthTakeIterable<E> extends TakeIterable<E>
505 implements EfficientLength {
506 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
507 : super._(iterable, takeCount);
508
509 int get length {
510 int iterableLength = _iterable.length;
511 if (iterableLength > _takeCount) return _takeCount;
512 return iterableLength;
513 }
514 }
515
516
479 class TakeIterator<E> extends Iterator<E> { 517 class TakeIterator<E> extends Iterator<E> {
480 final Iterator<E> _iterator; 518 final Iterator<E> _iterator;
481 int _remaining; 519 int _remaining;
482 520
483 TakeIterator(this._iterator, this._remaining) { 521 TakeIterator(this._iterator, this._remaining) {
484 assert(_remaining is int && _remaining >= 0); 522 assert(_remaining is int && _remaining >= 0);
485 } 523 }
486 524
487 bool moveNext() { 525 bool moveNext() {
488 _remaining--; 526 _remaining--;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 E get current { 567 E get current {
530 if (_isFinished) return null; 568 if (_isFinished) return null;
531 return _iterator.current; 569 return _iterator.current;
532 } 570 }
533 } 571 }
534 572
535 class SkipIterable<E> extends IterableBase<E> { 573 class SkipIterable<E> extends IterableBase<E> {
536 final Iterable<E> _iterable; 574 final Iterable<E> _iterable;
537 final int _skipCount; 575 final int _skipCount;
538 576
539 SkipIterable(this._iterable, this._skipCount) { 577 factory SkipIterable(Iterable<E> iterable, int skipCount) {
578 if (iterable is EfficientLength) {
579 return new EfficientLengthSkipIterable<E>(iterable, skipCount);
580 }
581 return new SkipIterable<E>._(iterable, skipCount);
582 }
583
584 SkipIterable._(this._iterable, this._skipCount) {
540 if (_skipCount is! int || _skipCount < 0) { 585 if (_skipCount is! int || _skipCount < 0) {
sra1 2013/10/09 21:16:53 Skip and Take are asymmetrical w.r.t. where the sk
541 throw new RangeError(_skipCount); 586 throw new RangeError(_skipCount);
542 } 587 }
543 } 588 }
544 589
545 Iterable<E> skip(int n) { 590 Iterable<E> skip(int n) {
546 if (n is! int || n < 0) { 591 if (n is! int || n < 0) {
547 throw new RangeError.value(n); 592 throw new RangeError.value(n);
548 } 593 }
549 return new SkipIterable<E>(_iterable, _skipCount + n); 594 return new SkipIterable<E>(_iterable, _skipCount + n);
550 } 595 }
551 596
552 Iterator<E> get iterator { 597 Iterator<E> get iterator {
553 return new SkipIterator<E>(_iterable.iterator, _skipCount); 598 return new SkipIterator<E>(_iterable.iterator, _skipCount);
554 } 599 }
555 } 600 }
556 601
602 class EfficientLengthSkipIterable<E> extends SkipIterable<E>
603 implements EfficientLength {
604 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount)
605 : super._(iterable, skipCount);
606
607 int get length {
608 int length = _iterable.length - _skipCount;
609 if (length >= 0) return length;
610 return 0;
611 }
612 }
613
557 class SkipIterator<E> extends Iterator<E> { 614 class SkipIterator<E> extends Iterator<E> {
558 final Iterator<E> _iterator; 615 final Iterator<E> _iterator;
559 int _skipCount; 616 int _skipCount;
560 617
561 SkipIterator(this._iterator, this._skipCount) { 618 SkipIterator(this._iterator, this._skipCount) {
562 assert(_skipCount is int && _skipCount >= 0); 619 assert(_skipCount is int && _skipCount >= 0);
563 } 620 }
564 621
565 bool moveNext() { 622 bool moveNext() {
566 for (int i = 0; i < _skipCount; i++) _iterator.moveNext(); 623 for (int i = 0; i < _skipCount; i++) _iterator.moveNext();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 } 655 }
599 return _iterator.moveNext(); 656 return _iterator.moveNext();
600 } 657 }
601 658
602 E get current => _iterator.current; 659 E get current => _iterator.current;
603 } 660 }
604 661
605 /** 662 /**
606 * The always empty [Iterable]. 663 * The always empty [Iterable].
607 */ 664 */
608 class EmptyIterable<E> extends IterableBase<E> { 665 class EmptyIterable<E> extends IterableBase<E> implements EfficientLength {
609 const EmptyIterable(); 666 const EmptyIterable();
610 667
611 Iterator<E> get iterator => const EmptyIterator(); 668 Iterator<E> get iterator => const EmptyIterator();
612 669
613 void forEach(void action(E element)) {} 670 void forEach(void action(E element)) {}
614 671
615 bool get isEmpty => true; 672 bool get isEmpty => true;
616 673
617 int get length => 0; 674 int get length => 0;
618 675
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 947 }
891 } 948 }
892 return buffer.toString(); 949 return buffer.toString();
893 } 950 }
894 951
895 static String toStringIterable(Iterable iterable, String leftDelimiter, 952 static String toStringIterable(Iterable iterable, String leftDelimiter,
896 String rightDelimiter) { 953 String rightDelimiter) {
897 for (int i = 0; i < _toStringList.length; i++) { 954 for (int i = 0; i < _toStringList.length; i++) {
898 if (identical(_toStringList[i], iterable)) { 955 if (identical(_toStringList[i], iterable)) {
899 return '$leftDelimiter...$rightDelimiter'; 956 return '$leftDelimiter...$rightDelimiter';
900 } 957 }
901 } 958 }
902 959
903 StringBuffer result = new StringBuffer(); 960 StringBuffer result = new StringBuffer();
904 try { 961 try {
905 _toStringList.add(iterable); 962 _toStringList.add(iterable);
906 result.write(leftDelimiter); 963 result.write(leftDelimiter);
907 result.writeAll(iterable, ', '); 964 result.writeAll(iterable, ', ');
908 result.write(rightDelimiter); 965 result.write(rightDelimiter);
909 } finally { 966 } finally {
910 assert(identical(_toStringList.last, iterable)); 967 assert(identical(_toStringList.last, iterable));
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 } 1071 }
1015 if (otherStart + length > otherList.length) { 1072 if (otherStart + length > otherList.length) {
1016 throw new StateError("Not enough elements"); 1073 throw new StateError("Not enough elements");
1017 } 1074 }
1018 Arrays.copy(otherList, otherStart, list, start, length); 1075 Arrays.copy(otherList, otherStart, list, start, length);
1019 } 1076 }
1020 1077
1021 static void replaceRangeList(List list, int start, int end, 1078 static void replaceRangeList(List list, int start, int end,
1022 Iterable iterable) { 1079 Iterable iterable) {
1023 _rangeCheck(list, start, end); 1080 _rangeCheck(list, start, end);
1024 // TODO(floitsch): optimize this. 1081 if (iterable is! EfficientLength) {
1025 list.removeRange(start, end); 1082 iterable = iterable.toList();
1026 list.insertAll(start, iterable); 1083 }
1084 int removeLength = end - start;
1085 int insertLength = iterable.length;
1086 if (removeLength >= insertLength) {
1087 int delta = removeLength - insertLength;
1088 int insertEnd = start + insertLength;
1089 int newEnd = list.length - delta;
1090 list.setRange(start, insertEnd, iterable);
1091 if (delta != 0) {
1092 list.setRange(insertEnd, newEnd, list, end);
1093 list.length = newEnd;
1094 }
1095 } else {
1096 int delta = insertLength - removeLength;
1097 int newLength = list.length + delta;
1098 int insertEnd = start + insertLength; // aka. end + delta.
1099 list.length = newLength;
1100 list.setRange(insertEnd, newLength, list, end);
1101 list.setRange(start, insertEnd, iterable);
1102 }
1027 } 1103 }
1028 1104
1029 static void fillRangeList(List list, int start, int end, fillValue) { 1105 static void fillRangeList(List list, int start, int end, fillValue) {
1030 _rangeCheck(list, start, end); 1106 _rangeCheck(list, start, end);
1031 for (int i = start; i < end; i++) { 1107 for (int i = start; i < end; i++) {
1032 list[i] = fillValue; 1108 list[i] = fillValue;
1033 } 1109 }
1034 } 1110 }
1035 1111
1036 static void insertAllList(List list, int index, Iterable iterable) { 1112 static void insertAllList(List list, int index, Iterable iterable) {
1037 if (index < 0 || index > list.length) { 1113 if (index < 0 || index > list.length) {
1038 throw new RangeError.range(index, 0, list.length); 1114 throw new RangeError.range(index, 0, list.length);
1039 } 1115 }
1040 if (iterable is! List && iterable is! Set) { 1116 if (iterable is! EfficientLength) {
1041 iterable = iterable.toList(growable: false); 1117 iterable = iterable.toList(growable: false);
1042 } 1118 }
1043 int insertionLength = iterable.length; 1119 int insertionLength = iterable.length;
1044 list.length += insertionLength; 1120 list.length += insertionLength;
1045 list.setRange(index + insertionLength, list.length, list, index); 1121 list.setRange(index + insertionLength, list.length, list, index);
1046 for (var element in iterable) { 1122 for (var element in iterable) {
1047 list[index++] = element; 1123 list[index++] = element;
1048 } 1124 }
1049 } 1125 }
1050 1126
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 1170
1095 static Set setDifference(Set set, Set other, Set result) { 1171 static Set setDifference(Set set, Set other, Set result) {
1096 for (var element in set) { 1172 for (var element in set) {
1097 if (!other.contains(element)) { 1173 if (!other.contains(element)) {
1098 result.add(element); 1174 result.add(element);
1099 } 1175 }
1100 } 1176 }
1101 return result; 1177 return result;
1102 } 1178 }
1103 } 1179 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698