ReverseIterator.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* An iterator that acts like another iterator, but iterating in
  6. * the negative direction. (Note that not all iterators can iterate
  7. * in the negative direction.) */
  8. #ifndef mozilla_ReverseIterator_h
  9. #define mozilla_ReverseIterator_h
  10. #include "mozilla/Attributes.h"
  11. #include "mozilla/TypeTraits.h"
  12. namespace mozilla {
  13. template<typename IteratorT>
  14. class ReverseIterator
  15. {
  16. public:
  17. template<typename Iterator>
  18. explicit ReverseIterator(Iterator aIter)
  19. : mCurrent(aIter) { }
  20. template<typename Iterator>
  21. MOZ_IMPLICIT ReverseIterator(const ReverseIterator<Iterator>& aOther)
  22. : mCurrent(aOther.mCurrent) { }
  23. decltype(*DeclVal<IteratorT>()) operator*() const
  24. {
  25. IteratorT tmp = mCurrent;
  26. return *--tmp;
  27. }
  28. /* Increments and decrements operators */
  29. ReverseIterator& operator++() { --mCurrent; return *this; }
  30. ReverseIterator& operator--() { ++mCurrent; return *this; }
  31. ReverseIterator operator++(int) { auto ret = *this; mCurrent--; return ret; }
  32. ReverseIterator operator--(int) { auto ret = *this; mCurrent++; return ret; }
  33. /* Comparison operators */
  34. template<typename Iterator1, typename Iterator2>
  35. friend bool operator==(const ReverseIterator<Iterator1>& aIter1,
  36. const ReverseIterator<Iterator2>& aIter2);
  37. template<typename Iterator1, typename Iterator2>
  38. friend bool operator!=(const ReverseIterator<Iterator1>& aIter1,
  39. const ReverseIterator<Iterator2>& aIter2);
  40. template<typename Iterator1, typename Iterator2>
  41. friend bool operator<(const ReverseIterator<Iterator1>& aIter1,
  42. const ReverseIterator<Iterator2>& aIter2);
  43. template<typename Iterator1, typename Iterator2>
  44. friend bool operator<=(const ReverseIterator<Iterator1>& aIter1,
  45. const ReverseIterator<Iterator2>& aIter2);
  46. template<typename Iterator1, typename Iterator2>
  47. friend bool operator>(const ReverseIterator<Iterator1>& aIter1,
  48. const ReverseIterator<Iterator2>& aIter2);
  49. template<typename Iterator1, typename Iterator2>
  50. friend bool operator>=(const ReverseIterator<Iterator1>& aIter1,
  51. const ReverseIterator<Iterator2>& aIter2);
  52. private:
  53. IteratorT mCurrent;
  54. };
  55. template<typename Iterator1, typename Iterator2>
  56. bool
  57. operator==(const ReverseIterator<Iterator1>& aIter1,
  58. const ReverseIterator<Iterator2>& aIter2)
  59. {
  60. return aIter1.mCurrent == aIter2.mCurrent;
  61. }
  62. template<typename Iterator1, typename Iterator2>
  63. bool
  64. operator!=(const ReverseIterator<Iterator1>& aIter1,
  65. const ReverseIterator<Iterator2>& aIter2)
  66. {
  67. return aIter1.mCurrent != aIter2.mCurrent;
  68. }
  69. template<typename Iterator1, typename Iterator2>
  70. bool
  71. operator<(const ReverseIterator<Iterator1>& aIter1,
  72. const ReverseIterator<Iterator2>& aIter2)
  73. {
  74. return aIter1.mCurrent > aIter2.mCurrent;
  75. }
  76. template<typename Iterator1, typename Iterator2>
  77. bool
  78. operator<=(const ReverseIterator<Iterator1>& aIter1,
  79. const ReverseIterator<Iterator2>& aIter2)
  80. {
  81. return aIter1.mCurrent >= aIter2.mCurrent;
  82. }
  83. template<typename Iterator1, typename Iterator2>
  84. bool
  85. operator>(const ReverseIterator<Iterator1>& aIter1,
  86. const ReverseIterator<Iterator2>& aIter2)
  87. {
  88. return aIter1.mCurrent < aIter2.mCurrent;
  89. }
  90. template<typename Iterator1, typename Iterator2>
  91. bool
  92. operator>=(const ReverseIterator<Iterator1>& aIter1,
  93. const ReverseIterator<Iterator2>& aIter2)
  94. {
  95. return aIter1.mCurrent <= aIter2.mCurrent;
  96. }
  97. namespace detail {
  98. template<typename IteratorT>
  99. class IteratorRange
  100. {
  101. public:
  102. typedef IteratorT iterator;
  103. typedef IteratorT const_iterator;
  104. typedef ReverseIterator<IteratorT> reverse_iterator;
  105. typedef ReverseIterator<IteratorT> const_reverse_iterator;
  106. template<typename Iterator1, typename Iterator2>
  107. MOZ_IMPLICIT IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd)
  108. : mIterBegin(aIterBegin), mIterEnd(aIterEnd) { }
  109. template<typename Iterator>
  110. MOZ_IMPLICIT IteratorRange(const IteratorRange<Iterator>& aOther)
  111. : mIterBegin(aOther.mIterBegin), mIterEnd(aOther.mIterEnd) { }
  112. iterator begin() const { return mIterBegin; }
  113. const_iterator cbegin() const { return begin(); }
  114. iterator end() const { return mIterEnd; }
  115. const_iterator cend() const { return end(); }
  116. reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); }
  117. const_reverse_iterator crbegin() const { return rbegin(); }
  118. reverse_iterator rend() const { return reverse_iterator(mIterBegin); }
  119. const_reverse_iterator crend() const { return rend(); }
  120. private:
  121. IteratorT mIterBegin;
  122. IteratorT mIterEnd;
  123. };
  124. } // namespace detail
  125. template<typename Range>
  126. detail::IteratorRange<typename Range::reverse_iterator>
  127. Reversed(Range& aRange)
  128. {
  129. return {aRange.rbegin(), aRange.rend()};
  130. }
  131. template<typename Range>
  132. detail::IteratorRange<typename Range::const_reverse_iterator>
  133. Reversed(const Range& aRange)
  134. {
  135. return {aRange.rbegin(), aRange.rend()};
  136. }
  137. } // namespace mozilla
  138. #endif // mozilla_ReverseIterator_h