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
) -> 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
>
35 decltype(begin(std::declval
<const std::decay_t
<NestedRange
>&>()));
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
)} {
44 const T
& operator*() const { return *mInnerIter
; }
46 FlatIter
& operator++() {
48 if (mInnerIter
== mInnerEnd
) {
55 bool operator!=(const FlatIter
& aOther
) const {
56 return mOuterIter
!= aOther
.mOuterIter
||
57 (mOuterIter
!= mOuterEnd
&& mInnerIter
!= aOther
.mInnerIter
);
62 while (mOuterIter
!= mOuterEnd
) {
63 const typename
OuterIterator::value_type
& innerRange
= *mOuterIter
;
65 mInnerIter
= begin(innerRange
);
66 mInnerEnd
= end(innerRange
);
68 if (mInnerIter
!= mInnerEnd
) {
76 OuterIterator mOuterIter
;
77 const OuterIterator mOuterEnd
;
79 InnerIterator mInnerIter
;
80 InnerIterator mInnerEnd
;
83 template <typename T
, typename NestedRange
>
85 explicit FlatRange(NestedRange aRange
) : mRange
{std::move(aRange
)} {}
89 return FlatIter
<T
, NestedRange
>{mRange
, begin(mRange
)};
93 return FlatIter
<T
, NestedRange
>{mRange
, end(mRange
)};
100 template <typename T
, typename NestedRange
>
101 auto Flatten(NestedRange
&& aRange
) -> std::enable_if_t
<
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