Bug 1647319 - Add NestedIterator template class r=sfink
☠☠ backed out by 17e8b5e9f8f9 ☠ ☠
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 23 Jun 2020 08:30:34 +0000
changeset 600838 bd0b3614efcf062451ed9443fdae06e5cf43b808
parent 600837 1adf40ab95b9e04460a4b4e644a1490ed8a86f46
child 600839 0e900e18ead7ea87acc2cdc68ddb5e7b1054da6a
push id13310
push userffxbld-merge
push dateMon, 29 Jun 2020 14:50:06 +0000
treeherdermozilla-beta@15a59a0afa5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1647319
milestone79.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1647319 - Add NestedIterator template class r=sfink Differential Revision: https://phabricator.services.mozilla.com/D80483
js/src/gc/IteratorUtils.h
new file mode 100644
--- /dev/null
+++ b/js/src/gc/IteratorUtils.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef gc_IteratorUtils_h
+#define gc_IteratorUtils_h
+
+#include "mozilla/Maybe.h"
+
+namespace js {
+
+/*
+ * Create an iterator that yields the values from IteratorB(a) for all a in
+ * IteratorA(). Equivalent to nested for loops over IteratorA and IteratorB
+ * where IteratorB is constructed with a value from IteratorA.
+ */
+template <typename IteratorA, typename IteratorB>
+class NestedIterator {
+  using T = decltype(std::declval<IteratorB>().get());
+
+  IteratorA a;
+  mozilla::Maybe<IteratorB> b;
+
+ public:
+  template <typename... Args>
+  NestedIterator(Args&&... args) : a(std::forward<Args>(args)...) {
+    settle();
+  }
+
+  bool done() const { return b.isNothing(); }
+
+  T get() const {
+    MOZ_ASSERT(!done());
+    return b.ref().get();
+  }
+
+  void next() {
+    MOZ_ASSERT(!done());
+    b->next();
+    if (b->done()) {
+      b.reset();
+      a.next();
+      settle();
+    }
+  }
+
+  operator T() const { return get(); }
+
+  T operator->() const { return get(); }
+
+ private:
+  void settle() {
+    MOZ_ASSERT(b.isNothing());
+    while (!a.done()) {
+      b.emplace(a.get());
+      if (!b->done()) {
+        break;
+      }
+      b.reset();
+      a.next();
+    }
+  }
+};
+
+} /* namespace js */
+
+#endif  // gc_IteratorUtils_h