EnumeratedRange.h 6.1 KB

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