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_
11 #include <type_traits>
14 // XXX This should be moved to MFBT.
16 namespace mozilla::dom::quota
{
23 template <typename T
, typename NestedRange
>
24 auto Flatten(NestedRange
&& aRange
)
27 std::decay_t
<typename
decltype(begin(
28 std::declval
<const NestedRange
&>()))::value_type
>>,
29 std::conditional_t
<std::is_rvalue_reference_v
<NestedRange
>,
30 std::decay_t
<NestedRange
>, NestedRange
>> {
31 return std::forward
<NestedRange
>(aRange
);
34 template <typename T
, typename NestedRange
>
37 decltype(begin(std::declval
<const std::decay_t
<NestedRange
>&>()));
39 decltype(begin(*begin(std::declval
<const std::decay_t
<NestedRange
>&>())));
41 explicit FlatIter(const NestedRange
& aRange
, OuterIterator aIter
)
42 : mOuterIter
{std::move(aIter
)}, mOuterEnd
{end(aRange
)} {
46 const T
& operator*() const { return *mInnerIter
; }
48 FlatIter
& operator++() {
50 if (mInnerIter
== mInnerEnd
) {
57 bool operator!=(const FlatIter
& aOther
) const {
58 return mOuterIter
!= aOther
.mOuterIter
||
59 (mOuterIter
!= mOuterEnd
&& mInnerIter
!= aOther
.mInnerIter
);
64 while (mOuterIter
!= mOuterEnd
) {
65 const typename
OuterIterator::value_type
& innerRange
= *mOuterIter
;
67 mInnerIter
= begin(innerRange
);
68 mInnerEnd
= end(innerRange
);
70 if (mInnerIter
!= mInnerEnd
) {
78 OuterIterator mOuterIter
;
79 const OuterIterator mOuterEnd
;
81 InnerIterator mInnerIter
;
82 InnerIterator mInnerEnd
;
85 template <typename T
, typename NestedRange
>
87 explicit FlatRange(NestedRange aRange
) : mRange
{std::move(aRange
)} {}
91 return FlatIter
<T
, NestedRange
>{mRange
, begin(mRange
)};
95 return FlatIter
<T
, NestedRange
>{mRange
, end(mRange
)};
102 template <typename T
, typename NestedRange
>
103 auto Flatten(NestedRange
&& aRange
)
105 !std::is_same_v
<T
, std::decay_t
<typename
decltype(begin(
106 std::declval
<const std::decay_t
<
107 NestedRange
>&>()))::value_type
>>,
108 FlatRange
<T
, NestedRange
>> {
109 return FlatRange
<T
, NestedRange
>{std::forward
<NestedRange
>(aRange
)};
112 } // namespace detail
114 template <typename T
, typename NestedRange
>
115 auto Flatten(NestedRange
&& aRange
) -> decltype(auto) {
116 return detail::Flatten
<T
>(std::forward
<NestedRange
>(aRange
));
119 } // namespace mozilla::dom::quota