From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- mfbt/ReverseIterator.h | 173 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 mfbt/ReverseIterator.h (limited to 'mfbt/ReverseIterator.h') diff --git a/mfbt/ReverseIterator.h b/mfbt/ReverseIterator.h new file mode 100644 index 0000000000..c9e77ffc89 --- /dev/null +++ b/mfbt/ReverseIterator.h @@ -0,0 +1,173 @@ +/* -*- 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/. */ + +/* An iterator that acts like another iterator, but iterating in + * the negative direction. (Note that not all iterators can iterate + * in the negative direction.) */ + +#ifndef mozilla_ReverseIterator_h +#define mozilla_ReverseIterator_h + +#include + +#include "mozilla/Attributes.h" + +namespace mozilla { + +// This should only be used in cases where std::reverse_iterator cannot be used, +// because the underlying iterator is not a proper bidirectional iterator, but +// rather, e.g., a stashing iterator such as IntegerIterator. It is less +// efficient than std::reverse_iterator for proper bidirectional iterators. +template +class ReverseIterator { + public: + using value_type = typename IteratorT::value_type; + using pointer = typename IteratorT::pointer; + using reference = typename IteratorT::reference; + using difference_type = typename IteratorT::difference_type; + using iterator_category = typename IteratorT::iterator_category; + + explicit ReverseIterator(IteratorT aIter) : mCurrent(std::move(aIter)) {} + + // The return type is not reference, but rather the return type of + // Iterator::operator*(), which might be value_type, to allow this to work + // with stashing iterators such as IntegerIterator, see also Bug 1175485. + decltype(*std::declval()) operator*() const { + IteratorT tmp = mCurrent; + return *--tmp; + } + + /* Difference operator */ + difference_type operator-(const ReverseIterator& aOther) const { + return aOther.mCurrent - mCurrent; + } + + /* Increments and decrements operators */ + + ReverseIterator& operator++() { + --mCurrent; + return *this; + } + ReverseIterator& operator--() { + ++mCurrent; + return *this; + } + ReverseIterator operator++(int) { + auto ret = *this; + mCurrent--; + return ret; + } + ReverseIterator operator--(int) { + auto ret = *this; + mCurrent++; + return ret; + } + + /* Comparison operators */ + + template + friend bool operator==(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + template + friend bool operator!=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + template + friend bool operator<(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + template + friend bool operator<=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + template + friend bool operator>(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + template + friend bool operator>=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2); + + private: + IteratorT mCurrent; +}; + +template +bool operator==(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent == aIter2.mCurrent; +} + +template +bool operator!=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent != aIter2.mCurrent; +} + +template +bool operator<(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent > aIter2.mCurrent; +} + +template +bool operator<=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent >= aIter2.mCurrent; +} + +template +bool operator>(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent < aIter2.mCurrent; +} + +template +bool operator>=(const ReverseIterator& aIter1, + const ReverseIterator& aIter2) { + return aIter1.mCurrent <= aIter2.mCurrent; +} + +namespace detail { + +template > +class IteratorRange { + public: + typedef IteratorT iterator; + typedef IteratorT const_iterator; + typedef ReverseIteratorT reverse_iterator; + typedef ReverseIteratorT const_reverse_iterator; + + IteratorRange(IteratorT aIterBegin, IteratorT aIterEnd) + : mIterBegin(std::move(aIterBegin)), mIterEnd(std::move(aIterEnd)) {} + + iterator begin() const { return mIterBegin; } + const_iterator cbegin() const { return begin(); } + iterator end() const { return mIterEnd; } + const_iterator cend() const { return end(); } + reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); } + const_reverse_iterator crbegin() const { return rbegin(); } + reverse_iterator rend() const { return reverse_iterator(mIterBegin); } + const_reverse_iterator crend() const { return rend(); } + + IteratorT mIterBegin; + IteratorT mIterEnd; +}; + +} // namespace detail + +template +detail::IteratorRange Reversed( + Range& aRange) { + return {aRange.rbegin(), aRange.rend()}; +} + +template +detail::IteratorRange Reversed( + const Range& aRange) { + return {aRange.rbegin(), aRange.rend()}; +} + +} // namespace mozilla + +#endif // mozilla_ReverseIterator_h -- cgit v1.2.3