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