IntegerTypeTraits.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. /* Helpers to manipulate integer types that don't fit in TypeTraits.h */
  6. #ifndef mozilla_IntegerTypeTraits_h
  7. #define mozilla_IntegerTypeTraits_h
  8. #include "mozilla/TypeTraits.h"
  9. #include <stdint.h>
  10. namespace mozilla {
  11. namespace detail {
  12. /**
  13. * StdintTypeForSizeAndSignedness returns the stdint integer type
  14. * of given size (can be 1, 2, 4 or 8) and given signedness
  15. * (false means unsigned, true means signed).
  16. */
  17. template<size_t Size, bool Signedness>
  18. struct StdintTypeForSizeAndSignedness;
  19. template<>
  20. struct StdintTypeForSizeAndSignedness<1, true>
  21. {
  22. typedef int8_t Type;
  23. };
  24. template<>
  25. struct StdintTypeForSizeAndSignedness<1, false>
  26. {
  27. typedef uint8_t Type;
  28. };
  29. template<>
  30. struct StdintTypeForSizeAndSignedness<2, true>
  31. {
  32. typedef int16_t Type;
  33. };
  34. template<>
  35. struct StdintTypeForSizeAndSignedness<2, false>
  36. {
  37. typedef uint16_t Type;
  38. };
  39. template<>
  40. struct StdintTypeForSizeAndSignedness<4, true>
  41. {
  42. typedef int32_t Type;
  43. };
  44. template<>
  45. struct StdintTypeForSizeAndSignedness<4, false>
  46. {
  47. typedef uint32_t Type;
  48. };
  49. template<>
  50. struct StdintTypeForSizeAndSignedness<8, true>
  51. {
  52. typedef int64_t Type;
  53. };
  54. template<>
  55. struct StdintTypeForSizeAndSignedness<8, false>
  56. {
  57. typedef uint64_t Type;
  58. };
  59. } // namespace detail
  60. template<size_t Size>
  61. struct UnsignedStdintTypeForSize
  62. : detail::StdintTypeForSizeAndSignedness<Size, false>
  63. {};
  64. template<size_t Size>
  65. struct SignedStdintTypeForSize
  66. : detail::StdintTypeForSizeAndSignedness<Size, true>
  67. {};
  68. template<typename IntegerType>
  69. struct PositionOfSignBit
  70. {
  71. static_assert(IsIntegral<IntegerType>::value,
  72. "PositionOfSignBit is only for integral types");
  73. // 8 here should be CHAR_BIT from limits.h, but the world has moved on.
  74. static const size_t value = 8 * sizeof(IntegerType) - 1;
  75. };
  76. /**
  77. * MinValue returns the minimum value of the given integer type as a
  78. * compile-time constant, which std::numeric_limits<IntegerType>::min()
  79. * cannot do in c++98.
  80. */
  81. template<typename IntegerType>
  82. struct MinValue
  83. {
  84. private:
  85. static_assert(IsIntegral<IntegerType>::value,
  86. "MinValue is only for integral types");
  87. typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType;
  88. static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
  89. public:
  90. // Bitwise ops may return a larger type, that's why we cast explicitly.
  91. // In C++, left bit shifts on signed values is undefined by the standard
  92. // unless the shifted value is representable.
  93. // Notice that signed-to-unsigned conversions are always well-defined in
  94. // the standard as the value congruent to 2**n, as expected. By contrast,
  95. // unsigned-to-signed is only well-defined if the value is representable.
  96. static const IntegerType value =
  97. IsSigned<IntegerType>::value
  98. ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
  99. : IntegerType(0);
  100. };
  101. /**
  102. * MaxValue returns the maximum value of the given integer type as a
  103. * compile-time constant, which std::numeric_limits<IntegerType>::max()
  104. * cannot do in c++98.
  105. */
  106. template<typename IntegerType>
  107. struct MaxValue
  108. {
  109. static_assert(IsIntegral<IntegerType>::value,
  110. "MaxValue is only for integral types");
  111. // Tricksy, but covered by the CheckedInt unit test.
  112. // Relies on the type of MinValue<IntegerType>::value
  113. // being IntegerType.
  114. static const IntegerType value = ~MinValue<IntegerType>::value;
  115. };
  116. } // namespace mozilla
  117. #endif // mozilla_IntegerTypeTraits_h