tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ReverseIterator.h (6033B)


      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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* An iterator that acts like another iterator, but iterating in
      8 * the negative direction. (Note that not all iterators can iterate
      9 * in the negative direction.) */
     10 
     11 #ifndef mozilla_ReverseIterator_h
     12 #define mozilla_ReverseIterator_h
     13 
     14 #include <utility>
     15 
     16 namespace mozilla {
     17 
     18 // This should only be used in cases where std::reverse_iterator cannot be used,
     19 // because the underlying iterator is not a proper bidirectional iterator, but
     20 // rather, e.g., a stashing iterator such as IntegerIterator. It is less
     21 // efficient than std::reverse_iterator for proper bidirectional iterators.
     22 template <typename IteratorT>
     23 class ReverseIterator {
     24 public:
     25  using value_type = typename IteratorT::value_type;
     26  using pointer = typename IteratorT::pointer;
     27  using reference = typename IteratorT::reference;
     28  using difference_type = typename IteratorT::difference_type;
     29  using iterator_category = typename IteratorT::iterator_category;
     30 
     31  explicit ReverseIterator(IteratorT aIter) : mCurrent(std::move(aIter)) {}
     32 
     33  // The return type is not reference, but rather the return type of
     34  // Iterator::operator*(), which might be value_type, to allow this to work
     35  // with stashing iterators such as IntegerIterator, see also Bug 1175485.
     36  decltype(*std::declval<IteratorT>()) operator*() const {
     37    IteratorT tmp = mCurrent;
     38    return *--tmp;
     39  }
     40 
     41  /* Difference operator */
     42  difference_type operator-(const ReverseIterator& aOther) const {
     43    return aOther.mCurrent - mCurrent;
     44  }
     45 
     46  /* Increments and decrements operators */
     47 
     48  ReverseIterator& operator++() {
     49    --mCurrent;
     50    return *this;
     51  }
     52  ReverseIterator& operator--() {
     53    ++mCurrent;
     54    return *this;
     55  }
     56  ReverseIterator operator++(int) {
     57    auto ret = *this;
     58    mCurrent--;
     59    return ret;
     60  }
     61  ReverseIterator operator--(int) {
     62    auto ret = *this;
     63    mCurrent++;
     64    return ret;
     65  }
     66 
     67  /* Comparison operators */
     68 
     69  template <typename Iterator1, typename Iterator2>
     70  friend bool operator==(const ReverseIterator<Iterator1>& aIter1,
     71                         const ReverseIterator<Iterator2>& aIter2);
     72  template <typename Iterator1, typename Iterator2>
     73  friend bool operator!=(const ReverseIterator<Iterator1>& aIter1,
     74                         const ReverseIterator<Iterator2>& aIter2);
     75  template <typename Iterator1, typename Iterator2>
     76  friend bool operator<(const ReverseIterator<Iterator1>& aIter1,
     77                        const ReverseIterator<Iterator2>& aIter2);
     78  template <typename Iterator1, typename Iterator2>
     79  friend bool operator<=(const ReverseIterator<Iterator1>& aIter1,
     80                         const ReverseIterator<Iterator2>& aIter2);
     81  template <typename Iterator1, typename Iterator2>
     82  friend bool operator>(const ReverseIterator<Iterator1>& aIter1,
     83                        const ReverseIterator<Iterator2>& aIter2);
     84  template <typename Iterator1, typename Iterator2>
     85  friend bool operator>=(const ReverseIterator<Iterator1>& aIter1,
     86                         const ReverseIterator<Iterator2>& aIter2);
     87 
     88 private:
     89  IteratorT mCurrent;
     90 };
     91 
     92 template <typename Iterator1, typename Iterator2>
     93 bool operator==(const ReverseIterator<Iterator1>& aIter1,
     94                const ReverseIterator<Iterator2>& aIter2) {
     95  return aIter1.mCurrent == aIter2.mCurrent;
     96 }
     97 
     98 template <typename Iterator1, typename Iterator2>
     99 bool operator!=(const ReverseIterator<Iterator1>& aIter1,
    100                const ReverseIterator<Iterator2>& aIter2) {
    101  return aIter1.mCurrent != aIter2.mCurrent;
    102 }
    103 
    104 template <typename Iterator1, typename Iterator2>
    105 bool operator<(const ReverseIterator<Iterator1>& aIter1,
    106               const ReverseIterator<Iterator2>& aIter2) {
    107  return aIter1.mCurrent > aIter2.mCurrent;
    108 }
    109 
    110 template <typename Iterator1, typename Iterator2>
    111 bool operator<=(const ReverseIterator<Iterator1>& aIter1,
    112                const ReverseIterator<Iterator2>& aIter2) {
    113  return aIter1.mCurrent >= aIter2.mCurrent;
    114 }
    115 
    116 template <typename Iterator1, typename Iterator2>
    117 bool operator>(const ReverseIterator<Iterator1>& aIter1,
    118               const ReverseIterator<Iterator2>& aIter2) {
    119  return aIter1.mCurrent < aIter2.mCurrent;
    120 }
    121 
    122 template <typename Iterator1, typename Iterator2>
    123 bool operator>=(const ReverseIterator<Iterator1>& aIter1,
    124                const ReverseIterator<Iterator2>& aIter2) {
    125  return aIter1.mCurrent <= aIter2.mCurrent;
    126 }
    127 
    128 namespace detail {
    129 
    130 template <typename IteratorT,
    131          typename ReverseIteratorT = ReverseIterator<IteratorT>>
    132 class IteratorRange {
    133 public:
    134  typedef IteratorT iterator;
    135  typedef IteratorT const_iterator;
    136  typedef ReverseIteratorT reverse_iterator;
    137  typedef ReverseIteratorT const_reverse_iterator;
    138 
    139  IteratorRange(IteratorT aIterBegin, IteratorT aIterEnd)
    140      : mIterBegin(std::move(aIterBegin)), mIterEnd(std::move(aIterEnd)) {}
    141 
    142  iterator begin() const { return mIterBegin; }
    143  const_iterator cbegin() const { return begin(); }
    144  iterator end() const { return mIterEnd; }
    145  const_iterator cend() const { return end(); }
    146  reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); }
    147  const_reverse_iterator crbegin() const { return rbegin(); }
    148  reverse_iterator rend() const { return reverse_iterator(mIterBegin); }
    149  const_reverse_iterator crend() const { return rend(); }
    150 
    151  IteratorT mIterBegin;
    152  IteratorT mIterEnd;
    153 };
    154 
    155 }  // namespace detail
    156 
    157 template <typename Range>
    158 detail::IteratorRange<typename Range::reverse_iterator> Reversed(
    159    Range& aRange) {
    160  return {aRange.rbegin(), aRange.rend()};
    161 }
    162 
    163 template <typename Range>
    164 detail::IteratorRange<typename Range::const_reverse_iterator> Reversed(
    165    const Range& aRange) {
    166  return {aRange.rbegin(), aRange.rend()};
    167 }
    168 
    169 }  // namespace mozilla
    170 
    171 #endif  // mozilla_ReverseIterator_h