tor-browser

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

Flatten.h (3450B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef DOM_QUOTA_FLATTEN_H_
      8 #define DOM_QUOTA_FLATTEN_H_
      9 
     10 #include <iterator>
     11 #include <type_traits>
     12 #include <utility>
     13 
     14 // XXX This should be moved to MFBT.
     15 
     16 namespace mozilla::dom::quota {
     17 
     18 namespace detail {
     19 
     20 using std::begin;
     21 using std::end;
     22 
     23 template <typename T, typename NestedRange>
     24 auto Flatten(NestedRange&& aRange) -> std::enable_if_t<
     25    std::is_same_v<T, std::decay_t<typename decltype(begin(
     26                          std::declval<const NestedRange&>()))::value_type>>,
     27    std::conditional_t<std::is_rvalue_reference_v<NestedRange>,
     28                       std::decay_t<NestedRange>, NestedRange>> {
     29  return std::forward<NestedRange>(aRange);
     30 }
     31 
     32 template <typename T, typename NestedRange>
     33 struct FlatIter {
     34  using OuterIterator =
     35      decltype(begin(std::declval<const std::decay_t<NestedRange>&>()));
     36  using InnerIterator =
     37      decltype(begin(*begin(std::declval<const std::decay_t<NestedRange>&>())));
     38 
     39  using iterator_category = std::input_iterator_tag;
     40  using value_type = T;
     41  using difference_type = std::ptrdiff_t;
     42  using pointer = const T*;
     43  using reference = const T&;
     44 
     45  explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
     46      : mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
     47    InitInner();
     48  }
     49 
     50  const T& operator*() const { return *mInnerIter; }
     51 
     52  FlatIter& operator++() {
     53    ++mInnerIter;
     54    if (mInnerIter == mInnerEnd) {
     55      ++mOuterIter;
     56      InitInner();
     57    }
     58    return *this;
     59  }
     60 
     61  bool operator!=(const FlatIter& aOther) const {
     62    return mOuterIter != aOther.mOuterIter ||
     63           (mOuterIter != mOuterEnd && mInnerIter != aOther.mInnerIter);
     64  }
     65 
     66  bool operator==(const FlatIter& aOther) const { return !(*this != aOther); }
     67 
     68 private:
     69  void InitInner() {
     70    while (mOuterIter != mOuterEnd) {
     71      const typename OuterIterator::value_type& innerRange = *mOuterIter;
     72 
     73      mInnerIter = begin(innerRange);
     74      mInnerEnd = end(innerRange);
     75 
     76      if (mInnerIter != mInnerEnd) {
     77        break;
     78      }
     79 
     80      ++mOuterIter;
     81    }
     82  }
     83 
     84  OuterIterator mOuterIter;
     85  const OuterIterator mOuterEnd;
     86 
     87  InnerIterator mInnerIter;
     88  InnerIterator mInnerEnd;
     89 };
     90 
     91 template <typename T, typename NestedRange>
     92 struct FlatRange {
     93  explicit FlatRange(NestedRange aRange) : mRange{std::move(aRange)} {}
     94 
     95  auto begin() const {
     96    using std::begin;
     97    return FlatIter<T, NestedRange>{mRange, begin(mRange)};
     98  }
     99  auto end() const {
    100    using std::end;
    101    return FlatIter<T, NestedRange>{mRange, end(mRange)};
    102  }
    103 
    104 private:
    105  NestedRange mRange;
    106 };
    107 
    108 template <typename T, typename NestedRange>
    109 auto Flatten(NestedRange&& aRange) -> std::enable_if_t<
    110    !std::is_same_v<
    111        T, std::decay_t<typename decltype(begin(
    112               std::declval<const std::decay_t<NestedRange>&>()))::value_type>>,
    113    FlatRange<T, NestedRange>> {
    114  return FlatRange<T, NestedRange>{std::forward<NestedRange>(aRange)};
    115 }
    116 
    117 }  // namespace detail
    118 
    119 template <typename T, typename NestedRange>
    120 auto Flatten(NestedRange&& aRange) -> decltype(auto) {
    121  return detail::Flatten<T>(std::forward<NestedRange>(aRange));
    122 }
    123 
    124 }  // namespace mozilla::dom::quota
    125 
    126 #endif