IteratorUtils.h (2608B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef gc_IteratorUtils_h 8 #define gc_IteratorUtils_h 9 10 #include "mozilla/Array.h" 11 #include "mozilla/Maybe.h" 12 13 namespace js { 14 15 /* 16 * Create an iterator that yields the values from IteratorB(a) for all a in 17 * IteratorA(). Equivalent to nested for loops over IteratorA and IteratorB 18 * where IteratorB is constructed with a value from IteratorA. 19 */ 20 template <typename IteratorA, typename IteratorB> 21 class NestedIterator { 22 using T = decltype(std::declval<IteratorB>().get()); 23 24 IteratorA a; 25 mozilla::Maybe<IteratorB> b; 26 27 public: 28 template <typename... Args> 29 explicit NestedIterator(Args&&... args) : a(std::forward<Args>(args)...) { 30 settle(); 31 } 32 33 bool done() const { return b.isNothing(); } 34 35 T get() const { 36 MOZ_ASSERT(!done()); 37 return b.ref().get(); 38 } 39 40 void next() { 41 MOZ_ASSERT(!done()); 42 b->next(); 43 if (b->done()) { 44 b.reset(); 45 a.next(); 46 settle(); 47 } 48 } 49 50 const IteratorB& ref() const { return *b; } 51 52 operator T() const { return get(); } 53 54 T operator->() const { return get(); } 55 56 private: 57 void settle() { 58 MOZ_ASSERT(b.isNothing()); 59 while (!a.done()) { 60 b.emplace(a.get()); 61 if (!b->done()) { 62 break; 63 } 64 b.reset(); 65 a.next(); 66 } 67 } 68 69 protected: 70 const IteratorA& iterA() const { return a; } 71 }; 72 73 /* 74 * An iterator the yields values from each of N of instances of Iterator in 75 * sequence. 76 */ 77 template <typename Iterator, size_t N> 78 class ChainedIterator { 79 using T = decltype(std::declval<Iterator>().get()); 80 81 mozilla::Array<Iterator, N> iterators; 82 size_t index = 0; 83 84 public: 85 template <typename... Args> 86 MOZ_IMPLICIT ChainedIterator(Args&&... args) 87 : iterators(Iterator(std::forward<Args>(args))...) { 88 static_assert(N > 1); 89 settle(); 90 } 91 92 bool done() const { return index == N; } 93 94 void next() { 95 MOZ_ASSERT(!done()); 96 iterators[index].next(); 97 settle(); 98 } 99 100 T get() const { 101 MOZ_ASSERT(!done()); 102 return iterators[index].get(); 103 } 104 105 operator T() const { return get(); } 106 T operator->() const { return get(); } 107 108 private: 109 void settle() { 110 MOZ_ASSERT(!done()); 111 while (iterators[index].done()) { 112 index++; 113 if (done()) { 114 break; 115 } 116 } 117 } 118 }; 119 120 } /* namespace js */ 121 122 #endif // gc_IteratorUtils_h