Bug 1297306 - part4:rename IsEnumFittingWithin with EnumTypeFitsWithin and move it to mfbt/EnumTypeTraits.h.
With this change, we could share this EnumTypeTraits between files easily.
MozReview-Commit-ID: 9Q2augati7l
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -444,17 +444,17 @@ public:
void SetNormalValue();
void SetAutoValue();
void SetNoneValue();
void SetIntValue(int32_t aInt, Unit aUnit);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
void SetIntValue(T aInt, Unit aUnit)
{
- static_assert(mozilla::IsEnumFittingWithin<T, int32_t>::value,
+ static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
"aValue must be an enum that fits within mValue.mInt");
SetIntValue(static_cast<int32_t>(aInt), aUnit);
}
void SetCoordValue(nscoord aCoord);
void SetPercentValue(float aPercent);
void SetFloatValue(float aFloat);
void SetColorValue(nscolor aColor);
void SetCurrentColorValue();
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -14,16 +14,17 @@
#include <limits>
#include <type_traits>
#include "nsString.h"
#include "nsCSSPropertyID.h"
#include "nsStyleStructFwd.h"
#include "nsCSSKeywords.h"
#include "mozilla/CSSEnabledState.h"
#include "mozilla/UseCounter.h"
+#include "mozilla/EnumTypeTraits.h"
// Length of the "--" prefix on custom names (such as custom property names,
// and, in the future, custom media query names).
#define CSS_CUSTOM_NAME_PREFIX_LENGTH 2
// Flags for ParseVariant method
#define VARIANT_KEYWORD 0x000001 // K
#define VARIANT_LENGTH 0x000002 // L
@@ -322,34 +323,16 @@ enum nsStyleAnimType {
// discrete values
eStyleAnimType_Discrete,
// property not animatable
eStyleAnimType_None
};
-namespace mozilla {
-
-// Type trait that determines whether the integral or enum type Type can fit
-// within the integral type Storage without loss.
-template<typename T, typename Storage>
-struct IsEnumFittingWithin
- : IntegralConstant<
- bool,
- std::is_integral<Storage>::value &&
- std::numeric_limits<typename std::underlying_type<T>::type>::min() >=
- std::numeric_limits<Storage>::min() &&
- std::numeric_limits<typename std::underlying_type<T>::type>::max() <=
- std::numeric_limits<Storage>::max()
- >
-{};
-
-} // namespace mozilla
-
class nsCSSProps {
public:
typedef mozilla::CSSEnabledState EnabledState;
struct KTableEntry
{
// KTableEntry objects can be initialized either with an int16_t value
// or a value of an enumeration type that can fit within an int16_t.
@@ -361,17 +344,17 @@ public:
}
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
KTableEntry(nsCSSKeyword aKeyword, T aValue)
: mKeyword(aKeyword)
, mValue(static_cast<int16_t>(aValue))
{
- static_assert(mozilla::IsEnumFittingWithin<T, int16_t>::value,
+ static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
"aValue must be an enum that fits within mValue");
}
nsCSSKeyword mKeyword;
int16_t mValue;
};
static void AddRefTable(void);
@@ -447,29 +430,29 @@ public:
// Return |eCSSKeyword_UNKNOWN| if not found.
static nsCSSKeyword ValueToKeywordEnum(int32_t aValue,
const KTableEntry aTable[]);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
static nsCSSKeyword ValueToKeywordEnum(T aValue,
const KTableEntry aTable[])
{
- static_assert(mozilla::IsEnumFittingWithin<T, int16_t>::value,
+ static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
"aValue must be an enum that fits within KTableEntry::mValue");
return ValueToKeywordEnum(static_cast<int16_t>(aValue), aTable);
}
// Ditto but as a string, return "" when not found.
static const nsAFlatCString& ValueToKeyword(int32_t aValue,
const KTableEntry aTable[]);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
static const nsAFlatCString& ValueToKeyword(T aValue,
const KTableEntry aTable[])
{
- static_assert(mozilla::IsEnumFittingWithin<T, int16_t>::value,
+ static_assert(mozilla::EnumTypeFitsWithin<T, int16_t>::value,
"aValue must be an enum that fits within KTableEntry::mValue");
return ValueToKeyword(static_cast<int16_t>(aValue), aTable);
}
static const nsStyleStructID kSIDTable[eCSSProperty_COUNT_no_shorthands];
static const KTableEntry* const kKeywordTableTable[eCSSProperty_COUNT_no_shorthands];
static const nsStyleAnimType kAnimTypeTable[eCSSProperty_COUNT_no_shorthands];
static const ptrdiff_t
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -753,17 +753,17 @@ private:
void DoReset();
public:
void SetIntValue(int32_t aValue, nsCSSUnit aUnit);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
void SetIntValue(T aValue, nsCSSUnit aUnit)
{
- static_assert(mozilla::IsEnumFittingWithin<T, int32_t>::value,
+ static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
"aValue must be an enum that fits within mValue.mInt");
SetIntValue(static_cast<int32_t>(aValue), aUnit);
}
void SetPercentValue(float aValue);
void SetFloatValue(float aValue, nsCSSUnit aUnit);
void SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
void SetColorValue(nscolor aValue);
void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit);
new file mode 100644
--- /dev/null
+++ b/mfbt/EnumTypeTraits.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/* Type traits for enums. */
+
+#ifndef mozilla_EnumTypeTraits_h
+#define mozilla_EnumTypeTraits_h
+
+#include <type_traits>
+
+namespace mozilla {
+
+namespace detail {
+
+template<size_t EnumSize, bool EnumSigned, size_t StorageSize, bool StorageSigned>
+struct EnumFitsWithinHelper;
+
+// Signed enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+// Signed enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
+ : public std::integral_constant<bool, false>
+{};
+
+// Unsigned enum, signed storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
+ : public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)>
+{};
+
+// Unsigned enum, unsigned storage.
+template<size_t EnumSize, size_t StorageSize>
+struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
+ : public std::integral_constant<bool, (EnumSize <= StorageSize)>
+{};
+
+} // namespace detail
+
+/*
+ * Type trait that determines whether the enum type T can fit within the
+ * integral type Storage without data loss. This trait should be used with
+ * caution with an enum type whose underlying type has not been explicitly
+ * specified: for such enums, the C++ implementation is free to choose a type
+ * no smaller than int whose range encompasses all possible values of the enum.
+ * So for an enum with only small non-negative values, the underlying type may
+ * be either int or unsigned int, depending on the whims of the implementation.
+ */
+template<typename T, typename Storage>
+struct EnumTypeFitsWithin
+ : public detail::EnumFitsWithinHelper<
+ sizeof(T),
+ std::is_signed<typename std::underlying_type<T>::type>::value,
+ sizeof(Storage),
+ std::is_signed<Storage>::value
+ >
+{
+ static_assert(std::is_enum<T>::value, "must provide an enum type");
+ static_assert(std::is_integral<Storage>::value, "must provide an integral type");
+};
+
+} // namespace mozilla
+
+#endif /* mozilla_EnumTypeTraits_h */
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -34,16 +34,17 @@ EXPORTS.mozilla = [
'DebugOnly.h',
'decimal/Decimal.h',
'double-conversion/double-conversion.h',
'double-conversion/utils.h',
'EndianUtils.h',
'EnumeratedArray.h',
'EnumeratedRange.h',
'EnumSet.h',
+ 'EnumTypeTraits.h',
'FastBernoulliTrial.h',
'FloatingPoint.h',
'Function.h',
'GuardObjects.h',
'HashFunctions.h',
'IndexSequence.h',
'InitializerList.h',
'IntegerPrintfMacros.h',
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestEnumTypeTraits.cpp
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "mozilla/IntegerTypeTraits.h"
+#include "mozilla/EnumTypeTraits.h"
+
+using namespace mozilla;
+
+/* Feature check for EnumTypeFitsWithin. */
+
+#define MAKE_FIXED_EMUM_FOR_TYPE(IntType) \
+ enum FixedEnumFor_##IntType : IntType { \
+ A_##IntType, \
+ B_##IntType, \
+ C_##IntType, \
+ };
+
+template<typename EnumType, typename IntType>
+static void
+TestShouldFit()
+{
+ static_assert(EnumTypeFitsWithin<EnumType, IntType>::value,
+ "Should fit within exact/promoted integral type");
+}
+
+template<typename EnumType, typename IntType>
+static void
+TestShouldNotFit()
+{
+ static_assert(!EnumTypeFitsWithin<EnumType, IntType>::value,
+ "Should not fit within");
+}
+
+int
+main()
+{
+ // check for int8_t
+ MAKE_FIXED_EMUM_FOR_TYPE(int8_t);
+ TestShouldFit<FixedEnumFor_int8_t, int8_t>();
+ TestShouldFit<FixedEnumFor_int8_t, int16_t>();
+ TestShouldFit<FixedEnumFor_int8_t, int32_t>();
+ TestShouldFit<FixedEnumFor_int8_t, int64_t>();
+
+ TestShouldNotFit<FixedEnumFor_int8_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_int8_t, uint16_t>();
+ TestShouldNotFit<FixedEnumFor_int8_t, uint32_t>();
+ TestShouldNotFit<FixedEnumFor_int8_t, uint64_t>();
+
+ // check for uint8_t
+ MAKE_FIXED_EMUM_FOR_TYPE(uint8_t);
+ TestShouldFit<FixedEnumFor_uint8_t, uint8_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, uint16_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, uint32_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, uint64_t>();
+
+ TestShouldNotFit<FixedEnumFor_uint8_t, int8_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, int16_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, int32_t>();
+ TestShouldFit<FixedEnumFor_uint8_t, int64_t>();
+
+ // check for int16_t
+ MAKE_FIXED_EMUM_FOR_TYPE(int16_t);
+ TestShouldNotFit<FixedEnumFor_int16_t, int8_t>();
+ TestShouldFit<FixedEnumFor_int16_t, int16_t>();
+ TestShouldFit<FixedEnumFor_int16_t, int32_t>();
+ TestShouldFit<FixedEnumFor_int16_t, int64_t>();
+
+ TestShouldNotFit<FixedEnumFor_int16_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_int16_t, uint16_t>();
+ TestShouldNotFit<FixedEnumFor_int16_t, uint32_t>();
+ TestShouldNotFit<FixedEnumFor_int16_t, uint64_t>();
+
+ // check for uint16_t
+ MAKE_FIXED_EMUM_FOR_TYPE(uint16_t);
+ TestShouldNotFit<FixedEnumFor_uint16_t, uint8_t>();
+ TestShouldFit<FixedEnumFor_uint16_t, uint16_t>();
+ TestShouldFit<FixedEnumFor_uint16_t, uint32_t>();
+ TestShouldFit<FixedEnumFor_uint16_t, uint64_t>();
+
+ TestShouldNotFit<FixedEnumFor_uint16_t, int8_t>();
+ TestShouldNotFit<FixedEnumFor_uint16_t, int16_t>();
+ TestShouldFit<FixedEnumFor_uint16_t, int32_t>();
+ TestShouldFit<FixedEnumFor_uint16_t, int64_t>();
+
+ // check for int32_t
+ MAKE_FIXED_EMUM_FOR_TYPE(int32_t);
+ TestShouldNotFit<FixedEnumFor_int32_t, int8_t>();
+ TestShouldNotFit<FixedEnumFor_int32_t, int16_t>();
+ TestShouldFit<FixedEnumFor_int32_t, int32_t>();
+ TestShouldFit<FixedEnumFor_int32_t, int64_t>();
+
+ TestShouldNotFit<FixedEnumFor_int32_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_int32_t, uint16_t>();
+ TestShouldNotFit<FixedEnumFor_int32_t, uint32_t>();
+ TestShouldNotFit<FixedEnumFor_int32_t, uint64_t>();
+
+ // check for uint32_t
+ MAKE_FIXED_EMUM_FOR_TYPE(uint32_t);
+ TestShouldNotFit<FixedEnumFor_uint32_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_uint32_t, uint16_t>();
+ TestShouldFit<FixedEnumFor_uint32_t, uint32_t>();
+ TestShouldFit<FixedEnumFor_uint32_t, uint64_t>();
+
+ TestShouldNotFit<FixedEnumFor_uint32_t, int8_t>();
+ TestShouldNotFit<FixedEnumFor_uint32_t, int16_t>();
+ TestShouldNotFit<FixedEnumFor_uint32_t, int32_t>();
+ TestShouldFit<FixedEnumFor_uint32_t, int64_t>();
+
+ // check for int64_t
+ MAKE_FIXED_EMUM_FOR_TYPE(int64_t);
+ TestShouldNotFit<FixedEnumFor_int64_t, int8_t>();
+ TestShouldNotFit<FixedEnumFor_int64_t, int16_t>();
+ TestShouldNotFit<FixedEnumFor_int64_t, int32_t>();
+ TestShouldFit<FixedEnumFor_int64_t, int64_t>();
+
+ TestShouldNotFit<FixedEnumFor_int64_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_int64_t, uint16_t>();
+ TestShouldNotFit<FixedEnumFor_int64_t, uint32_t>();
+ TestShouldNotFit<FixedEnumFor_int64_t, uint64_t>();
+
+ // check for uint64_t
+ MAKE_FIXED_EMUM_FOR_TYPE(uint64_t);
+ TestShouldNotFit<FixedEnumFor_uint64_t, uint8_t>();
+ TestShouldNotFit<FixedEnumFor_uint64_t, uint16_t>();
+ TestShouldNotFit<FixedEnumFor_uint64_t, uint32_t>();
+ TestShouldFit<FixedEnumFor_uint64_t, uint64_t>();
+
+ TestShouldNotFit<FixedEnumFor_uint64_t, int8_t>();
+ TestShouldNotFit<FixedEnumFor_uint64_t, int16_t>();
+ TestShouldNotFit<FixedEnumFor_uint64_t, int32_t>();
+ TestShouldNotFit<FixedEnumFor_uint64_t, int64_t>();
+
+ return 0;
+}
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -12,16 +12,17 @@ CppUnitTests([
'TestBufferList',
'TestCasting',
'TestCeilingFloor',
'TestCheckedInt',
'TestCountPopulation',
'TestCountZeroes',
'TestEndian',
'TestEnumSet',
+ 'TestEnumTypeTraits',
'TestFastBernoulliTrial',
'TestFloatingPoint',
'TestFunction',
'TestInitializerList',
'TestIntegerPrintfMacros',
'TestIntegerRange',
'TestJSONWriter',
'TestLinkedList',
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -28,16 +28,17 @@ skip-if = os == 'b2g' || (os == 'android
[TestCountZeroes]
[TestDeadlockDetector]
skip-if = os == 'b2g' || (os == 'android' && debug) # Bug 1054249
[TestDeadlockDetectorScalability]
[TestDllInterceptor]
skip-if = os != 'win'
[TestEndian]
[TestEnumSet]
+[TestEnumTypeTraits]
[TestFastBernoulliTrial]
[TestFile]
[TestFloatingPoint]
[TestFunction]
[TestGetURL]
[TestHashtables]
[TestID]
[TestInitializerList]