summaryrefslogtreecommitdiff
path: root/mfbt/IntegerTypeTraits.h
blob: 6144d2084c4851c26217f6b971956648a97289c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* -*- 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/. */

/* Helpers to manipulate integer types that don't fit in TypeTraits.h */

#ifndef mozilla_IntegerTypeTraits_h
#define mozilla_IntegerTypeTraits_h

#include "mozilla/TypeTraits.h"
#include <stdint.h>

namespace mozilla {

namespace detail {

/**
 * StdintTypeForSizeAndSignedness returns the stdint integer type
 * of given size (can be 1, 2, 4 or 8) and given signedness
 * (false means unsigned, true means signed).
 */
template<size_t Size, bool Signedness>
struct StdintTypeForSizeAndSignedness;

template<>
struct StdintTypeForSizeAndSignedness<1, true>
{
  typedef int8_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<1, false>
{
  typedef uint8_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<2, true>
{
  typedef int16_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<2, false>
{
  typedef uint16_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<4, true>
{
  typedef int32_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<4, false>
{
  typedef uint32_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<8, true>
{
  typedef int64_t Type;
};

template<>
struct StdintTypeForSizeAndSignedness<8, false>
{
  typedef uint64_t Type;
};

} // namespace detail

template<size_t Size>
struct UnsignedStdintTypeForSize
  : detail::StdintTypeForSizeAndSignedness<Size, false>
{};

template<size_t Size>
struct SignedStdintTypeForSize
  : detail::StdintTypeForSizeAndSignedness<Size, true>
{};

template<typename IntegerType>
struct PositionOfSignBit
{
  static_assert(IsIntegral<IntegerType>::value,
                "PositionOfSignBit is only for integral types");
  // 8 here should be CHAR_BIT from limits.h, but the world has moved on.
  static const size_t value = 8 * sizeof(IntegerType) - 1;
};

/**
 * MinValue returns the minimum value of the given integer type as a
 * compile-time constant, which std::numeric_limits<IntegerType>::min()
 * cannot do in c++98.
 */
template<typename IntegerType>
struct MinValue
{
private:
  static_assert(IsIntegral<IntegerType>::value,
                "MinValue is only for integral types");

  typedef typename MakeUnsigned<IntegerType>::Type UnsignedIntegerType;
  static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;

public:
  // Bitwise ops may return a larger type, that's why we cast explicitly.
  // In C++, left bit shifts on signed values is undefined by the standard
  // unless the shifted value is representable.
  // Notice that signed-to-unsigned conversions are always well-defined in
  // the standard as the value congruent to 2**n, as expected. By contrast,
  // unsigned-to-signed is only well-defined if the value is representable.
  static const IntegerType value =
      IsSigned<IntegerType>::value
      ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
      : IntegerType(0);
};

/**
 * MaxValue returns the maximum value of the given integer type as a
 * compile-time constant, which std::numeric_limits<IntegerType>::max()
 * cannot do in c++98.
 */
template<typename IntegerType>
struct MaxValue
{
  static_assert(IsIntegral<IntegerType>::value,
                "MaxValue is only for integral types");

  // Tricksy, but covered by the CheckedInt unit test.
  // Relies on the type of MinValue<IntegerType>::value
  // being IntegerType.
  static const IntegerType value = ~MinValue<IntegerType>::value;
};

} // namespace mozilla

#endif // mozilla_IntegerTypeTraits_h