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