rcolyer.net
RC Lib  Version 202403231100
Types.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////
2 //
3 // RC Library, (c) 2011-2016, Ryan A. Colyer
4 // Distributed under the Boost Software License, v1.0. (LICENSE.txt)
5 //
6 /// \file Types.h
7 /// Provides typedefs and routines for working with primitives.
8 /////////////////////////////////////////////////////////////////////
9 
10 #ifndef RC_TYPES_H
11 #define RC_TYPES_H
12 
13 #include "RCconfig.h"
14 #include "Macros.h"
15 
16 #include <stdint.h>
17 #include <stddef.h> // Includes size_t and NULL
18 #include <limits>
19 #include <cfloat>
20 #ifdef CPP11
21 #include <type_traits>
22 #endif
23 
24 typedef int8_t i8; ///< 8-bit signed integer.
25 typedef uint8_t u8; ///< 8-bit unsigned integer.
26 typedef int16_t i16; ///< 16-bit signed integer.
27 typedef uint16_t u16; ///< 16-bit unsigned integer.
28 typedef int32_t i32; ///< 32-bit signed integer.
29 typedef uint32_t u32; ///< 32-bit unsigned integer.
30 typedef int64_t i64; ///< 64-bit signed integer.
31 typedef uint64_t u64; ///< 64-bit unsigned integer.
32 
33 typedef float f32; ///< 32-bit float.
34 typedef double f64; ///< 64-bit float.
35 #ifdef unix
36 #if __LDBL_MAX_EXP__ == 16384
37 /// Defined if the 80-bit float was found available on this system.
38 #define RC_HAVE_F80
39 typedef long double f80; ///< 80-bit float. (Note: Usually takes 16 bytes.)
40 #endif
41 #endif
42 #if (__SIZEOF_FLOAT128__ == 16)
43 /// Defined if the 128-bit float was found available on this system.
44 #define RC_HAVE_F128
45 typedef __float128 f128; ///< 128-bit float.
46 #endif
47 
48 #ifdef RC_HAVE_F128
49 typedef f128 fBIGGEST; ///< The biggest float type available.
50 #else
51 #ifdef RC_HAVE_F80
52 typedef f80 fBIGGEST;
53 #else
54 typedef f64 fBIGGEST;
55 #endif
56 #endif
57 
58 #ifdef CPP11
59 /// \def RC_THREAD_LOCAL
60 /// Provides thread_local if available
61 #define RC_THREAD_LOCAL thread_local
62 /// \def RC_NOEXCEPT
63 /// Provides noexcept if available
64 #define RC_NOEXCEPT noexcept
65 #else
66 #define decltype(x) typeof(x)
67 #define RC_THREAD_LOCAL
68 #define RC_NOEXCEPT throw()
69 #endif
70 
71 namespace RC {
72 
73  /// True if the type is signed.
74  /** Use as IsSignedType<u32>() or u32 x; IsSignedType(x); */
75  template<class T> inline bool IsSignedType(const T& RC_UNUSED_PARAM(x)=0) {
76  return (0 > (T(-1)));
77  }
78  /// True if the type is an integer type.
79  /** Use as IsIntegerType<u32>() or u32 x; IsIntegerType(x); */
80  template<class T> inline bool IsIntegerType(const T& RC_UNUSED_PARAM(x)=1) {
81  return (1 == (T(1.1)));
82  }
83 
84 
85  /// @cond UNDOC
86  template<class T, class Error, bool> struct TypeCheck {
87  static inline void Assert() { }
88  };
89  template<class T, class Error> struct TypeCheck<T, Error, false> {
90  static inline void Assert() { T::__TypeCheckFailed__; }
91  };
92  /// @endcond
93 
94 
95  /// \def RC_TYPE_TRUE_MACRO
96  /// For adding a new float or integral type, where StructName is FloatType
97  /// or IntegerType
98 #define RC_TYPE_TRUE_MACRO(StructName, Type) \
99  template<> struct StructName<Type> { static const bool value = true; };\
100  template<> struct StructName<const Type> { static const bool value = true; };\
101  template<> struct StructName<volatile Type> { static const bool value = true; };\
102  template<> struct StructName<const volatile Type> { static const bool value = true; };
103 
104  /// @cond UNDOC
105  template<class T> struct FloatType { static const bool value = false; };
106  RC_TYPE_TRUE_MACRO(FloatType, f32)
107  RC_TYPE_TRUE_MACRO(FloatType, f64)
108 #ifdef RC_HAVE_F80
109  RC_TYPE_TRUE_MACRO(FloatType, f80)
110 #endif
111 #ifdef RC_HAVE_F128
112  RC_TYPE_TRUE_MACRO(FloatType, f128)
113 #endif
114 
115  template<class T> struct IntegerType { static const bool value = false; };
116  RC_TYPE_TRUE_MACRO(IntegerType, char)
117  RC_TYPE_TRUE_MACRO(IntegerType, u8)
118  RC_TYPE_TRUE_MACRO(IntegerType, i8)
119  RC_TYPE_TRUE_MACRO(IntegerType, u16)
120  RC_TYPE_TRUE_MACRO(IntegerType, i16)
121  RC_TYPE_TRUE_MACRO(IntegerType, u32)
122  RC_TYPE_TRUE_MACRO(IntegerType, i32)
123  RC_TYPE_TRUE_MACRO(IntegerType, u64)
124  RC_TYPE_TRUE_MACRO(IntegerType, i64)
125 
126  class ThisTypeIsNotAFloat { };
127  class ThisTypeIsNotAnInteger { };
128  /// @endcond
129 
130  /// For generating compilation errors if the type is not a float.
131  template<class T> inline void AssertFloat() {
132  TypeCheck<T, ThisTypeIsNotAFloat, FloatType<T>::value>::Assert();
133  }
134 
135  /// For generating compilation errors if the type is not an integer.
136  template<class T> inline void AssertInteger() {
137  TypeCheck<T, ThisTypeIsNotAnInteger, IntegerType<T>::value>::Assert();
138  }
139 
140 #ifdef CPP11
141  /// @cond UNDOC
142  template<class T, bool> struct ForceFloatHelper {
143  typedef T type;
144  };
145  template<class T> struct ForceFloatHelper<T, false> {
146  typedef f64 type;
147  };
148  /// @endcond
149 
150  /// If T is a float type, return the same type. Otherwise return it as
151  /// an f64.
152  template<class T> inline auto ForceFloat(T val)
153  -> typename ForceFloatHelper<T, FloatType<T>::value>::type {
154  return val;
155  }
156 #endif
157 
158 #ifdef CPP11
159  /// Returns the unsigned equivalent to the given type.
160  template<class T> typename std::make_unsigned<T>::type ForceUnsigned(T val) {
161  return val;
162  }
163  /// Returns the signed equivalent to the given type.
164  template<class T> typename std::make_signed<T>::type ForceSigned(T val) {
165  return val;
166  }
167 #else
168 #define RC_MAKE_FORCESIGNS(TS) \
169  u##TS ForceUnsigned(i##TS val) { return val; } \
170  i##TS ForceSigned(u##TS val) { return val; }
171  template <class T> T ForceUnsigned(T val) { return val; }
172  template <class T> T ForceSigned(T val) { return val; }
173  RC_ARGS_EACH(RC_MAKE_FORCESIGNS, 8, 16, 32, 64)
174 #endif
175 
176 
177  /// Provide the minimum value held by this type. For floats, the
178  /// smallest positive value.
179  /** Use as MIN_VAL<u32>() or as u32 x = MIN_VAL(x); */
180  template<class T> inline T MIN_VAL(const T& RC_UNUSED_PARAM(x)
181  = std::numeric_limits<T>::min()) { return std::numeric_limits<T>::min();}
182  /// Provide the maximum value held by this type.
183  /** Use as MAX_VAL<u32>() or as u32 x = MAX_VAL(x); */
184  template<class T> inline T MAX_VAL(const T& RC_UNUSED_PARAM(x)
185  = std::numeric_limits<T>::max()) { return std::numeric_limits<T>::max();}
186 #ifdef CPP11
187  /// Provide the lowest value held by this type, for which no value is less.
188  /** Use as LOW_VAL<f32>() or as f32 x = LOW_VAL(x); */
189  template<class T> inline T LOW_VAL(const T & RC_UNUSED_PARAM(x)
190  = std::numeric_limits<T>::lowest()) {
191  return std::numeric_limits<T>::lowest();
192  }
193 #else
194  template<class T, bool> struct LOW_VAL_Helper {
195  static inline T F() { return MIN_VAL<T>(); }
196  };
197  template<class T> struct LOW_VAL_Helper<T, true> {
198  // Usually true. CPP11 version always true.
199  static inline T F() { return -MAX_VAL<T>(); }
200  };
201 
202  template<class T> inline T LOW_VAL(const T &x
203  = LOW_VAL_Helper<T, FloatType<T>::value>::F()) {
204  return LOW_VAL_Helper<T, FloatType<T>::value>::F();
205  }
206 #endif
207 
208  /// @cond UNDOC
209  template<class T, bool> struct MIN_POS_Helper {
210  static inline T F() { return 1; }
211  };
212  template<class T> struct MIN_POS_Helper<T, true> {
213  static inline T F() { return MIN_VAL<T>(); }
214  };
215  /// @endcond
216  /// Provide the minimum positive value held by this type.
217  /** Use as MIN_POS<f32>() or as f32 x = MIN_POS(x); */
218  template<class T> inline T MIN_POS(const T& RC_UNUSED_PARAM(x)
219  = MIN_POS_Helper<T, FloatType<T>::value>::F()) {
220  return MIN_POS_Helper<T, FloatType<T>::value>::F();
221  }
222 
223 
224 #ifdef CPP11
225  /// Clean C-style function pointers: FuncPtr<void(int)> f = \&func; f(4);
226  template<class FT> using FuncPtr = FT*;
227 
228  /// Clean function pointer syntax for member function.
229  /** MemFuncPtr<A, void(int)> f = &A::func; A a; (a.*f)(4); */
230  template<class C, class FT> using MemFuncPtr = FT(C::*);
231 #endif
232 
233 
234  /// @cond UNDOC
235  class RC_Float_Size_Checker {
236  protected:
237 
238  // Asserts the sizes for the float types. If it fails, correct or
239  // comment out. f80 varies between 12 and 16, and is not checked.
240 #ifdef CPP11
241  static_assert(sizeof(f32)==4, "f32 is not 4 bytes");
242  static_assert(sizeof(f64)==8, "f64 is not 8 bytes");
243 #ifdef RC_HAVE_F128
244  static_assert(sizeof(f128)==16, "f128 is not 16 bytes");
245 #endif
246 #else
247  char RC_f32_Is_Not_4_bytes[0-(sizeof(f32)!=4)];
248  char RC_f64_Is_Not_8_bytes[0-2*(sizeof(f64)!=8)];
249 #ifdef RC_HAVE_F128
250  char RC_f128_Is_Not_16_bytes[0-2*(sizeof(f128)!=16)];
251 #endif
252 #endif
253  };
254  /// @endcond
255 
256 
257  /// Auto-detects the endianness of the compilation target, and provides
258  /// automatic endian conversion features.
259  class Endian {
260  public:
261 
262  /// Reverse the byte order.
263  static inline u16 Swap(u16 x) {
264  return ( (x >> 8) | (x << 8) );
265  }
266 
267  /// Reverse the byte order.
268  static inline u32 Swap(u32 x) {
269  return ( (x >> 24)
270  | ((x >> 8) & 0x0000FF00)
271  | ((x << 8) & 0x00FF0000)
272  | (x << 24) );
273  }
274 
275  /// Reverse the byte order.
276  static inline u64 Swap(u64 x) {
277  return ( (x >> 56)
278  | ((x >> 40) & 0x000000000000FF00ull)
279  | ((x >> 24) & 0x0000000000FF0000ull)
280  | ((x >> 8) & 0x00000000FF000000ull)
281  | ((x << 8) & 0x000000FF00000000ull)
282  | ((x << 24) & 0x0000FF0000000000ull)
283  | ((x << 40) & 0x00FF000000000000ull)
284  | (x << 56) );
285  }
286 
287 
288  /// Do nothing. (For consistency.)
289  static inline u8 Swap(u8 x) { return x; }
290  /// Do nothing. (For consistency.)
291  static inline i8 Swap(i8 x) { return x; }
292  /// Reverse the byte order.
293  static inline i16 Swap(i16 x) { return Swap(u16(x)); }
294  /// Reverse the byte order.
295  static inline i32 Swap(i32 x) { return Swap(u32(x)); }
296  /// Reverse the byte order.
297  static inline i64 Swap(i64 x) { return Swap(u64(x)); }
298 
299 
300  /// Converts x to little-endian.
301  template<class T>
302  static inline T ToLittle(const T& x) {
303  if (IsLittle()) {
304  return x;
305  }
306  else {
307  return Swap(x);
308  }
309  }
310 
311  /// Converts x from little-endian.
312  template<class T>
313  static inline T FromLittle(const T& x) {
314  return ToLittle(x);
315  }
316 
317  /// Converts x to big-endian.
318  template<class T>
319  static inline T ToBig(const T& x) {
320  if (IsLittle()) {
321  return Swap(x);
322  }
323  else {
324  return x;
325  }
326  }
327 
328  /// Converts x from big-endian.
329  template<class T>
330  static inline T FromBig(const T& x) {
331  return ToBig(x);
332  }
333 
334  /// True if this system is little-endian.
335  static inline bool IsLittle() {
336  u16 test = 0x0001;
337  return (*reinterpret_cast<char *>(&test) == 1);
338  }
339 
340  /// True if this system is big-endian.
341  static inline bool IsBig() {
342  return ( ! IsLittle() );
343  }
344  };
345 
346 }
347 
348 #endif // RC_TYPES_H
349 
Provides a set of convenience macros for metaprogramming and debugging.
#define RC_UNUSED_PARAM(v)
Use in function headers as void func(int RC_UNUSED_PARAM(x)) to suppress warnings about non-use.
Definition: Macros.h:175
#define RC_ARGS_EACH(Macro,...)
Does RC_ARGS_EACH(Macro,a,b,c) --> Macro(a)Macro(b)Macro(c), for any number of parameters up to 342 o...
Definition: Macros.h:87
void Assert() const
Throws RC::ErrorMsgNull if the pointer is null.
Definition: PtrCommon.h:12
The version information and configuration settings for RC Lib.
uint64_t u64
64-bit unsigned integer.
Definition: Types.h:31
int32_t i32
32-bit signed integer.
Definition: Types.h:28
float f32
32-bit float.
Definition: Types.h:33
f128 fBIGGEST
The biggest float type available.
Definition: Types.h:49
int64_t i64
64-bit signed integer.
Definition: Types.h:30
uint8_t u8
8-bit unsigned integer.
Definition: Types.h:25
double f64
64-bit float.
Definition: Types.h:34
long double f80
80-bit float. (Note: Usually takes 16 bytes.)
Definition: Types.h:39
#define RC_TYPE_TRUE_MACRO(StructName, Type)
For adding a new float or integral type, where StructName is FloatType or IntegerType.
Definition: Types.h:98
uint16_t u16
16-bit unsigned integer.
Definition: Types.h:27
int16_t i16
16-bit signed integer.
Definition: Types.h:26
int8_t i8
8-bit signed integer.
Definition: Types.h:24
uint32_t u32
32-bit unsigned integer.
Definition: Types.h:29
Auto-detects the endianness of the compilation target, and provides automatic endian conversion featu...
Definition: Types.h:259
static bool IsLittle()
True if this system is little-endian.
Definition: Types.h:335
static i16 Swap(i16 x)
Reverse the byte order.
Definition: Types.h:293
static i32 Swap(i32 x)
Reverse the byte order.
Definition: Types.h:295
static bool IsBig()
True if this system is big-endian.
Definition: Types.h:341
static u16 Swap(u16 x)
Reverse the byte order.
Definition: Types.h:263
static u8 Swap(u8 x)
Do nothing. (For consistency.)
Definition: Types.h:289
static i8 Swap(i8 x)
Do nothing. (For consistency.)
Definition: Types.h:291
static u32 Swap(u32 x)
Reverse the byte order.
Definition: Types.h:268
static T FromLittle(const T &x)
Converts x from little-endian.
Definition: Types.h:313
static T ToBig(const T &x)
Converts x to big-endian.
Definition: Types.h:319
static T FromBig(const T &x)
Converts x from big-endian.
Definition: Types.h:330
static i64 Swap(i64 x)
Reverse the byte order.
Definition: Types.h:297
static u64 Swap(u64 x)
Reverse the byte order.
Definition: Types.h:276
static T ToLittle(const T &x)
Converts x to little-endian.
Definition: Types.h:302
Definition: APtr.h:25
std::make_unsigned< T >::type ForceUnsigned(T val)
Returns the unsigned equivalent to the given type.
Definition: Types.h:160
T MIN_POS(const T &x __attribute__((unused))=MIN_POS_Helper< T, FloatType< T >::value >::F())
Provide the minimum positive value held by this type.
Definition: Types.h:218
FT * FuncPtr
Clean C-style function pointers: FuncPtr<void(int)> f = &func; f(4);.
Definition: Types.h:226
bool IsSignedType(const T &x __attribute__((unused))=0)
True if the type is signed.
Definition: Types.h:75
void AssertFloat()
For generating compilation errors if the type is not a float.
Definition: Types.h:131
bool IsIntegerType(const T &x __attribute__((unused))=1)
True if the type is an integer type.
Definition: Types.h:80
void AssertInteger()
For generating compilation errors if the type is not an integer.
Definition: Types.h:136
T MIN_VAL(const T &x __attribute__((unused))=std::numeric_limits< T >::min())
Provide the minimum value held by this type. For floats, the smallest positive value.
Definition: Types.h:180
T LOW_VAL(const T &x __attribute__((unused))=std::numeric_limits< T >::lowest())
Provide the lowest value held by this type, for which no value is less.
Definition: Types.h:189
FT(C::*) MemFuncPtr
Clean function pointer syntax for member function.
Definition: Types.h:230
std::make_signed< T >::type ForceSigned(T val)
Returns the signed equivalent to the given type.
Definition: Types.h:164
auto ForceFloat(T val) -> typename ForceFloatHelper< T, FloatType< T >::value >::type
If T is a float type, return the same type. Otherwise return it as an f64.
Definition: Types.h:152
T MAX_VAL(const T &x __attribute__((unused))=std::numeric_limits< T >::max())
Provide the maximum value held by this type.
Definition: Types.h:184
email address
— (c) 2015