Bug 1700051: part 46) Const-qualify `mozInlineSpellStatus::mAnchorRange`. r=smaug
[gecko.git] / dom / quota / Flatten.h
blob2eb29c6010c2c105873235890dafffc32bc7866c
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/. */
7 #ifndef DOM_QUOTA_FLATTEN_H_
8 #define DOM_QUOTA_FLATTEN_H_
10 #include <iterator>
11 #include <type_traits>
12 #include <utility>
14 // XXX This should be moved to MFBT.
16 namespace mozilla::dom::quota {
18 namespace detail {
20 using std::begin;
21 using std::end;
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);
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>&>())));
39 explicit FlatIter(const NestedRange& aRange, OuterIterator aIter)
40 : mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} {
41 InitInner();
44 const T& operator*() const { return *mInnerIter; }
46 FlatIter& operator++() {
47 ++mInnerIter;
48 if (mInnerIter == mInnerEnd) {
49 ++mOuterIter;
50 InitInner();
52 return *this;
55 bool operator!=(const FlatIter& aOther) const {
56 return mOuterIter != aOther.mOuterIter ||
57 (mOuterIter != mOuterEnd && mInnerIter != aOther.mInnerIter);
60 private:
61 void InitInner() {
62 while (mOuterIter != mOuterEnd) {
63 const typename OuterIterator::value_type& innerRange = *mOuterIter;
65 mInnerIter = begin(innerRange);
66 mInnerEnd = end(innerRange);
68 if (mInnerIter != mInnerEnd) {
69 break;
72 ++mOuterIter;
76 OuterIterator mOuterIter;
77 const OuterIterator mOuterEnd;
79 InnerIterator mInnerIter;
80 InnerIterator mInnerEnd;
83 template <typename T, typename NestedRange>
84 struct FlatRange {
85 explicit FlatRange(NestedRange aRange) : mRange{std::move(aRange)} {}
87 auto begin() const {
88 using std::begin;
89 return FlatIter<T, NestedRange>{mRange, begin(mRange)};
91 auto end() const {
92 using std::end;
93 return FlatIter<T, NestedRange>{mRange, end(mRange)};
96 private:
97 NestedRange mRange;
100 template <typename T, typename NestedRange>
101 auto Flatten(NestedRange&& aRange) -> std::enable_if_t<
102 !std::is_same_v<
103 T, std::decay_t<typename decltype(begin(
104 std::declval<const std::decay_t<NestedRange>&>()))::value_type>>,
105 FlatRange<T, NestedRange>> {
106 return FlatRange<T, NestedRange>{std::forward<NestedRange>(aRange)};
109 } // namespace detail
111 template <typename T, typename NestedRange>
112 auto Flatten(NestedRange&& aRange) -> decltype(auto) {
113 return detail::Flatten<T>(std::forward<NestedRange>(aRange));
116 } // namespace mozilla::dom::quota
118 #endif