| OLD | NEW |
| 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 /** | 7 /** |
| 9 * An [Iterable] for classes that have efficient [length] and [elementAt]. | 8 * An [Iterable] for classes that have efficient [length] and [elementAt]. |
| 10 * | 9 * |
| 11 * All other methods are implemented in terms of [length] and [elementAt], | 10 * All other methods are implemented in terms of [length] and [elementAt], |
| 12 * including [iterator]. | 11 * including [iterator]. |
| 13 */ | 12 */ |
| 14 abstract class ListIterable<E> extends Iterable<E> { | 13 abstract class ListIterable<E> extends Iterable<E> { |
| 15 int get length; | 14 int get length; |
| 16 E elementAt(int i); | 15 E elementAt(int i); |
| 17 | 16 |
| 18 Iterator<E> get iterator => new ListIterableIterator<E>(this); | 17 Iterator<E> get iterator => new ListIterator<E>(this); |
| 19 | 18 |
| 20 void forEach(void action(E element)) { | 19 void forEach(void action(E element)) { |
| 21 int length = this.length; | 20 int length = this.length; |
| 22 for (int i = 0; i < length; i++) { | 21 for (int i = 0; i < length; i++) { |
| 23 action(elementAt(i)); | 22 action(elementAt(i)); |
| 24 if (length != this.length) { | 23 if (length != this.length) { |
| 25 throw new ConcurrentModificationError(this); | 24 throw new ConcurrentModificationError(this); |
| 26 } | 25 } |
| 27 } | 26 } |
| 28 } | 27 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 if (length != this.length) { | 85 if (length != this.length) { |
| 87 throw new ConcurrentModificationError(this); | 86 throw new ConcurrentModificationError(this); |
| 88 } | 87 } |
| 89 } | 88 } |
| 90 if (orElse != null) return orElse(); | 89 if (orElse != null) return orElse(); |
| 91 throw new StateError("No matching element"); | 90 throw new StateError("No matching element"); |
| 92 } | 91 } |
| 93 | 92 |
| 94 E lastMatching(bool test(E element), { E orElse() }) { | 93 E lastMatching(bool test(E element), { E orElse() }) { |
| 95 int length = this.length; | 94 int length = this.length; |
| 96 for (int i = length - 1; i >= 0; i++) { | 95 for (int i = length - 1; i >= 0; i--) { |
| 97 E element = elementAt(i); | 96 E element = elementAt(i); |
| 98 if (test(element)) return element; | 97 if (test(element)) return element; |
| 99 if (length != this.length) { | 98 if (length != this.length) { |
| 100 throw new ConcurrentModificationError(this); | 99 throw new ConcurrentModificationError(this); |
| 101 } | 100 } |
| 102 } | 101 } |
| 103 if (orElse != null) return orElse(); | 102 if (orElse != null) return orElse(); |
| 104 throw new StateError("No matching element"); | 103 throw new StateError("No matching element"); |
| 105 } | 104 } |
| 106 | 105 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 if (length != this.length) { | 188 if (length != this.length) { |
| 190 throw new ConcurrentModificationError(this); | 189 throw new ConcurrentModificationError(this); |
| 191 } | 190 } |
| 192 } | 191 } |
| 193 return buffer.toString(); | 192 return buffer.toString(); |
| 194 } | 193 } |
| 195 } | 194 } |
| 196 | 195 |
| 197 Iterable<E> where(bool test(E element)) => super.where(test); | 196 Iterable<E> where(bool test(E element)) => super.where(test); |
| 198 | 197 |
| 199 Iterable map(f(E element)) => new MappedIterable(this, f); | 198 Iterable map(f(E element)) => new MappedListIterable(this, f); |
| 200 | |
| 201 Iterable mappedBy(f(E element)) => super.mappedBy(f); | |
| 202 | 199 |
| 203 reduce(var initialValue, combine(var previousValue, E element)) { | 200 reduce(var initialValue, combine(var previousValue, E element)) { |
| 204 var value = initialValue; | 201 var value = initialValue; |
| 205 int length = this.length; | 202 int length = this.length; |
| 206 for (int i = 0; i < length; i++) { | 203 for (int i = 0; i < length; i++) { |
| 207 value = reduce(value, elementAt(i)); | 204 value = combine(value, elementAt(i)); |
| 208 if (length != this.length) { | 205 if (length != this.length) { |
| 209 throw new ConcurrentModificationError(this); | 206 throw new ConcurrentModificationError(this); |
| 210 } | 207 } |
| 211 } | 208 } |
| 212 return value; | 209 return value; |
| 213 } | 210 } |
| 214 | 211 |
| 215 Iterable<E> skip(int count) => new SubListIterable(this, count, null); | 212 Iterable<E> skip(int count) => new SubListIterable(this, count, null); |
| 216 | 213 |
| 217 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); | 214 Iterable<E> skipWhile(bool test(E element)) => super.skipWhile(test); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 230 | 227 |
| 231 Set<E> toSet() { | 228 Set<E> toSet() { |
| 232 Set<E> result = new Set<E>(); | 229 Set<E> result = new Set<E>(); |
| 233 for (int i = 0; i < length; i++) { | 230 for (int i = 0; i < length; i++) { |
| 234 result.add(elementAt(i)); | 231 result.add(elementAt(i)); |
| 235 } | 232 } |
| 236 return result; | 233 return result; |
| 237 } | 234 } |
| 238 } | 235 } |
| 239 | 236 |
| 240 abstract class SubListIterable<E> extends ListIterable<E> { | 237 class SubListIterable<E> extends ListIterable<E> { |
| 241 final Iterable<E> _iterable; | 238 final Iterable<E> _iterable; |
| 242 final int _start; | 239 final int _start; |
| 243 /** If null, represents the length of the iterable. */ | 240 /** If null, represents the length of the iterable. */ |
| 244 final int _endOrLength; | 241 final int _endOrLength; |
| 245 | 242 |
| 246 SubListIterable(this._iterable, this._start, this._endOrLength); | 243 SubListIterable(this._iterable, this._start, this._endOrLength); |
| 247 | 244 |
| 248 int get _endIndex { | 245 int get _endIndex { |
| 249 int length = _iterable.length; | 246 int length = _iterable.length; |
| 250 if (_endOrLength == null || _endOrLength > length) return length; | 247 if (_endOrLength == null || _endOrLength > length) return length; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 277 Iterable<E> skip(int count) { | 274 Iterable<E> skip(int count) { |
| 278 if (count < 0) throw new ArgumentError(count); | 275 if (count < 0) throw new ArgumentError(count); |
| 279 return new SubListIterable(_iterable, _start + count, _endOrLength); | 276 return new SubListIterable(_iterable, _start + count, _endOrLength); |
| 280 } | 277 } |
| 281 | 278 |
| 282 Iterable<E> take(int count) { | 279 Iterable<E> take(int count) { |
| 283 if (count < 0) throw new ArgumentError(count); | 280 if (count < 0) throw new ArgumentError(count); |
| 284 if (_endOrLength == null) { | 281 if (_endOrLength == null) { |
| 285 return new SubListIterable(_iterable, _start, _start + count); | 282 return new SubListIterable(_iterable, _start, _start + count); |
| 286 } else { | 283 } else { |
| 287 newEnd = _start + count; | 284 int newEnd = _start + count; |
| 288 if (_endOrLength < newEnd) return this; | 285 if (_endOrLength < newEnd) return this; |
| 289 return new SubListIterable(_iterable, _start, newEnd); | 286 return new SubListIterable(_iterable, _start, newEnd); |
| 290 } | 287 } |
| 291 } | 288 } |
| 292 } | 289 } |
| 293 | 290 |
| 294 class ListIterableIterator<E> implements Iterator<E> { | 291 /** |
| 292 * An [Iterator] that iterates a list-like [Iterable]. |
| 293 * |
| 294 * All iterations is done in terms of [Iterable.length] and |
| 295 * [Iterable.elementAt]. These operations are fast for list-like |
| 296 * iterables. |
| 297 */ |
| 298 class ListIterator<E> implements Iterator<E> { |
| 295 final Iterable<E> _iterable; | 299 final Iterable<E> _iterable; |
| 296 final int _length; | 300 final int _length; |
| 297 int _index; | 301 int _index; |
| 298 E _current; | 302 E _current; |
| 299 ListIterableIterator(Iterable<E> iterable) | 303 |
| 304 ListIterator(Iterable<E> iterable) |
| 300 : _iterable = iterable, _length = iterable.length, _index = 0; | 305 : _iterable = iterable, _length = iterable.length, _index = 0; |
| 301 | 306 |
| 302 E get current => _current; | 307 E get current => _current; |
| 303 | 308 |
| 304 bool moveNext() { | 309 bool moveNext() { |
| 305 if (_length != _iterable.length) { | 310 if (_length != _iterable.length) { |
| 306 throw new ConcurrentModificationError(_iterable); | 311 throw new ConcurrentModificationError(_iterable); |
| 307 } | 312 } |
| 308 if (_index == _length) { | 313 if (_index == _length) { |
| 309 _current = null; | 314 _current = null; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 323 // checked mode. http://dartbug.com/7733 | 328 // checked mode. http://dartbug.com/7733 |
| 324 final /* _Transformation<S, T> */ _f; | 329 final /* _Transformation<S, T> */ _f; |
| 325 | 330 |
| 326 MappedIterable(this._iterable, T this._f(S element)); | 331 MappedIterable(this._iterable, T this._f(S element)); |
| 327 | 332 |
| 328 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); | 333 Iterator<T> get iterator => new MappedIterator<S, T>(_iterable.iterator, _f); |
| 329 | 334 |
| 330 // Length related functions are independent of the mapping. | 335 // Length related functions are independent of the mapping. |
| 331 int get length => _iterable.length; | 336 int get length => _iterable.length; |
| 332 bool get isEmpty => _iterable.isEmpty; | 337 bool get isEmpty => _iterable.isEmpty; |
| 338 |
| 339 // Index based lookup can be done before transforming. |
| 340 T get first => _f(_iterable.first); |
| 341 T get last => _f(_iterable.last); |
| 342 T get single => _f(_iterable.single); |
| 343 T elementAt(int index) => _f(_iterable.elementAt(index)); |
| 333 } | 344 } |
| 334 | 345 |
| 335 | |
| 336 class MappedIterator<S, T> extends Iterator<T> { | 346 class MappedIterator<S, T> extends Iterator<T> { |
| 337 T _current; | 347 T _current; |
| 338 final Iterator<S> _iterator; | 348 final Iterator<S> _iterator; |
| 339 // TODO(ahe): Restore type when feature is implemented in dart2js | 349 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 340 // checked mode. http://dartbug.com/7733 | 350 // checked mode. http://dartbug.com/7733 |
| 341 final /* _Transformation<S, T> */ _f; | 351 final /* _Transformation<S, T> */ _f; |
| 342 | 352 |
| 343 MappedIterator(this._iterator, T this._f(S element)); | 353 MappedIterator(this._iterator, T this._f(S element)); |
| 344 | 354 |
| 345 bool moveNext() { | 355 bool moveNext() { |
| 346 if (_iterator.moveNext()) { | 356 if (_iterator.moveNext()) { |
| 347 _current = _f(_iterator.current); | 357 _current = _f(_iterator.current); |
| 348 return true; | 358 return true; |
| 349 } else { | |
| 350 _current = null; | |
| 351 return false; | |
| 352 } | 359 } |
| 360 _current = null; |
| 361 return false; |
| 353 } | 362 } |
| 354 | 363 |
| 355 T get current => _current; | 364 T get current => _current; |
| 356 } | 365 } |
| 357 | 366 |
| 358 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ | 367 /** Specialized alternative to [MappedIterable] for mapped [List]s. */ |
| 359 class MappedListIterable<S, T> extends Iterable<T> { | 368 class MappedListIterable<S, T> extends ListIterable<T> { |
| 360 final List<S> _list; | 369 final Iterable<S> _source; |
| 361 /** | |
| 362 * Start index of the part of the list to map. | |
| 363 * | |
| 364 * Allows mapping only a sub-list of an existing list. | |
| 365 * | |
| 366 * Used to implement lazy skip/take on a [MappedListIterable]. | |
| 367 */ | |
| 368 final int _start; | |
| 369 | |
| 370 /** | |
| 371 * End index of the part of the list to map. | |
| 372 * | |
| 373 * If null, always use the length of the list. | |
| 374 */ | |
| 375 final int _end; | |
| 376 | |
| 377 // TODO(ahe): Restore type when feature is implemented in dart2js | 370 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 378 // checked mode. http://dartbug.com/7733 | 371 // checked mode. http://dartbug.com/7733 |
| 379 final /* _Transformation<S, T> */ _f; | 372 final /* _Transformation<S, T> */ _f; |
| 380 | 373 |
| 381 MappedListIterable(this._list, T this._f(S element), this._start, this._end) { | 374 MappedListIterable(this._source, T this._f(S value)); |
| 382 if (_end != null && _end < _start) { | |
| 383 throw new ArgumentError("End ($_end) before start ($_start)"); | |
| 384 } | |
| 385 } | |
| 386 | 375 |
| 387 /** The start index, limited to the current length of the list. */ | 376 int get length => _source.length; |
| 388 int get _startIndex { | 377 T elementAt(int index) => _f(_source.elementAt(index)); |
| 389 if (_start <= _list.length) return _start; | |
| 390 return _list.length; | |
| 391 } | |
| 392 | |
| 393 /** The end index, if given, limited to the current length of the list. */ | |
| 394 int get _endIndex { | |
| 395 if (_end == null || _end > _list.length) return _list.length; | |
| 396 return _end; | |
| 397 } | |
| 398 | |
| 399 Iterator<T> get iterator => | |
| 400 new MappedListIterator<S, T>(_list, _f, _startIndex, _endIndex); | |
| 401 | |
| 402 void forEach(void action(T element)) { | |
| 403 int length = _list.length; | |
| 404 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 405 action(_f(_list[i])); | |
| 406 if (_list.length != length) { | |
| 407 throw new ConcurrentModificationError(_list); | |
| 408 } | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 bool get isEmpty => _startIndex == _endIndex; | |
| 413 | |
| 414 int get length => _endIndex - _startIndex; | |
| 415 | |
| 416 T get first { | |
| 417 int start = _startIndex; | |
| 418 if (start == _endIndex) { | |
| 419 throw new StateError("No elements"); | |
| 420 } | |
| 421 return _f(_list.elementAt(start)); | |
| 422 } | |
| 423 | |
| 424 T get last { | |
| 425 int end = _endIndex; | |
| 426 if (end == _startIndex) { | |
| 427 throw new StateError("No elements"); | |
| 428 } | |
| 429 return _f(_list.elementAt(end - 1)); | |
| 430 } | |
| 431 | |
| 432 T get single { | |
| 433 int start = _startIndex; | |
| 434 int end = _endIndex; | |
| 435 if (start != end - 1) { | |
| 436 if (start == end) { | |
| 437 throw new StateError("No elements"); | |
| 438 } | |
| 439 throw new StateError("Too many elements"); | |
| 440 } | |
| 441 return _f(_list[start]); | |
| 442 } | |
| 443 | |
| 444 T elementAt(int index) { | |
| 445 index += _startIndex; | |
| 446 if (index >= _endIndex) { | |
| 447 throw new StateError("No matching element"); | |
| 448 } | |
| 449 return _f(_list.elementAt(index)); | |
| 450 } | |
| 451 | |
| 452 bool contains(T element) { | |
| 453 int length = _list.length; | |
| 454 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 455 if (_f(_list[i]) == element) { | |
| 456 return true; | |
| 457 } | |
| 458 if (_list.length != length) { | |
| 459 throw new ConcurrentModificationError(_list); | |
| 460 } | |
| 461 } | |
| 462 return false; | |
| 463 } | |
| 464 | |
| 465 bool every(bool test(T element)) { | |
| 466 int length = _list.length; | |
| 467 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 468 if (!test(_f(_list[i]))) return false; | |
| 469 if (_list.length != length) { | |
| 470 throw new ConcurrentModificationError(_list); | |
| 471 } | |
| 472 } | |
| 473 return true; | |
| 474 } | |
| 475 | |
| 476 bool any(bool test(T element)) { | |
| 477 int length = _list.length; | |
| 478 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 479 if (test(_f(_list[i]))) return true; | |
| 480 if (_list.length != length) { | |
| 481 throw new ConcurrentModificationError(_list); | |
| 482 } | |
| 483 } | |
| 484 return false; | |
| 485 } | |
| 486 | |
| 487 T firstMatching(bool test(T element), { T orElse() }) { | |
| 488 int length = _list.length; | |
| 489 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 490 T value = _f(_list[i]); | |
| 491 if (test(value)) return value; | |
| 492 if (_list.length != length) { | |
| 493 throw new ConcurrentModificationError(_list); | |
| 494 } | |
| 495 } | |
| 496 if (orElse != null) return orElse(); | |
| 497 throw new StateError("No matching element"); | |
| 498 } | |
| 499 | |
| 500 T lastMatching(bool test(T element), { T orElse() }) { | |
| 501 int length = _list.length; | |
| 502 for (int i = _endIndex - 1, start = _startIndex; i >= start; i++) { | |
| 503 T value = _f(_list[i]); | |
| 504 if (test(value)) return value; | |
| 505 if (_list.length != length) { | |
| 506 throw new ConcurrentModificationError(_list); | |
| 507 } | |
| 508 } | |
| 509 if (orElse != null) return orElse(); | |
| 510 throw new StateError("No matching element"); | |
| 511 } | |
| 512 | |
| 513 T singleMatching(bool test(T element)) { | |
| 514 int length = _list.length; | |
| 515 T match; | |
| 516 bool matchFound = false; | |
| 517 for (int i = _startIndex, n = _endIndex; i < n; i++) { | |
| 518 T value = _f(_list[i]); | |
| 519 if (test(value)) { | |
| 520 if (matchFound) { | |
| 521 throw new StateError("More than one matching element"); | |
| 522 } | |
| 523 matchFound = true; | |
| 524 match = value; | |
| 525 } | |
| 526 if (_list.length != length) { | |
| 527 throw new ConcurrentModificationError(_list); | |
| 528 } | |
| 529 } | |
| 530 if (matchFound) return match; | |
| 531 throw new StateError("No matching element"); | |
| 532 } | |
| 533 | |
| 534 T min([int compare(T a, T b)]) { | |
| 535 if (compare == null) { | |
| 536 var defaultCompare = Comparable.compare; | |
| 537 compare = defaultCompare; | |
| 538 } | |
| 539 int length = _list.length; | |
| 540 int start = _startIndex; | |
| 541 int end = _endIndex; | |
| 542 if (start == end) return null; | |
| 543 T value = _f(_list[start]); | |
| 544 if (_list.length != length) { | |
| 545 throw new ConcurrentModificationError(_list); | |
| 546 } | |
| 547 for (int i = start + 1; i < end; i++) { | |
| 548 T nextValue = _f(_list[i]); | |
| 549 if (compare(value, nextValue) > 0) { | |
| 550 value = nextValue; | |
| 551 } | |
| 552 if (_list.length != length) { | |
| 553 throw new ConcurrentModificationError(_list); | |
| 554 } | |
| 555 } | |
| 556 return value; | |
| 557 } | |
| 558 | |
| 559 T max([int compare(T a, T b)]) { | |
| 560 if (compare == null) { | |
| 561 var defaultCompare = Comparable.compare; | |
| 562 compare = defaultCompare; | |
| 563 } | |
| 564 int length = _list.length; | |
| 565 int start = _startIndex; | |
| 566 int end = _endIndex; | |
| 567 if (start == end) return null; | |
| 568 T value = _f(_list[start]); | |
| 569 if (_list.length != length) { | |
| 570 throw new ConcurrentModificationError(_list); | |
| 571 } | |
| 572 for (int i = start + 1; i < end; i++) { | |
| 573 T nextValue = _f(_list[i]); | |
| 574 if (compare(value, nextValue) < 0) { | |
| 575 value = nextValue; | |
| 576 } | |
| 577 if (_list.length != length) { | |
| 578 throw new ConcurrentModificationError(_list); | |
| 579 } | |
| 580 } | |
| 581 return value; | |
| 582 } | |
| 583 | |
| 584 String join([String separator]) { | |
| 585 int start = _startIndex; | |
| 586 int end = _endIndex; | |
| 587 if (start == end) return ""; | |
| 588 StringBuffer buffer = new StringBuffer("${_f(_list[start])}"); | |
| 589 if (_list.length != length) { | |
| 590 throw new ConcurrentModificationError(_list); | |
| 591 } | |
| 592 for (int i = start + 1; i < end; i++) { | |
| 593 if (separator != null && separator != "") { | |
| 594 buffer.add(separator); | |
| 595 } | |
| 596 buffer.add("${_f(_list[i])}"); | |
| 597 if (_list.length != length) { | |
| 598 throw new ConcurrentModificationError(_list); | |
| 599 } | |
| 600 } | |
| 601 return buffer.toString(); | |
| 602 } | |
| 603 | |
| 604 Iterable<T> where(bool test(T element)) => super.where(test); | |
| 605 | |
| 606 Iterable map(f(T element)) { | |
| 607 return new MappedListIterable(_list, (S v) => f(_f(v)), _start, _end); | |
| 608 } | |
| 609 | |
| 610 Iterable mappedBy(f(T element)) => map(f); | |
| 611 | |
| 612 reduce(var initialValue, combine(var previousValue, T element)) { | |
| 613 return _list.reduce(initialValue, (v, S e) => combine(v, _f(e))); | |
| 614 } | |
| 615 | |
| 616 Iterable<T> skip(int count) { | |
| 617 int start = _startIndex + count; | |
| 618 if (_end != null && start >= _end) { | |
| 619 return new EmptyIterable<T>(); | |
| 620 } | |
| 621 return new MappedListIterable(_list, _f, start, _end); | |
| 622 } | |
| 623 | |
| 624 Iterable<T> skipWhile(bool test(T element)) => super.skipWhile(test); | |
| 625 | |
| 626 Iterable<T> take(int count) { | |
| 627 int newEnd = _start + count; | |
| 628 if (_end == null || newEnd < _end) { | |
| 629 return new MappedListIterable(_list, _f, _start, newEnd); | |
| 630 } | |
| 631 // Equivalent to "this". | |
| 632 return new MappedListIterable(_list, _f, _start, _end); | |
| 633 } | |
| 634 | |
| 635 Iterable<T> takeWhile(bool test(T element)) => super.takeWhile(test); | |
| 636 | |
| 637 List<T> toList() { | |
| 638 List<T> result = new List<T>(); | |
| 639 forEach(result.add); | |
| 640 return result; | |
| 641 } | |
| 642 | |
| 643 Set<T> toSet() { | |
| 644 Set<T> result = new Set<T>(); | |
| 645 forEach(result.add); | |
| 646 return result; | |
| 647 } | |
| 648 } | 378 } |
| 649 | 379 |
| 650 /** | |
| 651 * Iterator for [MappedListIterable]. | |
| 652 * | |
| 653 * A list iterator that iterates over (a sublist of) a list and | |
| 654 * returns the values transformed by a function. | |
| 655 * | |
| 656 * As a list iterator, it throws if the length of the list has | |
| 657 * changed during iteration. | |
| 658 */ | |
| 659 class MappedListIterator<S, T> implements Iterator<T> { | |
| 660 List<S> _list; | |
| 661 // TODO(ahe): Restore type when feature is implemented in dart2js | |
| 662 // checked mode. http://dartbug.com/7733 | |
| 663 final /* _Transformation<S, T> */ _f; | |
| 664 final int _endIndex; | |
| 665 final int _length; | |
| 666 int _index; | |
| 667 T _current; | |
| 668 | |
| 669 MappedListIterator(List<S> list, this._f, int start, this._endIndex) | |
| 670 : _list = list, _length = list.length, _index = start; | |
| 671 | |
| 672 T get current => _current; | |
| 673 | |
| 674 bool moveNext() { | |
| 675 if (_list.length != _length) { | |
| 676 throw new ConcurrentModificationError(_list); | |
| 677 } | |
| 678 if (_index >= _endIndex) { | |
| 679 _current = null; | |
| 680 return false; | |
| 681 } | |
| 682 _current = _f(_list[_index]); | |
| 683 _index++; | |
| 684 return true; | |
| 685 } | |
| 686 } | |
| 687 | 380 |
| 688 typedef bool _ElementPredicate<E>(E element); | 381 typedef bool _ElementPredicate<E>(E element); |
| 689 | 382 |
| 690 class WhereIterable<E> extends Iterable<E> { | 383 class WhereIterable<E> extends Iterable<E> { |
| 691 final Iterable<E> _iterable; | 384 final Iterable<E> _iterable; |
| 692 // TODO(ahe): Restore type when feature is implemented in dart2js | 385 // TODO(ahe): Restore type when feature is implemented in dart2js |
| 693 // checked mode. http://dartbug.com/7733 | 386 // checked mode. http://dartbug.com/7733 |
| 694 final /* _ElementPredicate */ _f; | 387 final /* _ElementPredicate */ _f; |
| 695 | 388 |
| 696 WhereIterable(this._iterable, bool this._f(E element)); | 389 WhereIterable(this._iterable, bool this._f(E element)); |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 E min([int compare(E a, E b)]) => null; | 655 E min([int compare(E a, E b)]) => null; |
| 963 | 656 |
| 964 E max([int compare(E a, E b)]) => null; | 657 E max([int compare(E a, E b)]) => null; |
| 965 | 658 |
| 966 String join([String separator]) => ""; | 659 String join([String separator]) => ""; |
| 967 | 660 |
| 968 Iterable<E> where(bool test(E element)) => this; | 661 Iterable<E> where(bool test(E element)) => this; |
| 969 | 662 |
| 970 Iterable map(f(E element)) => const EmptyIterable(); | 663 Iterable map(f(E element)) => const EmptyIterable(); |
| 971 | 664 |
| 972 Iterable mappedBy(f(E element)) => const EmptyIterable(); | |
| 973 | |
| 974 reduce(var initialValue, combine(var previousValue, E element)) { | 665 reduce(var initialValue, combine(var previousValue, E element)) { |
| 975 return initialValue; | 666 return initialValue; |
| 976 } | 667 } |
| 977 | 668 |
| 978 Iterable<E> skip(int count) => this; | 669 Iterable<E> skip(int count) => this; |
| 979 | 670 |
| 980 Iterable<E> skipWhile(bool test(E element)) => this; | 671 Iterable<E> skipWhile(bool test(E element)) => this; |
| 981 | 672 |
| 982 Iterable<E> take(int count) => this; | 673 Iterable<E> take(int count) => this; |
| 983 | 674 |
| 984 Iterable<E> takeWhile(bool test(E element)) => this; | 675 Iterable<E> takeWhile(bool test(E element)) => this; |
| 985 | 676 |
| 986 List toList() => <E>[]; | 677 List toList() => <E>[]; |
| 987 | 678 |
| 988 Set toSet() => new Set<E>(); | 679 Set toSet() => new Set<E>(); |
| 989 } | 680 } |
| 990 | 681 |
| 991 /** The always empty iterator. */ | 682 /** The always empty iterator. */ |
| 992 class EmptyIterator<E> implements Iterator<E> { | 683 class EmptyIterator<E> implements Iterator<E> { |
| 993 const EmptyIterator(); | 684 const EmptyIterator(); |
| 994 bool moveNext() => false; | 685 bool moveNext() => false; |
| 995 E get current => null; | 686 E get current => null; |
| 996 } | 687 } |
| 997 | 688 |
| 998 /** An [Iterator] that can move in both directions. */ | 689 /** An [Iterator] that can move in both directions. */ |
| 999 abstract class BiDirectionalIterator<T> implements Iterator<T> { | 690 abstract class BiDirectionalIterator<T> implements Iterator<T> { |
| 1000 bool movePrevious(); | 691 bool movePrevious(); |
| 1001 } | 692 } |
| OLD | NEW |