DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (dcc6d7a0dc00)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
/* -*- 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/. */

/* Iterator over contiguous enum values */

/*
 * Implements generator functions that create a range to iterate over the values
 * of a scoped or unscoped enum. Unlike IntegerRange, which can only function on
 * the underlying integral type, the elements of the generated sequence will
 * have the type of the enum in question.
 *
 * Note that the enum values should be contiguous in the iterated range;
 * unfortunately there exists no way for EnumeratedRange to enforce this
 * either dynamically or at compile time.
 */

#ifndef mozilla_EnumeratedRange_h
#define mozilla_EnumeratedRange_h

#include "mozilla/IntegerTypeTraits.h"
#include "mozilla/ReverseIterator.h"

namespace mozilla {

namespace detail {

template<typename IntTypeT, typename EnumTypeT>
class EnumeratedIterator
{
public:
  template<typename EnumType>
  explicit EnumeratedIterator(EnumType aCurrent)
    : mCurrent(aCurrent) { }

  template<typename IntType, typename EnumType>
  explicit EnumeratedIterator(const EnumeratedIterator<IntType, EnumType>& aOther)
    : mCurrent(aOther.mCurrent) { }

  EnumTypeT operator*() const { return mCurrent; }

  /* Increment and decrement operators */

  EnumeratedIterator& operator++()
  {
    mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
    return *this;
  }
  EnumeratedIterator& operator--()
  {
    mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
    return *this;
  }
  EnumeratedIterator operator++(int)
  {
    auto ret = *this;
    mCurrent = EnumTypeT(IntTypeT(mCurrent) + IntTypeT(1));
    return ret;
  }
  EnumeratedIterator operator--(int)
  {
    auto ret = *this;
    mCurrent = EnumTypeT(IntTypeT(mCurrent) - IntTypeT(1));
    return ret;
  }

  /* Comparison operators */

  template<typename IntType, typename EnumType>
  friend bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
                         const EnumeratedIterator<IntType, EnumType>& aIter2);
  template<typename IntType, typename EnumType>
  friend bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                         const EnumeratedIterator<IntType, EnumType>& aIter2);
  template<typename IntType, typename EnumType>
  friend bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
                        const EnumeratedIterator<IntType, EnumType>& aIter2);
  template<typename IntType, typename EnumType>
  friend bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                         const EnumeratedIterator<IntType, EnumType>& aIter2);
  template<typename IntType, typename EnumType>
  friend bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
                        const EnumeratedIterator<IntType, EnumType>& aIter2);
  template<typename IntType, typename EnumType>
  friend bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                         const EnumeratedIterator<IntType, EnumType>& aIter2);

private:
  EnumTypeT mCurrent;
};

template<typename IntType, typename EnumType>
bool operator==(const EnumeratedIterator<IntType, EnumType>& aIter1,
                const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent == aIter2.mCurrent;
}

template<typename IntType, typename EnumType>
bool operator!=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent != aIter2.mCurrent;
}

template<typename IntType, typename EnumType>
bool operator<(const EnumeratedIterator<IntType, EnumType>& aIter1,
               const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent < aIter2.mCurrent;
}

template<typename IntType, typename EnumType>
bool operator<=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent <= aIter2.mCurrent;
}

template<typename IntType, typename EnumType>
bool operator>(const EnumeratedIterator<IntType, EnumType>& aIter1,
               const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent > aIter2.mCurrent;
}

template<typename IntType, typename EnumType>
bool operator>=(const EnumeratedIterator<IntType, EnumType>& aIter1,
                const EnumeratedIterator<IntType, EnumType>& aIter2)
{
  return aIter1.mCurrent >= aIter2.mCurrent;
}

template<typename IntTypeT, typename EnumTypeT>
class EnumeratedRange
{
public:
  typedef EnumeratedIterator<IntTypeT, EnumTypeT> iterator;
  typedef EnumeratedIterator<IntTypeT, EnumTypeT> const_iterator;
  typedef ReverseIterator<iterator> reverse_iterator;
  typedef ReverseIterator<const_iterator> const_reverse_iterator;

  template<typename EnumType>
  EnumeratedRange(EnumType aBegin, EnumType aEnd)
    : mBegin(aBegin), mEnd(aEnd) { }

  iterator begin() const { return iterator(mBegin); }
  const_iterator cbegin() const { return begin(); }
  iterator end() const { return iterator(mEnd); }
  const_iterator cend() const { return end(); }
  reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
  const_reverse_iterator crbegin() const { return rbegin(); }
  reverse_iterator rend() const { return reverse_iterator(mBegin); }
  const_reverse_iterator crend() const { return rend(); }

private:
  EnumTypeT mBegin;
  EnumTypeT mEnd;
};

} // namespace detail

#ifdef __GNUC__
// Enums can have an unsigned underlying type, which makes some of the
// comparisons below always true or always false. Temporarily disable
// -Wtype-limits to avoid breaking -Werror builds.
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wtype-limits"
#endif

// Create a range to iterate from aBegin to aEnd, exclusive.
//
// (Once we can rely on std::underlying_type, we can remove the IntType
// template parameter.)
template<typename IntType, typename EnumType>
inline detail::EnumeratedRange<IntType, EnumType>
MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
{
#ifdef DEBUG
  typedef typename MakeUnsigned<IntType>::Type UnsignedType;
#endif
  static_assert(sizeof(IntType) >= sizeof(EnumType),
                "IntType should be at least as big as EnumType!");
  MOZ_ASSERT(aBegin <= aEnd, "Cannot generate invalid, unbounded range!");
  MOZ_ASSERT_IF(aBegin < EnumType(0), IsSigned<IntType>::value);
  MOZ_ASSERT_IF(aBegin >= EnumType(0) && IsSigned<IntType>::value,
                UnsignedType(aEnd) <= UnsignedType(MaxValue<IntType>::value));
  return detail::EnumeratedRange<IntType, EnumType>(aBegin, aEnd);
}

// Create a range to iterate from EnumType(0) to aEnd, exclusive. EnumType(0)
// should exist, but note that there is no way for us to ensure that it does!
// Since the enumeration starts at EnumType(0), we know for sure that the values
// will be in range of our deduced IntType.
template<typename EnumType>
inline detail::EnumeratedRange<
  typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type,
  EnumType>
MakeEnumeratedRange(EnumType aEnd)
{
  return MakeEnumeratedRange<
    typename UnsignedStdintTypeForSize<sizeof(EnumType)>::Type>(EnumType(0),
                                                                aEnd);
}

#ifdef __GNUC__
#  pragma GCC diagnostic pop
#endif

} // namespace mozilla

#endif // mozilla_EnumeratedRange_h