Bug 1142999 - Add an EnumeratedRange class to iterate EnumeratedArrays. r=nfroyd
authorEmanuel Hoogeveen <emanuel.hoogeveen@gmail.com>
Mon, 23 Mar 2015 15:06:00 -0400
changeset 235352 f6850a11e3158d4235a538b609ac19b0b7b57287
parent 235351 2494c427364b7d75381ceee6d22b450a9a50f79b
child 235353 331ed8230be21fcd9ea0064eebf2b8df0cf8ba2c
push id28471
push userkwierso@gmail.com
push dateWed, 25 Mar 2015 01:04:03 +0000
treeherderautoland@515084cb28c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs1142999
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1142999 - Add an EnumeratedRange class to iterate EnumeratedArrays. r=nfroyd
mfbt/EnumeratedRange.h
mfbt/IntegerRange.h
mfbt/moz.build
new file mode 100644
--- /dev/null
+++ b/mfbt/EnumeratedRange.h
@@ -0,0 +1,228 @@
+/* -*- 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/IntegerRange.h"
+#include "mozilla/IntegerTypeTraits.h"
+
+namespace mozilla {
+
+namespace detail {
+
+template<typename IntTypeT, typename EnumTypeT>
+class EnumeratedIterator
+{
+public:
+  typedef const EnumTypeT ValueType;
+  typedef typename MakeSigned<IntTypeT>::Type DifferenceType;
+
+  template<typename EnumType>
+  explicit EnumeratedIterator(EnumType aCurrent)
+    : mCurrent(aCurrent) { }
+
+  template<typename IntType, typename EnumType>
+  EnumeratedIterator(const EnumeratedIterator<IntType, EnumType>& aOther)
+    : mCurrent(aOther.mCurrent) { }
+
+  // Since operator* is required to return a reference, we return
+  // a reference to our member here.
+  const 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;
+  }
+
+  EnumeratedIterator operator+(DifferenceType aN) const
+  {
+    return EnumeratedIterator(EnumTypeT(IntTypeT(mCurrent) + aN));
+  }
+  EnumeratedIterator operator-(DifferenceType aN) const
+  {
+    return EnumeratedIterator(EnumTypeT(IntTypeT(mCurrent) - aN));
+  }
+  EnumeratedIterator& operator+=(DifferenceType aN)
+  {
+    mCurrent = EnumTypeT(IntTypeT(mCurrent) + aN);
+    return *this;
+  }
+  EnumeratedIterator& operator-=(DifferenceType aN)
+  {
+    mCurrent = EnumTypeT(IntTypeT(mCurrent) - aN);
+    return *this;
+  }
+
+  /* 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.
+template<typename IntType, typename EnumType>
+inline detail::EnumeratedRange<IntType, EnumType>
+MakeEnumeratedRange(EnumType aBegin, EnumType aEnd)
+{
+  typedef typename MakeUnsigned<IntType>::Type UnsignedType;
+  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!
+template<typename IntType, typename EnumType>
+inline detail::EnumeratedRange<IntType, EnumType>
+MakeEnumeratedRange(EnumType aEnd)
+{
+  return MakeEnumeratedRange<IntType>(EnumType(0), aEnd);
+}
+
+#ifdef __GNUC__
+#  pragma GCC diagnostic pop
+#endif
+
+} // namespace mozilla
+
+#endif // mozilla_EnumeratedRange_h
+
--- a/mfbt/IntegerRange.h
+++ b/mfbt/IntegerRange.h
@@ -28,20 +28,20 @@ public:
   explicit IntegerIterator(IntType aCurrent)
     : mCurrent(aCurrent) { }
 
   template<typename IntType>
   IntegerIterator(const IntegerIterator<IntType>& aOther)
     : mCurrent(aOther.mCurrent) { }
 
   // Since operator* is required to return a reference, we return
-  // the reference of our member here.
+  // a reference to our member here.
   const IntTypeT& operator*() const { return mCurrent; }
 
-  /* Increments and descrements operators */
+  /* Increment and decrement operators */
 
   IntegerIterator& operator++() { ++mCurrent; return *this; }
   IntegerIterator& operator--() { --mCurrent; return *this; }
   IntegerIterator operator++(int) { auto ret = *this; ++mCurrent; return ret; }
   IntegerIterator operator--(int) { auto ret = *this; --mCurrent; return ret; }
 
   IntegerIterator operator+(DifferenceType aN) const
   {
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -27,16 +27,17 @@ EXPORTS.mozilla = [
     'Compression.h',
     'Constants.h',
     'DebugOnly.h',
     'decimal/Decimal.h',
     'double-conversion/double-conversion.h',
     'double-conversion/utils.h',
     'Endian.h',
     'EnumeratedArray.h',
+    'EnumeratedRange.h',
     'EnumSet.h',
     'FloatingPoint.h',
     'GuardObjects.h',
     'HashFunctions.h',
     'IntegerPrintfMacros.h',
     'IntegerRange.h',
     'IntegerTypeTraits.h',
     'IteratorTraits.h',