Line data Source code
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 0 : const CombinedIterableView(this._iterables);
20 :
21 : Iterator<T> get iterator =>
22 0 : 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 0 : bool contains(Object element) => _iterables.any((i) => i.contains(element));
28 :
29 0 : bool get isEmpty => _iterables.every((i) => i.isEmpty);
30 :
31 0 : 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 0 : _CombinedIterator(this._iterators);
45 :
46 0 : T get current => _iterators.current?.current;
47 :
48 : bool moveNext() {
49 0 : var current = _iterators.current;
50 0 : if (current != null && current.moveNext()) {
51 : return true;
52 : }
53 0 : return _iterators.moveNext() && moveNext();
54 : }
55 : }
|