OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, 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 import 'dart:collection'; |
| 6 |
| 7 /// A view of several iterables combined sequentially into a single iterable. |
| 8 /// |
| 9 /// All methods and accessors treat the [CombinedIterableView] as if it were a |
| 10 /// single concatenated iterable, but the underlying implementation is based on |
| 11 /// lazily accessing individual iterable instances. This means that if the |
| 12 /// underlying iterables change, the [CombinedIterableView] will reflect those |
| 13 /// changes. |
| 14 class CombinedIterableView<T> extends IterableBase<T> { |
| 15 /// The iterables that this combines. |
| 16 final Iterable<Iterable<T>> _iterables; |
| 17 |
| 18 /// Creates a combined view of [iterables]. |
| 19 const CombinedIterableView(this._iterables); |
| 20 |
| 21 Iterator<T> get iterator => |
| 22 new _CombinedIterator<T>(_iterables.map((i) => i.iterator).iterator); |
| 23 |
| 24 // Special cased contains/isEmpty/length since many iterables have an |
| 25 // efficient implementation instead of running through the entire iterator. |
| 26 |
| 27 bool contains(Object element) => _iterables.any((i) => i.contains(element)); |
| 28 |
| 29 bool get isEmpty => _iterables.every((i) => i.isEmpty); |
| 30 |
| 31 int get length => _iterables.fold(0, (length, i) => length + i.length); |
| 32 } |
| 33 |
| 34 /// The iterator for [CombinedIterableView]. |
| 35 /// |
| 36 /// This moves through each iterable's iterators in sequence. |
| 37 class _CombinedIterator<T> implements Iterator<T> { |
| 38 /// The iterators that this combines. |
| 39 /// |
| 40 /// Because this comes from a call to [Iterable.map], it's lazy and will |
| 41 /// avoid instantiating unnecessary iterators. |
| 42 final Iterator<Iterator<T>> _iterators; |
| 43 |
| 44 _CombinedIterator(this._iterators); |
| 45 |
| 46 T get current => _iterators.current?.current; |
| 47 |
| 48 bool moveNext() { |
| 49 var current = _iterators.current; |
| 50 if (current != null && current.moveNext()) { |
| 51 return true; |
| 52 } |
| 53 return _iterators.moveNext() && moveNext(); |
| 54 } |
| 55 } |
OLD | NEW |