tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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