1 /*****************************************************************************
2  * $LastChangedDate: 2009-12-18 16:29:35 -0500 (Fri, 18 Dec 2009) $
3  * @file
4  * @author  Jim E. Brooks  http://www.palomino3d.org
5  * @brief   Basic types.
6  *//*
7  * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
8  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
9  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
10  *****************************************************************************/
11 
12 #ifndef BASE_TYPES_HH
13 #define BASE_TYPES_HH 1
14 
15 // Basic types must be fast, prevent them having virtual functions.
16 #define virtual VIRTUAL_METHODS_IN_BASIC_TYPES_IS_TOO_SLOW
17 
18 ////////////////////////////////////////////////////////////////////////////////
19 // Basic types.
20 //
21 #if ! BASE_OMIT_BOOL
22 typedef unsigned char      Bool;  ///< byte-sized bool
23 #endif
24 typedef unsigned char      uchar;
25 #ifdef OS_WINDOWS
26 #undef uint
27 #define uint unsigned int
28 #else
29 typedef unsigned int       uint;
30 #endif
31 #undef ulong
32 typedef unsigned long      ulong;
33 typedef float              fp;
34 #if SPEED
35 typedef fp                 fpx;  // extended-precision float
36 #else
37 typedef double             fpx;
38 #endif
39 
40 #define UINT_CAST( U ) (static_cast<unsigned int>((U)))
41 #define ULONG_CAST( U ) (static_cast<unsigned long>((U)))
42 
43 //------------------------------------------------------------------------------
44 
45 namespace base {
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 // Exact-size types (limited use).
49 // int64() cast or "LL" suffix is critical to compile 64-bit shifts correctly.
50 #if ! NO_STDINT
51 typedef int8_t             int8;
52 typedef uint8_t            uint8;
53 typedef int16_t            int16;
54 typedef uint16_t           uint16;
55 typedef int32_t            int32;
56 typedef uint32_t           uint32;
57 typedef int64_t            int64;   // C99
58 typedef uint64_t           uint64;  // C99
59 #else
60 typedef char               int8;
61 typedef unsigned char      uint8;
62 typedef short              int16;
63 typedef unsigned short     uint16;
64 typedef int                int32;
65 typedef unsigned int       uint32;
66 typedef long long          int64;   // C99
67 typedef unsigned long long uint64;  // C99
68 #endif
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 // Limited use: may result in unportable code.
72 // FYI, on Linux x86-64, int is 32-bits, long is 64-bits.
73 //
74 const uint INT_BITS     = sizeof(int)   * 8;
75 const uint LONG_BITS    = sizeof(long)  * 8;
76 const uint POINTER_BITS = sizeof(void*) * 8;
77 
78 /// @class base::Void
79 /// @brief Void that can be instantiated (useful with templates).
80 class Void { };
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// @brief Macro to turn a fundamental type into a distinct class.
84 /// @verbatim
85 /// For example:
86 /// DECLARE_DISTINCT_TYPE( Radian, fp )
87 /// DECLARE_DISTINCT_TYPE( Degree, fp )
88 /// BTW, this can't done using a template class and typedefs
89 /// as the typedefs would still be the same type eg:
90 /// typedef Distinct<fp> Radian;
91 /// typedef Distinct<fp> Degree;
92 /// @endverbatim
93 ///
94 /// ----------------------------------------------------------------------------
95 /// NOTE: DECLARE_DISTINCT_TYPE() MIGHT CAUSE BUGS IF NOT CAREFUL!
96 /// !!!!! DECLARE_DISTINCT_TYPE() allows implied conversion to fundamental type!
97 ///       Instead use DECLARE_DISTINCT_TYPE_STRICT() to force explicit conversion.
98 /// ----------------------------------------------------------------------------
99 #define DECLARE_DISTINCT_TYPE( CLASS, T, CONV_FUNC )                                        \
100 class CLASS                                                                                 \
101 {                                                                                           \
102 public:                                                                                     \
103     typedef T value_type;                                                                   \
104                 CLASS( void ) : mVal(0) { }  /* clients depends on zero */                  \
105                 CLASS( T val ) : mVal(val) { }                                              \
106     T           CONV_FUNC( void ) const { return mVal; }  /* explicit conversion */         \
107                 operator T() const { return mVal; }                                         \
108     CLASS&      operator=( const T& val ) { mVal = val; return *this; }                     \
109     friend bool operator==( const CLASS a, const CLASS b ) { return a.mVal == b.mVal; }     \
110     friend bool operator!=( const CLASS a, const CLASS b ) { return a.mVal != b.mVal; }     \
111     /* Arithmetic operators are omitted because of ambiguity. */                            \
112     /* Rather, cast to fundamental type then do the math. */                                \
113 private:                                                                                    \
114     T   mVal;                                                                               \
115 };
116 
117 // Strict variant requires explicit conversion.
118 // This one is tedious but it can prevent conversion bugs.
119 // Example:
120 // DECLARE_DISTINCT_TYPE_STRICT( Meter, fp, FP )
121 // void Func( Meter meter )
122 // {
123 //   fp distance = ...;
124 //   fp sum = distance + meter.FP();  // explicitly convert to fp
125 // }
126 #define DECLARE_DISTINCT_TYPE_STRICT( CLASS, T, CONV_FUNC )                                 \
127 class CLASS                                                                                 \
128 {                                                                                           \
129 public:                                                                                     \
130     typedef T value_type;                                                                   \
131                  CLASS( void ) : mVal(0) { }  /* clients depends on zero */                 \
132     explicit     CLASS( T val ) : mVal(val) { }  /* explicit conversion */                  \
133               /* operator T() const { return mVal; } [wrong] */                             \
134     T            CONV_FUNC( void ) const { return mVal; }  /* explicit conversion */        \
135   /*CLASS&       operator=( const T& val ) { mVal = val; return *this; } [circumvents] */   \
136     CLASS&       operator=(  const CLASS src ) { mVal =  src.mVal; return *this; }          \
137     CLASS&       operator+=( const CLASS src ) { mVal += src.mVal; return *this; }          \
138     CLASS&       operator-=( const CLASS src ) { mVal -= src.mVal; return *this; }          \
139     CLASS&       operator*=( const CLASS src ) { mVal *= src.mVal; return *this; }          \
140     CLASS&       operator/=( const CLASS src ) { mVal /= src.mVal; return *this; }          \
141     friend CLASS operator+( CLASS a, CLASS b ) { return CLASS(a.mVal + b.mVal); }           \
142     friend CLASS operator-( CLASS a, CLASS b ) { return CLASS(a.mVal - b.mVal); }           \
143     friend CLASS operator*( CLASS a, CLASS b ) { return CLASS(a.mVal * b.mVal); }           \
144     friend CLASS operator/( CLASS a, CLASS b ) { return CLASS(a.mVal / b.mVal); }           \
145     friend CLASS operator-( CLASS a )          { return CLASS(-a.mVal); }                   \
146     friend bool  operator==( const CLASS a, const CLASS b ) { return a.mVal == b.mVal; }    \
147     friend bool  operator!=( const CLASS a, const CLASS b ) { return a.mVal != b.mVal; }    \
148     friend bool  operator>( CLASS a, CLASS b ) { return a.mVal > b.mVal; }                  \
149     friend bool  operator<( CLASS a, CLASS b ) { return a.mVal < b.mVal; }                  \
150     friend bool  operator>=( CLASS a, CLASS b ) { return a.mVal >= b.mVal; }                \
151     friend bool  operator<=( CLASS a, CLASS b ) { return a.mVal <= b.mVal; }                \
152 private:                                                                                    \
153     T   mVal;                                                                               \
154 };
155 
156 /// @class base::bool0
157 /// @brief Fundamental type auto-initialized as zero.
158 /// @class base::int0
159 /// @brief Fundamental type auto-initialized as zero.
160 /// @class base::uint0
161 /// @brief Fundamental type auto-initialized as zero.
162 DECLARE_DISTINCT_TYPE( bool0, bool, CONV_FUNC_UNUSED )
163 DECLARE_DISTINCT_TYPE( int0,  int , CONV_FUNC_UNUSED )
164 DECLARE_DISTINCT_TYPE( uint0, uint, CONV_FUNC_UNUSED )
165 
166 #undef virtual
167 
168 } // namespace base
169 
170 #endif // BASE_TYPES_HH
171