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

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: Also document Map.length is efficient, while we are at it. 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
« no previous file with comments | « runtime/lib/immutable_map.dart ('k') | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /**
8 * Marker interface for [Iterable] subclasses that have an efficient
9 * [length] implementation.
10 */
11 abstract class EfficientLength {
12 /**
13 * Returns the number of elements in the iterable.
14 *
15 * This is an efficient operation that doesn't require iterating through
16 * the elements.
17 */
18 int get length;
19 }
7 20
8 // This is a hack to make @deprecated work in dart:io. Don't remove or use this, 21 // 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! 22 // unless coordinated with either me or the core library team. Thanks!
10 // TODO(ajohnsen): Remove at the 11th of August 2013. 23 // TODO(ajohnsen): Remove at the 11th of August 2013.
11 // TODO(ajohnsen): Remove hide in: 24 // TODO(ajohnsen): Remove hide in:
12 // tools/dom/templates/html/dart2js/html_dart2js.darttemplate 25 // tools/dom/templates/html/dart2js/html_dart2js.darttemplate
13 // tools/dom/templates/html/dart2js/svg_dart2js.darttemplate 26 // tools/dom/templates/html/dart2js/svg_dart2js.darttemplate
14 // tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate 27 // tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
15 // tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate 28 // tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
16 // tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate 29 // tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
(...skipping 12 matching lines...) Expand all
29 // This is, because we have a test that verifies that no metadata is included 42 // This is, because we have a test that verifies that no metadata is included
30 // in the output, when no mirrors need them. 43 // in the output, when no mirrors need them.
31 const deprecated = "qB2n4PYM"; 44 const deprecated = "qB2n4PYM";
32 45
33 /** 46 /**
34 * An [Iterable] for classes that have efficient [length] and [elementAt]. 47 * An [Iterable] for classes that have efficient [length] and [elementAt].
35 * 48 *
36 * All other methods are implemented in terms of [length] and [elementAt], 49 * All other methods are implemented in terms of [length] and [elementAt],
37 * including [iterator]. 50 * including [iterator].
38 */ 51 */
39 abstract class ListIterable<E> extends IterableBase<E> { 52 abstract class ListIterable<E> extends IterableBase<E>
53 implements EfficientLength {
40 int get length; 54 int get length;
41 E elementAt(int i); 55 E elementAt(int i);
42 56
43 const ListIterable(); 57 const ListIterable();
44 58
45 Iterator<E> get iterator => new ListIterator<E>(this); 59 Iterator<E> get iterator => new ListIterator<E>(this);
46 60
47 void forEach(void action(E element)) { 61 void forEach(void action(E element)) {
48 int length = this.length; 62 int length = this.length;
49 for (int i = 0; i < length; i++) { 63 for (int i = 0; i < length; i++) {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 return true; 348 return true;
335 } 349 }
336 } 350 }
337 351
338 typedef T _Transformation<S, T>(S value); 352 typedef T _Transformation<S, T>(S value);
339 353
340 class MappedIterable<S, T> extends IterableBase<T> { 354 class MappedIterable<S, T> extends IterableBase<T> {
341 final Iterable<S> _iterable; 355 final Iterable<S> _iterable;
342 final _Transformation<S, T> _f; 356 final _Transformation<S, T> _f;
343 357
344 MappedIterable(this._iterable, T this._f(S element)); 358 factory MappedIterable(Iterable iterable, T function(S value)) {
359 if (iterable is EfficientLength) {
360 return new EfficientLengthMappedIterable<S, T>(iterable, function);
361 }
362 return new MappedIterable<S, T>._(iterable, function);
363 }
364
365 MappedIterable._(this._iterable, T this._f(S element));
345 366
346 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); 367 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f);
347 368
348 // Length related functions are independent of the mapping. 369 // Length related functions are independent of the mapping.
349 int get length => _iterable.length; 370 int get length => _iterable.length;
350 bool get isEmpty => _iterable.isEmpty; 371 bool get isEmpty => _iterable.isEmpty;
351 372
352 // Index based lookup can be done before transforming. 373 // Index based lookup can be done before transforming.
353 T get first => _f(_iterable.first); 374 T get first => _f(_iterable.first);
354 T get last => _f(_iterable.last); 375 T get last => _f(_iterable.last);
355 T get single => _f(_iterable.single); 376 T get single => _f(_iterable.single);
356 T elementAt(int index) => _f(_iterable.elementAt(index)); 377 T elementAt(int index) => _f(_iterable.elementAt(index));
357 } 378 }
358 379
380 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
381 implements EfficientLength {
382 EfficientLengthMappedIterable(Iterable iterable, T function(S value))
383 : super._(iterable, function);
384 }
385
359 class MappedIterator<S, T> extends Iterator<T> { 386 class MappedIterator<S, T> extends Iterator<T> {
360 T _current; 387 T _current;
361 final Iterator<S> _iterator; 388 final Iterator<S> _iterator;
362 final _Transformation<S, T> _f; 389 final _Transformation<S, T> _f;
363 390
364 MappedIterator(this._iterator, T this._f(S element)); 391 MappedIterator(this._iterator, T this._f(S element));
365 392
366 bool moveNext() { 393 bool moveNext() {
367 if (_iterator.moveNext()) { 394 if (_iterator.moveNext()) {
368 _current = _f(_iterator.current); 395 _current = _f(_iterator.current);
369 return true; 396 return true;
370 } 397 }
371 _current = null; 398 _current = null;
372 return false; 399 return false;
373 } 400 }
374 401
375 T get current => _current; 402 T get current => _current;
376 } 403 }
377 404
378 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ 405 /**
379 class MappedListIterable<S, T> extends ListIterable<T> { 406 * Specialized alternative to [MappedIterable] for mapped [List]s.
407 *
408 * Expects efficient `length` and `elementAt` on the source iterable.
409 */
410 class MappedListIterable<S, T> extends ListIterable<T>
411 implements EfficientLength {
380 final Iterable<S> _source; 412 final Iterable<S> _source;
381 final _Transformation<S, T> _f; 413 final _Transformation<S, T> _f;
382 414
383 MappedListIterable(this._source, T this._f(S value)); 415 MappedListIterable(this._source, T this._f(S value));
384 416
385 int get length => _source.length; 417 int get length => _source.length;
386 T elementAt(int index) => _f(_source.elementAt(index)); 418 T elementAt(int index) => _f(_source.elementAt(index));
387 } 419 }
388 420
389 421
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 } 490 }
459 _current = _currentExpansion.current; 491 _current = _currentExpansion.current;
460 return true; 492 return true;
461 } 493 }
462 } 494 }
463 495
464 class TakeIterable<E> extends IterableBase<E> { 496 class TakeIterable<E> extends IterableBase<E> {
465 final Iterable<E> _iterable; 497 final Iterable<E> _iterable;
466 final int _takeCount; 498 final int _takeCount;
467 499
468 TakeIterable(this._iterable, this._takeCount) { 500 factory TakeIterable(Iterable<E> iterable, int takeCount) {
469 if (_takeCount is! int || _takeCount < 0) { 501 if (takeCount is! int || takeCount < 0) {
470 throw new ArgumentError(_takeCount); 502 throw new ArgumentError(takeCount);
471 } 503 }
504 if (iterable is EfficientLength) {
505 return new EfficientLengthTakeIterable<E>(iterable, takeCount);
506 }
507 return new TakeIterable<E>._(iterable, takeCount);
472 } 508 }
473 509
510 Iterable<E> take(int takeCount) {
511 if (takeCount is! int || takeCount < 0) {
512 throw new RangeError.value(takeCount);
513 }
514 if (_takeCount < takeCount) {
515 takeCount = _takeCount;
516 }
517 return new TakeIterable<E>._(_iterable, takeCount)
518 }
519
520 TakeIterable._(this._iterable, this._takeCount);
521
474 Iterator<E> get iterator { 522 Iterator<E> get iterator {
475 return new TakeIterator<E>(_iterable.iterator, _takeCount); 523 return new TakeIterator<E>(_iterable.iterator, _takeCount);
476 } 524 }
477 } 525 }
478 526
527 class EfficientLengthTakeIterable<E> extends TakeIterable<E>
528 implements EfficientLength {
529 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
530 : super._(iterable, takeCount);
531
532 Iterable<E> take(int takeCount) {
533 if (takeCount is! int || takeCount < 0) {
534 throw new RangeError.value(takeCount);
535 }
536 if (_takeCount < takeCount) {
537 takeCount = _takeCount;
538 }
539 return new EfficientLengthTakeIterable<E>(_iterable, takeCount)
540 }
541
542 int get length {
543 int iterableLength = _iterable.length;
544 if (iterableLength > _takeCount) return _takeCount;
545 return iterableLength;
546 }
547 }
548
549
479 class TakeIterator<E> extends Iterator<E> { 550 class TakeIterator<E> extends Iterator<E> {
480 final Iterator<E> _iterator; 551 final Iterator<E> _iterator;
481 int _remaining; 552 int _remaining;
482 553
483 TakeIterator(this._iterator, this._remaining) { 554 TakeIterator(this._iterator, this._remaining) {
484 assert(_remaining is int && _remaining >= 0); 555 assert(_remaining is int && _remaining >= 0);
485 } 556 }
486 557
487 bool moveNext() { 558 bool moveNext() {
488 _remaining--; 559 _remaining--;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 E get current { 600 E get current {
530 if (_isFinished) return null; 601 if (_isFinished) return null;
531 return _iterator.current; 602 return _iterator.current;
532 } 603 }
533 } 604 }
534 605
535 class SkipIterable<E> extends IterableBase<E> { 606 class SkipIterable<E> extends IterableBase<E> {
536 final Iterable<E> _iterable; 607 final Iterable<E> _iterable;
537 final int _skipCount; 608 final int _skipCount;
538 609
539 SkipIterable(this._iterable, this._skipCount) { 610 factory SkipIterable(Iterable<E> iterable, int skipCount) {
611 if (iterable is EfficientLength) {
612 return new EfficientLengthSkipIterable<E>(iterable, skipCount);
613 }
614 return new SkipIterable<E>._(iterable, skipCount);
615 }
616
617 SkipIterable._(this._iterable, this._skipCount) {
540 if (_skipCount is! int || _skipCount < 0) { 618 if (_skipCount is! int || _skipCount < 0) {
541 throw new RangeError(_skipCount); 619 throw new RangeError(_skipCount);
542 } 620 }
543 } 621 }
544 622
545 Iterable<E> skip(int n) { 623 Iterable<E> skip(int n) {
546 if (n is! int || n < 0) { 624 if (n is! int || n < 0) {
547 throw new RangeError.value(n); 625 throw new RangeError.value(n);
548 } 626 }
549 return new SkipIterable<E>(_iterable, _skipCount + n); 627 return new SkipIterable<E>._(_iterable, _skipCount + n);
550 } 628 }
551 629
552 Iterator<E> get iterator { 630 Iterator<E> get iterator {
553 return new SkipIterator<E>(_iterable.iterator, _skipCount); 631 return new SkipIterator<E>(_iterable.iterator, _skipCount);
554 } 632 }
555 } 633 }
556 634
635 class EfficientLengthSkipIterable<E> extends SkipIterable<E>
636 implements EfficientLength {
637 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount)
638 : super._(iterable, skipCount);
639
640 Iterable<E> skip(int n) {
641 if (n is! int || n < 0) {
642 throw new RangeError.value(n);
643 }
644 return new EfficientLengthSkipIterable<E>(_iterable, _skipCount + n);
645 }
646
647 int get length {
648 int length = _iterable.length - _skipCount;
649 if (length >= 0) return length;
650 return 0;
651 }
652 }
653
557 class SkipIterator<E> extends Iterator<E> { 654 class SkipIterator<E> extends Iterator<E> {
558 final Iterator<E> _iterator; 655 final Iterator<E> _iterator;
559 int _skipCount; 656 int _skipCount;
560 657
561 SkipIterator(this._iterator, this._skipCount) { 658 SkipIterator(this._iterator, this._skipCount) {
562 assert(_skipCount is int && _skipCount >= 0); 659 assert(_skipCount is int && _skipCount >= 0);
563 } 660 }
564 661
565 bool moveNext() { 662 bool moveNext() {
566 for (int i = 0; i < _skipCount; i++) _iterator.moveNext(); 663 for (int i = 0; i < _skipCount; i++) _iterator.moveNext();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 } 695 }
599 return _iterator.moveNext(); 696 return _iterator.moveNext();
600 } 697 }
601 698
602 E get current => _iterator.current; 699 E get current => _iterator.current;
603 } 700 }
604 701
605 /** 702 /**
606 * The always empty [Iterable]. 703 * The always empty [Iterable].
607 */ 704 */
608 class EmptyIterable<E> extends IterableBase<E> { 705 class EmptyIterable<E> extends IterableBase<E> implements EfficientLength {
609 const EmptyIterable(); 706 const EmptyIterable();
610 707
611 Iterator<E> get iterator => const EmptyIterator(); 708 Iterator<E> get iterator => const EmptyIterator();
612 709
613 void forEach(void action(E element)) {} 710 void forEach(void action(E element)) {}
614 711
615 bool get isEmpty => true; 712 bool get isEmpty => true;
616 713
617 int get length => 0; 714 int get length => 0;
618 715
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 987 }
891 } 988 }
892 return buffer.toString(); 989 return buffer.toString();
893 } 990 }
894 991
895 static String toStringIterable(Iterable iterable, String leftDelimiter, 992 static String toStringIterable(Iterable iterable, String leftDelimiter,
896 String rightDelimiter) { 993 String rightDelimiter) {
897 for (int i = 0; i < _toStringList.length; i++) { 994 for (int i = 0; i < _toStringList.length; i++) {
898 if (identical(_toStringList[i], iterable)) { 995 if (identical(_toStringList[i], iterable)) {
899 return '$leftDelimiter...$rightDelimiter'; 996 return '$leftDelimiter...$rightDelimiter';
900 } 997 }
901 } 998 }
902 999
903 StringBuffer result = new StringBuffer(); 1000 StringBuffer result = new StringBuffer();
904 try { 1001 try {
905 _toStringList.add(iterable); 1002 _toStringList.add(iterable);
906 result.write(leftDelimiter); 1003 result.write(leftDelimiter);
907 result.writeAll(iterable, ', '); 1004 result.writeAll(iterable, ', ');
908 result.write(rightDelimiter); 1005 result.write(rightDelimiter);
909 } finally { 1006 } finally {
910 assert(identical(_toStringList.last, iterable)); 1007 assert(identical(_toStringList.last, iterable));
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 } 1111 }
1015 if (otherStart + length > otherList.length) { 1112 if (otherStart + length > otherList.length) {
1016 throw new StateError("Not enough elements"); 1113 throw new StateError("Not enough elements");
1017 } 1114 }
1018 Arrays.copy(otherList, otherStart, list, start, length); 1115 Arrays.copy(otherList, otherStart, list, start, length);
1019 } 1116 }
1020 1117
1021 static void replaceRangeList(List list, int start, int end, 1118 static void replaceRangeList(List list, int start, int end,
1022 Iterable iterable) { 1119 Iterable iterable) {
1023 _rangeCheck(list, start, end); 1120 _rangeCheck(list, start, end);
1024 // TODO(floitsch): optimize this. 1121 if (iterable is! EfficientLength) {
1025 list.removeRange(start, end); 1122 iterable = iterable.toList();
1026 list.insertAll(start, iterable); 1123 }
1124 int removeLength = end - start;
1125 int insertLength = iterable.length;
1126 if (removeLength >= insertLength) {
1127 int delta = removeLength - insertLength;
1128 int insertEnd = start + insertLength;
1129 int newEnd = list.length - delta;
1130 list.setRange(start, insertEnd, iterable);
1131 if (delta != 0) {
1132 list.setRange(insertEnd, newEnd, list, end);
1133 list.length = newEnd;
1134 }
1135 } else {
1136 int delta = insertLength - removeLength;
1137 int newLength = list.length + delta;
1138 int insertEnd = start + insertLength; // aka. end + delta.
1139 list.length = newLength;
1140 list.setRange(insertEnd, newLength, list, end);
1141 list.setRange(start, insertEnd, iterable);
1142 }
1027 } 1143 }
1028 1144
1029 static void fillRangeList(List list, int start, int end, fillValue) { 1145 static void fillRangeList(List list, int start, int end, fillValue) {
1030 _rangeCheck(list, start, end); 1146 _rangeCheck(list, start, end);
1031 for (int i = start; i < end; i++) { 1147 for (int i = start; i < end; i++) {
1032 list[i] = fillValue; 1148 list[i] = fillValue;
1033 } 1149 }
1034 } 1150 }
1035 1151
1036 static void insertAllList(List list, int index, Iterable iterable) { 1152 static void insertAllList(List list, int index, Iterable iterable) {
1037 if (index < 0 || index > list.length) { 1153 if (index < 0 || index > list.length) {
1038 throw new RangeError.range(index, 0, list.length); 1154 throw new RangeError.range(index, 0, list.length);
1039 } 1155 }
1040 if (iterable is! List && iterable is! Set) { 1156 if (iterable is! EfficientLength) {
1041 iterable = iterable.toList(growable: false); 1157 iterable = iterable.toList(growable: false);
1042 } 1158 }
1043 int insertionLength = iterable.length; 1159 int insertionLength = iterable.length;
1044 list.length += insertionLength; 1160 list.length += insertionLength;
1045 list.setRange(index + insertionLength, list.length, list, index); 1161 list.setRange(index + insertionLength, list.length, list, index);
1046 for (var element in iterable) { 1162 for (var element in iterable) {
1047 list[index++] = element; 1163 list[index++] = element;
1048 } 1164 }
1049 } 1165 }
1050 1166
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 1210
1095 static Set setDifference(Set set, Set other, Set result) { 1211 static Set setDifference(Set set, Set other, Set result) {
1096 for (var element in set) { 1212 for (var element in set) {
1097 if (!other.contains(element)) { 1213 if (!other.contains(element)) {
1098 result.add(element); 1214 result.add(element);
1099 } 1215 }
1100 } 1216 }
1101 return result; 1217 return result;
1102 } 1218 }
1103 } 1219 }
OLDNEW
« no previous file with comments | « runtime/lib/immutable_map.dart ('k') | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698