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

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

Issue 133273011: Revert "Rename internal library dart:_collection-dev to dart:_internal." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: reapply after revert. Created 6 years, 11 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 | « sdk/lib/_collection_dev/collection_dev_sources.gypi ('k') | sdk/lib/_collection_dev/list.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart._collection.dev;
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 }
20
21 /**
22 * An [Iterable] for classes that have efficient [length] and [elementAt].
23 *
24 * All other methods are implemented in terms of [length] and [elementAt],
25 * including [iterator].
26 */
27 abstract class ListIterable<E> extends IterableBase<E>
28 implements EfficientLength {
29 int get length;
30 E elementAt(int i);
31
32 const ListIterable();
33
34 Iterator<E> get iterator => new ListIterator<E>(this);
35
36 void forEach(void action(E element)) {
37 int length = this.length;
38 for (int i = 0; i < length; i++) {
39 action(elementAt(i));
40 if (length != this.length) {
41 throw new ConcurrentModificationError(this);
42 }
43 }
44 }
45
46 bool get isEmpty => length == 0;
47
48 E get first {
49 if (length == 0) throw new StateError("No elements");
50 return elementAt(0);
51 }
52
53 E get last {
54 if (length == 0) throw new StateError("No elements");
55 return elementAt(length - 1);
56 }
57
58 E get single {
59 if (length == 0) throw new StateError("No elements");
60 if (length > 1) throw new StateError("Too many elements");
61 return elementAt(0);
62 }
63
64 bool contains(Object element) {
65 int length = this.length;
66 for (int i = 0; i < length; i++) {
67 if (elementAt(i) == element) return true;
68 if (length != this.length) {
69 throw new ConcurrentModificationError(this);
70 }
71 }
72 return false;
73 }
74
75 bool every(bool test(E element)) {
76 int length = this.length;
77 for (int i = 0; i < length; i++) {
78 if (!test(elementAt(i))) return false;
79 if (length != this.length) {
80 throw new ConcurrentModificationError(this);
81 }
82 }
83 return true;
84 }
85
86 bool any(bool test(E element)) {
87 int length = this.length;
88 for (int i = 0; i < length; i++) {
89 if (test(elementAt(i))) return true;
90 if (length != this.length) {
91 throw new ConcurrentModificationError(this);
92 }
93 }
94 return false;
95 }
96
97 dynamic firstWhere(bool test(E element), { Object orElse() }) {
98 int length = this.length;
99 for (int i = 0; i < length; i++) {
100 E element = elementAt(i);
101 if (test(element)) return element;
102 if (length != this.length) {
103 throw new ConcurrentModificationError(this);
104 }
105 }
106 if (orElse != null) return orElse();
107 throw new StateError("No matching element");
108 }
109
110 dynamic lastWhere(bool test(E element), { Object orElse() }) {
111 int length = this.length;
112 for (int i = length - 1; i >= 0; i--) {
113 E element = elementAt(i);
114 if (test(element)) return element;
115 if (length != this.length) {
116 throw new ConcurrentModificationError(this);
117 }
118 }
119 if (orElse != null) return orElse();
120 throw new StateError("No matching element");
121 }
122
123 E singleWhere(bool test(E element)) {
124 int length = this.length;
125 E match = null;
126 bool matchFound = false;
127 for (int i = 0; i < length; i++) {
128 E element = elementAt(i);
129 if (test(element)) {
130 if (matchFound) {
131 throw new StateError("More than one matching element");
132 }
133 matchFound = true;
134 match = element;
135 }
136 if (length != this.length) {
137 throw new ConcurrentModificationError(this);
138 }
139 }
140 if (matchFound) return match;
141 throw new StateError("No matching element");
142 }
143
144 String join([String separator = ""]) {
145 int length = this.length;
146 if (!separator.isEmpty) {
147 if (length == 0) return "";
148 String first = "${elementAt(0)}";
149 if (length != this.length) {
150 throw new ConcurrentModificationError(this);
151 }
152 StringBuffer buffer = new StringBuffer(first);
153 for (int i = 1; i < length; i++) {
154 buffer.write(separator);
155 buffer.write(elementAt(i));
156 if (length != this.length) {
157 throw new ConcurrentModificationError(this);
158 }
159 }
160 return buffer.toString();
161 } else {
162 StringBuffer buffer = new StringBuffer();
163 for (int i = 0; i < length; i++) {
164 buffer.write(elementAt(i));
165 if (length != this.length) {
166 throw new ConcurrentModificationError(this);
167 }
168 }
169 return buffer.toString();
170 }
171 }
172
173 Iterable<E> where(bool test(E element)) => super.where(test);
174
175 Iterable map(f(E element)) => new MappedListIterable(this, f);
176
177 E reduce(E combine(var value, E element)) {
178 if (length == 0) throw new StateError("No elements");
179 E value = elementAt(0);
180 for (int i = 1; i < length; i++) {
181 value = combine(value, elementAt(i));
182 }
183 return value;
184 }
185
186 fold(var initialValue, combine(var previousValue, E element)) {
187 var value = initialValue;
188 int length = this.length;
189 for (int i = 0; i < length; i++) {
190 value = combine(value, elementAt(i));
191 if (length != this.length) {
192 throw new ConcurrentModificationError(this);
193 }
194 }
195 return value;
196 }
197
198 Iterable<E> skip(int count) => new SubListIterable(this, count, null);
199
200 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test);
201
202 Iterable<E> take(int count) => new SubListIterable(this, 0, count);
203
204 Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test);
205
206 List<E> toList({ bool growable: true }) {
207 List<E> result;
208 if (growable) {
209 result = new List<E>()..length = length;
210 } else {
211 result = new List<E>(length);
212 }
213 for (int i = 0; i < length; i++) {
214 result[i] = elementAt(i);
215 }
216 return result;
217 }
218
219 Set<E> toSet() {
220 Set<E> result = new Set<E>();
221 for (int i = 0; i < length; i++) {
222 result.add(elementAt(i));
223 }
224 return result;
225 }
226 }
227
228 class SubListIterable<E> extends ListIterable<E> {
229 final Iterable<E> _iterable;
230 final int _start;
231 /** If null, represents the length of the iterable. */
232 final int _endOrLength;
233
234 SubListIterable(this._iterable, this._start, this._endOrLength) {
235 if (_start < 0) {
236 throw new RangeError.value(_start);
237 }
238 if (_endOrLength != null) {
239 if (_endOrLength < 0) {
240 throw new RangeError.value(_endOrLength);
241 }
242 if (_start > _endOrLength) {
243 throw new RangeError.range(_start, 0, _endOrLength);
244 }
245 }
246 }
247
248 int get _endIndex {
249 int length = _iterable.length;
250 if (_endOrLength == null || _endOrLength > length) return length;
251 return _endOrLength;
252 }
253
254 int get _startIndex {
255 int length = _iterable.length;
256 if (_start > length) return length;
257 return _start;
258 }
259
260 int get length {
261 int length = _iterable.length;
262 if (_start >= length) return 0;
263 if (_endOrLength == null || _endOrLength >= length) {
264 return length - _start;
265 }
266 return _endOrLength - _start;
267 }
268
269 E elementAt(int index) {
270 int realIndex = _startIndex + index;
271 if (index < 0 || realIndex >= _endIndex) {
272 throw new RangeError.range(index, 0, length);
273 }
274 return _iterable.elementAt(realIndex);
275 }
276
277 Iterable<E> skip(int count) {
278 if (count < 0) throw new RangeError.value(count);
279 return new SubListIterable(_iterable, _start + count, _endOrLength);
280 }
281
282 Iterable<E> take(int count) {
283 if (count < 0) throw new RangeError.value(count);
284 if (_endOrLength == null) {
285 return new SubListIterable(_iterable, _start, _start + count);
286 } else {
287 int newEnd = _start + count;
288 if (_endOrLength < newEnd) return this;
289 return new SubListIterable(_iterable, _start, newEnd);
290 }
291 }
292 }
293
294 /**
295 * An [Iterator] that iterates a list-like [Iterable].
296 *
297 * All iterations is done in terms of [Iterable.length] and
298 * [Iterable.elementAt]. These operations are fast for list-like
299 * iterables.
300 */
301 class ListIterator<E> implements Iterator<E> {
302 final Iterable<E> _iterable;
303 final int _length;
304 int _index;
305 E _current;
306
307 ListIterator(Iterable<E> iterable)
308 : _iterable = iterable, _length = iterable.length, _index = 0;
309
310 E get current => _current;
311
312 bool moveNext() {
313 int length = _iterable.length;
314 if (_length != length) {
315 throw new ConcurrentModificationError(_iterable);
316 }
317 if (_index >= length) {
318 _current = null;
319 return false;
320 }
321 _current = _iterable.elementAt(_index);
322 _index++;
323 return true;
324 }
325 }
326
327 typedef T _Transformation<S, T>(S value);
328
329 class MappedIterable<S, T> extends IterableBase<T> {
330 final Iterable<S> _iterable;
331 final _Transformation<S, T> _f;
332
333 factory MappedIterable(Iterable iterable, T function(S value)) {
334 if (iterable is EfficientLength) {
335 return new EfficientLengthMappedIterable<S, T>(iterable, function);
336 }
337 return new MappedIterable<S, T>._(iterable, function);
338 }
339
340 MappedIterable._(this._iterable, T this._f(S element));
341
342 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f);
343
344 // Length related functions are independent of the mapping.
345 int get length => _iterable.length;
346 bool get isEmpty => _iterable.isEmpty;
347
348 // Index based lookup can be done before transforming.
349 T get first => _f(_iterable.first);
350 T get last => _f(_iterable.last);
351 T get single => _f(_iterable.single);
352 T elementAt(int index) => _f(_iterable.elementAt(index));
353 }
354
355 class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
356 implements EfficientLength {
357 EfficientLengthMappedIterable(Iterable iterable, T function(S value))
358 : super._(iterable, function);
359 }
360
361 class MappedIterator<S, T> extends Iterator<T> {
362 T _current;
363 final Iterator<S> _iterator;
364 final _Transformation<S, T> _f;
365
366 MappedIterator(this._iterator, T this._f(S element));
367
368 bool moveNext() {
369 if (_iterator.moveNext()) {
370 _current = _f(_iterator.current);
371 return true;
372 }
373 _current = null;
374 return false;
375 }
376
377 T get current => _current;
378 }
379
380 /**
381 * Specialized alternative to [MappedIterable] for mapped [List]s.
382 *
383 * Expects efficient `length` and `elementAt` on the source iterable.
384 */
385 class MappedListIterable<S, T> extends ListIterable<T>
386 implements EfficientLength {
387 final Iterable<S> _source;
388 final _Transformation<S, T> _f;
389
390 MappedListIterable(this._source, T this._f(S value));
391
392 int get length => _source.length;
393 T elementAt(int index) => _f(_source.elementAt(index));
394 }
395
396
397 typedef bool _ElementPredicate<E>(E element);
398
399 class WhereIterable<E> extends IterableBase<E> {
400 final Iterable<E> _iterable;
401 final _ElementPredicate _f;
402
403 WhereIterable(this._iterable, bool this._f(E element));
404
405 Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f);
406 }
407
408 class WhereIterator<E> extends Iterator<E> {
409 final Iterator<E> _iterator;
410 final _ElementPredicate _f;
411
412 WhereIterator(this._iterator, bool this._f(E element));
413
414 bool moveNext() {
415 while (_iterator.moveNext()) {
416 if (_f(_iterator.current)) {
417 return true;
418 }
419 }
420 return false;
421 }
422
423 E get current => _iterator.current;
424 }
425
426 typedef Iterable<T> _ExpandFunction<S, T>(S sourceElement);
427
428 class ExpandIterable<S, T> extends IterableBase<T> {
429 final Iterable<S> _iterable;
430 final _ExpandFunction _f;
431
432 ExpandIterable(this._iterable, Iterable<T> this._f(S element));
433
434 Iterator<T> get iterator => new ExpandIterator<S, T>(_iterable.iterator, _f);
435 }
436
437 class ExpandIterator<S, T> implements Iterator<T> {
438 final Iterator<S> _iterator;
439 final _ExpandFunction _f;
440 // Initialize _currentExpansion to an empty iterable. A null value
441 // marks the end of iteration, and we don't want to call _f before
442 // the first moveNext call.
443 Iterator<T> _currentExpansion = const EmptyIterator();
444 T _current;
445
446 ExpandIterator(this._iterator, Iterable<T> this._f(S element));
447
448 void _nextExpansion() {
449 }
450
451 T get current => _current;
452
453 bool moveNext() {
454 if (_currentExpansion == null) return false;
455 while (!_currentExpansion.moveNext()) {
456 _current = null;
457 if (_iterator.moveNext()) {
458 // If _f throws, this ends iteration. Otherwise _currentExpansion and
459 // _current will be set again below.
460 _currentExpansion = null;
461 _currentExpansion = _f(_iterator.current).iterator;
462 } else {
463 return false;
464 }
465 }
466 _current = _currentExpansion.current;
467 return true;
468 }
469 }
470
471 class TakeIterable<E> extends IterableBase<E> {
472 final Iterable<E> _iterable;
473 final int _takeCount;
474
475 factory TakeIterable(Iterable<E> iterable, int takeCount) {
476 if (takeCount is! int || takeCount < 0) {
477 throw new ArgumentError(takeCount);
478 }
479 if (iterable is EfficientLength) {
480 return new EfficientLengthTakeIterable<E>(iterable, takeCount);
481 }
482 return new TakeIterable<E>._(iterable, takeCount);
483 }
484
485 TakeIterable._(this._iterable, this._takeCount);
486
487 Iterator<E> get iterator {
488 return new TakeIterator<E>(_iterable.iterator, _takeCount);
489 }
490 }
491
492 class EfficientLengthTakeIterable<E> extends TakeIterable<E>
493 implements EfficientLength {
494 EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
495 : super._(iterable, takeCount);
496
497 int get length {
498 int iterableLength = _iterable.length;
499 if (iterableLength > _takeCount) return _takeCount;
500 return iterableLength;
501 }
502 }
503
504
505 class TakeIterator<E> extends Iterator<E> {
506 final Iterator<E> _iterator;
507 int _remaining;
508
509 TakeIterator(this._iterator, this._remaining) {
510 assert(_remaining is int && _remaining >= 0);
511 }
512
513 bool moveNext() {
514 _remaining--;
515 if (_remaining >= 0) {
516 return _iterator.moveNext();
517 }
518 _remaining = -1;
519 return false;
520 }
521
522 E get current {
523 if (_remaining < 0) return null;
524 return _iterator.current;
525 }
526 }
527
528 class TakeWhileIterable<E> extends IterableBase<E> {
529 final Iterable<E> _iterable;
530 final _ElementPredicate _f;
531
532 TakeWhileIterable(this._iterable, bool this._f(E element));
533
534 Iterator<E> get iterator {
535 return new TakeWhileIterator<E>(_iterable.iterator, _f);
536 }
537 }
538
539 class TakeWhileIterator<E> extends Iterator<E> {
540 final Iterator<E> _iterator;
541 final _ElementPredicate _f;
542 bool _isFinished = false;
543
544 TakeWhileIterator(this._iterator, bool this._f(E element));
545
546 bool moveNext() {
547 if (_isFinished) return false;
548 if (!_iterator.moveNext() || !_f(_iterator.current)) {
549 _isFinished = true;
550 return false;
551 }
552 return true;
553 }
554
555 E get current {
556 if (_isFinished) return null;
557 return _iterator.current;
558 }
559 }
560
561 class SkipIterable<E> extends IterableBase<E> {
562 final Iterable<E> _iterable;
563 final int _skipCount;
564
565 factory SkipIterable(Iterable<E> iterable, int skipCount) {
566 if (iterable is EfficientLength) {
567 return new EfficientLengthSkipIterable<E>(iterable, skipCount);
568 }
569 return new SkipIterable<E>._(iterable, skipCount);
570 }
571
572 SkipIterable._(this._iterable, this._skipCount) {
573 if (_skipCount is! int || _skipCount < 0) {
574 throw new RangeError(_skipCount);
575 }
576 }
577
578 Iterable<E> skip(int n) {
579 if (n is! int || n < 0) {
580 throw new RangeError.value(n);
581 }
582 return new SkipIterable<E>(_iterable, _skipCount + n);
583 }
584
585 Iterator<E> get iterator {
586 return new SkipIterator<E>(_iterable.iterator, _skipCount);
587 }
588 }
589
590 class EfficientLengthSkipIterable<E> extends SkipIterable<E>
591 implements EfficientLength {
592 EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount)
593 : super._(iterable, skipCount);
594
595 int get length {
596 int length = _iterable.length - _skipCount;
597 if (length >= 0) return length;
598 return 0;
599 }
600 }
601
602 class SkipIterator<E> extends Iterator<E> {
603 final Iterator<E> _iterator;
604 int _skipCount;
605
606 SkipIterator(this._iterator, this._skipCount) {
607 assert(_skipCount is int && _skipCount >= 0);
608 }
609
610 bool moveNext() {
611 for (int i = 0; i < _skipCount; i++) _iterator.moveNext();
612 _skipCount = 0;
613 return _iterator.moveNext();
614 }
615
616 E get current => _iterator.current;
617 }
618
619 class SkipWhileIterable<E> extends IterableBase<E> {
620 final Iterable<E> _iterable;
621 final _ElementPredicate _f;
622
623 SkipWhileIterable(this._iterable, bool this._f(E element));
624
625 Iterator<E> get iterator {
626 return new SkipWhileIterator<E>(_iterable.iterator, _f);
627 }
628 }
629
630 class SkipWhileIterator<E> extends Iterator<E> {
631 final Iterator<E> _iterator;
632 final _ElementPredicate _f;
633 bool _hasSkipped = false;
634
635 SkipWhileIterator(this._iterator, bool this._f(E element));
636
637 bool moveNext() {
638 if (!_hasSkipped) {
639 _hasSkipped = true;
640 while (_iterator.moveNext()) {
641 if (!_f(_iterator.current)) return true;
642 }
643 }
644 return _iterator.moveNext();
645 }
646
647 E get current => _iterator.current;
648 }
649
650 /**
651 * The always empty [Iterable].
652 */
653 class EmptyIterable<E> extends IterableBase<E> implements EfficientLength {
654 const EmptyIterable();
655
656 Iterator<E> get iterator => const EmptyIterator();
657
658 void forEach(void action(E element)) {}
659
660 bool get isEmpty => true;
661
662 int get length => 0;
663
664 E get first { throw new StateError("No elements"); }
665
666 E get last { throw new StateError("No elements"); }
667
668 E get single { throw new StateError("No elements"); }
669
670 E elementAt(int index) { throw new RangeError.value(index); }
671
672 bool contains(Object element) => false;
673
674 bool every(bool test(E element)) => true;
675
676 bool any(bool test(E element)) => false;
677
678 E firstWhere(bool test(E element), { E orElse() }) {
679 if (orElse != null) return orElse();
680 throw new StateError("No matching element");
681 }
682
683 E lastWhere(bool test(E element), { E orElse() }) {
684 if (orElse != null) return orElse();
685 throw new StateError("No matching element");
686 }
687
688 E singleWhere(bool test(E element), { E orElse() }) {
689 if (orElse != null) return orElse();
690 throw new StateError("No matching element");
691 }
692
693 String join([String separator = ""]) => "";
694
695 Iterable<E> where(bool test(E element)) => this;
696
697 Iterable map(f(E element)) => const EmptyIterable();
698
699 E reduce(E combine(E value, E element)) {
700 throw new StateError("No elements");
701 }
702
703 fold(var initialValue, combine(var previousValue, E element)) {
704 return initialValue;
705 }
706
707 Iterable<E> skip(int count) {
708 if (count < 0) throw new RangeError.value(count);
709 return this;
710 }
711
712 Iterable<E> skipWhile(bool test(E element)) => this;
713
714 Iterable<E> take(int count) {
715 if (count < 0) throw new RangeError.value(count);
716 this;
717 }
718
719 Iterable<E> takeWhile(bool test(E element)) => this;
720
721 List toList({ bool growable: true }) => growable ? <E>[] : new List<E>(0);
722
723 Set toSet() => new Set<E>();
724 }
725
726 /** The always empty iterator. */
727 class EmptyIterator<E> implements Iterator<E> {
728 const EmptyIterator();
729 bool moveNext() => false;
730 E get current => null;
731 }
732
733 /** An [Iterator] that can move in both directions. */
734 abstract class BidirectionalIterator<T> implements Iterator<T> {
735 bool movePrevious();
736 }
737
738 /**
739 * This class provides default implementations for Iterables (including Lists).
740 *
741 * The uses of this class will be replaced by mixins.
742 */
743 class IterableMixinWorkaround {
744 // A list to identify cyclic collections during toString() calls.
745 static List _toStringList = new List();
746
747 static bool contains(Iterable iterable, var element) {
748 for (final e in iterable) {
749 if (e == element) return true;
750 }
751 return false;
752 }
753
754 static void forEach(Iterable iterable, void f(o)) {
755 for (final e in iterable) {
756 f(e);
757 }
758 }
759
760 static bool any(Iterable iterable, bool f(o)) {
761 for (final e in iterable) {
762 if (f(e)) return true;
763 }
764 return false;
765 }
766
767 static bool every(Iterable iterable, bool f(o)) {
768 for (final e in iterable) {
769 if (!f(e)) return false;
770 }
771 return true;
772 }
773
774 static dynamic reduce(Iterable iterable,
775 dynamic combine(previousValue, element)) {
776 Iterator iterator = iterable.iterator;
777 if (!iterator.moveNext()) throw new StateError("No elements");
778 var value = iterator.current;
779 while (iterator.moveNext()) {
780 value = combine(value, iterator.current);
781 }
782 return value;
783 }
784
785 static dynamic fold(Iterable iterable,
786 dynamic initialValue,
787 dynamic combine(dynamic previousValue, element)) {
788 for (final element in iterable) {
789 initialValue = combine(initialValue, element);
790 }
791 return initialValue;
792 }
793
794 /**
795 * Removes elements matching [test] from [list].
796 *
797 * This is performed in two steps, to avoid exposing an inconsistent state
798 * to the [test] function. First the elements to retain are found, and then
799 * the original list is updated to contain those elements.
800 */
801 static void removeWhereList(List list, bool test(var element)) {
802 List retained = [];
803 int length = list.length;
804 for (int i = 0; i < length; i++) {
805 var element = list[i];
806 if (!test(element)) {
807 retained.add(element);
808 }
809 if (length != list.length) {
810 throw new ConcurrentModificationError(list);
811 }
812 }
813 if (retained.length == length) return;
814 list.length = retained.length;
815 for (int i = 0; i < retained.length; i++) {
816 list[i] = retained[i];
817 }
818 }
819
820 static bool isEmpty(Iterable iterable) {
821 return !iterable.iterator.moveNext();
822 }
823
824 static dynamic first(Iterable iterable) {
825 Iterator it = iterable.iterator;
826 if (!it.moveNext()) {
827 throw new StateError("No elements");
828 }
829 return it.current;
830 }
831
832 static dynamic last(Iterable iterable) {
833 Iterator it = iterable.iterator;
834 if (!it.moveNext()) {
835 throw new StateError("No elements");
836 }
837 dynamic result;
838 do {
839 result = it.current;
840 } while(it.moveNext());
841 return result;
842 }
843
844 static dynamic single(Iterable iterable) {
845 Iterator it = iterable.iterator;
846 if (!it.moveNext()) throw new StateError("No elements");
847 dynamic result = it.current;
848 if (it.moveNext()) throw new StateError("More than one element");
849 return result;
850 }
851
852 static dynamic firstWhere(Iterable iterable,
853 bool test(dynamic value),
854 dynamic orElse()) {
855 for (dynamic element in iterable) {
856 if (test(element)) return element;
857 }
858 if (orElse != null) return orElse();
859 throw new StateError("No matching element");
860 }
861
862 static dynamic lastWhere(Iterable iterable,
863 bool test(dynamic value),
864 dynamic orElse()) {
865 dynamic result = null;
866 bool foundMatching = false;
867 for (dynamic element in iterable) {
868 if (test(element)) {
869 result = element;
870 foundMatching = true;
871 }
872 }
873 if (foundMatching) return result;
874 if (orElse != null) return orElse();
875 throw new StateError("No matching element");
876 }
877
878 static dynamic lastWhereList(List list,
879 bool test(dynamic value),
880 dynamic orElse()) {
881 // TODO(floitsch): check that arguments are of correct type?
882 for (int i = list.length - 1; i >= 0; i--) {
883 dynamic element = list[i];
884 if (test(element)) return element;
885 }
886 if (orElse != null) return orElse();
887 throw new StateError("No matching element");
888 }
889
890 static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) {
891 dynamic result = null;
892 bool foundMatching = false;
893 for (dynamic element in iterable) {
894 if (test(element)) {
895 if (foundMatching) {
896 throw new StateError("More than one matching element");
897 }
898 result = element;
899 foundMatching = true;
900 }
901 }
902 if (foundMatching) return result;
903 throw new StateError("No matching element");
904 }
905
906 static dynamic elementAt(Iterable iterable, int index) {
907 if (index is! int || index < 0) throw new RangeError.value(index);
908 int remaining = index;
909 for (dynamic element in iterable) {
910 if (remaining == 0) return element;
911 remaining--;
912 }
913 throw new RangeError.value(index);
914 }
915
916 static String join(Iterable iterable, [String separator]) {
917 StringBuffer buffer = new StringBuffer();
918 buffer.writeAll(iterable, separator);
919 return buffer.toString();
920 }
921
922 static String joinList(List list, [String separator]) {
923 if (list.isEmpty) return "";
924 if (list.length == 1) return "${list[0]}";
925 StringBuffer buffer = new StringBuffer();
926 if (separator.isEmpty) {
927 for (int i = 0; i < list.length; i++) {
928 buffer.write(list[i]);
929 }
930 } else {
931 buffer.write(list[0]);
932 for (int i = 1; i < list.length; i++) {
933 buffer.write(separator);
934 buffer.write(list[i]);
935 }
936 }
937 return buffer.toString();
938 }
939
940 static String toStringIterable(Iterable iterable, String leftDelimiter,
941 String rightDelimiter) {
942 for (int i = 0; i < _toStringList.length; i++) {
943 if (identical(_toStringList[i], iterable)) {
944 return '$leftDelimiter...$rightDelimiter';
945 }
946 }
947
948 StringBuffer result = new StringBuffer();
949 try {
950 _toStringList.add(iterable);
951 result.write(leftDelimiter);
952 result.writeAll(iterable, ', ');
953 result.write(rightDelimiter);
954 } finally {
955 assert(identical(_toStringList.last, iterable));
956 _toStringList.removeLast();
957 }
958 return result.toString();
959 }
960
961 static Iterable where(Iterable iterable, bool f(var element)) {
962 return new WhereIterable(iterable, f);
963 }
964
965 static Iterable map(Iterable iterable, f(var element)) {
966 return new MappedIterable(iterable, f);
967 }
968
969 static Iterable mapList(List list, f(var element)) {
970 return new MappedListIterable(list, f);
971 }
972
973 static Iterable expand(Iterable iterable, Iterable f(var element)) {
974 return new ExpandIterable(iterable, f);
975 }
976
977 static Iterable takeList(List list, int n) {
978 // The generic type is currently lost. It will be fixed with mixins.
979 return new SubListIterable(list, 0, n);
980 }
981
982 static Iterable takeWhile(Iterable iterable, bool test(var value)) {
983 // The generic type is currently lost. It will be fixed with mixins.
984 return new TakeWhileIterable(iterable, test);
985 }
986
987 static Iterable skipList(List list, int n) {
988 // The generic type is currently lost. It will be fixed with mixins.
989 return new SubListIterable(list, n, null);
990 }
991
992 static Iterable skipWhile(Iterable iterable, bool test(var value)) {
993 // The generic type is currently lost. It will be fixed with mixins.
994 return new SkipWhileIterable(iterable, test);
995 }
996
997 static Iterable reversedList(List list) {
998 return new ReversedListIterable(list);
999 }
1000
1001 static void sortList(List list, int compare(a, b)) {
1002 if (compare == null) compare = Comparable.compare;
1003 Sort.sort(list, compare);
1004 }
1005
1006 static void shuffleList(List list, Random random) {
1007 if (random == null) random = new Random();
1008 int length = list.length;
1009 while (length > 1) {
1010 int pos = random.nextInt(length);
1011 length -= 1;
1012 var tmp = list[length];
1013 list[length] = list[pos];
1014 list[pos] = tmp;
1015 }
1016 }
1017
1018 static int indexOfList(List list, var element, int start) {
1019 return Lists.indexOf(list, element, start, list.length);
1020 }
1021
1022 static int lastIndexOfList(List list, var element, int start) {
1023 if (start == null) start = list.length - 1;
1024 return Lists.lastIndexOf(list, element, start);
1025 }
1026
1027 static void _rangeCheck(List list, int start, int end) {
1028 if (start < 0 || start > list.length) {
1029 throw new RangeError.range(start, 0, list.length);
1030 }
1031 if (end < start || end > list.length) {
1032 throw new RangeError.range(end, start, list.length);
1033 }
1034 }
1035
1036 static Iterable getRangeList(List list, int start, int end) {
1037 _rangeCheck(list, start, end);
1038 // The generic type is currently lost. It will be fixed with mixins.
1039 return new SubListIterable(list, start, end);
1040 }
1041
1042 static void setRangeList(List list, int start, int end,
1043 Iterable from, int skipCount) {
1044 _rangeCheck(list, start, end);
1045 int length = end - start;
1046 if (length == 0) return;
1047
1048 if (skipCount < 0) throw new ArgumentError(skipCount);
1049
1050 // TODO(floitsch): Make this accept more.
1051 List otherList;
1052 int otherStart;
1053 if (from is List) {
1054 otherList = from;
1055 otherStart = skipCount;
1056 } else {
1057 otherList = from.skip(skipCount).toList(growable: false);
1058 otherStart = 0;
1059 }
1060 if (otherStart + length > otherList.length) {
1061 throw new StateError("Not enough elements");
1062 }
1063 Lists.copy(otherList, otherStart, list, start, length);
1064 }
1065
1066 static void replaceRangeList(List list, int start, int end,
1067 Iterable iterable) {
1068 _rangeCheck(list, start, end);
1069 if (iterable is! EfficientLength) {
1070 iterable = iterable.toList();
1071 }
1072 int removeLength = end - start;
1073 int insertLength = iterable.length;
1074 if (removeLength >= insertLength) {
1075 int delta = removeLength - insertLength;
1076 int insertEnd = start + insertLength;
1077 int newEnd = list.length - delta;
1078 list.setRange(start, insertEnd, iterable);
1079 if (delta != 0) {
1080 list.setRange(insertEnd, newEnd, list, end);
1081 list.length = newEnd;
1082 }
1083 } else {
1084 int delta = insertLength - removeLength;
1085 int newLength = list.length + delta;
1086 int insertEnd = start + insertLength; // aka. end + delta.
1087 list.length = newLength;
1088 list.setRange(insertEnd, newLength, list, end);
1089 list.setRange(start, insertEnd, iterable);
1090 }
1091 }
1092
1093 static void fillRangeList(List list, int start, int end, fillValue) {
1094 _rangeCheck(list, start, end);
1095 for (int i = start; i < end; i++) {
1096 list[i] = fillValue;
1097 }
1098 }
1099
1100 static void insertAllList(List list, int index, Iterable iterable) {
1101 if (index < 0 || index > list.length) {
1102 throw new RangeError.range(index, 0, list.length);
1103 }
1104 if (iterable is! EfficientLength) {
1105 iterable = iterable.toList(growable: false);
1106 }
1107 int insertionLength = iterable.length;
1108 list.length += insertionLength;
1109 list.setRange(index + insertionLength, list.length, list, index);
1110 for (var element in iterable) {
1111 list[index++] = element;
1112 }
1113 }
1114
1115 static void setAllList(List list, int index, Iterable iterable) {
1116 if (index < 0 || index > list.length) {
1117 throw new RangeError.range(index, 0, list.length);
1118 }
1119 for (var element in iterable) {
1120 list[index++] = element;
1121 }
1122 }
1123
1124 static Map<int, dynamic> asMapList(List l) {
1125 return new ListMapView(l);
1126 }
1127
1128 static bool setContainsAll(Set set, Iterable other) {
1129 for (var element in other) {
1130 if (!set.contains(element)) return false;
1131 }
1132 return true;
1133 }
1134
1135 static Set setIntersection(Set set, Set other, Set result) {
1136 Set smaller;
1137 Set larger;
1138 if (set.length < other.length) {
1139 smaller = set;
1140 larger = other;
1141 } else {
1142 smaller = other;
1143 larger = set;
1144 }
1145 for (var element in smaller) {
1146 if (larger.contains(element)) {
1147 result.add(element);
1148 }
1149 }
1150 return result;
1151 }
1152
1153 static Set setUnion(Set set, Set other, Set result) {
1154 result.addAll(set);
1155 result.addAll(other);
1156 return result;
1157 }
1158
1159 static Set setDifference(Set set, Set other, Set result) {
1160 for (var element in set) {
1161 if (!other.contains(element)) {
1162 result.add(element);
1163 }
1164 }
1165 return result;
1166 }
1167 }
OLDNEW
« no previous file with comments | « sdk/lib/_collection_dev/collection_dev_sources.gypi ('k') | sdk/lib/_collection_dev/list.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698