|
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 { typedef int8_t Type; }; |
|
30 |
|
31 template<> |
|
32 struct StdintTypeForSizeAndSignedness<1, false> |
|
33 { typedef uint8_t Type; }; |
|
34 |
|
35 template<> |
|
36 struct StdintTypeForSizeAndSignedness<2, true> |
|
37 { typedef int16_t Type; }; |
|
38 |
|
39 template<> |
|
40 struct StdintTypeForSizeAndSignedness<2, false> |
|
41 { typedef uint16_t Type; }; |
|
42 |
|
43 template<> |
|
44 struct StdintTypeForSizeAndSignedness<4, true> |
|
45 { typedef int32_t Type; }; |
|
46 |
|
47 template<> |
|
48 struct StdintTypeForSizeAndSignedness<4, false> |
|
49 { typedef uint32_t Type; }; |
|
50 |
|
51 template<> |
|
52 struct StdintTypeForSizeAndSignedness<8, true> |
|
53 { typedef int64_t Type; }; |
|
54 |
|
55 template<> |
|
56 struct StdintTypeForSizeAndSignedness<8, false> |
|
57 { typedef uint64_t Type; }; |
|
58 |
|
59 } // namespace detail |
|
60 |
|
61 template<size_t Size> |
|
62 struct UnsignedStdintTypeForSize |
|
63 : detail::StdintTypeForSizeAndSignedness<Size, false> |
|
64 {}; |
|
65 |
|
66 template<typename IntegerType> |
|
67 struct PositionOfSignBit |
|
68 { |
|
69 static_assert(IsIntegral<IntegerType>::value, "PositionOfSignBit is only for integral types"); |
|
70 // 8 here should be CHAR_BIT from limits.h, but the world has moved on. |
|
71 static const size_t value = 8 * sizeof(IntegerType) - 1; |
|
72 }; |
|
73 |
|
74 /** |
|
75 * MinValue returns the minimum value of the given integer type as a |
|
76 * compile-time constant, which std::numeric_limits<IntegerType>::min() |
|
77 * cannot do in c++98. |
|
78 */ |
|
79 template<typename IntegerType> |
|
80 struct MinValue |
|
81 { |
|
82 private: |
|
83 static_assert(IsIntegral<IntegerType>::value, "MinValue is only for integral types"); |
|
84 |
|
85 typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType; |
|
86 static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value; |
|
87 |
|
88 public: |
|
89 // Bitwise ops may return a larger type, that's why we cast explicitly. |
|
90 // In C++, left bit shifts on signed values is undefined by the standard |
|
91 // unless the shifted value is representable. |
|
92 // Notice that signed-to-unsigned conversions are always well-defined in |
|
93 // the standard as the value congruent to 2**n, as expected. By contrast, |
|
94 // unsigned-to-signed is only well-defined if the value is representable. |
|
95 static const IntegerType value = |
|
96 IsSigned<IntegerType>::value |
|
97 ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit) |
|
98 : IntegerType(0); |
|
99 }; |
|
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, "MaxValue is only for integral types"); |
|
110 |
|
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 |
|
117 } // namespace mozilla |
|
118 |
|
119 #endif // mozilla_IntegerTypeTraits_h |