/* -*- 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 DOM_QUOTA_FLATTEN_H_ #define DOM_QUOTA_FLATTEN_H_ #include #include #include // XXX This should be moved to MFBT. namespace mozilla::dom::quota { namespace detail { using std::begin; using std::end; template auto Flatten(NestedRange&& aRange) -> std::enable_if_t< std::is_same_v()))::value_type>>, std::conditional_t, std::decay_t, NestedRange>> { return std::forward(aRange); } template struct FlatIter { using OuterIterator = decltype(begin(std::declval&>())); using InnerIterator = decltype(begin(*begin(std::declval&>()))); explicit FlatIter(const NestedRange& aRange, OuterIterator aIter) : mOuterIter{std::move(aIter)}, mOuterEnd{end(aRange)} { InitInner(); } const T& operator*() const { return *mInnerIter; } FlatIter& operator++() { ++mInnerIter; if (mInnerIter == mInnerEnd) { ++mOuterIter; InitInner(); } return *this; } bool operator!=(const FlatIter& aOther) const { return mOuterIter != aOther.mOuterIter || (mOuterIter != mOuterEnd && mInnerIter != aOther.mInnerIter); } private: void InitInner() { while (mOuterIter != mOuterEnd) { const typename OuterIterator::value_type& innerRange = *mOuterIter; mInnerIter = begin(innerRange); mInnerEnd = end(innerRange); if (mInnerIter != mInnerEnd) { break; } ++mOuterIter; } } OuterIterator mOuterIter; const OuterIterator mOuterEnd; InnerIterator mInnerIter; InnerIterator mInnerEnd; }; template struct FlatRange { explicit FlatRange(NestedRange aRange) : mRange{std::move(aRange)} {} auto begin() const { using std::begin; return FlatIter{mRange, begin(mRange)}; } auto end() const { using std::end; return FlatIter{mRange, end(mRange)}; } private: NestedRange mRange; }; template auto Flatten(NestedRange&& aRange) -> std::enable_if_t< !std::is_same_v< T, std::decay_t&>()))::value_type>>, FlatRange> { return FlatRange{std::forward(aRange)}; } } // namespace detail template auto Flatten(NestedRange&& aRange) -> decltype(auto) { return detail::Flatten(std::forward(aRange)); } } // namespace mozilla::dom::quota #endif