EnumeratedRange.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. /* Iterator over contiguous enum values */
  6. /*
  7. * Implements generator functions that create a range to iterate over the values
  8. * of a scoped or unscoped enum. Unlike IntegerRange, which can only function on
  9. * the underlying integral type, the elements of the generated sequence will
  10. * have the type of the enum in question.
  11. *
  12. * Note that the enum values should be contiguous in the iterated range;
  13. * unfortunately there exists no way for EnumeratedRange to enforce this
  14. * either dynamically or at compile time.
  15. */
  16. #ifndef mozilla_EnumeratedRange_h
  17. #define mozilla_EnumeratedRange_h
  18. #include <type_traits>
  19. #include "mozilla/ReverseIterator.h"
  20. namespace mozilla {
  21. namespace detail {
  22. template<typename EnumTypeT>
  23. class EnumeratedIterator
  24. {
  25. public:
  26. typedef typename std::underlying_type<EnumTypeT>::type IntTypeT;
  27. template<typename EnumType>
  28. explicit EnumeratedIterator(EnumType aCurrent)
  29. : mCurrent(aCurrent) { }
  30. template<typename EnumType>
  31. explicit EnumeratedIterator(const EnumeratedIterator<EnumType>& aOther)
  32. : mCurrent(aOther.mCurrent) { }
  33. EnumTypeT operator*() const { return mCurrent; }
  34. /* Increment and decrement operators */
  35. EnumeratedIterator& operator++()
  36. {
  37. mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
  38. return *this;
  39. }
  40. EnumeratedIterator& operator--()
  41. {
  42. mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
  43. return *this;
  44. }
  45. EnumeratedIterator operator++(int)
  46. {
  47. auto ret = *this;
  48. mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
  49. return ret;
  50. }
  51. EnumeratedIterator operator--(int)
  52. {
  53. auto ret = *this;
  54. mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
  55. return ret;
  56. }
  57. /* Comparison operators */
  58. template<typename EnumType>
  59. friend bool operator==(const EnumeratedIterator<EnumType>& aIter1,
  60. const EnumeratedIterator<EnumType>& aIter2);
  61. template<typename EnumType>
  62. friend bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
  63. const EnumeratedIterator<EnumType>& aIter2);
  64. template<typename EnumType>
  65. friend bool operator<(const EnumeratedIterator<EnumType>& aIter1,
  66. const EnumeratedIterator<EnumType>& aIter2);
  67. template<typename EnumType>
  68. friend bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
  69. const EnumeratedIterator<EnumType>& aIter2);
  70. template<typename EnumType>
  71. friend bool operator>(const EnumeratedIterator<EnumType>& aIter1,
  72. const EnumeratedIterator<EnumType>& aIter2);
  73. template<typename EnumType>
  74. friend bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
  75. const EnumeratedIterator<EnumType>& aIter2);
  76. private:
  77. EnumTypeT mCurrent;
  78. };
  79. template<typename EnumType>
  80. bool operator==(const EnumeratedIterator<EnumType>& aIter1,
  81. const EnumeratedIterator<EnumType>& aIter2)
  82. {
  83. return aIter1.mCurrent == aIter2.mCurrent;
  84. }
  85. template<typename EnumType>
  86. bool operator!=(const EnumeratedIterator<EnumType>& aIter1,
  87. const EnumeratedIterator<EnumType>& aIter2)
  88. {
  89. return aIter1.mCurrent != aIter2.mCurrent;
  90. }
  91. template<typename EnumType>
  92. bool operator<(const EnumeratedIterator<EnumType>& aIter1,
  93. const EnumeratedIterator<EnumType>& aIter2)
  94. {
  95. return aIter1.mCurrent < aIter2.mCurrent;
  96. }
  97. template<typename EnumType>
  98. bool operator<=(const EnumeratedIterator<EnumType>& aIter1,
  99. const EnumeratedIterator<EnumType>& aIter2)
  100. {
  101. return aIter1.mCurrent <= aIter2.mCurrent;
  102. }
  103. template<typename EnumType>
  104. bool operator>(const EnumeratedIterator<EnumType>& aIter1,
  105. const EnumeratedIterator<EnumType>& aIter2)
  106. {
  107. return aIter1.mCurrent > aIter2.mCurrent;
  108. }
  109. template<typename EnumType>
  110. bool operator>=(const EnumeratedIterator<EnumType>& aIter1,
  111. const EnumeratedIterator<EnumType>& aIter2)
  112. {
  113. return aIter1.mCurrent >= aIter2.mCurrent;
  114. }
  115. template<typename EnumTypeT>
  116. class EnumeratedRange
  117. {
  118. public:
  119. typedef EnumeratedIterator<EnumTypeT> iterator;
  120. typedef EnumeratedIterator<EnumTypeT> const_iterator;
  121. typedef ReverseIterator<iterator> reverse_iterator;
  122. typedef ReverseIterator<const_iterator> const_reverse_iterator;
  123. template<typename EnumType>
  124. EnumeratedRange(EnumType aBegin, EnumType aEnd)
  125. : mBegin(aBegin), mEnd(aEnd) { }
  126. iterator begin() const { return iterator(mBegin); }
  127. const_iterator cbegin() const { return begin(); }
  128. iterator end() const { return iterator(mEnd); }
  129. const_iterator cend() const { return end(); }
  130. reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
  131. const_reverse_iterator crbegin() const { return rbegin(); }
  132. reverse_iterator rend() const { return reverse_iterator(mBegin); }
  133. const_reverse_iterator crend() const { return rend(); }
  134. private:
  135. EnumTypeT mBegin;
  136. EnumTypeT mEnd;
  137. };
  138. } // namespace detail
  139. #ifdef __GNUC__
  140. // Enums can have an unsigned underlying type, which makes some of the
  141. // comparisons below always true or always false. Temporarily disable
  142. // -Wtype-limits to avoid breaking -Werror builds.
  143. # pragma GCC diagnostic push
  144. # pragma GCC diagnostic ignored "-Wtype-limits"
  145. #endif
  146. // Create a range to iterate from aBegin to aEnd, exclusive.
  147. template<typename EnumType>
  148. inline detail::EnumeratedRange<EnumType>
  149. MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
  150. {
  151. MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
  152. return detail::EnumeratedRange<EnumType>(aBegin, aEnd);
  153. }
  154. // Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
  155. // should exist, but note that there is no way for us to ensure that it does!
  156. template<typename EnumType>
  157. inline detail::EnumeratedRange<EnumType>
  158. MakeEnumeratedRange(EnumType aEnd)
  159. {
  160. return MakeEnumeratedRange(EnumType(0), aEnd);
  161. }
  162. #ifdef __GNUC__
  163. # pragma GCC diagnostic pop
  164. #endif
  165. } // namespace mozilla
  166. #endif // mozilla_EnumeratedRange_h