diff options
author | Brad Davis <[email protected]> | 2014-07-24 16:47:31 -0700 |
---|---|---|
committer | Brad Davis <[email protected]> | 2014-07-24 16:47:31 -0700 |
commit | 0f49ce8fc6aa54224e4c0d6fda8c4527ad39cce1 (patch) | |
tree | da07ebc6a7f75185bda857dd5f1c34710b416a93 /LibOVR/Src/Kernel | |
parent | ca79271759ff7eecd22ec5c4db438370fe51d687 (diff) |
0.4 Win-Beta0.4.0
Diffstat (limited to 'LibOVR/Src/Kernel')
49 files changed, 6622 insertions, 2197 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Alg.cpp b/LibOVR/Src/Kernel/OVR_Alg.cpp index 2e52bc3..26731fc 100644 --- a/LibOVR/Src/Kernel/OVR_Alg.cpp +++ b/LibOVR/Src/Kernel/OVR_Alg.cpp @@ -29,7 +29,7 @@ limitations under the License. namespace OVR { namespace Alg { //------------------------------------------------------------------------ -extern const UByte UpperBitTable[256] = +extern const uint8_t UpperBitTable[256] = { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, @@ -41,7 +41,7 @@ extern const UByte UpperBitTable[256] = 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; -extern const UByte LowerBitTable[256] = +extern const uint8_t LowerBitTable[256] = { 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, diff --git a/LibOVR/Src/Kernel/OVR_Alg.h b/LibOVR/Src/Kernel/OVR_Alg.h index e03cea0..00264b5 100644 --- a/LibOVR/Src/Kernel/OVR_Alg.h +++ b/LibOVR/Src/Kernel/OVR_Alg.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Alg.h Content : Simple general purpose algorithms: Sort, Binary Search, etc. Created : September 19, 2012 @@ -66,12 +66,12 @@ template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f) // absolutelly the same as regular gmin/gmax. template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b) { - OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t)); return (a < b) ? a : b; } template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b) { - OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(size_t)); return (b < a) ? a : b; } @@ -99,7 +99,7 @@ template<class T> struct OperatorLess // The range is specified with start, end, where "end" is exclusive! // The comparison predicate must be specified. template<class Array, class Less> -void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) +void QuickSortSliced(Array& arr, size_t start, size_t end, Less less) { enum { @@ -108,15 +108,15 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) if(end - start < 2) return; - SPInt stack[80]; - SPInt* top = stack; - SPInt base = (SPInt)start; - SPInt limit = (SPInt)end; + intptr_t stack[80]; + intptr_t* top = stack; + intptr_t base = (intptr_t)start; + intptr_t limit = (intptr_t)end; for(;;) { - SPInt len = limit - base; - SPInt i, j, pivot; + intptr_t len = limit - base; + intptr_t i, j, pivot; if(len > Threshold) { @@ -201,7 +201,7 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> -void QuickSortSliced(Array& arr, UPInt start, UPInt end) +void QuickSortSliced(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); @@ -210,7 +210,7 @@ void QuickSortSliced(Array& arr, UPInt start, UPInt end) // Same as corresponding G_QuickSortSliced but with checking array limits to avoid // crash in the case of wrong comparator functor. template<class Array, class Less> -bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end, Less less) { enum { @@ -219,15 +219,15 @@ bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) if(end - start < 2) return true; - SPInt stack[80]; - SPInt* top = stack; - SPInt base = (SPInt)start; - SPInt limit = (SPInt)end; + intptr_t stack[80]; + intptr_t* top = stack; + intptr_t base = (intptr_t)start; + intptr_t limit = (intptr_t)end; for(;;) { - SPInt len = limit - base; - SPInt i, j, pivot; + intptr_t len = limit - base; + intptr_t i, j, pivot; if(len > Threshold) { @@ -316,7 +316,7 @@ bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) } template<class Array> -bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end) +bool QuickSortSlicedSafe(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare); @@ -374,11 +374,11 @@ bool QuickSortSafe(Array& arr) // an array with all equal elements will remain "untouched", while // Quick Sort will considerably shuffle the elements in this case. template<class Array, class Less> -void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) +void InsertionSortSliced(Array& arr, size_t start, size_t end, Less less) { - UPInt j = start; - UPInt i = j + 1; - UPInt limit = end; + size_t j = start; + size_t i = j + 1; + size_t limit = end; for(; i < limit; j = i, i++) { @@ -401,7 +401,7 @@ void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) // The range is specified with start, end, where "end" is exclusive! // The data type must have a defined "<" operator. template<class Array> -void InsertionSortSliced(Array& arr, UPInt start, UPInt end) +void InsertionSortSliced(Array& arr, size_t start, size_t end) { typedef typename Array::ValueType ValueType; InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); @@ -442,14 +442,14 @@ void InsertionSort(Array& arr) template<class Array> typename Array::ValueType& Median(Array& arr) { - UPInt count = arr.GetSize(); - UPInt mid = (count - 1) / 2; + size_t count = arr.GetSize(); + size_t mid = (count - 1) / 2; OVR_ASSERT(count > 0); - for (UPInt j = 0; j <= mid; j++) + for (size_t j = 0; j <= mid; j++) { - UPInt min = j; - for (UPInt k = j + 1; k < count; k++) + size_t min = j; + for (size_t k = j + 1; k < count; k++) if (arr[k] < arr[min]) min = k; Swap(arr[j], arr[min]); @@ -461,12 +461,12 @@ typename Array::ValueType& Median(Array& arr) // ***** LowerBoundSliced // template<class Array, class Value, class Less> -UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less) { - SPInt first = (SPInt)start; - SPInt len = (SPInt)(end - start); - SPInt half; - SPInt middle; + intptr_t first = (intptr_t)start; + intptr_t len = (intptr_t)(end - start); + intptr_t half; + intptr_t middle; while(len > 0) { @@ -482,7 +482,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va len = half; } } - return (UPInt)first; + return (size_t)first; } @@ -490,7 +490,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** LowerBoundSliced // template<class Array, class Value> -UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) +size_t LowerBoundSliced(const Array& arr, size_t start, size_t end, const Value& val) { return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } @@ -499,7 +499,7 @@ UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** LowerBoundSized // template<class Array, class Value> -UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) +size_t LowerBoundSized(const Array& arr, size_t size, const Value& val) { return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } @@ -508,7 +508,7 @@ UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) // ***** LowerBound // template<class Array, class Value, class Less> -UPInt LowerBound(const Array& arr, const Value& val, Less less) +size_t LowerBound(const Array& arr, const Value& val, Less less) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, less); } @@ -518,7 +518,7 @@ UPInt LowerBound(const Array& arr, const Value& val, Less less) // ***** LowerBound // template<class Array, class Value> -UPInt LowerBound(const Array& arr, const Value& val) +size_t LowerBound(const Array& arr, const Value& val) { return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } @@ -529,12 +529,12 @@ UPInt LowerBound(const Array& arr, const Value& val) // ***** UpperBoundSliced // template<class Array, class Value, class Less> -UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val, Less less) { - SPInt first = (SPInt)start; - SPInt len = (SPInt)(end - start); - SPInt half; - SPInt middle; + intptr_t first = (intptr_t)start; + intptr_t len = (intptr_t)(end - start); + intptr_t half; + intptr_t middle; while(len > 0) { @@ -550,7 +550,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va len = len - half - 1; } } - return (UPInt)first; + return (size_t)first; } @@ -558,7 +558,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** UpperBoundSliced // template<class Array, class Value> -UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) +size_t UpperBoundSliced(const Array& arr, size_t start, size_t end, const Value& val) { return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); } @@ -568,7 +568,7 @@ UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& va // ***** UpperBoundSized // template<class Array, class Value> -UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) +size_t UpperBoundSized(const Array& arr, size_t size, const Value& val) { return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); } @@ -578,7 +578,7 @@ UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) // ***** UpperBound // template<class Array, class Value, class Less> -UPInt UpperBound(const Array& arr, const Value& val, Less less) +size_t UpperBound(const Array& arr, const Value& val, Less less) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, less); } @@ -588,7 +588,7 @@ UPInt UpperBound(const Array& arr, const Value& val, Less less) // ***** UpperBound // template<class Array, class Value> -UPInt UpperBound(const Array& arr, const Value& val) +size_t UpperBound(const Array& arr, const Value& val) { return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); } @@ -599,8 +599,8 @@ UPInt UpperBound(const Array& arr, const Value& val) // template<class Array> void ReverseArray(Array& arr) { - SPInt from = 0; - SPInt to = arr.GetSize() - 1; + intptr_t from = 0; + intptr_t to = arr.GetSize() - 1; while(from < to) { Swap(arr[from], arr[to]); @@ -615,7 +615,7 @@ template<class Array> void ReverseArray(Array& arr) template<class CDst, class CSrc> void AppendArray(CDst& dst, const CSrc& src) { - UPInt i; + size_t i; for(i = 0; i < src.GetSize(); i++) dst.PushBack(src[i]); } @@ -630,13 +630,14 @@ template<class T> class ArrayAdaptor public: typedef T ValueType; ArrayAdaptor() : Data(0), Size(0) {} - ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {} - UPInt GetSize() const { return Size; } - const T& operator [] (UPInt i) const { return Data[i]; } - T& operator [] (UPInt i) { return Data[i]; } + ArrayAdaptor(T* ptr, size_t size) : Data(ptr), Size(size) {} + size_t GetSize() const { return Size; } + int GetSizeI() const { return (int)GetSize(); } + const T& operator [] (size_t i) const { return Data[i]; } + T& operator [] (size_t i) { return Data[i]; } private: T* Data; - UPInt Size; + size_t Size; }; @@ -650,24 +651,25 @@ template<class T> class ConstArrayAdaptor public: typedef T ValueType; ConstArrayAdaptor() : Data(0), Size(0) {} - ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {} - UPInt GetSize() const { return Size; } - const T& operator [] (UPInt i) const { return Data[i]; } + ConstArrayAdaptor(const T* ptr, size_t size) : Data(ptr), Size(size) {} + size_t GetSize() const { return Size; } + int GetSizeI() const { return (int)GetSize(); } + const T& operator [] (size_t i) const { return Data[i]; } private: const T* Data; - UPInt Size; + size_t Size; }; //----------------------------------------------------------------------------------- -extern const UByte UpperBitTable[256]; -extern const UByte LowerBitTable[256]; +extern const uint8_t UpperBitTable[256]; +extern const uint8_t LowerBitTable[256]; //----------------------------------------------------------------------------------- -inline UByte UpperBit(UPInt val) +inline uint8_t UpperBit(size_t val) { #ifndef OVR_64BIT_POINTERS @@ -712,7 +714,7 @@ inline UByte UpperBit(UPInt val) } //----------------------------------------------------------------------------------- -inline UByte LowerBit(UPInt val) +inline uint8_t LowerBit(size_t val) { #ifndef OVR_64BIT_POINTERS @@ -765,18 +767,18 @@ class MemUtil public: // Memory compare - static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } - static int Cmp16(const void* p1, const void* p2, UPInt int16Count); - static int Cmp32(const void* p1, const void* p2, UPInt int32Count); - static int Cmp64(const void* p1, const void* p2, UPInt int64Count); + static int Cmp (const void* p1, const void* p2, size_t byteCount) { return memcmp(p1, p2, byteCount); } + static int Cmp16(const void* p1, const void* p2, size_t int16Count); + static int Cmp32(const void* p1, const void* p2, size_t int32Count); + static int Cmp64(const void* p1, const void* p2, size_t int64Count); }; // ** Inline Implementation -inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) +inline int MemUtil::Cmp16(const void* p1, const void* p2, size_t int16Count) { - SInt16* pa = (SInt16*)p1; - SInt16* pb = (SInt16*)p2; + int16_t* pa = (int16_t*)p1; + int16_t* pb = (int16_t*)p2; unsigned ic = 0; if (int16Count == 0) return 0; @@ -785,10 +787,10 @@ inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } -inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) +inline int MemUtil::Cmp32(const void* p1, const void* p2, size_t int32Count) { - SInt32* pa = (SInt32*)p1; - SInt32* pb = (SInt32*)p2; + int32_t* pa = (int32_t*)p1; + int32_t* pb = (int32_t*)p2; unsigned ic = 0; if (int32Count == 0) return 0; @@ -797,10 +799,10 @@ inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) return 0; return pa[ic] > pb[ic] ? 1 : -1; } -inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) +inline int MemUtil::Cmp64(const void* p1, const void* p2, size_t int64Count) { - SInt64* pa = (SInt64*)p1; - SInt64* pb = (SInt64*)p2; + int64_t* pa = (int64_t*)p1; + int64_t* pb = (int64_t*)p2; unsigned ic = 0; if (int64Count == 0) return 0; @@ -822,8 +824,8 @@ namespace ByteUtil { // Swap the byte order of a byte array inline void SwapOrder(void* pv, int size) { - UByte* pb = (UByte*)pv; - UByte temp; + uint8_t* pb = (uint8_t*)pv; + uint8_t temp; for (int i = 0; i < size>>1; i++) { temp = pb[size-1-i]; @@ -833,29 +835,29 @@ namespace ByteUtil { } // Swap the byte order of primitive types - inline UByte SwapOrder(UByte v) { return v; } - inline SByte SwapOrder(SByte v) { return v; } - inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } - inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } - inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } - inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } - inline UInt64 SwapOrder(UInt64 v) + inline uint8_t SwapOrder(uint8_t v) { return v; } + inline int8_t SwapOrder(int8_t v) { return v; } + inline uint16_t SwapOrder(uint16_t v) { return uint16_t(v>>8)|uint16_t(v<<8); } + inline int16_t SwapOrder(int16_t v) { return int16_t((uint16_t(v)>>8)|(v<<8)); } + inline uint32_t SwapOrder(uint32_t v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } + inline int32_t SwapOrder(int32_t p) { return (int32_t)SwapOrder(uint32_t(p)); } + inline uint64_t SwapOrder(uint64_t v) { return (v>>56) | - ((v&UInt64(0x00FF000000000000ULL))>>40) | - ((v&UInt64(0x0000FF0000000000ULL))>>24) | - ((v&UInt64(0x000000FF00000000ULL))>>8) | - ((v&UInt64(0x00000000FF000000ULL))<<8) | - ((v&UInt64(0x0000000000FF0000ULL))<<24) | - ((v&UInt64(0x000000000000FF00ULL))<<40) | + ((v&uint64_t(0x00FF000000000000ULL))>>40) | + ((v&uint64_t(0x0000FF0000000000ULL))>>24) | + ((v&uint64_t(0x000000FF00000000ULL))>>8) | + ((v&uint64_t(0x00000000FF000000ULL))<<8) | + ((v&uint64_t(0x0000000000FF0000ULL))<<24) | + ((v&uint64_t(0x000000000000FF00ULL))<<40) | (v<<56); } - inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } + inline int64_t SwapOrder(int64_t v) { return (int64_t)SwapOrder(uint64_t(v)); } inline float SwapOrder(float p) { union { float p; - UInt32 v; + uint32_t v; } u; u.p = p; u.v = SwapOrder(u.v); @@ -866,7 +868,7 @@ namespace ByteUtil { { union { double p; - UInt64 v; + uint64_t v; } u; u.p = p; u.v = SwapOrder(u.v); @@ -877,99 +879,99 @@ namespace ByteUtil { #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN) // Little Endian to System (LE) - inline UByte LEToSystem(UByte v) { return v; } - inline SByte LEToSystem(SByte v) { return v; } - inline UInt16 LEToSystem(UInt16 v) { return v; } - inline SInt16 LEToSystem(SInt16 v) { return v; } - inline UInt32 LEToSystem(UInt32 v) { return v; } - inline SInt32 LEToSystem(SInt32 v) { return v; } - inline UInt64 LEToSystem(UInt64 v) { return v; } - inline SInt64 LEToSystem(SInt64 v) { return v; } + inline uint8_t LEToSystem(uint8_t v) { return v; } + inline int8_t LEToSystem(int8_t v) { return v; } + inline uint16_t LEToSystem(uint16_t v) { return v; } + inline int16_t LEToSystem(int16_t v) { return v; } + inline uint32_t LEToSystem(uint32_t v) { return v; } + inline int32_t LEToSystem(int32_t v) { return v; } + inline uint64_t LEToSystem(uint64_t v) { return v; } + inline int64_t LEToSystem(int64_t v) { return v; } inline float LEToSystem(float v) { return v; } inline double LEToSystem(double v) { return v; } // Big Endian to System (LE) - inline UByte BEToSystem(UByte v) { return SwapOrder(v); } - inline SByte BEToSystem(SByte v) { return SwapOrder(v); } - inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } - inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } - inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } - inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } - inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } - inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } + inline uint8_t BEToSystem(uint8_t v) { return SwapOrder(v); } + inline int8_t BEToSystem(int8_t v) { return SwapOrder(v); } + inline uint16_t BEToSystem(uint16_t v) { return SwapOrder(v); } + inline int16_t BEToSystem(int16_t v) { return SwapOrder(v); } + inline uint32_t BEToSystem(uint32_t v) { return SwapOrder(v); } + inline int32_t BEToSystem(int32_t v) { return SwapOrder(v); } + inline uint64_t BEToSystem(uint64_t v) { return SwapOrder(v); } + inline int64_t BEToSystem(int64_t v) { return SwapOrder(v); } inline float BEToSystem(float v) { return SwapOrder(v); } inline double BEToSystem(double v) { return SwapOrder(v); } // System (LE) to Little Endian - inline UByte SystemToLE(UByte v) { return v; } - inline SByte SystemToLE(SByte v) { return v; } - inline UInt16 SystemToLE(UInt16 v) { return v; } - inline SInt16 SystemToLE(SInt16 v) { return v; } - inline UInt32 SystemToLE(UInt32 v) { return v; } - inline SInt32 SystemToLE(SInt32 v) { return v; } - inline UInt64 SystemToLE(UInt64 v) { return v; } - inline SInt64 SystemToLE(SInt64 v) { return v; } + inline uint8_t SystemToLE(uint8_t v) { return v; } + inline int8_t SystemToLE(int8_t v) { return v; } + inline uint16_t SystemToLE(uint16_t v) { return v; } + inline int16_t SystemToLE(int16_t v) { return v; } + inline uint32_t SystemToLE(uint32_t v) { return v; } + inline int32_t SystemToLE(int32_t v) { return v; } + inline uint64_t SystemToLE(uint64_t v) { return v; } + inline int64_t SystemToLE(int64_t v) { return v; } inline float SystemToLE(float v) { return v; } inline double SystemToLE(double v) { return v; } // System (LE) to Big Endian - inline UByte SystemToBE(UByte v) { return SwapOrder(v); } - inline SByte SystemToBE(SByte v) { return SwapOrder(v); } - inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } - inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } - inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } - inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } - inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } - inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } + inline uint8_t SystemToBE(uint8_t v) { return SwapOrder(v); } + inline int8_t SystemToBE(int8_t v) { return SwapOrder(v); } + inline uint16_t SystemToBE(uint16_t v) { return SwapOrder(v); } + inline int16_t SystemToBE(int16_t v) { return SwapOrder(v); } + inline uint32_t SystemToBE(uint32_t v) { return SwapOrder(v); } + inline int32_t SystemToBE(int32_t v) { return SwapOrder(v); } + inline uint64_t SystemToBE(uint64_t v) { return SwapOrder(v); } + inline int64_t SystemToBE(int64_t v) { return SwapOrder(v); } inline float SystemToBE(float v) { return SwapOrder(v); } inline double SystemToBE(double v) { return SwapOrder(v); } #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN) // Little Endian to System (BE) - inline UByte LEToSystem(UByte v) { return SwapOrder(v); } - inline SByte LEToSystem(SByte v) { return SwapOrder(v); } - inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } - inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } - inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } - inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } - inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } - inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } + inline uint8_t LEToSystem(uint8_t v) { return SwapOrder(v); } + inline int8_t LEToSystem(int8_t v) { return SwapOrder(v); } + inline uint16_t LEToSystem(uint16_t v) { return SwapOrder(v); } + inline int16_t LEToSystem(int16_t v) { return SwapOrder(v); } + inline uint32_t LEToSystem(uint32_t v) { return SwapOrder(v); } + inline int32_t LEToSystem(int32_t v) { return SwapOrder(v); } + inline uint64_t LEToSystem(uint64_t v) { return SwapOrder(v); } + inline int64_t LEToSystem(int64_t v) { return SwapOrder(v); } inline float LEToSystem(float v) { return SwapOrder(v); } inline double LEToSystem(double v) { return SwapOrder(v); } // Big Endian to System (BE) - inline UByte BEToSystem(UByte v) { return v; } - inline SByte BEToSystem(SByte v) { return v; } - inline UInt16 BEToSystem(UInt16 v) { return v; } - inline SInt16 BEToSystem(SInt16 v) { return v; } - inline UInt32 BEToSystem(UInt32 v) { return v; } - inline SInt32 BEToSystem(SInt32 v) { return v; } - inline UInt64 BEToSystem(UInt64 v) { return v; } - inline SInt64 BEToSystem(SInt64 v) { return v; } + inline uint8_t BEToSystem(uint8_t v) { return v; } + inline int8_t BEToSystem(int8_t v) { return v; } + inline uint16_t BEToSystem(uint16_t v) { return v; } + inline int16_t BEToSystem(int16_t v) { return v; } + inline uint32_t BEToSystem(uint32_t v) { return v; } + inline int32_t BEToSystem(int32_t v) { return v; } + inline uint64_t BEToSystem(uint64_t v) { return v; } + inline int64_t BEToSystem(int64_t v) { return v; } inline float BEToSystem(float v) { return v; } inline double BEToSystem(double v) { return v; } // System (BE) to Little Endian - inline UByte SystemToLE(UByte v) { return SwapOrder(v); } - inline SByte SystemToLE(SByte v) { return SwapOrder(v); } - inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } - inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } - inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } - inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } - inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } - inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } + inline uint8_t SystemToLE(uint8_t v) { return SwapOrder(v); } + inline int8_t SystemToLE(int8_t v) { return SwapOrder(v); } + inline uint16_t SystemToLE(uint16_t v) { return SwapOrder(v); } + inline int16_t SystemToLE(int16_t v) { return SwapOrder(v); } + inline uint32_t SystemToLE(uint32_t v) { return SwapOrder(v); } + inline int32_t SystemToLE(int32_t v) { return SwapOrder(v); } + inline uint64_t SystemToLE(uint64_t v) { return SwapOrder(v); } + inline int64_t SystemToLE(int64_t v) { return SwapOrder(v); } inline float SystemToLE(float v) { return SwapOrder(v); } inline double SystemToLE(double v) { return SwapOrder(v); } // System (BE) to Big Endian - inline UByte SystemToBE(UByte v) { return v; } - inline SByte SystemToBE(SByte v) { return v; } - inline UInt16 SystemToBE(UInt16 v) { return v; } - inline SInt16 SystemToBE(SInt16 v) { return v; } - inline UInt32 SystemToBE(UInt32 v) { return v; } - inline SInt32 SystemToBE(SInt32 v) { return v; } - inline UInt64 SystemToBE(UInt64 v) { return v; } - inline SInt64 SystemToBE(SInt64 v) { return v; } + inline uint8_t SystemToBE(uint8_t v) { return v; } + inline int8_t SystemToBE(int8_t v) { return v; } + inline uint16_t SystemToBE(uint16_t v) { return v; } + inline int16_t SystemToBE(int16_t v) { return v; } + inline uint32_t SystemToBE(uint32_t v) { return v; } + inline int32_t SystemToBE(int32_t v) { return v; } + inline uint64_t SystemToBE(uint64_t v) { return v; } + inline int64_t SystemToBE(int64_t v) { return v; } inline float SystemToBE(float v) { return v; } inline double SystemToBE(double v) { return v; } @@ -983,30 +985,30 @@ namespace ByteUtil { // Used primarily for hardware interfacing such as sensor reports, firmware, etc. // Reported data is all little-endian. -inline UInt16 DecodeUInt16(const UByte* buffer) +inline uint16_t DecodeUInt16(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const UInt16*)buffer ); + return ByteUtil::LEToSystem ( *(const uint16_t*)buffer ); } -inline SInt16 DecodeSInt16(const UByte* buffer) +inline int16_t DecodeSInt16(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const SInt16*)buffer ); + return ByteUtil::LEToSystem ( *(const int16_t*)buffer ); } -inline UInt32 DecodeUInt32(const UByte* buffer) +inline uint32_t DecodeUInt32(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const UInt32*)buffer ); + return ByteUtil::LEToSystem ( *(const uint32_t*)buffer ); } -inline SInt32 DecodeSInt32(const UByte* buffer) +inline int32_t DecodeSInt32(const uint8_t* buffer) { - return ByteUtil::LEToSystem ( *(const SInt32*)buffer ); + return ByteUtil::LEToSystem ( *(const int32_t*)buffer ); } -inline float DecodeFloat(const UByte* buffer) +inline float DecodeFloat(const uint8_t* buffer) { union { - UInt32 U; + uint32_t U; float F; }; @@ -1014,30 +1016,30 @@ inline float DecodeFloat(const UByte* buffer) return F; } -inline void EncodeUInt16(UByte* buffer, UInt16 val) +inline void EncodeUInt16(uint8_t* buffer, uint16_t val) { - *(UInt16*)buffer = ByteUtil::SystemToLE ( val ); + *(uint16_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeSInt16(UByte* buffer, SInt16 val) +inline void EncodeSInt16(uint8_t* buffer, int16_t val) { - *(SInt16*)buffer = ByteUtil::SystemToLE ( val ); + *(int16_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeUInt32(UByte* buffer, UInt32 val) +inline void EncodeUInt32(uint8_t* buffer, uint32_t val) { - *(UInt32*)buffer = ByteUtil::SystemToLE ( val ); + *(uint32_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeSInt32(UByte* buffer, SInt32 val) +inline void EncodeSInt32(uint8_t* buffer, int32_t val) { - *(SInt32*)buffer = ByteUtil::SystemToLE ( val ); + *(int32_t*)buffer = ByteUtil::SystemToLE ( val ); } -inline void EncodeFloat(UByte* buffer, float val) +inline void EncodeFloat(uint8_t* buffer, float val) { union { - UInt32 U; + uint32_t U; float F; }; @@ -1046,12 +1048,12 @@ inline void EncodeFloat(UByte* buffer, float val) } // Converts an 8-bit binary-coded decimal -inline SByte DecodeBCD(UByte byte) +inline int8_t DecodeBCD(uint8_t byte) { - UByte digit1 = (byte >> 4) & 0x0f; - UByte digit2 = byte & 0x0f; + uint8_t digit1 = (byte >> 4) & 0x0f; + uint8_t digit2 = byte & 0x0f; int decimal = digit1 * 10 + digit2; // maximum value = 99 - return (SByte)decimal; + return (int8_t)decimal; } diff --git a/LibOVR/Src/Kernel/OVR_Allocator.cpp b/LibOVR/Src/Kernel/OVR_Allocator.cpp index 0f82561..1dc3326 100644 --- a/LibOVR/Src/Kernel/OVR_Allocator.cpp +++ b/LibOVR/Src/Kernel/OVR_Allocator.cpp @@ -39,25 +39,25 @@ namespace OVR { Allocator* Allocator::pInstance = 0; // Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding. -void* Allocator::AllocAligned(UPInt size, UPInt align) +void* Allocator::AllocAligned(size_t size, size_t align) { OVR_ASSERT((align & (align-1)) == 0); - align = (align > sizeof(UPInt)) ? align : sizeof(UPInt); - UPInt p = (UPInt)Alloc(size+align); - UPInt aligned = 0; + align = (align > sizeof(size_t)) ? align : sizeof(size_t); + size_t p = (size_t)Alloc(size+align); + size_t aligned = 0; if (p) { - aligned = (UPInt(p) + align-1) & ~(align-1); + aligned = (size_t(p) + align-1) & ~(align-1); if (aligned == p) aligned += align; - *(((UPInt*)aligned)-1) = aligned-p; + *(((size_t*)aligned)-1) = aligned-p; } return (void*)aligned; } void Allocator::FreeAligned(void* p) { - UPInt src = UPInt(p) - *(((UPInt*)p)-1); + size_t src = size_t(p) - *(((size_t*)p)-1); Free((void*)src); } @@ -68,11 +68,11 @@ void Allocator::FreeAligned(void* p) // This allocator is created and used if no other allocator is installed. // Default allocator delegates to system malloc. -void* DefaultAllocator::Alloc(UPInt size) +void* DefaultAllocator::Alloc(size_t size) { return malloc(size); } -void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line) +void* DefaultAllocator::AllocDebug(size_t size, const char* file, unsigned line) { #if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC) return _malloc_dbg(size, _NORMAL_BLOCK, file, line); @@ -82,7 +82,7 @@ void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line) #endif } -void* DefaultAllocator::Realloc(void* p, UPInt newSize) +void* DefaultAllocator::Realloc(void* p, size_t newSize) { return realloc(p, newSize); } diff --git a/LibOVR/Src/Kernel/OVR_Allocator.h b/LibOVR/Src/Kernel/OVR_Allocator.h index b862557..dfeeac5 100644 --- a/LibOVR/Src/Kernel/OVR_Allocator.h +++ b/LibOVR/Src/Kernel/OVR_Allocator.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Allocator.h Content : Installable memory allocator Created : September 19, 2012 @@ -56,7 +56,7 @@ limitations under the License. # include <new> # else // Useful on MSVC - OVR_FORCE_INLINE void* operator new (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } + OVR_FORCE_INLINE void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } OVR_FORCE_INLINE void operator delete (void *, void *) { } # endif @@ -71,9 +71,9 @@ limitations under the License. // class member operator new. #define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \ - void* operator new(UPInt sz) \ + void* operator new(size_t sz) \ { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \ - void* operator new(UPInt sz, const char* file, int line) \ + void* operator new(size_t sz, const char* file, int line) \ { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \ void operator delete(void *p) \ { check_delete(class_name, p); OVR_FREE(p); } \ @@ -81,7 +81,7 @@ limitations under the License. { check_delete(class_name, p); OVR_FREE(p); } #define OVR_MEMORY_DEFINE_PLACEMENT_NEW \ - void* operator new (UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } \ + void* operator new (size_t n, void *ptr) { OVR_UNUSED(n); return ptr; } \ void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); } @@ -127,20 +127,20 @@ OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2) } template <class T> -OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count) +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) { Construct<T>(pdata); } } template <class T> -OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source) +OVR_FORCE_INLINE void ConstructArray(void *p, size_t count, const T& source) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) { Construct<T>(pdata, source); } @@ -154,9 +154,9 @@ OVR_FORCE_INLINE void Destruct(T *pobj) } template <class T> -OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count) +OVR_FORCE_INLINE void DestructArray(T *pobj, size_t count) { - for (UPInt i=0; i<count; ++i, ++pobj) + for (size_t i=0; i<count; ++i, ++pobj) pobj->~T(); } @@ -184,9 +184,9 @@ public: // Allocate memory of specified size with default alignment. // Alloc of size==0 will allocate a tiny block & return a valid pointer; // this makes it suitable for new operator. - virtual void* Alloc(UPInt size) = 0; + virtual void* Alloc(size_t size) = 0; // Same as Alloc, but provides an option of passing debug data. - virtual void* AllocDebug(UPInt size, const char* file, unsigned line) + virtual void* AllocDebug(size_t size, const char* file, unsigned line) { OVR_UNUSED2(file, line); return Alloc(size); } // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to @@ -195,7 +195,7 @@ public: // Realloc to decrease size will never fail. // Realloc of pointer == 0 is equivalent to Alloc // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free(). - virtual void* Realloc(void* p, UPInt newSize) = 0; + virtual void* Realloc(void* p, size_t newSize) = 0; // Frees memory allocated by Alloc/Realloc. // Free of null pointer is valid and will do nothing. @@ -207,7 +207,7 @@ public: // Allocate memory of specified alignment. // Memory allocated with AllocAligned MUST be freed with FreeAligned. // Default implementation will delegate to Alloc/Free after doing rounding. - virtual void* AllocAligned(UPInt size, UPInt align); + virtual void* AllocAligned(size_t size, size_t align); // Frees memory allocated with AllocAligned. virtual void FreeAligned(void* p); @@ -250,7 +250,7 @@ class Allocator_SingletonSupport : public Allocator { struct AllocContainer { - UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)]; + size_t Data[(sizeof(D) + sizeof(size_t)-1) / sizeof(size_t)]; bool Initialized; AllocContainer() : Initialized(0) { } }; @@ -295,9 +295,9 @@ protected: class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator> { public: - virtual void* Alloc(UPInt size); - virtual void* AllocDebug(UPInt size, const char* file, unsigned line); - virtual void* Realloc(void* p, UPInt newSize); + virtual void* Alloc(size_t size); + virtual void* AllocDebug(size_t size, const char* file, unsigned line); + virtual void* Realloc(void* p, size_t newSize); virtual void Free(void *p); }; diff --git a/LibOVR/Src/Kernel/OVR_Array.h b/LibOVR/Src/Kernel/OVR_Array.h index 7a715ba..6e0ad28 100644 --- a/LibOVR/Src/Kernel/OVR_Array.h +++ b/LibOVR/Src/Kernel/OVR_Array.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Array.h Content : Template implementation for Array Created : September 19, 2012 @@ -44,14 +44,14 @@ struct ArrayDefaultPolicy ArrayDefaultPolicy() : Capacity(0) {} ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {} - UPInt GetMinCapacity() const { return 0; } - UPInt GetGranularity() const { return 4; } + size_t GetMinCapacity() const { return 0; } + size_t GetGranularity() const { return 4; } bool NeverShrinking() const { return 0; } - UPInt GetCapacity() const { return Capacity; } - void SetCapacity(UPInt capacity) { Capacity = capacity; } + size_t GetCapacity() const { return Capacity; } + void SetCapacity(size_t capacity) { Capacity = capacity; } private: - UPInt Capacity; + size_t Capacity; }; @@ -68,14 +68,14 @@ struct ArrayConstPolicy ArrayConstPolicy() : Capacity(0) {} ArrayConstPolicy(const SelfType&) : Capacity(0) {} - UPInt GetMinCapacity() const { return MinCapacity; } - UPInt GetGranularity() const { return Granularity; } + size_t GetMinCapacity() const { return MinCapacity; } + size_t GetGranularity() const { return Granularity; } bool NeverShrinking() const { return NeverShrink; } - UPInt GetCapacity() const { return Capacity; } - void SetCapacity(UPInt capacity) { Capacity = capacity; } + size_t GetCapacity() const { return Capacity; } + void SetCapacity(size_t capacity) { Capacity = capacity; } private: - UPInt Capacity; + size_t Capacity; }; //----------------------------------------------------------------------------------- @@ -103,7 +103,7 @@ struct ArrayDataBase Allocator::Free(Data); } - UPInt GetCapacity() const + size_t GetCapacity() const { return Policy.GetCapacity(); } @@ -117,7 +117,7 @@ struct ArrayDataBase Policy.SetCapacity(0); } - void Reserve(UPInt newCapacity) + void Reserve(size_t newCapacity) { if (Policy.NeverShrinking() && newCapacity < GetCapacity()) return; @@ -137,7 +137,7 @@ struct ArrayDataBase } else { - UPInt gran = Policy.GetGranularity(); + size_t gran = Policy.GetGranularity(); newCapacity = (newCapacity + gran - 1) / gran * gran; if (Data) { @@ -148,7 +148,7 @@ struct ArrayDataBase else { T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity); - UPInt i, s; + size_t i, s; s = (Size < newCapacity) ? Size : newCapacity; for (i = 0; i < s; ++i) { @@ -176,9 +176,9 @@ struct ArrayDataBase // This version of Resize DOES NOT construct the elements. // It's done to optimize PushBack, which uses a copy constructor // instead of the default constructor and assignment - void ResizeNoConstruct(UPInt newSize) + void ResizeNoConstruct(size_t newSize) { - UPInt oldSize = Size; + size_t oldSize = Size; if (newSize < oldSize) { @@ -199,7 +199,7 @@ struct ArrayDataBase } ValueType* Data; - UPInt Size; + size_t Size; SizePolicy Policy; }; @@ -222,16 +222,16 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> ArrayData() : BaseType() { } - ArrayData(UPInt size) + ArrayData(size_t size) : BaseType() { Resize(size); } ArrayData(const SelfType& a) : BaseType(a.Policy) { Append(a.Data, a.Size); } - void Resize(UPInt newSize) + void Resize(size_t newSize) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(newSize); if(newSize > oldSize) Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize); @@ -251,11 +251,11 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { if (count) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(this->Size + count); Allocator::ConstructArray(this->Data + oldSize, count, other); } @@ -281,16 +281,16 @@ struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> ArrayDataCC(const ValueType& defval) : BaseType(), DefaultValue(defval) { } - ArrayDataCC(const ValueType& defval, UPInt size) + ArrayDataCC(const ValueType& defval, size_t size) : BaseType(), DefaultValue(defval) { Resize(size); } ArrayDataCC(const SelfType& a) : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); } - void Resize(UPInt newSize) + void Resize(size_t newSize) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(newSize); if(newSize > oldSize) Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue); @@ -310,11 +310,11 @@ struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { if (count) { - UPInt oldSize = this->Size; + size_t oldSize = this->Size; BaseType::ResizeNoConstruct(this->Size + count); Allocator::ConstructArray(this->Data + oldSize, count, other); } @@ -359,61 +359,62 @@ public: ArrayBase() : Data() {} - ArrayBase(UPInt size) + ArrayBase(size_t size) : Data(size) {} ArrayBase(const SelfType& a) : Data(a.Data) {} ArrayBase(const ValueType& defval) : Data(defval) {} - ArrayBase(const ValueType& defval, UPInt size) + ArrayBase(const ValueType& defval, size_t size) : Data(defval, size) {} SizePolicyType* GetSizePolicy() const { return Data.Policy; } void SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; } bool NeverShrinking()const { return Data.Policy.NeverShrinking(); } - UPInt GetSize() const { return Data.Size; } - bool IsEmpty() const { return Data.Size == 0; } - UPInt GetCapacity() const { return Data.GetCapacity(); } - UPInt GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } + size_t GetSize() const { return Data.Size; } + int GetSizeI() const { return (int)Data.Size; } + bool IsEmpty() const { return Data.Size == 0; } + size_t GetCapacity() const { return Data.GetCapacity(); } + size_t GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } void ClearAndRelease() { Data.ClearAndRelease(); } void Clear() { Data.Resize(0); } - void Resize(UPInt newSize) { Data.Resize(newSize); } + void Resize(size_t newSize) { Data.Resize(newSize); } // Reserve can only increase the capacity - void Reserve(UPInt newCapacity) + void Reserve(size_t newCapacity) { if (newCapacity > Data.GetCapacity()) Data.Reserve(newCapacity); } // Basic access. - ValueType& At(UPInt index) + ValueType& At(size_t index) { OVR_ASSERT(index < Data.Size); return Data.Data[index]; } - const ValueType& At(UPInt index) const + const ValueType& At(size_t index) const { OVR_ASSERT(index < Data.Size); return Data.Data[index]; } - ValueType ValueAt(UPInt index) const + ValueType ValueAt(size_t index) const { OVR_ASSERT(index < Data.Size); return Data.Data[index]; } // Basic access. - ValueType& operator [] (UPInt index) + ValueType& operator [] (size_t index) { OVR_ASSERT(index < Data.Size); return Data.Data[index]; } - const ValueType& operator [] (UPInt index) const + const ValueType& operator [] (size_t index) const { OVR_ASSERT(index < Data.Size); return Data.Data[index]; @@ -440,7 +441,7 @@ public: } // Remove the last element. - void PopBack(UPInt count = 1) + void PopBack(size_t count = 1) { OVR_ASSERT(Data.Size >= count); Data.Resize(Data.Size - count); @@ -472,14 +473,14 @@ public: const SelfType& operator = (const SelfType& a) { Resize(a.GetSize()); - for (UPInt i = 0; i < Data.Size; i++) { + for (size_t i = 0; i < Data.Size; i++) { *(Data.Data + i) = a[i]; } return *this; } // Removing multiple elements from the array. - void RemoveMultipleAt(UPInt index, UPInt num) + void RemoveMultipleAt(size_t index, size_t num) { OVR_ASSERT(index + num <= Data.Size); if (Data.Size == num) @@ -502,7 +503,7 @@ public: // If order of elements in the array is not important then use // RemoveAtUnordered, that could be much faster than the regular // RemoveAt. - void RemoveAt(UPInt index) + void RemoveAt(size_t index) { OVR_ASSERT(index < Data.Size); if (Data.Size == 1) @@ -523,7 +524,7 @@ public: // Removes an element from the array without respecting of original order of // elements for better performance. Do not use on array where order of elements // is important, otherwise use it instead of regular RemoveAt(). - void RemoveAtUnordered(UPInt index) + void RemoveAtUnordered(size_t index) { OVR_ASSERT(index < Data.Size); if (Data.Size == 1) @@ -535,7 +536,7 @@ public: // copy the last element into the 'index' position // and decrement the size (instead of moving all elements // in [index + 1 .. size - 1] range). - const UPInt lastElemIndex = Data.Size - 1; + const size_t lastElemIndex = Data.Size - 1; if (index < lastElemIndex) { AllocatorType::Destruct(Data.Data + index); @@ -547,7 +548,7 @@ public: } // Insert the given object at the given index shifting all the elements up. - void InsertAt(UPInt index, const ValueType& val = ValueType()) + void InsertAt(size_t index, const ValueType& val = ValueType()) { OVR_ASSERT(index <= Data.Size); @@ -563,7 +564,7 @@ public: } // Insert the given object at the given index shifting all the elements up. - void InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType()) + void InsertMultipleAt(size_t index, size_t num, const ValueType& val = ValueType()) { OVR_ASSERT(index <= Data.Size); @@ -575,7 +576,7 @@ public: Data.Data + index, Data.Size - num - index); } - for (UPInt i = 0; i < num; ++i) + for (size_t i = 0; i < num; ++i) AllocatorType::Construct(Data.Data + index + i, val); } @@ -586,7 +587,7 @@ public: } // Append the given data to the array. - void Append(const ValueType other[], UPInt count) + void Append(const ValueType other[], size_t count) { Data.Append(other, count); } @@ -594,11 +595,11 @@ public: class Iterator { SelfType* pArray; - SPInt CurIndex; + intptr_t CurIndex; public: Iterator() : pArray(0), CurIndex(-1) {} - Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} + Iterator(SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {} bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } @@ -607,7 +608,7 @@ public: { if (pArray) { - if (CurIndex < (SPInt)pArray->GetSize()) + if (CurIndex < (intptr_t)pArray->GetSize()) ++CurIndex; } return *this; @@ -641,7 +642,7 @@ public: { return Iterator(pArray, CurIndex - delta); } - SPInt operator-(const Iterator& right) const + intptr_t operator-(const Iterator& right) const { OVR_ASSERT(pArray == right.pArray); return CurIndex - right.CurIndex; @@ -658,21 +659,21 @@ public: pArray->RemoveAt(CurIndex); } - SPInt GetIndex() const { return CurIndex; } + intptr_t GetIndex() const { return CurIndex; } }; Iterator Begin() { return Iterator(this); } - Iterator End() { return Iterator(this, (SPInt)GetSize()); } - Iterator Last() { return Iterator(this, (SPInt)GetSize() - 1); } + Iterator End() { return Iterator(this, (intptr_t)GetSize()); } + Iterator Last() { return Iterator(this, (intptr_t)GetSize() - 1); } class ConstIterator { const SelfType* pArray; - SPInt CurIndex; + intptr_t CurIndex; public: ConstIterator() : pArray(0), CurIndex(-1) {} - ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} + ConstIterator(const SelfType* parr, intptr_t idx = 0) : pArray(parr), CurIndex(idx) {} bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } @@ -715,7 +716,7 @@ public: { return ConstIterator(pArray, CurIndex - delta); } - SPInt operator-(const ConstIterator& right) const + intptr_t operator-(const ConstIterator& right) const { OVR_ASSERT(pArray == right.pArray); return CurIndex - right.CurIndex; @@ -726,11 +727,11 @@ public: bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } - SPInt GetIndex() const { return CurIndex; } + intptr_t GetIndex() const { return CurIndex; } }; ConstIterator Begin() const { return ConstIterator(this); } - ConstIterator End() const { return ConstIterator(this, (SPInt)GetSize()); } - ConstIterator Last() const { return ConstIterator(this, (SPInt)GetSize() - 1); } + ConstIterator End() const { return ConstIterator(this, (intptr_t)GetSize()); } + ConstIterator Last() const { return ConstIterator(this, (intptr_t)GetSize() - 1); } protected: ArrayData Data; @@ -754,7 +755,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType; Array() : BaseType() {} - Array(UPInt size) : BaseType(size) {} + Array(size_t size) : BaseType(size) {} Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } Array(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -776,7 +777,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType; ArrayPOD() : BaseType() {} - ArrayPOD(UPInt size) : BaseType(size) {} + ArrayPOD(size_t size) : BaseType(size) {} ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } ArrayPOD(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -798,7 +799,7 @@ public: typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType; ArrayCPP() : BaseType() {} - ArrayCPP(UPInt size) : BaseType(size) {} + ArrayCPP(size_t size) : BaseType(size) {} ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } ArrayCPP(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } @@ -822,7 +823,7 @@ public: typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > BaseType; ArrayCC(const ValueType& defval) : BaseType(defval) {} - ArrayCC(const ValueType& defval, UPInt size) : BaseType(defval, size) {} + ArrayCC(const ValueType& defval, size_t size) : BaseType(defval, size) {} ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); } ArrayCC(const SelfType& a) : BaseType(a) {} const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } diff --git a/LibOVR/Src/Kernel/OVR_Atomic.h b/LibOVR/Src/Kernel/OVR_Atomic.h index b826251..6ef862d 100644 --- a/LibOVR/Src/Kernel/OVR_Atomic.h +++ b/LibOVR/Src/Kernel/OVR_Atomic.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Atomic.h Content : Contains atomic operations and inline fastest locking functionality. Will contain #ifdefs for OS efficiency. @@ -26,6 +26,7 @@ See the License for the specific language governing permissions and limitations under the License. ************************************************************************************/ + #ifndef OVR_Atomic_h #define OVR_Atomic_h @@ -33,7 +34,10 @@ limitations under the License. // Include System thread functionality. #if defined(OVR_OS_WIN32) -#include <windows.h> +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <Windows.h> #else #include <pthread.h> #endif @@ -50,7 +54,7 @@ template<class C> class AtomicOps; template<class T> class AtomicInt; template<class T> class AtomicPtr; -class Lock; +class Lock; //----------------------------------------------------------------------------------- @@ -130,11 +134,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase #if !defined(OVR_ENABLE_THREADS) // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. - typedef UInt32 T; + typedef uint32_t T; // *** Thread - Safe Atomic Versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) // Use special defined for VC6, where volatile is not used and // InterlockedCompareExchange is declared incorrectly. @@ -153,10 +157,10 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; } #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) - typedef UInt32 T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + typedef uint32_t T; + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -167,9 +171,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 dummy, ret; + uint32_t dummy, ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -181,9 +185,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "lwarx %[r],0,%[i]\n\t" @@ -199,11 +203,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_MIPS) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "ll %[r],0(%[i])\n\t" @@ -215,9 +219,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret; + uint32_t ret; asm volatile("1:\n\t" "ll %[r],0(%[i])\n\t" @@ -230,9 +234,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret, dummy; + uint32_t ret, dummy; asm volatile("1:\n\t" "move %[r],$0\n\t" @@ -250,9 +254,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { for(;;) { @@ -261,7 +265,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return r; } } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { for(;;) { @@ -271,7 +275,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { for(;;) { @@ -284,11 +288,11 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_ARM) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret, dummy; + uint32_t ret, dummy; asm volatile("1:\n\t" "ldrex %[r],[%[i]]\n\t" @@ -300,9 +304,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { - UInt32 ret, dummy, test; + uint32_t ret, dummy, test; asm volatile("1:\n\t" "ldrex %[r],[%[i]]\n\t" @@ -315,9 +319,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret = 1, dummy, test; + uint32_t ret = 1, dummy, test; asm volatile("1:\n\t" "ldrex %[o],[%[i]]\n\t" @@ -334,9 +338,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase } #elif defined(OVR_CPU_X86) - typedef UInt32 T; + typedef uint32_t T; - static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t Exchange_NoSync(volatile uint32_t *i, uint32_t j) { asm volatile("xchgl %1,%[i]\n" : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory"); @@ -344,7 +348,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return j; } - static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) + static inline uint32_t ExchangeAdd_NoSync(volatile uint32_t *i, uint32_t j) { asm volatile("lock; xaddl %1,%[i]\n" : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory"); @@ -352,9 +356,9 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase return j; } - static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) + static inline bool CompareAndSet_NoSync(volatile uint32_t *i, uint32_t c, uint32_t value) { - UInt32 ret; + uint32_t ret; asm volatile("lock; cmpxchgl %[v],%[i]\n" : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory"); @@ -364,7 +368,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) - typedef UInt32 T; + typedef uint32_t T; static inline T Exchange_NoSync(volatile T *i, T j) { @@ -396,10 +400,10 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS) // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. - typedef UInt64 T; + typedef uint64_t T; // *** Thread - Safe OS specific versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) // This is only for 64-bit systems. typedef LONG64 T; @@ -410,11 +414,11 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CPU_PPC64) - typedef UInt64 T; + typedef uint64_t T; - static inline UInt64 Exchange_NoSync(volatile UInt64 *i, UInt64 j) + static inline uint64_t Exchange_NoSync(volatile uint64_t *i, uint64_t j) { - UInt64 dummy, ret; + uint64_t dummy, ret; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -426,9 +430,9 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase return ret; } - static inline UInt64 ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j) + static inline uint64_t ExchangeAdd_NoSync(volatile uint64_t *i, uint64_t j) { - UInt64 dummy, ret; + uint64_t dummy, ret; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -440,9 +444,9 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase return ret; } - static inline bool CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value) + static inline bool CompareAndSet_NoSync(volatile uint64_t *i, uint64_t c, uint64_t value) { - UInt64 ret, dummy; + uint64_t ret, dummy; asm volatile("1:\n\t" "ldarx %[r],0,%[i]\n\t" @@ -459,7 +463,7 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) - typedef UInt64 T; + typedef uint64_t T; static inline T Exchange_NoSync(volatile T *i, T j) { @@ -787,7 +791,6 @@ public: }; - //----------------------------------------------------------------------------------- // ***** Lock @@ -816,7 +819,7 @@ public: inline void Unlock() { } // Windows. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) CRITICAL_SECTION cs; public: @@ -881,7 +884,7 @@ private: // UseCount and max alignment. volatile int UseCount; - UInt64 Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)]; + uint64_t Buffer[(sizeof(Lock)+sizeof(uint64_t)-1)/sizeof(uint64_t)]; }; diff --git a/LibOVR/Src/Kernel/OVR_CRC32.cpp b/LibOVR/Src/Kernel/OVR_CRC32.cpp new file mode 100644 index 0000000..07d0dc3 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_CRC32.cpp @@ -0,0 +1,85 @@ +/************************************************************************************ + +Filename : OVR_CRC32.cpp +Content : CRC-32 with polynomial used for sensor devices +Created : June 20, 2014 +Author : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "OVR_CRC32.h" + +namespace OVR { + + +static const uint32_t CRC_Table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + + +//// CRC-32 + +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t accumulator) +{ + const uint8_t* inputBytes = reinterpret_cast<const uint8_t*>( data ); + + for (int j = 0; j < bytes; ++j) + { + int i = ((uint32_t)(accumulator >> 24) ^ *inputBytes++) & 0xFF; + + accumulator = (accumulator << 8) ^ CRC_Table[i]; + } + + return ~accumulator; +} + + +} // OVR diff --git a/LibOVR/Src/Kernel/OVR_CRC32.h b/LibOVR/Src/Kernel/OVR_CRC32.h new file mode 100644 index 0000000..4fd31a5 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_CRC32.h @@ -0,0 +1,45 @@ +/************************************************************************************ + +PublicHeader: OVR +Filename : OVR_CRC32.h +Content : CRC-32 with polynomial used for sensor devices +Created : June 20, 2014 +Author : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_CRC32_h +#define OVR_CRC32_h + +#include "OVR_Types.h" + +namespace OVR { + + +//----------------------------------------------------------------------------------- +// ***** CRC-32 + +// Polynomial used and algorithm details are proprietary to our sensor board +uint32_t CRC32_Calculate(const void* data, int bytes, uint32_t prevCRC = 0); + + +} // namespace OVR + +#endif diff --git a/LibOVR/Src/Kernel/OVR_Color.h b/LibOVR/Src/Kernel/OVR_Color.h index cf536da..618a0b2 100644 --- a/LibOVR/Src/Kernel/OVR_Color.h +++ b/LibOVR/Src/Kernel/OVR_Color.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Color.h Content : Contains color struct. Created : February 7, 2013 @@ -31,9 +31,10 @@ limitations under the License. namespace OVR { + struct Color { - UByte R,G,B,A; + uint8_t R,G,B,A; Color() {} @@ -61,6 +62,7 @@ struct Color } }; -} + +} // namespace OVR #endif diff --git a/LibOVR/Src/Kernel/OVR_Compiler.h b/LibOVR/Src/Kernel/OVR_Compiler.h new file mode 100644 index 0000000..dba5b19 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Compiler.h @@ -0,0 +1,1523 @@ +/************************************************************************************ + +PublicHeader: OVR.h +Filename : OVR_Compiler.h +Content : Compiler-specific feature identification and utilities +Created : June 19, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + + +#ifndef OVR_Compiler_h +#define OVR_Compiler_h + +#pragma once + + +// References +// https://gcc.gnu.org/projects/cxx0x.html +// https://gcc.gnu.org/projects/cxx1y.html +// http://clang.llvm.org/cxx_status.html +// http://msdn.microsoft.com/en-us/library/hh567368.aspx +// https://docs.google.com/spreadsheet/pub?key=0AoBblDsbooe4dHZuVTRoSTFBejk5eFBfVk1GWlE5UlE&output=html +// http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros + + +//----------------------------------------------------------------------------------- +// ***** Compiler +// +// The following compilers are defined: (OVR_CC_x) +// +// MSVC - Microsoft Visual C/C++ +// INTEL - Intel C++ for Linux / Windows +// GNU - GNU C++ +// ARM - ARM C/C++ + +#if defined(__INTEL_COMPILER) +// Intel 4.0 = 400 +// Intel 5.0 = 500 +// Intel 6.0 = 600 +// Intel 8.0 = 800 +// Intel 9.0 = 900 +# define OVR_CC_INTEL __INTEL_COMPILER + +#elif defined(_MSC_VER) +// MSVC 5.0 = 1100 +// MSVC 6.0 = 1200 +// MSVC 7.0 (VC2002) = 1300 +// MSVC 7.1 (VC2003) = 1310 +// MSVC 8.0 (VC2005) = 1400 +// MSVC 9.0 (VC2008) = 1500 +// MSVC 10.0 (VC2010) = 1600 +// MSVC 11.0 (VC2012) = 1700 +// MSVC 12.0 (VC2013) = 1800 +# define OVR_CC_MSVC _MSC_VER + +#if _MSC_VER == 0x1600 +# if _MSC_FULL_VER < 160040219 +# error "Oculus does not support VS2010 without SP1 installed." +# endif +#endif + +#elif defined(__GNUC__) +# define OVR_CC_GNU + +#elif defined(__clang__) +# define OVR_CC_CLANG + +#elif defined(__CC_ARM) +# define OVR_CC_ARM + +#else +# error "Oculus does not support this Compiler" +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_VERSION +// +// M = major version +// m = minor version +// p = patch release +// b = build number +// +// Compiler Format Example +// ---------------------------- +// OVR_CC_GNU Mmm 408 means GCC 4.8 +// OVR_CC_CLANG Mmm 305 means clang 3.5 +// OVR_CC_MSVC MMMM 1700 means VS2012 +// OVR_CC_ARM Mmpbbb 401677 means 4.0, patch 1, build 677 +// OVR_CC_INTEL MMmm 1210 means 12.10 +// OVR_CC_EDG Mmm 407 means EDG 4.7 +// +#if defined(OVR_CC_GNU) + #define OVR_CC_VERSION ((__GNUC__ * 100) + __GNUC_MINOR__) +#elif defined(OVR_CC_CLANG) + #define OVR_CC_VERSION ((__clang_major__ * 100) + __clang_minor__) +#elif defined(OVR_CC_MSVC) + #define OVR_CC_VERSION _MSC_VER // Question: Should we recognize _MSC_FULL_VER? +#elif defined(OVR_CC_ARM) + #define OVR_CC_VERSION __ARMCC_VERSION +#elif defined(OVR_CC_INTEL) + #if defined(__INTEL_COMPILER) + #define OVR_CC_VERSION __INTEL_COMPILER + #elif defined(__ICL) + #define OVR_CC_VERSION __ICL + #elif defined(__ICC) + #define OVR_CC_VERSION __ICC + #elif defined(__ECC) + #define OVR_CC_VERSION __ECC + #endif +#elif defined(OVR_CC_EDG) + #define OVR_CC_VERSION __EDG_VERSION__ // This is a generic fallback for EDG-based compilers which aren't specified above (e.g. as OVR_CC_ARM) +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_OPTIMIZATION / OVR_RESTORE_OPTIMIZATION +// +// Allows for the dynamic disabling and restoring of compiler optimizations in code. +// This is useful for helping deal with potential compiler code generation problems. +// With VC++ the usage must be outside of function bodies. This can be used only to +// temporarily disable optimization for a block of code and not to temporarily enable +// optimization for a block of code. +// +// Clang doesn't support this as of June 2014, though function __attribute__((optimize(0)) +// is supposedly supported by clang in addition to GCC. To consider: Make a wrapper for +// this attribute-based functionality. +// +// Example usage: +// OVR_DISABLE_OPTIMIZATION() +// void Test() { ... } +// OVR_RESTORE_OPTIMIZATION() +// +#if !defined(OVR_DISABLE_OPTIMIZATION) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)) + #define OVR_DISABLE_OPTIMIZATION() \ + _Pragma("GCC push_options") \ + _Pragma("GCC optimize 0") + #elif defined(OVR_CC_MSVC) + #define OVR_DISABLE_OPTIMIZATION() __pragma(optimize("", off)) + #else + #define OVR_DISABLE_OPTIMIZATION() + #endif +#endif + +#if !defined(OVR_RESTORE_OPTIMIZATION) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION > 404) && (defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)) + #define OVR_RESTORE_OPTIMIZATION() _Pragma("GCC pop_options") + #elif defined(OVR_CC_MSVC) + #define OVR_RESTORE_OPTIMIZATION() __pragma(optimize("", on)) + #else + #define OVR_RESTORE_OPTIMIZATION() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_GNU_WARNING / OVR_RESTORE_GNU_WARNING +// +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example +// usage for usage by example. +// +// Example usage: +// OVR_DISABLE_GNU_WARNING(-Wmissing-braces) // Only one warning per usage. +// OVR_DISABLE_GNU_WARNING(-Wunused-variable) +// <code> +// OVR_RESTORE_GNU_WARNINGS() +// OVR_RESTORE_GNU_WARNINGS() // Must match each disable with a restore. +// +#if !defined(OVR_DISABLE_GNU_WARNING) + #if defined(OVR_CC_GNU) + #define ODGW1(x) #x + #define ODGW2(x) ODGW1(GCC diagnostic ignored x) + #define ODGW3(x) ODGW2(#x) + #endif + + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 406) + #define OVR_DISABLE_GNU_WARNING(w) \ + _Pragma("GCC diagnostic push") \ + _Pragma(ODGW3(w)) + #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 404) // GCC 4.4 doesn't support diagnostic push, but supports disabling warnings. + #define OVR_DISABLE_GNU_WARNING(w) \ + _Pragma(ODGW3(w)) + #else + #define OVR_DISABLE_GNU_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_GNU_WARNING) + #if defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 4006) + #define OVR_RESTORE_GNU_WARNINGS() \ + _Pragma("GCC diagnostic pop") + #else + #define OVR_RESTORE_GNU_WARNING() + #endif +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_CLANG_WARNING / OVR_RESTORE_CLANG_WARNING +// +// Portable wrapper for disabling GCC compiler warnings, one at a time. See example +// usage for usage by example. +// +// Example usage: +// OVR_DISABLE_CLANG_WARNING(-Wmissing-braces) // Only one warning per usage. +// OVR_DISABLE_CLANG_WARNING(-Wunused-variable) +// <code> +// OVR_RESTORE_CLANG_WARNINGS() +// OVR_RESTORE_CLANG_WARNINGS() // Must match each disable with a restore. +// +// +#if !defined(OVR_DISABLE_CLANG_WARNING) + #if defined(OVR_CC_CLANG) + #define ODCW1(x) #x + #define ODCW2(x) ODCW1(clang diagnostic ignored x) + #define ODCW3(x) ODCW2(#x) + + #define OVR_DISABLE_CLANG_WARNING(w) \ + _Pragma("clang diagnostic push") \ + _Pragma(ODCW3(w)) + #else + #define OVR_DISABLE_CLANG_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_CLANG_WARNING) + #if defined(OVR_CC_CLANG) + #define OVR_RESTORE_CLANG_WARNING() \ + _Pragma("clang diagnostic pop") + #else + #define OVR_RESTORE_CLANG_WARNING() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_MSVC_WARNING / OVR_RESTORE_MSVC_WARNING +// +// Portable wrapper for disabling VC++ compiler warnings. See example usage for usage +// by example. +// +// Example usage: +// OVR_DISABLE_MSVC_WARNING(4556 4782 4422) +// <code> +// OVR_RESTORE_MSVC_WARNING() +// +#if !defined(OVR_DISABLE_MSVC_WARNING) + #if defined(OVR_CC_MSVC) + #define OVR_DISABLE_MSVC_WARNING(w) \ + __pragma(warning(push)) \ + __pragma(warning(disable:w)) + #else + #define OVR_DISABLE_MSVC_WARNING(w) + #endif +#endif + +#if !defined(OVR_RESTORE_MSVC_WARNING) + #if defined(OVR_CC_MSVC) + #define OVR_RESTORE_MSVC_WARNING() \ + __pragma(warning(pop)) + #else + #define OVR_RESTORE_MSVC_WARNING() + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_DISABLE_ALL_MSVC_WARNINGS / OVR_RESTORE_ALL_MSVC_WARNINGS +// +// Portable wrapper for disabling all VC++ compiler warnings. +// OVR_RESTORE_ALL_MSVC_WARNINGS restores warnings that were disabled by +// OVR_DISABLE_ALL_MSVC_WARNINGS. Any previously enabled warnings will still be +// enabled after OVR_RESTORE_ALL_MSVC_WARNINGS. +// +// Example usage: +// OVR_DISABLE_ALL_MSVC_WARNINGS() +// <code> +// OVR_RESTORE_ALL_MSVC_WARNINGS() + +#if !defined(OVR_DISABLE_ALL_MSVC_WARNINGS) + #if defined(OVR_CC_MSVC) + #define OVR_DISABLE_ALL_MSVC_WARNINGS() \ + __pragma(warning(push, 0)) + #else + #define OVR_DISABLE_ALL_MSVC_WARNINGS() + #endif +#endif + +#if !defined(OVR_RESTORE_ALL_MSVC_WARNINGS) + #if defined(OVR_CC_MSVC) + #define OVR_RESTORE_ALL_MSVC_WARNINGS() \ + __pragma(warning(pop)) + #else + #define OVR_RESTORE_ALL_MSVC_WARNINGS() + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_HAS_FEATURE +// +// This is a portable way to use compile-time feature identification available +// with some compilers in a clean way. Direct usage of __has_feature in preprocessing +// statements of non-supporting compilers results in a preprocessing error. +// +// Example usage: +// #if OVR_CC_HAS_FEATURE(is_pod) +// if(__is_pod(T)) // If the type is plain data then we can safely memcpy it. +// memcpy(&destObject, &srcObject, sizeof(object)); +// #endif +// +#if !defined(OVR_CC_HAS_FEATURE) + #if defined(__clang__) // http://clang.llvm.org/docs/LanguageExtensions.html#id2 + #define OVR_CC_HAS_FEATURE(x) __has_feature(x) + #else + #define OVR_CC_HAS_FEATURE(x) 0 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CC_HAS_BUILTIN +// +// +// This is a portable way to use compile-time builtin identification available +// with some compilers in a clean way. Direct usage of __has_builtin in preprocessing +// statements of non-supporting compilers results in a preprocessing error. +// +// Example usage: +// #if OVR_CC_HAS_BUILTIN(__builtin_trap) +// #define DEBUG_BREAK __builtin_trap +// #endif +// +#if !defined(OVR_CC_HAS_BUILTIN) + #if defined(__clang__) + #define OVR_CC_HAS_BUILTIN(x) __has_builtin(x) // http://clang.llvm.org/docs/LanguageExtensions.html#id2 + #else + #define OVR_CC_HAS_BUILTIN(x) 0 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP11_ENABLED / OVR_CPP_CPP14_ENABLED +// +// Defined as 1 if the compiler has its available C++11 support enabled, else undefined. +// This does not mean that all of C++11 or any particular feature of C++11 is supported +// by the compiler. It means that whatever C++11 support the compiler has is enabled. +// This also includes existing and older compilers that still identify C++11 as C++0x. +// +#if !defined(OVR_CPP11_ENABLED) && defined(__cplusplus) + #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) + #define OVR_CPP11_ENABLED 1 + #elif defined(_MSC_VER) && (_MSC_VER >= 1500) // VS2010+, the first version with any significant C++11 support. + #define OVR_CPP11_ENABLED 1 + #elif (__cplusplus >= 201103L) // 201103 is the first C++11 version. + #define OVR_CPP11_ENABLED 1 + #else + // Leave undefined + #endif +#endif + +#if !defined(OVR_CPP_CPP14_ENABLED) && defined(__cplusplus) + #if defined(_MSC_VER) && (_MSC_VER >= 1800) // VS2013+, the first version with any significant C++14 support. + #define OVR_CPP_CPP14_ENABLED 1 + #elif (__cplusplus > 201103L) + #define OVR_CPP_CPP14_ENABLED 1 + #else + // Leave undefined + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXCEPTIONS / OVR_CPP_NO_UNWIND +// +// OVR_CPP_NO_EXCEPTIONS is defined as 1 if the compiler doesn't support C++ +// exceptions or is configured to disable support for them. Else not defined. +// If OVR_CPP_NO_EXCEPTIONS is defined then attempts to use try/catch +// related C++ statements result in a compilation error with many +// compilers. +// +// OVR_CPP_NO_UNWIND is defined as 1 if the compiler supports exceptions but +// doesn't support stack unwinding in the presence of an exception. Else not defined. +// For the Microsoft compiler, disabling exceptions means disabling stack unwinding +// and not disabling exceptions themselves. +// +// Example usage: +// void Test() { +// #if !defined(OVR_CPP_NO_EXCEPTIONS) +// try { +// #endif +// void* ptr = new Object; +// #if !defined(OVR_CPP_NO_EXCEPTIONS) +// catch(...) { ... } +// #endif + +#if !defined(OVR_CPP_NO_EXCEPTIONS) + #if defined(OVR_CPP_GNUC) && defined(_NO_EX) + #define OVR_CPP_NO_EXCEPTIONS 1 + #elif (defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || defined(OVR_CC_INTEL) || defined(OVR_CC_ARM)) && !defined(__EXCEPTIONS) + #define OVR_CPP_NO_EXCEPTIONS 1 + #elif defined(OVR_CC_MSVC) && !defined(_CPPUNWIND) + #define OVR_CPP_NO_UNWIND 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RTTI +// +// Defined as 1 if C++ run-time type information support is unavailable or disabled +// by the compiler. Else undefined. Allows you to write portable code in the face +// of the possibility that RTTI is disabled. +// +// Example usage: +// #if !OVR_CPP_NO_RTTI +// #include <typeinfo> +// int x = std::dynamic_cast<int>(3.4f); +// #endif + +#if defined(__clang__) && !OVR_CC_HAS_FEATURE(cxx_rtti) + #define OVR_CPP_NO_RTTI 1 +#elif defined(__GNUC__) && !defined(__GXX_RTTI) + #define OVR_CPP_NO_RTTI 1 +#elif defined(_MSC_VER) && !defined(_CPPRTTI) + #define OVR_CPP_NO_RTTI 1 +#elif defined(__CC_ARM) && defined(__TARGET_CPU_MPCORE) && !defined(__RTTI) + #define OVR_CPP_NO_RTTI 1 +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STATIC_ASSERT +// +// Defined as 1 if C++ run-time type information support is available and enabled +// by the compiler. Else undefined. +// +// Example usage: +// #if OVR_CPP_NO_STATIC_ASSERT +// #define MY_ASSERT(x) { int zero = 0; switch(zero) {case 0: case (x):;} } +// #else +// #define MY_ASSERT(x) static_assert((x), #x) +// #endif + +#if !defined(OVR_CPP_NO_STATIC_ASSERT) + #if !(defined(__GNUC__) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)))) && \ + !(defined(__clang__) && defined(__cplusplus) && OVR_CC_HAS_FEATURE(cxx_static_assert)) && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)) && /* VS2010+ */ \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) && defined(OVR_CPP11_ENABLED)) /* EDG 4.1+ */ + #define OVR_CPP_NO_STATIC_ASSERT 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NULLPTR +// +// Defined as 1 if the compiler doesn't support C++11 nullptr built in type. +// Otherwise undefined. Does not identify if the standard library defines +// std::nullptr_t, as some standard libraries are further behind in standardization +// than the compilers using them (e.g. Apple clang with the supplied libstdc++). +// +// OVR_Nullptr.h provides a portable nullptr and std::nullptr_t for when the +// compiler or standard library do not. + +#if !defined(OVR_CPP_NO_NULLPTR) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_nullptr)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_NULLPTR 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RVALUE_REFERENCES +// +// Defined as 1 if the compiler doesn't support C++11 rvalue references and move semantics. +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_RVALUE_REFERENCES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_rvalue_references)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_RVALUE_REFERENCES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_AUTO +// +// Defined as 1 if the compiler doesn't support C++11 auto keyword. Otherwise undefined. + +#if !defined(OVR_CPP_NO_AUTO) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_auto_type)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 309))) /* EDG 3.9+ */ + #define OVR_CPP_NO_AUTO 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RANGE_BASED_FOR_LOOP +// +// Defined as 1 if the compiler doesn't support C++11 range-based for loops. +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_RANGE_BASED_FOR_LOOP) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_range_for)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_RANGE_BASED_FOR_LOOP 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_CONSTEXPR / OVR_CPP_NO_RELAXED_CONSTEXPR +// +// OVR_CPP_NO_CONSTEXPR is defined as 1 if the compiler doesn't support C++11 constexpr. +// OVR_CPP_NO_RELAXED_CONSTEXPR is defined as 1 if the compiler doesn't support C++14 constexpr. +// Otherwise undefined. +// See the OVR_CONSTEXPR / OVR_CONSTEXPR_OR_CONST macros for portable wrappers of this functionality. + +#if !defined(OVR_CPP_NO_CONSTEXPR) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_constexpr)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + // Not supported by VC++ through at least VS2013. + #define OVR_CPP_NO_CONSTEXPR 1 + #endif +#endif + +#if !defined(OVR_CPP_NO_RELAXED_CONSTEXPR) + #if !defined(OVR_CPP14_ENABLED) || \ + !(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_relaxed_constexpr)) /* clang */ + // Supported only by clang as of this writing. + #define OVR_CPP_NO_RELAXED_CONSTEXPR 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_LAMBDA_EXPRESSIONS +// +// Defined as 1 if the compiler doesn't support C++11 lambda expressions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_LAMBDA_EXPRESSIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_lambdas)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Conversion of lambdas to function pointers is not supported until EDG 4.5. + #define OVR_CPP_NO_LAMBDA_EXPRESSIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_ALIGNOF +// +// Defined as 1 if the compiler supports C++11 alignof. Otherwise undefined. +// Some compilers support __alignof__ instead of alignof, so for portability you +// should use OVR_ALIGNOF instead of directly using C++11 alignof. + +#if !defined(OVR_CPP_NO_ALIGNOF) + #if (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 300)) /* Apple clang 3.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 401)) /* GCC 4.1+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400))) /* EDG 4.0+ */ + #define OVR_CPP_NO_ALIGNOF 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_ALIGNAS +// +// Defined as 1 if the compiler supports C++11 alignas. Otherwise undefined. +// See the OVR_ALIGNAS for a portable wrapper for alignas functionality. + +#if !defined(OVR_CPP_NO_ALIGNAS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_ALIGNAS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_OVERRIDE +// +// Defined as 1 if the compiler doesn't support C++11 override. Otherwise undefined. +// See the OVR_OVERRIDE and OVR_FINALOVERRIDE macros for a portable wrapper. + +#if !defined(OOVR_CPP_NO_OVERRIDE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_OVERRIDE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FINAL +// +// Defined as 1 if the compiler doesn't support C++11 final attribute. Otherwise undefined. +// See the OVR_FINAL and OVR_FINALOVERRIDE macros for a portable wrapper. + +#if !defined(OOVR_CPP_NO_FINAL) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_FINAL 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTERN_TEMPLATE +// +// Defined as 1 if the compiler doesn't support C++11 extern template. +// Otherwise undefined. See OVR_EXTERN_TEMPLATE for wrapper macro. + +#if !defined(OVR_CPP_NO_EXTERN_TEMPLATE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_EXTERN_TEMPLATE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_VARIADIC_TEMPLATES +// +// Defined as 1 if the compiler doesn't support C++11 variadic templates. Otherwise undefined. + +#if !defined(OVR_CPP_NO_VARIADIC_TEMPLATES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_variadic_templates)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_VARIADIC_TEMPLATES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NOEXCEPT +// +// Defined as 1 if the compiler supports C++11 noexcept. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/noexcept +// See OVR_NOEXCEPT / OVR_NOEXCEPT_IF / OVR_NOEXCEPT_EXPR for a portable wrapper +// for noexcept functionality. + +#if !defined(OVR_CPP_NO_NOEXCEPT) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_noexcept)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_NOEXCEPT 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DECLTYPE +// +// Defined as 1 if the compiler doesn't support C++11 decltype. Otherwise undefined. +// Some compilers (e.g. VS2012) support most uses of decltype but don't support +// decltype with incomplete types (which is an uncommon usage seen usually in +// template metaprogramming). We don't include this support as a requirement for +// our definition of decltype support here. + +#if !defined(OVR_CPP_NO_DECLTYPE) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_decltype)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + // VC++ fails to support decltype for incomplete types until VS2013. + // EDG fails to support decltype for incomplete types until v4.8. + #define OVR_CPP_NO_DECLTYPE 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DEFAULTED_FUNCTIONS +// +// Defined as 1 if the compiler doesn't support C++11 defaulted functions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions))/* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators. + // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators. + #define OVR_CPP_NO_DEFAULTED_FUNCTIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DELETED_FUNCTIONS +// +// Defined as 1 if the compiler doesn't support C++11 deleted functions. Otherwise undefined. +// Some compilers have slightly crippled versions of this. + +#if !defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_defaulted_functions)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + // Up through at least VS2013 it's unsupported for defaulted move constructors and move assignment operators. + // Until EDG 4.8 it's unsupported for defaulted move constructors and move assigment operators. + #define OVR_CPP_NO_DELETED_FUNCTIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STANDARD_LAYOUT_TYPES +// +// Defined as 1 if the compiler doesn't support C++11 standard layout (relaxed POD). Otherwise undefined. +// http://en.cppreference.com/w/cpp/types/is_standard_layout + +#if !defined(OVR_CPP_NO_STANDARD_LAYOUT_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_STANDARD_LAYOUT_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FORWARD_DECLARED_ENUMS +// +// Defined as 1 if the compiler doesn't support C++11 forward declared enums. Otherwise undefined. + +#if !defined(OVR_CPP_NO_FORWARD_DECLARED_ENUMS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_FORWARD_DECLARED_ENUMS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_STRONGLY_TYPED_ENUMS +// +// Defined as 1 if the compiler doesn't support C++11 strongly typed enums. Otherwise undefined. + +#if !defined(OVR_CPP_NO_STRONGLY_TYPED_ENUMS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_strong_enums)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400))) /* EDG 4.0+ */ + #define OVR_CPP_NO_STRONGLY_TYPED_ENUMS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_TRAILING_RETURN_TYPES +// +// Defined as 1 if the compiler doesn't support C++11 trailing return types. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#Alternative_function_syntax + +#if !defined(OVR_CPP_NO_TRAILING_RETURN_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_trailing_return)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_TRAILING_RETURN_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_TEMPLATE_ALIASES +// +// Defined as 1 if the compiler doesn't support C++11 template aliases. Otherwise undefined. + +#if !defined(OVR_CPP_NO_TEMPLATE_ALIASES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_alias_templates)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + #define OVR_CPP_NO_TEMPLATE_ALIASES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INITIALIZER_LISTS +// +// Defined as 1 if the compiler doesn't support C++11 initializer lists. Otherwise undefined. +// This refers to the compiler support for this and not the Standard Library support for std::initializer_list, +// as a new compiler with an old standard library (e.g. Apple clang with libstdc++) may not support std::initializer_list. + +#if !defined(OVR_CPP_NO_INITIALIZER_LISTS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_INITIALIZER_LISTS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NORETURN +// +// Defined as 1 if the compiler doesn't support the C++11 noreturn attribute. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/attributes +// +#if !defined(OVR_CPP_NO_NORETURN) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1500)) /* VS2008+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + // Supported with VC++ only via __declspec(noreturn) (see OVR_NORETURN). + #define OVR_CPP_NO_NORETURN 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS +// +// Defined as 1 if the compiler doesn't support C++11 in-class non-static member initializers. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/data_members + +#if !defined(OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_NONSTATIC_MEMBER_INITIALIZERS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS +// +// Defined as 1 if the compiler supports nested template declarations with >>, +// as supported by C++11. Otherwise undefined. + +#if !defined(OVR_CPP_NO_DOUBLE_TEMPLATE_ANGLE_BRACKETS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_DOUBLE_TEMPLATE_BRACKETS 1 + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INHERITING_CONSTRUCTORS +// +// Defined as 1 if the compiler supports C++11 inheriting constructors. Otherwise undefined. +// Example usage: +// struct A { explicit A(int x){} }; +// struct B : public A { using A::A; }; // As if B redeclared A::A(int). + +#if !defined(OVR_CPP_NO_INHERITING_CONSTRUCTORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_inheriting_constructors)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_INHERITING_CONSTRUCTORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_DELEGATING_CONSTRUCTORS +// +// Defined as 1 if the compiler supports C++11 delegating constructors. Otherwise undefined. + +#if !defined(OVR_CPP_NO_DELEGATING_CONSTRUCTORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 300)) /* clang 3.0+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + #define OVR_CPP_NO_DELEGATING_CONSTRUCTORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS +// +// Defined as 1 if the compiler supports C++11 function template default arguments. Otherwise undefined. + +#if !defined(OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 403)) /* GCC 4.3+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) /* EDG 4.3+ */ + #define OVR_CPP_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNRESTRICTED_UNIONS +// +// Defined as 1 if the compiler supports C++11 unrestricted unions. Otherwise undefined. + +#if !defined(OVR_CPP_NO_UNRESTRICTED_UNIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 406)) /* GCC 4.6+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_UNRESTRICTED_UNIONS 1 + #endif +#endif + + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTENDED_SIZEOF +// +// Defined as 1 if the compiler supports C++11 class sizeof extensions (e.g. sizeof SomeClass::someMember). +// Otherwise undefined. + +#if !defined(OVR_CPP_NO_EXTENDED_SIZEOF) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1900)) /* VS2014+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + #define OVR_CPP_NO_EXTENDED_SIZEOF 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_INLINE_NAMESPACES +// +// Defined as 1 if the compiler supports C++11 inlined namespaces. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces + +#if !defined(OVR_CPP_NO_INLINE_NAMESPACES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405))) /* EDG 4.5+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_INLINE_NAMESPACES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS +// +// Defined as 1 if the compiler supports C++11 explicit conversion operators. Otherwise undefined. +// http://en.cppreference.com/w/cpp/language/explicit + +#if !defined(OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_explicit_conversions)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404))) /* EDG 4.4+ */ + #define OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS +// +// Defined as 1 if the compiler supports C++11 local class template parameters. Otherwise undefined. +// Example: +// void Test() { +// struct LocalClass{ }; +// SomeTemplateClass<LocalClass> t; // Allowed only in C++11 +// } + +#if !defined(OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_local_type_template_args)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402))) /* EDG 4.2+ */ + #define OVR_CPP_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_NEW_CHARACTER_TYPES +// +// Defined as 1 if the compiler natively supports C++11 char16_t and char32_t. Otherwise undefined. +// VC++ through at least VS2013 defines char16_t as unsigned short in its standard library, +// but it is not a native type or unique type, nor can you for a string literal with it. + +#if !defined(OVR_CPP_NO_NEW_CHARACTER_TYPES) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_NEW_CHARACTER_TYPES 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS +// +// Defined as 1 if the compiler supports C++11 \u and \U character literals for +// native char16_t and char32_t types. +// +#if !defined(OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + // Not supported by VC++ as of VS2013. VC++'s existing \U and \u are non-conforming. + #define OVR_CPP_NO_UNICODE_CHAR_NAME_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_USER_DEFINED_LITERALS +// +// Defined as 1 if the compiler supports C++11 user-defined literals. Otherwise undefined. + +#if !defined(OVR_CPP_NO_USER_DEFINED_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 301)) /* clang 3.1+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 401)) /* Apple clang 4.1+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_USER_DEFINED_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNICODE_STRING_LITERALS +// +// Defined as 1 if the compiler supports C++11 Unicode string literals. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + +#if !defined(OVR_CPP_NO_UNICODE_STRING_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_unicode_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_UNICODE_STRING_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_RAW_STRING_LITERALS +// +// Defined as 1 if the compiler supports C++11 raw literals. Otherwise undefined. +// http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + +#if !defined(OVR_CPP_NO_RAW_STRING_LITERALS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_raw_string_literals)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 405)) /* GCC 4.5+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407))) /* EDG 4.7+ */ + // Not supported by VC++ as of VS2013. + #define OVR_CPP_NO_RAW_STRING_LITERALS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX +// +// Defined as 1 if the compiler supports C++11 unified initialization. +// http://en.wikipedia.org/wiki/C%2B%2B11#Uniform_initialization + +#if !defined(OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_generalized_initializers)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 404)) /* GCC 4.4+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1800)) /* VS2013+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406))) /* EDG 4.6+ */ + #define OVR_CPP_NO_UNIFIED_INITIALIZATION_SYNTAX 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS +// +// Defined as 1 if the compiler supports C++11 extended friends. + +#if !defined(OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && !defined(__APPLE__) && (__clang__ >= 209)) /* clang 2.9+ */ && \ + !(defined(__clang__) && defined(__APPLE__) && (__clang__ >= 400)) /* Apple clang 4.0+ */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 407)) /* GCC 4.7+ */ && \ + !(defined(_MSC_VER) && (_MSC_VER >= 1600)) /* VS2010+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401))) /* EDG 4.1+ */ + #define OVR_CPP_NO_EXTENDED_FRIEND_DECLARATIONS 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_CPP_NO_THREAD_LOCAL +// +// Defined as 1 if the compiler supports C++11 thread_local. Else undefined. Does not +// indicate if the compiler supports C thread-local compiler extensions such as __thread +// and declspec(thread). Use OVR_THREAD_LOCAL if you want to declare a thread-local +// variable that supports C++11 thread_local when available but the C extension when +// it's available. The primary difference between C++11 thread_local and C extensions is +// that C++11 thread_local supports non-PODs and calls their constructors and destructors. +// +// Note that thread_local requires both compiler and linker support, and so it's possible +// that the compiler may support thread_local but the linker does not. + +#if !defined(OVR_CPP_NO_THREAD_LOCAL) + #if !defined(OVR_CPP11_ENABLED) || \ + (!(defined(__clang__) && OVR_CC_HAS_FEATURE(cxx_thread_local)) /* clang */ && \ + !(defined(__GNUC__) && (OVR_CPP_VERSION >= 408)) /* GCC 4.8+ */ && \ + !(defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 408))) /* EDG 4.8+ */ + #define OVR_CPP_NO_THREAD_LOCAL 1 + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_ALIGNAS / OVR_ALIGNOF +// +// OVR_ALIGNAS(n) // Specifies a size_t power of two alignment for a type or instance. +// OVR_ALIGNOF(type) // Returns the size_t alignment of a type or instance. +// +// Example usage: +// OVR_ALIGNAS(8) char c = 'c'; // Specifies that the instance c be aligned to an 8 byte boundary. +// typedef OVR_ALIGNAS(8) char C; // Specifies that the type C be aligned to an 8 byte boundary. +// struct OVR_ALIGNAS(64) S{ char array[16]; }; // Specfies that the struct S have a natural alignment of 64. +// OVR_ALIGNAS(32) S s; // Specifies that the instance s of struct S be aligned to an 32 byte boundary. +// OVR_ALIGNAS(32) struct T{ char array[16]; } t; // Specfies that the instance t of struct T have a natural alignment of 32. +// struct OVR_ALIGNAS(T) U{}; // Specifes that U be aligned the same as T. Supported only by C++11 compilers (see OVR_CPP_NO_ALIGNAS). +// +// size_t a = OVR_ALIGNOF(double); // Returns the natural alignment of the double type. +// size_t a = OVR_ALIGNOF(S); // Returns the natural alignment of the struct S type. +// +// Note: If C++11 alignas is supported, then alignas/OVR_ALIGNAS may take a const expression in addition to a constant. +// Note: The C11 Standard species the _Alignas keyword and alignas as a macro for it in <stdalign.h> + +#if !defined(OVR_ALIGNAS) + #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNAS) // If C++11 alignas is supported... + #define OVR_ALIGNAS(n) alignas(n) + #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNAS) + #define OVR_ALIGNAS(n) alignas(n) + #elif defined(OVR_CC_GNU) || defined(__clang__) + #define OVR_ALIGNAS(n) __attribute__((aligned(n))) + #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL) + #define OVR_ALIGNAS(n) __declspec(align(n)) // For Microsoft the alignment must be a literal integer. + #elif defined(OVR_CC_ARM) + #define OVR_ALIGNAS(n) __align(n) + #else + #error Need to define OVR_ALIGNAS + #endif +#endif + +#if !defined(OVR_ALIGNOF) + #if defined(OVR_CC_GNU) && !defined(OVR_CPP_NO_ALIGNOF) // If C++11 alignof is supported... + #define OVR_ALIGNOF(type) alignof(t) + #elif defined(__clang__) && !defined(OVR_CPP_NO_ALIGNOF) + #define OVR_ALIGNOF(type) alignof(t) + #elif defined(OVR_CC_GNU) || defined(__clang__) + #define OVR_ALIGNOF(type) ((size_t)__alignof__(type)) + #elif defined(OVR_CC_MSVC) || defined(OVR_CC_INTEL) + #define OVR_ALIGNOF(type) ((size_t)__alignof(type)) + #elif defined(OVR_CC_ARM) + #define OVR_ALIGNOF(type) ((size_t)__ALIGNOF__(type)) + #else + #error Need to define OVR_ALIGNOF + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_ASSUME / OVR_ANALYSIS_ASSUME +// +// This is a portable wrapper for VC++'s __assume and __analysis_assume. +// __analysis_assume is typically used to quell VC++ static analysis warnings. +// +// Example usage: +// void Test(char c){ +// switch(c){ +// case 'a': +// case 'b': +// case 'c': +// case 'd': +// break; +// default: +// OVR_ASSUME(0); // Unreachable code. +// } +// } +// +// size_t Test(char* str){ +// OVR_ANALYSIS_ASSUME(str != nullptr); +// return strlen(str); +// } + +#if !defined(OVR_ASSUME) + #if defined(OVR_CC_MSVC) + #define OVR_ASSUME(x) __assume(x) + #define OVR_ANALYSIS_ASSUME(x) __analysis_assume(!!(x)) + #else + #define OVR_ASSUME(x) + #define OVR_ANALYSIS_ASSUME(x) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_RESTRICT +// +// Wraps the C99 restrict keyword in a portable way. +// C++11 and C++14 don't have restrict but this functionality is supported by +// all C++ compilers. +// +// Example usage: +// void* memcpy(void* OVR_RESTRICT s1, const void* OVR_RESTRICT s2, size_t n); + +#if !defined(OVR_RESTRICT) + #define OVR_RESTRICT __restrict // Currently supported by all compilers of significance to us. +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_NOEXCEPT / OVR_NOEXCEPT_IF(predicate) / OVR_NOEXCEPT_EXPR(expression) +// +// Implements a portable wrapper for C++11 noexcept. +// http://en.cppreference.com/w/cpp/language/noexcept +// +// Example usage: +// void Test() OVR_NOEXCEPT {} // This function doesn't throw. +// +// template <typename T> +// void DoNothing() OVR_NOEXCEPT_IF(OVR_NOEXCEPT_EXPR(T())) // Throws an if and only if T::T(int) throws. +// { T t(3); } +// +#if !defined(OVR_NOEXCEPT) + #if defined(OVR_CPP_NOEXCEPT) + #define OVR_NOEXCEPT + #define OVR_NOEXCEPT_IF(predicate) + #define OVR_NOEXCEPT_EXPR(expression) false + #else + #define OVR_NOEXCEPT noexcept + #define OVR_NOEXCEPT_IF(predicate) noexcept((predicate)) + #define OVR_NOEXCEPT_EXPR(expression) noexcept((expression)) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FINAL +// +// Wraps the C++11 final keyword in a portable way. +// http://en.cppreference.com/w/cpp/language/final +// +// Example usage: +// struct Test { virtual int GetValue() OVR_FINAL; }; + +#if !defined(OVR_FINAL) + #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION < 1700) // VC++ 2012 and earlier + #define OVR_FINAL sealed + #elif defined(OVR_CPP_INHERITANCE_FINAL) + #define OVR_FINAL + #else + #define OVR_FINAL final + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_OVERRIDE +// +// Wraps the C++11 override keyword in a portable way. +// http://en.cppreference.com/w/cpp/language/override +// +// Example usage: +// struct Parent { virtual void Func(int); }; +// struct Child : public Parent { void Func(int) OVR_OVERRIDE; }; + +#if !defined(OVR_CPP11_ENABLED) +#define OVR_OVERRIDE +#elif !defined(OVR_OVERRIDE) + #if defined(OVR_CPP_OVERRIDE) + #define OVR_OVERRIDE + #else + #if (defined(_MSC_VER) && (_MSC_VER <= 1600)) + #pragma warning(disable : 4481) + #endif + #define OVR_OVERRIDE override + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FINAL_OVERRIDE +// +// Wraps the C++11 final+override keywords (a common combination) in a portable way. +// +// Example usage: +// struct Parent { virtual void Func(); }; +// struct Child : public Parent { virtual void Func() OVR_FINAL_OVERRIDE; }; + +#if !defined(OVR_FINAL_OVERRIDE) + #define OVR_FINAL_OVERRIDE OVR_FINAL OVR_OVERRIDE +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_EXTERN_TEMPLATE +// +// Portable wrapper for C++11 extern template. This tells the compiler to not instantiate +// the template in the current translation unit, which can significantly speed up +// compilation and avoid problems due to two translation units compiling code with +// different settings. +// +// Example usage: +// OVR_EXTERN_TEMPLATE(class basic_string<char>); // Nothing to do for non-C++11 compilers. + +#if !defined(OVR_EXTERN_TEMPLATE) + #if defined(OVR_CPP_EXTERN_TEMPLATE) + #define OVR_EXTERN_TEMPLATE(decl) + #else + #define OVR_EXTERN_TEMPLATE(decl) extern template decl + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_CONSTEXPR / OVR_CONSTEXPR_OR_CONST +// +// Portable wrapper for C++11 constexpr. Doesn't include C++14 relaxed constexpr, +// for which a different wrapper name is reserved. +// +// Example usage: +// OVR_CONSTEXPR int Test() { return 15; } // This can be optimized better by a C++11 compiler that supports constexpr. +// OVR_CONSTEXPR_OR_CONST float x = 3.14159f; // This can be optimized better by a C++11 compiler, but if not then at least make it const. + +#if !defined(OVR_CONSTEXPR) + #if defined(OVR_CPP_NO_CONSTEXPR) + #define OVR_CONSTEXPR + #else + #define OVR_CONSTEXPR constexpr + #endif +#endif + +#if !defined(OVR_CONSTEXPR_OR_CONST) + #if defined(OVR_CPP_NO_CONSTEXPR) + #define OVR_CONSTEXPR_OR_CONST const + #else + #define OVR_CONSTEXPR_OR_CONST constexpr + #endif +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_FUNCTION_DELETE / OVR_FUNCTION_DEFAULT +// +// Wraps the C++11 delete and default keywords in a way that allows for cleaner code +// while making for a better version of uncallable or default functions. +// +// Example usage: +// struct Test{ +// Test() OVR_FUNCTION_DEFAULT; // Non-C++11 compilers will require a separate definition for Test(). +// private: // Users should put OVR_FUNCTION_DELETE usage in a private +// void Uncallable() OVR_FUNCTION_DELETE; // area for compatibility with pre-C++11 compilers. +// }; + +#if defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #define OVR_FUNCTION_DELETE +#else + #define OVR_FUNCTION_DELETE = delete +#endif + +#if defined(OVR_CPP_NO_DEFAULTED_FUNCTIONS) + #define OVR_FUNCTION_DEFAULT +#else + #define OVR_FUNCTION_DEFAULT = default +#endif + + + +// ----------------------------------------------------------------------------------- +// ***** OVR_NON_COPYABLE +// +// Allows you to specify a class as being neither copy-constructible nor assignable, +// which is a commonly needed pattern in C++ programming. Classes with this declaration +// are required to be default constructible (as are most classes). For pre-C++11 +// compilers this macro declares a private section for the class, which will be +// inherited by whatever code is directly below the macro invocation by default. +// +// Example usage: +// struct Test { +// Test(); +// ... +// OVR_NON_COPYABLE(Test) +// }; + +#if !defined(OVR_NON_COPYABLE) + #if defined(OVR_CPP_NO_DELETED_FUNCTIONS) + #define OVR_NON_COPYABLE(Type) \ + private: \ + Type(const Type&); \ + void operator=(const Type&); + #else + #define OVR_NON_COPYABLE(Type) \ + Type(const Type&) = delete; \ + void operator=(const Type&) = delete; + #endif +#endif + + + +#endif // header include guard + + + + diff --git a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h index afc0e6a..cc41d2b 100644 --- a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h +++ b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_ContainerAllocator.h Content : Template allocators and constructors for containers. Created : September 19, 2012 @@ -45,8 +45,8 @@ namespace OVR { class ContainerAllocatorBase { public: - static void* Alloc(UPInt size) { return OVR_ALLOC(size); } - static void* Realloc(void* p, UPInt newSize) { return OVR_REALLOC(p, newSize); } + static void* Alloc(size_t size) { return OVR_ALLOC(size); } + static void* Realloc(void* p, size_t newSize) { return OVR_REALLOC(p, newSize); } static void Free(void *p) { OVR_FREE(p); } }; @@ -73,29 +73,29 @@ public: *(T*)p = source; } - static void ConstructArray(void*, UPInt) {} + static void ConstructArray(void*, size_t) {} - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte *pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t *pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) *(T*)pdata = source; } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { memcpy(p, psource, sizeof(T) * count); } static void Destruct(T*) {} - static void DestructArray(T*, UPInt) {} + static void DestructArray(T*, size_t) {} - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } @@ -129,24 +129,24 @@ public: OVR::ConstructAlt<T,S>(p, source); } - static void ConstructArray(void* p, UPInt count) + static void ConstructArray(void* p, size_t count) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata); } - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, source); } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, *psource++); } @@ -156,19 +156,19 @@ public: OVR_UNUSED(p); // Suppress silly MSVC warning } - static void DestructArray(T* p, UPInt count) + static void DestructArray(T* p, size_t count) { p += count - 1; - for (UPInt i=0; i<count; ++i, --p) + for (size_t i=0; i<count; ++i, --p) p->~T(); } - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { memmove(dst, src, count * sizeof(T)); } @@ -202,24 +202,24 @@ public: OVR::ConstructAlt<T,S>(p, source); } - static void ConstructArray(void* p, UPInt count) + static void ConstructArray(void* p, size_t count) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata); } - static void ConstructArray(void* p, UPInt count, const T& source) + static void ConstructArray(void* p, size_t count, const T& source) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, source); } - static void ConstructArray(void* p, UPInt count, const T* psource) + static void ConstructArray(void* p, size_t count, const T* psource) { - UByte* pdata = (UByte*)p; - for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) + uint8_t* pdata = (uint8_t*)p; + for (size_t i=0; i< count; ++i, pdata += sizeof(T)) Construct(pdata, *psource++); } @@ -229,22 +229,22 @@ public: OVR_UNUSED(p); // Suppress silly MSVC warning } - static void DestructArray(T* p, UPInt count) + static void DestructArray(T* p, size_t count) { p += count - 1; - for (UPInt i=0; i<count; ++i, --p) + for (size_t i=0; i<count; ++i, --p) p->~T(); } - static void CopyArrayForward(T* dst, const T* src, UPInt count) + static void CopyArrayForward(T* dst, const T* src, size_t count) { - for(UPInt i = 0; i < count; ++i) + for(size_t i = 0; i < count; ++i) dst[i] = src[i]; } - static void CopyArrayBackward(T* dst, const T* src, UPInt count) + static void CopyArrayBackward(T* dst, const T* src, size_t count) { - for(UPInt i = count; i; --i) + for(size_t i = count; i; --i) dst[i-1] = src[i-1]; } diff --git a/LibOVR/Src/Kernel/OVR_Delegates.h b/LibOVR/Src/Kernel/OVR_Delegates.h new file mode 100644 index 0000000..7d1c399 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Delegates.h @@ -0,0 +1,541 @@ +/************************************************************************************ + +Filename : OVR_Delegates.h +Content : C++ Delegates +Created : June 15, 2014 +Authors : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +/* + Based on The Impossibly Fast C++ Delegates by Sergey Ryazanov from + http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx (2005) +*/ + +/* + Usage: + + Declare a delegate with a void (int) signature, also known as a + function that returns void and has one parameter that is an int: + typedef Delegate1<void, int> MyDelegate; + MyDelegate d; + + Point the delegate to a member function: + d.SetMember<A, &A::TestFunctionA>(&a); + d = MyDelegate::FromMember<A, &A::TestFunctionA>(&a); + + Point the delegate to a const member function: + d.SetConstMember<C, &C::TestFunctionA>(&c); + d = MyDelegate::FromConstMember<C, &C::TestFunctionA>(&c); + + Point the delegate to a free function: + d.SetFree<&FreeFunctionX>(); + d = MyDelegate::FromFree<&FreeFunctionX>(); + + Invoke the function via the delegate (works for all 3 cases): + d(1000); + + By default the delegates are uninitialized. + To clear an array of delegates quickly just zero the memory. + + This implementation is nicer than FastDelegates in my opinion + because it is simple and easy to read. It is a little slower + for virtual functions, but the size of the delegate is small, + and it will only get better as compilers improve. +*/ + +#ifndef OVR_Delegates_h +#define OVR_Delegates_h + +#include "OVR_Types.h" + +namespace OVR { + + +template <class ret_type> +class Delegate0 +{ + typedef ret_type (*StubPointer)(void *); + typedef Delegate0<ret_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate0(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)()> + static OVR_FORCE_INLINE ret_type FreeStub(void *object) + { + return (F)(); + } + + template <class T, ret_type (T::*F)()> + static OVR_FORCE_INLINE ret_type MemberStub(void *object) + { + T *p = static_cast<T*>(object); + return (p->*F)(); + } + + template <class T, ret_type (T::*F)() const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object) + { + T *p = static_cast<T*>(object); + return (p->*F)(); + } + +public: + OVR_FORCE_INLINE Delegate0() {} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()() const + { + return (*_stub)(_object); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)()> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)()> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)() const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)()> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)()> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)() const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type> +class Delegate1 +{ + typedef ret_type (*StubPointer)(void *, arg1_type); + typedef Delegate1<ret_type, arg1_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate1(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void *object, arg1_type a1) + { + return (F)(a1); + } + + template <class T, ret_type (T::*F)(arg1_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1); + } + +public: + OVR_FORCE_INLINE Delegate1() {} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1) const + { + return (*_stub)(_object, a1); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type, class arg2_type> +class Delegate2 +{ + typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type); + typedef Delegate2<ret_type, arg1_type, arg2_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate2(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void *object, arg1_type a1, arg2_type a2) + { + return (F)(a1, a2); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2); + } + +public: + OVR_FORCE_INLINE Delegate2() {} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2) const + { + return (*_stub)(_object, a1, a2); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type, arg2_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + + +template <class ret_type, class arg1_type, class arg2_type, class arg3_type> +class Delegate3 +{ + typedef ret_type (*StubPointer)(void *, arg1_type, arg2_type, arg3_type); + typedef Delegate3<ret_type, arg1_type, arg2_type, arg3_type> this_type; + + void *_object; + StubPointer _stub; + + OVR_FORCE_INLINE Delegate3(void *object, StubPointer stub) + { + _object = object; + _stub = stub; + } + + // Stubs + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE ret_type FreeStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3) + { + return (F)(a1, a2, a3); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE ret_type MemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2, a3); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + static OVR_FORCE_INLINE ret_type ConstMemberStub(void *object, arg1_type a1, arg2_type a2, arg3_type a3) + { + T *p = static_cast<T*>(object); + return (p->*F)(a1, a2, a3); + } + +public: + OVR_FORCE_INLINE Delegate3() {} + + // Function invocation + + OVR_FORCE_INLINE ret_type operator()(arg1_type a1, arg2_type a2, arg3_type a3) const + { + return (*_stub)(_object, a1, a2, a3); + } + + // Use stub pointer as a validity flag and equality checker + + OVR_FORCE_INLINE bool operator==(const this_type &rhs) const + { + return _object == rhs._object && _stub == rhs._stub; + } + + OVR_FORCE_INLINE bool operator!=(const this_type &rhs) const + { + return _object != rhs._object || _stub != rhs._stub; + } + + OVR_FORCE_INLINE bool IsValid() const + { + return _stub != 0; + } + + OVR_FORCE_INLINE bool operator!() const + { + return _stub == 0; + } + + OVR_FORCE_INLINE void Invalidate() + { + _stub = 0; + } + + // Delegate creation from a function + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE this_type FromFree() + { + return this_type(0, &FreeStub<F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + static OVR_FORCE_INLINE this_type FromMember(T *object) + { + return this_type(object, &MemberStub<T, F>); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + static OVR_FORCE_INLINE this_type FromConstMember(T const *object) + { + return this_type(const_cast<T*>( object ), &ConstMemberStub<T, F>); + } + + // In-place assignment to a different function + + template <ret_type (*F)(arg1_type, arg2_type, arg3_type)> + OVR_FORCE_INLINE void SetFree() + { + *this = FromFree<F>(); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type)> + OVR_FORCE_INLINE void SetMember(T *object) + { + *this = FromMember<T, F>(object); + } + + template <class T, ret_type (T::*F)(arg1_type, arg2_type, arg3_type) const> + OVR_FORCE_INLINE void SetConstMember(T const *object) + { + *this = FromConstMember<T, F>(object); + } +}; + +// Add more here if needed, but keep in mind that a short, simple interface +// is rewarded by making the delegates faster... + + +} // namespace OVR + +#endif // OVR_Delegates_h diff --git a/LibOVR/Src/Kernel/OVR_Deque.h b/LibOVR/Src/Kernel/OVR_Deque.h index ca242ad..8e57091 100644 --- a/LibOVR/Src/Kernel/OVR_Deque.h +++ b/LibOVR/Src/Kernel/OVR_Deque.h @@ -27,9 +27,11 @@ limitations under the License. #ifndef OVR_Deque_h #define OVR_Deque_h +#include "OVR_ContainerAllocator.h" + namespace OVR{ -template <class Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > class Deque { public: @@ -48,8 +50,12 @@ public: virtual const Elem& PeekBack (int count = 0) const; // Returns count-th Item from the end virtual const Elem& PeekFront (int count = 0) const; // Returns count-th Item from the beginning - virtual inline UPInt GetSize (void) const; // Returns Number of Elements - virtual inline UPInt GetCapacity(void) const; // Returns the maximum possible number of elements + virtual inline size_t GetSize (void) const; // Returns Number of Elements + OVR_FORCE_INLINE int GetSizeI (void) const + { + return (int)GetSize(); + } + virtual inline size_t GetCapacity(void) const; // Returns the maximum possible number of elements virtual void Clear (void); // Remove all elements virtual inline bool IsEmpty () const; virtual inline bool IsFull () const; @@ -66,29 +72,33 @@ protected: private: Deque& operator= (const Deque& q) { }; // forbidden - Deque(const Deque<Elem> &OtherDeque) { }; + Deque(const Deque<Elem, Allocator> &OtherDeque) { }; }; -template <class Elem> -class InPlaceMutableDeque : public Deque<Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > +class InPlaceMutableDeque : public Deque<Elem, Allocator> { + typedef Deque<Elem, Allocator> BaseType; + public: - InPlaceMutableDeque( int capacity = Deque<Elem>::DefaultCapacity ) : Deque<Elem>( capacity ) {} + InPlaceMutableDeque( int capacity = BaseType::DefaultCapacity ) : BaseType( capacity ) {} virtual ~InPlaceMutableDeque() {}; - using Deque<Elem>::PeekBack; - using Deque<Elem>::PeekFront; + using BaseType::PeekBack; + using BaseType::PeekFront; virtual Elem& PeekBack (int count = 0); // Returns count-th Item from the end virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning }; // Same as Deque, but allows to write more elements than maximum capacity // Old elements are lost as they are overwritten with the new ones -template <class Elem> -class CircularBuffer : public InPlaceMutableDeque<Elem> +template <class Elem, class Allocator = ContainerAllocator<Elem> > +class CircularBuffer : public InPlaceMutableDeque<Elem, Allocator> { + typedef InPlaceMutableDeque<Elem, Allocator> BaseType; + public: - CircularBuffer(int MaxSize = Deque<Elem>::DefaultCapacity) : InPlaceMutableDeque<Elem>(MaxSize) { }; + CircularBuffer(int MaxSize = BaseType::DefaultCapacity) : BaseType(MaxSize) { }; // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class @@ -99,42 +109,54 @@ public: //---------------------------------------------------------------------------------- // Deque Constructor function -template <class Elem> -Deque<Elem>::Deque(int capacity) : +template <class Elem, class Allocator> +Deque<Elem, Allocator>::Deque(int capacity) : Capacity( capacity ), Beginning(0), End(0), ElemCount(0) { - Data = (Elem*) OVR_ALLOC(Capacity * sizeof(Elem)); - ConstructArray<Elem>(Data, Capacity); + Data = (Elem*) Allocator::Alloc(Capacity * sizeof(Elem)); } // Deque Destructor function -template <class Elem> -Deque<Elem>::~Deque(void) +template <class Elem, class Allocator> +Deque<Elem, Allocator>::~Deque(void) { - DestructArray<Elem>(Data, Capacity); - OVR_FREE(Data); + Clear(); + Allocator::Free(Data); } -template <class Elem> -void Deque<Elem>::Clear() +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::Clear() { + if (!IsEmpty()) + { + if (Beginning < End) + { + // no wrap-around + Allocator::DestructArray(Data + Beginning, End - Beginning); + } + else + { + // wrap-around + Allocator::DestructArray(Data + Beginning, Capacity - Beginning); + Allocator::DestructArray(Data, End); + } + } + Beginning = 0; End = 0; ElemCount = 0; - - DestructArray<Elem>(Data, Capacity); - ConstructArray<Elem>(Data, Capacity); } // Push functions -template <class Elem> -void Deque<Elem>::PushBack(const Elem &Item) +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushBack(const Elem &Item) { // Error Check: Make sure we aren't // exceeding our maximum storage space OVR_ASSERT( ElemCount < Capacity ); - Data[ End++ ] = Item; + Allocator::Construct(Data + End, Item); + ++End; ++ElemCount; // Check for wrap-around @@ -142,32 +164,31 @@ void Deque<Elem>::PushBack(const Elem &Item) End -= Capacity; } -template <class Elem> -void Deque<Elem>::PushFront(const Elem &Item) +template <class Elem, class Allocator> +void Deque<Elem, Allocator>::PushFront(const Elem &Item) { // Error Check: Make sure we aren't // exceeding our maximum storage space OVR_ASSERT( ElemCount < Capacity ); - Beginning--; + --Beginning; // Check for wrap-around if (Beginning < 0) Beginning += Capacity; - Data[ Beginning ] = Item; + Allocator::Construct(Data + Beginning, Item); ++ElemCount; } // Pop functions -template <class Elem> -Elem Deque<Elem>::PopFront(void) +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopFront(void) { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > 0 ); Elem ReturnValue = Data[ Beginning ]; - Destruct<Elem>(&Data[ Beginning ]); - Construct<Elem>(&Data[ Beginning ]); + Allocator::Destruct(Data + Beginning); ++Beginning; --ElemCount; @@ -179,13 +200,13 @@ Elem Deque<Elem>::PopFront(void) return ReturnValue; } -template <class Elem> -Elem Deque<Elem>::PopBack(void) +template <class Elem, class Allocator> +Elem Deque<Elem, Allocator>::PopBack(void) { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > 0 ); - End--; + --End; --ElemCount; // Check for wrap-around @@ -193,15 +214,14 @@ Elem Deque<Elem>::PopBack(void) End += Capacity; Elem ReturnValue = Data[ End ]; - Destruct<Elem>(&Data[ End ]); - Construct<Elem>(&Data[ End ]); + Allocator::Destruct(Data + End); return ReturnValue; } // Peek functions -template <class Elem> -const Elem& Deque<Elem>::PeekFront(int count) const +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekFront(int count) const { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > count ); @@ -212,8 +232,8 @@ const Elem& Deque<Elem>::PeekFront(int count) const return Data[ idx ]; } -template <class Elem> -const Elem& Deque<Elem>::PeekBack(int count) const +template <class Elem, class Allocator> +const Elem& Deque<Elem, Allocator>::PeekBack(int count) const { // Error Check: Make sure we aren't reading from an empty Deque OVR_ASSERT( ElemCount > count ); @@ -225,70 +245,70 @@ const Elem& Deque<Elem>::PeekBack(int count) const } // Mutable Peek functions -template <class Elem> -Elem& InPlaceMutableDeque<Elem>::PeekFront(int count) +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekFront(int count) { // Error Check: Make sure we aren't reading from an empty Deque - OVR_ASSERT( Deque<Elem>::ElemCount > count ); + OVR_ASSERT( BaseType::ElemCount > count ); - int idx = Deque<Elem>::Beginning + count; - if (idx >= Deque<Elem>::Capacity) - idx -= Deque<Elem>::Capacity; - return Deque<Elem>::Data[ idx ]; + int idx = BaseType::Beginning + count; + if (idx >= BaseType::Capacity) + idx -= BaseType::Capacity; + return BaseType::Data[ idx ]; } -template <class Elem> -Elem& InPlaceMutableDeque<Elem>::PeekBack(int count) +template <class Elem, class Allocator> +Elem& InPlaceMutableDeque<Elem, Allocator>::PeekBack(int count) { // Error Check: Make sure we aren't reading from an empty Deque - OVR_ASSERT( Deque<Elem>::ElemCount > count ); + OVR_ASSERT( BaseType::ElemCount > count ); - int idx = Deque<Elem>::End - count - 1; + int idx = BaseType::End - count - 1; if (idx < 0) - idx += Deque<Elem>::Capacity; - return Deque<Elem>::Data[ idx ]; + idx += BaseType::Capacity; + return BaseType::Data[ idx ]; } -template <class Elem> -inline UPInt Deque<Elem>::GetCapacity(void) const +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetCapacity(void) const { - return Deque<Elem>::Capacity; + return Capacity; } -template <class Elem> -inline UPInt Deque<Elem>::GetSize(void) const +template <class Elem, class Allocator> +inline size_t Deque<Elem, Allocator>::GetSize(void) const { - return Deque<Elem>::ElemCount; + return ElemCount; } -template <class Elem> -inline bool Deque<Elem>::IsEmpty(void) const +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsEmpty(void) const { - return Deque<Elem>::ElemCount==0; + return ElemCount == 0; } -template <class Elem> -inline bool Deque<Elem>::IsFull(void) const +template <class Elem, class Allocator> +inline bool Deque<Elem, Allocator>::IsFull(void) const { - return Deque<Elem>::ElemCount==Deque<Elem>::Capacity; + return ElemCount == Capacity; } // ******* CircularBuffer<Elem> ******* // Push functions -template <class Elem> -void CircularBuffer<Elem>::PushBack(const Elem &Item) +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushBack(const Elem &Item) { if (this->IsFull()) this->PopFront(); - Deque<Elem>::PushBack(Item); + BaseType::PushBack(Item); } -template <class Elem> -void CircularBuffer<Elem>::PushFront(const Elem &Item) +template <class Elem, class Allocator> +void CircularBuffer<Elem, Allocator>::PushFront(const Elem &Item) { if (this->IsFull()) this->PopBack(); - Deque<Elem>::PushFront(Item); + BaseType::PushFront(Item); } }; diff --git a/LibOVR/Src/Kernel/OVR_File.cpp b/LibOVR/Src/Kernel/OVR_File.cpp index 31ab516..a1e7747 100644 --- a/LibOVR/Src/Kernel/OVR_File.cpp +++ b/LibOVR/Src/Kernel/OVR_File.cpp @@ -46,7 +46,7 @@ namespace OVR { // Not supposed to be used BufferedFile::BufferedFile() : DelegatedFile(0) { - pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE); BufferMode = NoBuffer; FilePos = 0; Pos = 0; @@ -56,7 +56,7 @@ BufferedFile::BufferedFile() : DelegatedFile(0) // Takes another file as source BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) { - pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE); BufferMode = NoBuffer; FilePos = pfile->LTell(); Pos = 0; @@ -177,12 +177,12 @@ int BufferedFile::Tell() return pos; } -SInt64 BufferedFile::LTell() +int64_t BufferedFile::LTell() { if (BufferMode == ReadBuffer) return FilePos - DataSize + Pos; - SInt64 pos = pFile->LTell(); + int64_t pos = pFile->LTell(); if (pos!=-1) { OVR_ASSERT(BufferMode != ReadBuffer); @@ -204,13 +204,13 @@ int BufferedFile::GetLength() } return len; } -SInt64 BufferedFile::LGetLength() +int64_t BufferedFile::LGetLength() { - SInt64 len = pFile->LGetLength(); + int64_t len = pFile->LGetLength(); // If writing through buffer, file length may actually be bigger if ((len!=-1) && (BufferMode==WriteBuffer)) { - SInt64 currPos = pFile->LTell() + Pos; + int64_t currPos = pFile->LTell() + Pos; if (currPos>len) len = currPos; } @@ -225,7 +225,7 @@ bool BufferedFile::Stat(FileStats *pfs) { if (BufferMode==WriteBuffer) { - SInt64 currPos = pFile->LTell() + Pos; + int64_t currPos = pFile->LTell() + Pos; if (currPos > pfs->Size) { pfs->Size = currPos; @@ -239,7 +239,7 @@ bool BufferedFile::Stat(FileStats *pfs) } */ -int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) +int BufferedFile::Write(const uint8_t *psourceBuffer, int numBytes) { if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) { @@ -268,7 +268,7 @@ int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) return sz; } -int BufferedFile::Read(UByte *pdestBuffer, int numBytes) +int BufferedFile::Read(uint8_t *pdestBuffer, int numBytes) { if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) { @@ -413,7 +413,7 @@ int BufferedFile::Seek(int offset, int origin) // Lightweight buffer "Flush". We do this to avoid an extra seek // back operation which would take place if we called FlushBuffer directly. origin = Seek_Set; - OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); + OVR_ASSERT(((FilePos - DataSize + Pos) + (uint64_t)offset) < ~(uint64_t)0); offset = (int)(FilePos - DataSize + Pos) + offset; Pos = DataSize = 0; } @@ -421,7 +421,7 @@ int BufferedFile::Seek(int offset, int origin) { if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) { - OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); + OVR_ASSERT((FilePos-DataSize) < ~(uint64_t)0); Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); return offset; } @@ -461,7 +461,7 @@ int BufferedFile::Seek(int offset, int origin) return int (FilePos); } -SInt64 BufferedFile::LSeek(SInt64 offset, int origin) +int64_t BufferedFile::LSeek(int64_t offset, int origin) { if (BufferMode == ReadBuffer) { @@ -472,20 +472,20 @@ SInt64 BufferedFile::LSeek(SInt64 offset, int origin) if (((unsigned(offset) + Pos)) <= DataSize) { Pos += (unsigned)offset; - return SInt64(FilePos - DataSize + Pos); + return int64_t(FilePos - DataSize + Pos); } // Lightweight buffer "Flush". We do this to avoid an extra seek // back operation which would take place if we called FlushBuffer directly. origin = Seek_Set; - offset = (SInt64)(FilePos - DataSize + Pos) + offset; + offset = (int64_t)(FilePos - DataSize + Pos) + offset; Pos = DataSize = 0; } else if (origin == Seek_Set) { - if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) + if (((uint64_t)offset - (FilePos-DataSize)) <= DataSize) { - Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); + Pos = (unsigned)((uint64_t)offset - (FilePos-DataSize)); return offset; } Pos = DataSize = 0; @@ -508,7 +508,7 @@ SInt64 BufferedFile::LSeek(SInt64 offset, int origin) Pos += int (offset); return FilePos - DataSize + Pos; } - else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) + else if (origin == Seek_Set && offset >= int64_t(FilePos - DataSize) && offset < int64_t(FilePos)) { Pos = unsigned(offset - FilePos + DataSize); return FilePos - DataSize + Pos; @@ -526,7 +526,7 @@ int BufferedFile::CopyFromStream(File *pstream, int byteSize) // We can't rely on overridden Write() // because delegation doesn't override virtual pointers // So, just re-implement - UByte buff[0x4000]; + uint8_t* buff = new uint8_t[0x4000]; int count = 0; int szRequest, szRead, szWritten; @@ -544,6 +544,9 @@ int BufferedFile::CopyFromStream(File *pstream, int byteSize) if (szWritten < szRequest) break; } + + delete[] buff; + return count; } @@ -571,8 +574,8 @@ bool BufferedFile::Close() // Find trailing short filename in a path. const char* OVR_CDECL GetShortFilename(const char* purl) { - UPInt len = OVR_strlen(purl); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(purl); + for (size_t i=len; i>0; i--) if (purl[i]=='\\' || purl[i]=='/') return purl+i+1; return purl; diff --git a/LibOVR/Src/Kernel/OVR_File.h b/LibOVR/Src/Kernel/OVR_File.h index a8dc615..60470fe 100644 --- a/LibOVR/Src/Kernel/OVR_File.h +++ b/LibOVR/Src/Kernel/OVR_File.h @@ -136,11 +136,11 @@ public: // Return position virtual int Tell() = 0; - virtual SInt64 LTell() = 0; + virtual int64_t LTell() = 0; // File size virtual int GetLength() = 0; - virtual SInt64 LGetLength() = 0; + virtual int64_t LGetLength() = 0; // Returns file stats // 0 for failure @@ -156,12 +156,12 @@ public: // Blocking write, will write in the given number of bytes to the stream // Returns : -1 for error // Otherwise number of bytes read - virtual int Write(const UByte *pbufer, int numBytes) = 0; + virtual int Write(const uint8_t *pbufer, int numBytes) = 0; // Blocking read, will read in the given number of bytes or less from the stream // Returns : -1 for error // Otherwise number of bytes read, // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed - virtual int Read(UByte *pbufer, int numBytes) = 0; + virtual int Read(uint8_t *pbufer, int numBytes) = 0; // Skips (ignores) a given # of bytes // Same return values as Read @@ -183,7 +183,7 @@ public: // Seeking // Returns new position, -1 for error virtual int Seek(int offset, int origin=Seek_Set) = 0; - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0; + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set) = 0; // Seek simplification int SeekToBegin() {return Seek(0); } int SeekToEnd() {return Seek(0,Seek_End); } @@ -203,70 +203,70 @@ public: // Read/Write helpers private: - UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; } - UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; } - UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; } - UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; } - void PWrite64(UInt64 v) { Write((UByte*)&v, 8); } - void PWrite32(UInt32 v) { Write((UByte*)&v, 4); } - void PWrite16(UInt16 v) { Write((UByte*)&v, 2); } - void PWrite8(UByte v) { Write((UByte*)&v, 1); } + uint64_t PRead64() { uint64_t v = 0; Read((uint8_t*)&v, 8); return v; } + uint32_t PRead32() { uint32_t v = 0; Read((uint8_t*)&v, 4); return v; } + uint16_t PRead16() { uint16_t v = 0; Read((uint8_t*)&v, 2); return v; } + uint8_t PRead8() { uint8_t v = 0; Read((uint8_t*)&v, 1); return v; } + void PWrite64(uint64_t v) { Write((uint8_t*)&v, 8); } + void PWrite32(uint32_t v) { Write((uint8_t*)&v, 4); } + void PWrite16(uint16_t v) { Write((uint8_t*)&v, 2); } + void PWrite8(uint8_t v) { Write((uint8_t*)&v, 1); } public: // Writing primitive types - Little Endian - inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } - inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } - inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); } + inline void WriteUByte(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSByte(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt8(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt8(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt16(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt16(int16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt32(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt32(int32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteUInt64(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteSInt64(int64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToLE(v)); } + inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 4); } + inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((uint8_t*)&v, 8); } // Writing primitive types - Big Endian - inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } - inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); } - inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); } + inline void WriteUByteBE(uint8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSByteBE(int8_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt8BE(uint16_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt8BE(int16_t v) { PWrite8((uint8_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt16BE(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt16BE(uint16_t v) { PWrite16((uint16_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt32BE(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt32BE(uint32_t v) { PWrite32((uint32_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteUInt64BE(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteSInt64BE(uint64_t v) { PWrite64((uint64_t)Alg::ByteUtil::SystemToBE(v)); } + inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 4); } + inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((uint8_t*)&v, 8); } // Reading primitive types - Little Endian - inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } - inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); } - inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); } - inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); } - inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); } - inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); } - inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); } - inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } - inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } + inline uint8_t ReadUByte() { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline int8_t ReadSByte() { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline uint8_t ReadUInt8() { return (uint8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline int8_t ReadSInt8() { return (int8_t)Alg::ByteUtil::LEToSystem(PRead8()); } + inline uint16_t ReadUInt16() { return (uint16_t)Alg::ByteUtil::LEToSystem(PRead16()); } + inline int16_t ReadSInt16() { return (int16_t)Alg::ByteUtil::LEToSystem(PRead16()); } + inline uint32_t ReadUInt32() { return (uint32_t)Alg::ByteUtil::LEToSystem(PRead32()); } + inline int32_t ReadSInt32() { return (int32_t)Alg::ByteUtil::LEToSystem(PRead32()); } + inline uint64_t ReadUInt64() { return (uint64_t)Alg::ByteUtil::LEToSystem(PRead64()); } + inline int64_t ReadSInt64() { return (int64_t)Alg::ByteUtil::LEToSystem(PRead64()); } + inline float ReadFloat() { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } + inline double ReadDouble() { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } // Reading primitive types - Big Endian - inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } - inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); } - inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); } - inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); } - inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); } - inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); } - inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); } - inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } - inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } + inline uint8_t ReadUByteBE() { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline int8_t ReadSByteBE() { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline uint8_t ReadUInt8BE() { return (uint8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline int8_t ReadSInt8BE() { return (int8_t)Alg::ByteUtil::BEToSystem(PRead8()); } + inline uint16_t ReadUInt16BE() { return (uint16_t)Alg::ByteUtil::BEToSystem(PRead16()); } + inline int16_t ReadSInt16BE() { return (int16_t)Alg::ByteUtil::BEToSystem(PRead16()); } + inline uint32_t ReadUInt32BE() { return (uint32_t)Alg::ByteUtil::BEToSystem(PRead32()); } + inline int32_t ReadSInt32BE() { return (int32_t)Alg::ByteUtil::BEToSystem(PRead32()); } + inline uint64_t ReadUInt64BE() { return (uint64_t)Alg::ByteUtil::BEToSystem(PRead64()); } + inline int64_t ReadSInt64BE() { return (int64_t)Alg::ByteUtil::BEToSystem(PRead64()); } + inline float ReadFloatBE() { float v = 0.0f; Read((uint8_t*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } + inline double ReadDoubleBE() { double v = 0.0; Read((uint8_t*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } }; @@ -294,18 +294,18 @@ public: // virtual bool IsRecoverable() { return pFile->IsRecoverable(); } virtual int Tell() { return pFile->Tell(); } - virtual SInt64 LTell() { return pFile->LTell(); } + virtual int64_t LTell() { return pFile->LTell(); } virtual int GetLength() { return pFile->GetLength(); } - virtual SInt64 LGetLength() { return pFile->LGetLength(); } + virtual int64_t LGetLength() { return pFile->LGetLength(); } //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); } virtual int GetErrorCode() { return pFile->GetErrorCode(); } // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } - virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } + virtual int Write(const uint8_t *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } + virtual int Read(uint8_t *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); } @@ -315,7 +315,7 @@ public: // Seeking virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); } - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); } @@ -342,14 +342,14 @@ protected: }; // Buffer & the mode it's in - UByte* pBuffer; + uint8_t* pBuffer; BufferModeType BufferMode; // Position in buffer unsigned Pos; // Data in buffer if reading unsigned DataSize; // Underlying file position - UInt64 FilePos; + uint64_t FilePos; // Initializes buffering to a certain mode bool SetBufferMode(BufferModeType mode); @@ -376,15 +376,15 @@ public: // We override all the functions that can possibly // require buffer mode switch, flush, or extra calculations virtual int Tell(); - virtual SInt64 LTell(); + virtual int64_t LTell(); virtual int GetLength(); - virtual SInt64 LGetLength(); + virtual int64_t LGetLength(); // virtual bool Stat(GFileStats *pfs); - virtual int Write(const UByte *pbufer, int numBytes); - virtual int Read(UByte *pbufer, int numBytes); + virtual int Write(const uint8_t *pbufer, int numBytes); + virtual int Read(uint8_t *pbufer, int numBytes); virtual int SkipBytes(int numBytes); @@ -393,7 +393,7 @@ public: virtual bool Flush(); virtual int Seek(int offset, int origin=Seek_Set); - virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set); + virtual int64_t LSeek(int64_t offset, int origin=Seek_Set); virtual int CopyFromStream(File *pstream, int byteSize); @@ -417,10 +417,10 @@ public: int GetErrorCode() { return 0; } int Tell() { return FileIndex; } - SInt64 LTell() { return (SInt64) FileIndex; } + int64_t LTell() { return (int64_t) FileIndex; } int GetLength() { return FileSize; } - SInt64 LGetLength() { return (SInt64) FileSize; } + int64_t LGetLength() { return (int64_t) FileSize; } bool Close() { @@ -433,12 +433,12 @@ public: return 0; } - int Write(const UByte *pbuffer, int numBytes) + int Write(const uint8_t *pbuffer, int numBytes) { OVR_UNUSED2(pbuffer, numBytes); return 0; } - int Read(UByte *pbufer, int numBytes) + int Read(uint8_t *pbufer, int numBytes) { if (FileIndex + numBytes > FileSize) { @@ -484,14 +484,14 @@ public: return FileIndex; } - SInt64 LSeek(SInt64 offset, int origin = Seek_Set) + int64_t LSeek(int64_t offset, int origin = Seek_Set) { - return (SInt64) Seek((int) offset, origin); + return (int64_t) Seek((int) offset, origin); } public: - MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize) + MemoryFile (const String& fileName, const uint8_t *pBuffer, int buffSize) : FilePath(fileName) { FileData = pBuffer; @@ -501,7 +501,7 @@ public: } // pfileName should be encoded as UTF-8 to support international file names. - MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize) + MemoryFile (const char* pfileName, const uint8_t *pBuffer, int buffSize) : FilePath(pfileName) { FileData = pBuffer; @@ -512,7 +512,7 @@ public: private: String FilePath; - const UByte *FileData; + const uint8_t *FileData; int FileSize; int FileIndex; bool Valid; diff --git a/LibOVR/Src/Kernel/OVR_FileFILE.cpp b/LibOVR/Src/Kernel/OVR_FileFILE.cpp index 8478086..86096a9 100644 --- a/LibOVR/Src/Kernel/OVR_FileFILE.cpp +++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp @@ -60,7 +60,8 @@ static int SFerror () return FileConstants::Error_IOError; }; -#ifdef OVR_OS_WIN32 +#if defined(OVR_OS_WIN32) +#define WIN32_LEAN_AND_MEAN #include "windows.h" // A simple helper class to disable/enable system error mode, if necessary // Disabling happens conditionally only if a drive name is involved @@ -121,7 +122,7 @@ protected: int LastOp; #ifdef OVR_FILE_VERIFY_SEEK_ERRORS - UByte* pFileTestBuffer; + uint8_t* pFileTestBuffer; unsigned FileTestLength; unsigned TestPos; // File pointer position during tests. #endif @@ -157,21 +158,21 @@ public: // Return position / file size virtual int Tell(); - virtual SInt64 LTell(); + virtual int64_t LTell(); virtual int GetLength(); - virtual SInt64 LGetLength(); + virtual int64_t LGetLength(); // virtual bool Stat(FileStats *pfs); virtual int GetErrorCode(); // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes); - virtual int Read(UByte *pbuffer, int numBytes); + virtual int Write(const uint8_t *pbuffer, int numBytes); + virtual int Read(uint8_t *pbuffer, int numBytes); virtual int SkipBytes(int numBytes); virtual int BytesAvailable(); virtual bool Flush(); virtual int Seek(int offset, int origin); - virtual SInt64 LSeek(SInt64 offset, int origin); + virtual int64_t LSeek(int64_t offset, int origin); virtual int CopyFromStream(File *pStream, int byteSize); virtual bool Close(); @@ -218,7 +219,7 @@ void FILEFile::init() else if (OpenFlags & Open_Write) omode = "r+b"; -#ifdef OVR_OS_WIN32 +#if defined(OVR_OS_WIN32) SysErrorModeDisabler disabler(FileName.ToCStr()); #endif @@ -248,7 +249,7 @@ void FILEFile::init() fseek(fs, 0, SEEK_END); FileTestLength = ftell(fs); fseek(fs, 0, SEEK_SET); - pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength); + pFileTestBuffer = (uint8_t*)OVR_ALLOC(FileTestLength); if (pFileTestBuffer) { OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength)); @@ -293,9 +294,9 @@ int FILEFile::Tell() return pos; } -SInt64 FILEFile::LTell() +int64_t FILEFile::LTell() { - SInt64 pos = ftell(fs); + int64_t pos = ftell(fs); if (pos < 0) ErrorCode = SFerror(); return pos; @@ -313,13 +314,13 @@ int FILEFile::GetLength() } return -1; } -SInt64 FILEFile::LGetLength() +int64_t FILEFile::LGetLength() { - SInt64 pos = LTell(); + int64_t pos = LTell(); if (pos >= 0) { LSeek (0, Seek_End); - SInt64 size = LTell(); + int64_t size = LTell(); LSeek (pos, Seek_Set); return size; } @@ -332,7 +333,7 @@ int FILEFile::GetErrorCode() } // ** Stream implementation & I/O -int FILEFile::Write(const UByte *pbuffer, int numBytes) +int FILEFile::Write(const uint8_t *pbuffer, int numBytes) { if (LastOp && LastOp != Open_Write) fflush(fs); @@ -349,7 +350,7 @@ int FILEFile::Write(const UByte *pbuffer, int numBytes) return written; } -int FILEFile::Read(UByte *pbuffer, int numBytes) +int FILEFile::Read(uint8_t *pbuffer, int numBytes) { if (LastOp && LastOp != Open_Read) fflush(fs); @@ -362,7 +363,7 @@ int FILEFile::Read(UByte *pbuffer, int numBytes) if (read > 0) { // Read-in data must match our pre-loaded buffer data! - UByte* pcompareBuffer = pFileTestBuffer + TestPos; + uint8_t* pcompareBuffer = pFileTestBuffer + TestPos; for (int i=0; i< read; i++) { OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]); @@ -380,8 +381,8 @@ int FILEFile::Read(UByte *pbuffer, int numBytes) // Seeks ahead to skip bytes int FILEFile::SkipBytes(int numBytes) { - SInt64 pos = LTell(); - SInt64 newPos = LSeek(numBytes, Seek_Cur); + int64_t pos = LTell(); + int64_t newPos = LSeek(numBytes, Seek_Cur); // Return -1 for major error if ((pos==-1) || (newPos==-1)) @@ -396,8 +397,8 @@ int FILEFile::SkipBytes(int numBytes) // Return # of bytes till EOF int FILEFile::BytesAvailable() { - SInt64 pos = LTell(); - SInt64 endPos = LGetLength(); + int64_t pos = LTell(); + int64_t endPos = LGetLength(); // Return -1 for major error if ((pos==-1) || (endPos==-1)) @@ -452,14 +453,14 @@ int FILEFile::Seek(int offset, int origin) return (int)Tell(); } -SInt64 FILEFile::LSeek(SInt64 offset, int origin) +int64_t FILEFile::LSeek(int64_t offset, int origin) { return Seek((int)offset,origin); } int FILEFile::CopyFromStream(File *pstream, int byteSize) { - UByte buff[0x4000]; + uint8_t* buff = new uint8_t[0x4000]; int count = 0; int szRequest, szRead, szWritten; @@ -477,6 +478,9 @@ int FILEFile::CopyFromStream(File *pstream, int byteSize) if (szWritten < szRequest) break; } + + delete[] buff; + return count; } @@ -570,7 +574,7 @@ Ptr<File> FileFILEOpen(const String& path, int flags, int mode) // Helper function: obtain file information time. bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) // 64-bit implementation on Windows. struct __stat64 fileStat; // Stat returns 0 for success. diff --git a/LibOVR/Src/Kernel/OVR_Hash.h b/LibOVR/Src/Kernel/OVR_Hash.h index 04c4db8..7522da7 100644 --- a/LibOVR/Src/Kernel/OVR_Hash.h +++ b/LibOVR/Src/Kernel/OVR_Hash.h @@ -71,8 +71,8 @@ template<class C> class IdentityHash { public: - UPInt operator()(const C& data) const - { return (UPInt) data; } + size_t operator()(const C& data) const + { return (size_t) data; } }; // Computes a hash of an object's representation. @@ -84,19 +84,19 @@ public: // above, http::/www.cs.yorku.ca/~oz/hash.html // This is somewhat slower then Bernstein, but it works way better than the above // hash function for hashing large numbers of 32-bit ints. - static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381) + static OVR_FORCE_INLINE size_t SDBM_Hash(const void* data_in, size_t size, size_t seed = 5381) { - const UByte* data = (const UByte*) data_in; - UPInt h = seed; + const uint8_t* data = (const uint8_t*) data_in; + size_t h = seed; while (size > 0) { size--; - h = (h << 16) + (h << 6) - h + (UPInt)data[size]; + h = (h << 16) + (h << 6) - h + (size_t)data[size]; } return h; } - UPInt operator()(const C& data) const + size_t operator()(const C& data) const { unsigned char* p = (unsigned char*) &data; int size = sizeof(C); @@ -116,14 +116,14 @@ class HashsetEntry { public: // Internal chaining for collisions. - SPInt NextInChain; + intptr_t NextInChain; C Value; HashsetEntry() : NextInChain(-2) { } HashsetEntry(const HashsetEntry& e) : NextInChain(e.NextInChain), Value(e.Value) { } - HashsetEntry(const C& key, SPInt next) + HashsetEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } bool IsEmpty() const { return NextInChain == -2; } @@ -131,8 +131,8 @@ public: // Cached hash value access - can be optimized bu storing hash locally. // Mask value only needs to be used if SetCachedHash is not implemented. - UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } - void SetCachedHash(UPInt) {} + size_t GetCachedHash(size_t maskValue) const { return HashF()(Value) & maskValue; } + void SetCachedHash(size_t) {} void Clear() { @@ -151,15 +151,15 @@ class HashsetCachedEntry { public: // Internal chaining for collisions. - SPInt NextInChain; - UPInt HashValue; + intptr_t NextInChain; + size_t HashValue; C Value; HashsetCachedEntry() : NextInChain(-2) { } HashsetCachedEntry(const HashsetCachedEntry& e) : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } - HashsetCachedEntry(const C& key, SPInt next) + HashsetCachedEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } bool IsEmpty() const { return NextInChain == -2; } @@ -167,8 +167,8 @@ public: // Cached hash value access - can be optimized bu storing hash locally. // Mask value only needs to be used if SetCachedHash is not implemented. - UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } - void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } + size_t GetCachedHash(size_t maskValue) const { OVR_UNUSED(maskValue); return HashValue; } + void SetCachedHash(size_t hashValue) { HashValue = hashValue; } void Clear() { @@ -210,7 +210,7 @@ public: if (pTable) { // Delete the entries. - for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) + for (size_t i = 0, n = pTable->SizeMask; i <= n; i++) { Entry* e = &E(i); if (!e->IsEmpty()) @@ -244,7 +244,7 @@ public: if (pTable) { // Delete the entries. - for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) + for (size_t i = 0, n = pTable->SizeMask; i <= n; i++) { Entry* e = &E(i); if (!e->IsEmpty()) @@ -269,8 +269,8 @@ public: template<class CRef> void Set(const CRef& key) { - UPInt hashValue = HashF()(key); - SPInt index = (SPInt)-1; + size_t hashValue = HashF()(key); + intptr_t index = (intptr_t)-1; if (pTable != NULL) index = findIndexCore(key, hashValue & pTable->SizeMask); @@ -289,7 +289,7 @@ public: template<class CRef> inline void Add(const CRef& key) { - UPInt hashValue = HashF()(key); + size_t hashValue = HashF()(key); add(key, hashValue); } @@ -300,20 +300,20 @@ public: if (pTable == NULL) return; - UPInt hashValue = AltHashF()(key); - SPInt index = hashValue & pTable->SizeMask; + size_t hashValue = AltHashF()(key); + intptr_t index = hashValue & pTable->SizeMask; Entry* e = &E(index); // If empty node or occupied by collider, we have nothing to remove. - if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index)) + if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (size_t)index)) return; // Save index - SPInt naturalIndex = index; - SPInt prevIndex = -1; + intptr_t naturalIndex = index; + intptr_t prevIndex = -1; - while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) + while ((e->GetCachedHash(pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key)) { // Keep looking through the chain. prevIndex = index; @@ -361,7 +361,7 @@ public: template<class K> C* Get(const K& key) { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return &E(index).Value; return 0; @@ -370,7 +370,7 @@ public: template<class K> const C* Get(const K& key) const { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return &E(index).Value; return 0; @@ -380,7 +380,7 @@ public: template<class K> const C* GetAlt(const K& key) const { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return &E(index).Value; return 0; @@ -389,7 +389,7 @@ public: template<class K> C* GetAlt(const K& key) { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return &E(index).Value; return 0; @@ -398,7 +398,7 @@ public: template<class K> bool GetAlt(const K& key, C* pval) const { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) { if (pval) @@ -409,10 +409,11 @@ public: } - UPInt GetSize() const + size_t GetSize() const { - return pTable == NULL ? 0 : (UPInt)pTable->EntryCount; + return pTable == NULL ? 0 : (size_t)pTable->EntryCount; } + int GetSizeI() const { return (int)GetSize(); } // Resize the HashSet table to fit one more Entry. Often this @@ -432,7 +433,7 @@ public: } // Hint the bucket count to >= n. - void Resize(UPInt n) + void Resize(size_t n) { // Not really sure what this means in relation to // STLport's hash_map... they say they "increase the @@ -446,9 +447,9 @@ public: // Size the HashSet so that it can comfortably contain the given // number of elements. If the HashSet already contains more // elements than newSize, then this may be a no-op. - void SetCapacity(UPInt newSize) + void SetCapacity(size_t newSize) { - UPInt newRawSize = (newSize * 5) / 4; + size_t newRawSize = (newSize * 5) / 4; if (newRawSize <= GetSize()) return; setRawCapacity(newRawSize); @@ -466,23 +467,23 @@ public: { const C& operator * () const { - OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); + OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask); return pHash->E(Index).Value; } const C* operator -> () const { - OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); + OVR_ASSERT(Index >= 0 && Index <= (intptr_t)pHash->pTable->SizeMask); return &pHash->E(Index).Value; } void operator ++ () { // Find next non-empty Entry. - if (Index <= (SPInt)pHash->pTable->SizeMask) + if (Index <= (intptr_t)pHash->pTable->SizeMask) { Index++; - while ((UPInt)Index <= pHash->pTable->SizeMask && + while ((size_t)Index <= pHash->pTable->SizeMask && pHash->E(Index).IsEmpty()) { Index++; @@ -512,7 +513,7 @@ public: { return (pHash == NULL) || (pHash->pTable == NULL) || - (Index > (SPInt)pHash->pTable->SizeMask); + (Index > (intptr_t)pHash->pTable->SizeMask); } ConstIterator() @@ -522,7 +523,7 @@ public: public: // Constructor was intentionally made public to allow create // iterator with arbitrary index. - ConstIterator(const SelfType* h, SPInt index) + ConstIterator(const SelfType* h, intptr_t index) : pHash(h), Index(index) { } @@ -530,7 +531,7 @@ public: { return pHash; } - SPInt GetIndex() const + intptr_t GetIndex() const { return Index; } @@ -539,7 +540,7 @@ public: friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; const SelfType* pHash; - SPInt Index; + intptr_t Index; }; friend struct ConstIterator; @@ -551,7 +552,7 @@ public: // Allow non-const access to entries. C& operator*() const { - OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask); + OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (intptr_t)ConstIterator::pHash->pTable->SizeMask); return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value; } @@ -577,20 +578,20 @@ public: //Entry* ee = &phash->E(ConstIterator::Index); //const C& key = ee->Value; - UPInt hashValue = AltHashF()(key); - SPInt index = hashValue & phash->pTable->SizeMask; + size_t hashValue = AltHashF()(key); + intptr_t index = hashValue & phash->pTable->SizeMask; Entry* e = &phash->E(index); // If empty node or occupied by collider, we have nothing to remove. - if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index)) + if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (size_t)index)) return; // Save index - SPInt naturalIndex = index; - SPInt prevIndex = -1; + intptr_t naturalIndex = index; + intptr_t prevIndex = -1; - while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) + while ((e->GetCachedHash(phash->pTable->SizeMask) != (size_t)naturalIndex) || !(e->Value == key)) { // Keep looking through the chain. prevIndex = index; @@ -600,7 +601,7 @@ public: e = &phash->E(index); } - if (index == (SPInt)ConstIterator::Index) + if (index == (intptr_t)ConstIterator::Index) { // Found it - our item is at index if (naturalIndex == index) @@ -633,7 +634,7 @@ public: private: friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; - Iterator(SelfType* h, SPInt i0) + Iterator(SelfType* h, intptr_t i0) : ConstIterator(h, i0) { } }; @@ -646,7 +647,7 @@ public: return Iterator(NULL, 0); // Scan till we hit the First valid Entry. - UPInt i0 = 0; + size_t i0 = 0; while (i0 <= pTable->SizeMask && E(i0).IsEmpty()) { i0++; @@ -661,7 +662,7 @@ public: template<class K> Iterator Find(const K& key) { - SPInt index = findIndex(key); + intptr_t index = findIndex(key); if (index >= 0) return Iterator(this, index); return Iterator(NULL, 0); @@ -670,7 +671,7 @@ public: template<class K> Iterator FindAlt(const K& key) { - SPInt index = findIndexAlt(key); + intptr_t index = findIndexAlt(key); if (index >= 0) return Iterator(this, index); return Iterator(NULL, 0); @@ -685,33 +686,33 @@ public: private: // Find the index of the matching Entry. If no match, then return -1. template<class K> - SPInt findIndex(const K& key) const + intptr_t findIndex(const K& key) const { if (pTable == NULL) return -1; - UPInt hashValue = HashF()(key) & pTable->SizeMask; + size_t hashValue = HashF()(key) & pTable->SizeMask; return findIndexCore(key, hashValue); } template<class K> - SPInt findIndexAlt(const K& key) const + intptr_t findIndexAlt(const K& key) const { if (pTable == NULL) return -1; - UPInt hashValue = AltHashF()(key) & pTable->SizeMask; + size_t hashValue = AltHashF()(key) & pTable->SizeMask; return findIndexCore(key, hashValue); } // Find the index of the matching Entry. If no match, then return -1. template<class K> - SPInt findIndexCore(const K& key, UPInt hashValue) const + intptr_t findIndexCore(const K& key, size_t hashValue) const { // Table must exist. OVR_ASSERT(pTable != 0); // Hash key must be 'and-ed' by the caller. OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0); - UPInt index = hashValue; + size_t index = hashValue; const Entry* e = &E(index); // If empty or occupied by a collider, not found. @@ -733,7 +734,7 @@ private: // Keep looking through the chain. index = e->NextInChain; - if (index == (UPInt)-1) + if (index == (size_t)-1) break; // end of chain e = &E(index); @@ -745,14 +746,14 @@ private: // Add a new value to the HashSet table, under the specified key. template<class CRef> - void add(const CRef& key, UPInt hashValue) + void add(const CRef& key, size_t hashValue) { CheckExpand(); hashValue &= pTable->SizeMask; pTable->EntryCount++; - SPInt index = hashValue; + intptr_t index = hashValue; Entry* naturalEntry = &(E(index)); if (naturalEntry->IsEmpty()) @@ -763,14 +764,14 @@ private: else { // Find a blank spot. - SPInt blankIndex = index; + intptr_t blankIndex = index; do { blankIndex = (blankIndex + 1) & pTable->SizeMask; } while(!E(blankIndex).IsEmpty()); Entry* blankEntry = &E(blankIndex); - if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index) + if (naturalEntry->GetCachedHash(pTable->SizeMask) == (size_t)index) { // Collision. Link into this chain. @@ -788,8 +789,8 @@ private: // Entry must be moved. // Find natural location of collided element (i.e. root of chain) - SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); - OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); + intptr_t collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask); for (;;) { Entry* e = &E(collidedIndex); @@ -801,7 +802,7 @@ private: break; } collidedIndex = e->NextInChain; - OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (intptr_t)pTable->SizeMask); } // Put the new data in the natural Entry. @@ -815,13 +816,13 @@ private: } // Index access helpers. - Entry& E(UPInt index) + Entry& E(size_t index) { // Must have pTable and access needs to be within bounds. OVR_ASSERT(index <= pTable->SizeMask); return *(((Entry*) (pTable + 1)) + index); } - const Entry& E(UPInt index) const + const Entry& E(size_t index) const { OVR_ASSERT(index <= pTable->SizeMask); return *(((Entry*) (pTable + 1)) + index); @@ -832,7 +833,7 @@ private: // contents of the current table). The arg is the number of // HashSet table entries, not the number of elements we should // actually contain (which will be less than this). - void setRawCapacity(UPInt newSize) + void setRawCapacity(size_t newSize) { if (newSize == 0) { @@ -850,8 +851,8 @@ private: { // Force newSize to be a power of two. int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1); - OVR_ASSERT((UPInt(1) << bits) >= newSize); - newSize = UPInt(1) << bits; + OVR_ASSERT((size_t(1) << bits) >= newSize); + newSize = size_t(1) << bits; } SelfType newHash; @@ -863,7 +864,7 @@ private: newHash.pTable->EntryCount = 0; newHash.pTable->SizeMask = newSize - 1; - UPInt i, n; + size_t i, n; // Mark all entries as empty. for (i = 0; i < newSize; i++) @@ -895,8 +896,8 @@ private: struct TableType { - UPInt EntryCount; - UPInt SizeMask; + size_t EntryCount; + size_t SizeMask; // Entry array follows this structure // in memory. }; @@ -939,7 +940,7 @@ public: } // Hint the bucket count to >= n. - void Resize(UPInt n) + void Resize(size_t n) { BaseType::SetCapacity(n); } @@ -947,7 +948,7 @@ public: // Size the HashSet so that it can comfortably contain the given // number of elements. If the HashSet already contains more // elements than newSize, then this may be a no-op. - void SetCapacity(UPInt newSize) + void SetCapacity(size_t newSize) { BaseType::SetCapacity(newSize); } @@ -1004,7 +1005,7 @@ struct HashNode NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { } // Enable computation of ghash_node_hashf. - inline UPInt GetHash() const { return HashF()(*pFirst); } + inline size_t GetHash() const { return HashF()(*pFirst); } // Necessary conversion to allow HashNode::operator == to work. operator const C& () const { return *pFirst; } }; @@ -1018,20 +1019,20 @@ struct HashNode bool operator == (const K& src) const { return (First == src); } template<class K> - static UPInt CalcHash(const K& data) { return HashF()(data); } - inline UPInt GetHash() const { return HashF()(First); } + static size_t CalcHash(const K& data) { return HashF()(data); } + inline size_t GetHash() const { return HashF()(First); } // Hash functors used with this node. A separate functor is used for alternative // key lookup so that it does not need to access the '.First' element. struct NodeHashF { template<class K> - UPInt operator()(const K& data) const { return data.GetHash(); } + size_t operator()(const K& data) const { return data.GetHash(); } }; struct NodeAltHashF { template<class K> - UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } + size_t operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } }; }; @@ -1050,22 +1051,22 @@ class HashsetNodeEntry { public: // Internal chaining for collisions. - SPInt NextInChain; + intptr_t NextInChain; C Value; HashsetNodeEntry() : NextInChain(-2) { } HashsetNodeEntry(const HashsetNodeEntry& e) : NextInChain(e.NextInChain), Value(e.Value) { } - HashsetNodeEntry(const C& key, SPInt next) + HashsetNodeEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } - HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next) + HashsetNodeEntry(const typename C::NodeRef& keyRef, intptr_t next) : NextInChain(next), Value(keyRef) { } bool IsEmpty() const { return NextInChain == -2; } bool IsEndOfChain() const { return NextInChain == -1; } - UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } - void SetCachedHash(UPInt hashValue) { OVR_UNUSED(hashValue); } + size_t GetCachedHash(size_t maskValue) const { return HashF()(Value) & maskValue; } + void SetCachedHash(size_t hashValue) { OVR_UNUSED(hashValue); } void Clear() { @@ -1084,23 +1085,23 @@ class HashsetCachedNodeEntry { public: // Internal chaining for collisions. - SPInt NextInChain; - UPInt HashValue; + intptr_t NextInChain; + size_t HashValue; C Value; HashsetCachedNodeEntry() : NextInChain(-2) { } HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e) : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } - HashsetCachedNodeEntry(const C& key, SPInt next) + HashsetCachedNodeEntry(const C& key, intptr_t next) : NextInChain(next), Value(key) { } - HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next) + HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, intptr_t next) : NextInChain(next), Value(keyRef) { } bool IsEmpty() const { return NextInChain == -2; } bool IsEndOfChain() const { return NextInChain == -1; } - UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } - void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } + size_t GetCachedHash(size_t maskValue) const { OVR_UNUSED(maskValue); return HashValue; } + void SetCachedHash(size_t hashValue) { HashValue = hashValue; } void Clear() { @@ -1227,9 +1228,10 @@ public: } // Sizing methods - delegate to Hash. - inline UPInt GetSize() const { return mHash.GetSize(); } - inline void Resize(UPInt n) { mHash.Resize(n); } - inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); } + inline size_t GetSize() const { return mHash.GetSize(); } + inline int GetSizeI() const { return (int)GetSize(); } + inline void Resize(size_t n) { mHash.Resize(n); } + inline void SetCapacity(size_t newSize) { mHash.SetCapacity(newSize); } // Iterator API, like STL. typedef typename Container::ConstIterator ConstIterator; diff --git a/LibOVR/Src/Kernel/OVR_KeyCodes.h b/LibOVR/Src/Kernel/OVR_KeyCodes.h index b5c5930..3b468da 100644 --- a/LibOVR/Src/Kernel/OVR_KeyCodes.h +++ b/LibOVR/Src/Kernel/OVR_KeyCodes.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_KeyCodes.h Content : Common keyboard constants Created : September 19, 2012 diff --git a/LibOVR/Src/Kernel/OVR_Lockless.cpp b/LibOVR/Src/Kernel/OVR_Lockless.cpp index 0f25805..67c9260 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.cpp +++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp @@ -1,6 +1,5 @@ /************************************************************************************ -PublicHeader: OVR.h Filename : OVR_Lockless.cpp Content : Test logic for lock-less classes Created : December 27, 2013 @@ -33,7 +32,6 @@ limitations under the License. #include "OVR_Timer.h" #include "OVR_Log.h" - namespace OVR { namespace LocklessTest { @@ -108,7 +106,6 @@ class Consumer : public Thread { LogText("LocklessTest::Consumer::Run started.\n"); - while (!FirstItemWritten) { // spin until producer wrote first value... diff --git a/LibOVR/Src/Kernel/OVR_Lockless.h b/LibOVR/Src/Kernel/OVR_Lockless.h index a12f824..72b6b31 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.h +++ b/LibOVR/Src/Kernel/OVR_Lockless.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Lockless.h Content : Lock-less classes for producer/consumer communication Created : November 9, 2013 @@ -42,12 +42,22 @@ namespace OVR { // necessarily getting every one that happens (vsync timing, SensorFusion updates). // // This is multiple consumer safe, but is currently only used with a single consumer. +// +// The SlotType can be the same as T, but should probably be a larger fixed size. +// This allows for forward compatibility when the updater is shared between processes. + +// FIXME: ExchangeAdd_Sync() should be replaced with a portable read-only primitive, +// so that the lockless pose state can be read-only on remote processes and to reduce +// false sharing between processes and improve performance. -template<class T> +template<class T, class SlotType> class LocklessUpdater { public: - LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) {} + LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) + { + OVR_COMPILER_ASSERT(sizeof(T) <= sizeof(SlotType)); + } T GetState() const { @@ -92,7 +102,7 @@ public: mutable AtomicInt<int> UpdateBegin; mutable AtomicInt<int> UpdateEnd; - T Slots[2]; + SlotType Slots[2]; }; diff --git a/LibOVR/Src/Kernel/OVR_Log.cpp b/LibOVR/Src/Kernel/OVR_Log.cpp index d5f8a68..c81845e 100644 --- a/LibOVR/Src/Kernel/OVR_Log.cpp +++ b/LibOVR/Src/Kernel/OVR_Log.cpp @@ -29,10 +29,13 @@ limitations under the License. #include <stdarg.h> #include <stdio.h> -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) +#define WIN32_LEAN_AND_MEAN #include <windows.h> #elif defined(OVR_OS_ANDROID) #include <android/log.h> +#elif defined(OVR_OS_LINUX) || defined(OVR_OS_MAC) +#include <syslog.h> #endif namespace OVR { @@ -43,8 +46,24 @@ Log* volatile OVR_GlobalLog = 0; //----------------------------------------------------------------------------------- // ***** Log Implementation +Log::Log(unsigned logMask) : + LoggingMask(logMask) +{ +#ifdef OVR_OS_WIN32 + hEventSource = RegisterEventSourceA(NULL, "OculusVR"); + OVR_ASSERT(hEventSource != NULL); +#endif +} + Log::~Log() { +#ifdef OVR_OS_WIN32 + if (hEventSource) + { + DeregisterEventSource(hEventSource); + } +#endif + // Clear out global log if (this == OVR_GlobalLog) { @@ -64,7 +83,7 @@ void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list ar char buffer[MaxLogBufferMessageSize]; FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList); - DefaultLogOutput(buffer, IsDebugMessage(messageType)); + DefaultLogOutput(buffer, messageType); } void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...) @@ -94,7 +113,7 @@ void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageTyp break; } - UPInt prefixLength = OVR_strlen(buffer); + size_t prefixLength = OVR_strlen(buffer); char *buffer2 = buffer + prefixLength; OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList); @@ -103,8 +122,9 @@ void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageTyp } -void Log::DefaultLogOutput(const char* formattedText, bool debug) +void Log::DefaultLogOutput(const char* formattedText, LogMessageType messageType) { + bool debug = IsDebugMessage(messageType); #if defined(OVR_OS_WIN32) // Under Win32, output regular messages to console if it exists; debug window otherwise. @@ -116,10 +136,8 @@ void Log::DefaultLogOutput(const char* formattedText, bool debug) { ::OutputDebugStringA(formattedText); } - else - { - fputs(formattedText, stdout); - } + + fputs(formattedText, stdout); #elif defined(OVR_OS_ANDROID) __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText); @@ -129,6 +147,22 @@ void Log::DefaultLogOutput(const char* formattedText, bool debug) #endif + if (messageType == Log_Error) + { +#if defined(OVR_OS_WIN32) + if (!ReportEventA(hEventSource, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, &formattedText, NULL)) + { + OVR_ASSERT(false); + } +#elif defined(OVR_OS_ANDROID) + // TBD +#elif defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) + syslog(LOG_ERR, "%s", formattedText); +#else + // TBD +#endif + } + // Just in case. OVR_UNUSED2(formattedText, debug); } diff --git a/LibOVR/Src/Kernel/OVR_Log.h b/LibOVR/Src/Kernel/OVR_Log.h index 4d9acc1..7c9d65b 100644 --- a/LibOVR/Src/Kernel/OVR_Log.h +++ b/LibOVR/Src/Kernel/OVR_Log.h @@ -103,8 +103,13 @@ enum LogMessageType class Log { friend class System; + +#ifdef OVR_OS_WIN32 + void* hEventSource; +#endif + public: - Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { } + Log(unsigned logMask = LogMask_Debug); virtual ~Log(); // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated. @@ -131,7 +136,7 @@ public: // Default log output implementation used by by LogMessageVarg. // Debug flag may be used to re-direct output on some platforms, but doesn't // necessarily disable it in release builds; that is the job of the called. - static void DefaultLogOutput(const char* textBuffer, bool debug); + void DefaultLogOutput(const char* textBuffer, LogMessageType messageType); // Determines if the specified message type is for debugging only. static bool IsDebugMessage(LogMessageType messageType) @@ -184,7 +189,7 @@ void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); // Macro to do debug logging, printf-style. // An extra set of set of parenthesis must be used around arguments, - // as in: OVR_LOG_DEBUG(("Value %d", 2)). + // as in: OVR_DEBUG_LOG(("Value %d", 2)). #define OVR_DEBUG_LOG(args) do { OVR::LogDebug args; } while(0) #define OVR_DEBUG_LOG_TEXT(args) do { OVR::LogDebugText args; } while(0) diff --git a/LibOVR/Src/Kernel/OVR_Math.cpp b/LibOVR/Src/Kernel/OVR_Math.cpp index 396d3ff..706fb33 100644 --- a/LibOVR/Src/Kernel/OVR_Math.cpp +++ b/LibOVR/Src/Kernel/OVR_Math.cpp @@ -34,45 +34,13 @@ namespace OVR { //------------------------------------------------------------------------------------- -// ***** Math - - -// Single-precision Math constants class. -const float Math<float>::Pi = 3.1415926f; -const float Math<float>::TwoPi = 3.1415926f * 2; -const float Math<float>::PiOver2 = 3.1415926f / 2.0f; -const float Math<float>::PiOver4 = 3.1415926f / 4.0f; -const float Math<float>::E = 2.7182818f; - -const float Math<float>::MaxValue = FLT_MAX; -const float Math<float>::MinPositiveValue = FLT_MIN; - -const float Math<float>::RadToDegreeFactor = 360.0f / Math<float>::TwoPi; -const float Math<float>::DegreeToRadFactor = Math<float>::TwoPi / 360.0f; - -const float Math<float>::Tolerance = 0.00001f; -const float Math<float>::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems - -// Double-precision Math constants class. -const double Math<double>::Pi = 3.14159265358979; -const double Math<double>::TwoPi = 3.14159265358979 * 2; -const double Math<double>::PiOver2 = 3.14159265358979 / 2.0; -const double Math<double>::PiOver4 = 3.14159265358979 / 4.0; -const double Math<double>::E = 2.71828182845905; - -const double Math<double>::MaxValue = DBL_MAX; -const double Math<double>::MinPositiveValue = DBL_MIN; - -const double Math<double>::RadToDegreeFactor = 360.0 / Math<double>::TwoPi; -const double Math<double>::DegreeToRadFactor = Math<double>::TwoPi / 360.0; - -const double Math<double>::Tolerance = 0.00001; -const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems - +// ***** Constants +template<> +const Vector3<float> Vector3<float>::ZERO = Vector3<float>(); -//------------------------------------------------------------------------------------- -// ***** Matrix4 +template<> +const Vector3<double> Vector3<double>::ZERO = Vector3<double>(); template<> const Matrix4<float> Matrix4<float>::IdentityValue = Matrix4<float>(1.0f, 0.0f, 0.0f, 0.0f, @@ -87,5 +55,4 @@ const Matrix4<double> Matrix4<double>::IdentityValue = Matrix4<double>(1.0, 0.0, 0.0, 0.0, 0.0, 1.0); - } // Namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_Math.h b/LibOVR/Src/Kernel/OVR_Math.h index 4aa42b0..82c1d03 100644 --- a/LibOVR/Src/Kernel/OVR_Math.h +++ b/LibOVR/Src/Kernel/OVR_Math.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Math.h Content : Implementation of 3D primitives such as vectors, matrices. Created : September 4, 2012 @@ -125,7 +125,7 @@ template<class T> class Vector2; template<class T> class Vector3; template<class T> class Matrix3; template<class T> class Matrix4; -template<class T> class Transform; +template<class T> class Pose; template<class T> class PoseState; // CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class. @@ -134,7 +134,7 @@ struct CompatibleTypes { // Declaration here seems necessary for MSVC; specializations are // used instead. - typedef float Type; + typedef struct {} Type; }; // Specializations providing CompatibleTypes::Type value. @@ -150,11 +150,8 @@ template<> struct CompatibleTypes<Vector2<float> > { typedef ovrVector2f Type; template<> struct CompatibleTypes<Vector3<float> > { typedef ovrVector3f Type; }; template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; }; -template<> struct CompatibleTypes<Transform<float> > { typedef ovrPosef Type; }; -template<> struct CompatibleTypes<PoseState<float> > { typedef ovrPoseStatef Type; }; - -template<> struct CompatibleTypes<Transform<double> > { typedef ovrPosed Type; }; -template<> struct CompatibleTypes<PoseState<double> > { typedef ovrPoseStated Type; }; +template<> struct CompatibleTypes<Pose<float> > { typedef ovrPosef Type; }; +template<> struct CompatibleTypes<Pose<double> > { typedef ovrPosed Type; }; //------------------------------------------------------------------------------------// // ***** Math @@ -170,28 +167,40 @@ public: typedef float OtherFloatType; }; + +#define MATH_FLOAT_PI (3.1415926f) +#define MATH_FLOAT_TWOPI (2.0f *MATH_FLOAT_PI) +#define MATH_FLOAT_PIOVER2 (0.5f *MATH_FLOAT_PI) +#define MATH_FLOAT_PIOVER4 (0.25f*MATH_FLOAT_PI) +#define MATH_FLOAT_E (2.7182818f) +#define MATH_FLOAT_MAXVALUE (FLT_MAX) +#define MATH_FLOAT MINPOSITIVEVALUE (FLT_MIN) +#define MATH_FLOAT_RADTODEGREEFACTOR (360.0f / MATH_FLOAT_TWOPI) +#define MATH_FLOAT_DEGREETORADFACTOR (MATH_FLOAT_TWOPI / 360.0f) +#define MATH_FLOAT_TOLERANCE (0.00001f) +#define MATH_FLOAT_SINGULARITYRADIUS (0.0000001f) // Use for Gimbal lock numerical problems + +#define MATH_DOUBLE_PI (3.14159265358979) +#define MATH_DOUBLE_TWOPI (2.0f *MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER2 (0.5f *MATH_DOUBLE_PI) +#define MATH_DOUBLE_PIOVER4 (0.25f*MATH_DOUBLE_PI) +#define MATH_DOUBLE_E (2.71828182845905) +#define MATH_DOUBLE_MAXVALUE (DBL_MAX) +#define MATH_DOUBLE MINPOSITIVEVALUE (DBL_MIN) +#define MATH_DOUBLE_RADTODEGREEFACTOR (360.0f / MATH_DOUBLE_TWOPI) +#define MATH_DOUBLE_DEGREETORADFACTOR (MATH_DOUBLE_TWOPI / 360.0f) +#define MATH_DOUBLE_TOLERANCE (0.00001) +#define MATH_DOUBLE_SINGULARITYRADIUS (0.000000000001) // Use for Gimbal lock numerical problems + + + + // Single-precision Math constants class. template<> class Math<float> { public: - static const float Pi; - static const float TwoPi; - static const float PiOver2; - static const float PiOver4; - static const float E; - - static const float MaxValue; // Largest positive float Value - static const float MinPositiveValue; // Smallest possible positive value - - static const float RadToDegreeFactor; - static const float DegreeToRadFactor; - - static const float Tolerance; // 0.00001f; - static const float SingularityRadius; // 0.0000001f for Gimbal lock numerical problems - - // Used to support direct conversions in template classes. - typedef double OtherFloatType; + typedef double OtherFloatType; }; // Double-precision Math constants class. @@ -199,21 +208,6 @@ template<> class Math<double> { public: - static const double Pi; - static const double TwoPi; - static const double PiOver2; - static const double PiOver4; - static const double E; - - static const double MaxValue; // Largest positive double Value - static const double MinPositiveValue; // Smallest possible positive value - - static const double RadToDegreeFactor; - static const double DegreeToRadFactor; - - static const double Tolerance; // 0.00001; - static const double SingularityRadius; // 0.000000000001 for Gimbal lock numerical problems - typedef float OtherFloatType; }; @@ -223,23 +217,23 @@ typedef Math<double> Mathd; // Conversion functions between degrees and radians template<class T> -T RadToDegree(T rads) { return rads * Math<T>::RadToDegreeFactor; } +T RadToDegree(T rads) { return rads * ((T)MATH_DOUBLE_RADTODEGREEFACTOR); } template<class T> -T DegreeToRad(T rads) { return rads * Math<T>::DegreeToRadFactor; } +T DegreeToRad(T rads) { return rads * ((T)MATH_DOUBLE_DEGREETORADFACTOR); } // Numerically stable acos function template<class T> T Acos(T val) { if (val > T(1)) return T(0); - else if (val < T(-1)) return Math<T>::Pi; + else if (val < T(-1)) return ((T)MATH_DOUBLE_PI); else return acos(val); }; // Numerically stable asin function template<class T> T Asin(T val) { - if (val > T(1)) return Math<T>::PiOver2; - else if (val < T(-1)) return Math<T>::PiOver2 * T(3); + if (val > T(1)) return ((T)MATH_DOUBLE_PIOVER2); + else if (val < T(-1)) return ((T)MATH_DOUBLE_PIOVER2) * T(3); else return asin(val); }; @@ -307,12 +301,24 @@ public: (a.y > b.y) ? a.y : b.y); } // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. - bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) + bool Compare(const Vector2&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); } - // Entrywise product of two vectors + // Access element by index + T& operator[] (int idx) + { + OVR_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + const T& operator[] (int idx) const + { + OVR_ASSERT(0 <= idx && idx < 2); + return *(&x + idx); + } + + // Entry-wise product of two vectors Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);} @@ -341,13 +347,13 @@ public: T Length() const { return sqrt(LengthSq()); } // Returns squared distance between two points represented by vectors. - T DistanceSq(Vector2& b) const { return (*this - b).LengthSq(); } + T DistanceSq(const Vector2& b) const { return (*this - b).LengthSq(); } // Returns distance between two points represented by vectors. - T Distance(Vector2& b) const { return (*this - b).Length(); } + T Distance(const Vector2& b) const { return (*this - b).Length(); } // Determine if this a unit vector. - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } // Normalize, convention vector length to 1. void Normalize() @@ -383,6 +389,10 @@ typedef Vector2<float> Vector2f; typedef Vector2<double> Vector2d; typedef Vector2<int> Vector2i; +typedef Vector2<float> Point2f; +typedef Vector2<double> Point2d; +typedef Vector2<int> Point2i; + //------------------------------------------------------------------------------------- // ***** Vector3<> - 3D vector of {x, y, z} @@ -396,12 +406,16 @@ class Vector3 public: T x, y, z; + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. Vector3() : x(0), y(0), z(0) { } Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { } explicit Vector3(T s) : x(s), y(s), z(s) { } explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src) : x((T)src.x), y((T)src.y), z((T)src.z) { } + static const Vector3 ZERO; // C-interop support. typedef typename CompatibleTypes<Vector3<T> >::Type CompatibleType; @@ -447,7 +461,7 @@ public: } // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. - bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) + bool Compare(const Vector3&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && @@ -515,7 +529,7 @@ public: T Distance(Vector3 const& b) const { return (*this - b).Length(); } // Determine if this a unit vector. - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } // Normalize, convention vector length to 1. void Normalize() @@ -550,27 +564,204 @@ public: Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); } }; - typedef Vector3<float> Vector3f; typedef Vector3<double> Vector3d; -typedef Vector3<SInt32> Vector3i; +typedef Vector3<int32_t> Vector3i; + +typedef Vector3<float> Point3f; +typedef Vector3<double> Point3d; +typedef Vector3<int32_t> Point3i; -// JDC: this was defined in Render_Device.h, I moved it here, but it -// needs to be fleshed out like the other Vector types. +//------------------------------------------------------------------------------------- +// ***** Vector4<> - 4D vector of {x, y, z, w} + // -// A vector with a dummy w component for alignment in uniform buffers (and for float colors). -// The w component is not used in any calculations. +// Vector4f (Vector4d) represents a 3-dimensional vector or point in space, +// consisting of coordinates x, y, z and w. + +template<class T> +class Vector4 +{ +public: + T x, y, z, w; + + // FIXME: default initialization of a vector class can be very expensive in a full-blown + // application. A few hundred thousand vector constructions is not unlikely and can add + // up to milliseconds of time on processors like the PS3 PPU. + Vector4() : x(0), y(0), z(0), w(0) { } + Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { } + explicit Vector4(T s) : x(s), y(s), z(s), w(s) { } + explicit Vector4(const Vector3<T>& v, const float w_=1) : x(v.x), y(v.y), z(v.z), w(w_) { } + explicit Vector4(const Vector4<typename Math<T>::OtherFloatType> &src) + : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { } + + static const Vector4 ZERO; + + // C-interop support. + typedef typename CompatibleTypes< Vector4<T> >::Type CompatibleType; + + Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + + operator const CompatibleType& () const + { + OVR_COMPILER_ASSERT(sizeof(Vector4<T>) == sizeof(CompatibleType)); + return reinterpret_cast<const CompatibleType&>(*this); + } + + Vector4& operator= (const Vector3<T>& other) { x=other.x; y=other.y; z=other.z; w=1; return *this; } + bool operator== (const Vector4& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } + bool operator!= (const Vector4& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } + + Vector4 operator+ (const Vector4& b) const { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); } + Vector4& operator+= (const Vector4& b) { x += b.x; y += b.y; z += b.z; w += b.w; return *this; } + Vector4 operator- (const Vector4& b) const { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); } + Vector4& operator-= (const Vector4& b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; } + Vector4 operator- () const { return Vector4(-x, -y, -z, -w); } + + // Scalar multiplication/division scales vector. + Vector4 operator* (T s) const { return Vector4(x*s, y*s, z*s, w*s); } + Vector4& operator*= (T s) { x *= s; y *= s; z *= s; w *= s;return *this; } + + Vector4 operator/ (T s) const { T rcp = T(1)/s; + return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); } + Vector4& operator/= (T s) { T rcp = T(1)/s; + x *= rcp; y *= rcp; z *= rcp; w *= rcp; + return *this; } + + static Vector4 Min(const Vector4& a, const Vector4& b) + { + return Vector4((a.x < b.x) ? a.x : b.x, + (a.y < b.y) ? a.y : b.y, + (a.z < b.z) ? a.z : b.z, + (a.w < b.w) ? a.w : b.w); + } + static Vector4 Max(const Vector4& a, const Vector4& b) + { + return Vector4((a.x > b.x) ? a.x : b.x, + (a.y > b.y) ? a.y : b.y, + (a.z > b.z) ? a.z : b.z, + (a.w > b.w) ? a.w : b.w); + } + + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. + bool Compare(const Vector4&b, T tolerance = ((T)MATH_DOUBLE_TOLERANCE)) + { + return (fabs(b.x-x) < tolerance) && + (fabs(b.y-y) < tolerance) && + (fabs(b.z-z) < tolerance) && + (fabs(b.w-w) < tolerance); + } + + T& operator[] (int idx) + { + OVR_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + const T& operator[] (int idx) const + { + OVR_ASSERT(0 <= idx && idx < 4); + return *(&x + idx); + } + + // Entry wise product of two vectors + Vector4 EntrywiseMultiply(const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z);} + + // Multiply and divide operators do entry-wise math + Vector4 operator* (const Vector4& b) const { return Vector4(x * b.x, + y * b.y, + z * b.z, + w * b.w); } + + Vector4 operator/ (const Vector4& b) const { return Vector4(x / b.x, + y / b.y, + z / b.z, + w / b.w); } + + + // Dot product + T Dot(const Vector4& b) const { return x*b.x + y*b.y + z*b.z + w*b.w; } -struct Vector4f : public Vector3f + // Return Length of the vector squared. + T LengthSq() const { return (x * x + y * y + z * z + w * w); } + + // Return vector length. + T Length() const { return sqrt(LengthSq()); } + + // Determine if this a unit vector. + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + + // Normalize, convention vector length to 1. + void Normalize() + { + T l = Length(); + OVR_ASSERT(l != T(0)); + *this /= l; + } + + // Returns normalized (unit) version of the vector without modifying itself. + Vector4 Normalized() const + { + T l = Length(); + OVR_ASSERT(l != T(0)); + return *this / l; + } +}; + +typedef Vector4<float> Vector4f; +typedef Vector4<double> Vector4d; +typedef Vector4<int> Vector4i; + + +//------------------------------------------------------------------------------------- +// ***** Bounds3 + +// Bounds class used to describe a 3D axis aligned bounding box. + +template<class T> +class Bounds3 +{ +public: + Vector3<T> b[2]; + + Bounds3() + { + } + + Bounds3( const Vector3<T> & mins, const Vector3<T> & maxs ) { - float w; + b[0] = mins; + b[1] = maxs; + } + + void Clear() + { + b[0].x = b[0].y = b[0].z = Math<T>::MaxValue; + b[1].x = b[1].y = b[1].z = -Math<T>::MaxValue; + } + + void AddPoint( const Vector3<T> & v ) + { + b[0].x = Alg::Min( b[0].x, v.x ); + b[0].y = Alg::Min( b[0].y, v.y ); + b[0].z = Alg::Min( b[0].z, v.z ); + b[1].x = Alg::Max( b[1].x, v.x ); + b[1].y = Alg::Max( b[1].y, v.y ); + b[1].z = Alg::Max( b[1].z, v.z ); + } + + const Vector3<T> & GetMins() const { return b[0]; } + const Vector3<T> & GetMaxs() const { return b[1]; } - Vector4f() : w(1) {} - Vector4f(const Vector3f& v) : Vector3f(v), w(1) {} - Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {} + Vector3<T> & GetMins() { return b[0]; } + Vector3<T> & GetMaxs() { return b[1]; } }; +typedef Bounds3<float> Bounds3f; +typedef Bounds3<double> Bounds3d; //------------------------------------------------------------------------------------- @@ -626,7 +817,6 @@ public: static Size Max(const Size& a, const Size& b) { return Size((a.w > b.w) ? a.w : b.w, (a.h > b.h) ? a.h : b.h); } - T Area() const { return w * h; } inline Vector2<T> ToVector() const { return Vector2<T>(w, h); } @@ -702,12 +892,14 @@ public: explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src) : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { } + typedef typename CompatibleTypes<Quat<T> >::Type CompatibleType; + // C-interop support. - Quat(const typename CompatibleTypes<Quat<T> >::Type& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } + Quat(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) { } - operator typename CompatibleTypes<Quat<T> >::Type () const + operator CompatibleType () const { - typename CompatibleTypes<Quat<T> >::Type result; + CompatibleType result; result.x = x; result.y = y; result.z = z; @@ -753,12 +945,12 @@ public: // Compute axis and angle from quaternion void GetAxisAngle(Vector3<T>* axis, T* angle) const { - if ( x*x + y*y + z*z > Math<T>::Tolerance * Math<T>::Tolerance ) { + if ( x*x + y*y + z*z > ((T)MATH_DOUBLE_TOLERANCE) * ((T)MATH_DOUBLE_TOLERANCE) ) { *axis = Vector3<T>(x, y, z).Normalized(); *angle = 2 * Acos(w); - if (*angle > Math<T>::Pi) // Reduce the magnitude of the angle, if necessary + if (*angle > ((T)MATH_DOUBLE_PI)) // Reduce the magnitude of the angle, if necessary { - *angle = Math<T>::TwoPi - *angle; + *angle = ((T)MATH_DOUBLE_TWOPI) - *angle; *axis = *axis * (-1); } } @@ -903,7 +1095,7 @@ public: } // Normalize - bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < ((T)MATH_DOUBLE_TOLERANCE); } void Normalize() { @@ -973,8 +1165,8 @@ public: // is followed by rotation b around axis A2 // is followed by rotation c around axis A3 // rotations are CCW or CW (D) in LH or RH coordinate system (S) - template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> - void GetEulerAngles(T *a, T *b, T *c) const + template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> + void GetEulerAngles(T *a, T *b, T *c) const { OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); @@ -992,17 +1184,17 @@ public: T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]); - if (s2 < T(-1) + Math<T>::SingularityRadius) + if (s2 < T(-1) + ((T)MATH_DOUBLE_SINGULARITYRADIUS)) { // South pole singularity *a = T(0); - *b = -S*D*Math<T>::PiOver2; + *b = -S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33 ); } - else if (s2 > T(1) - Math<T>::SingularityRadius) + else if (s2 > T(1) - ((T)MATH_DOUBLE_SINGULARITYRADIUS)) { // North pole singularity *a = T(0); - *b = S*D*Math<T>::PiOver2; + *b = S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33); } @@ -1025,7 +1217,6 @@ public: void GetEulerAngles(T *a, T *b, T *c) const { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); } - // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of // axis rotations and the specified coordinate system. Right-handed coordinate system // is the default, with CCW rotations while looking in the negative axis direction. @@ -1059,7 +1250,7 @@ public: if (c2 < T(-1) + Math<T>::SingularityRadius) { // South pole singularity *a = T(0); - *b = S*D*Math<T>::Pi; + *b = S*D*((T)MATH_DOUBLE_PI); *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]), ww + Q22 - Q11 - Qmm); } @@ -1091,25 +1282,24 @@ typedef Quat<double> Quatd; // Position and orientation combined. template<class T> -class Transform +class Pose { public: + typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType; - typedef typename CompatibleTypes<Transform<T> >::Type CompatibleType; - - Transform() { } - Transform(const Quat<T>& orientation, const Vector3<T>& pos) + Pose() { } + Pose(const Quat<T>& orientation, const Vector3<T>& pos) : Rotation(orientation), Translation(pos) { } - Transform(const Transform& s) + Pose(const Pose& s) : Rotation(s.Rotation), Translation(s.Translation) { } - Transform(const CompatibleType& s) + Pose(const CompatibleType& s) : Rotation(s.Orientation), Translation(s.Position) { } - explicit Transform(const Transform<typename Math<T>::OtherFloatType> &s) + explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s) : Rotation(s.Rotation), Translation(s.Translation) { } - operator typename CompatibleTypes<Transform<T> >::Type () const + operator typename CompatibleTypes<Pose<T> >::Type () const { - typename CompatibleTypes<Transform<T> >::Type result; + typename CompatibleTypes<Pose<T> >::Type result; result.Orientation = Rotation; result.Position = Translation; return result; @@ -1133,31 +1323,20 @@ public: return Translate(Rotate(v)); } - Transform operator*(const Transform& other) const + Pose operator*(const Pose& other) const { - return Transform(Rotation * other.Rotation, Apply(other.Translation)); + return Pose(Rotation * other.Rotation, Apply(other.Translation)); } - PoseState<T> operator*(const PoseState<T>& poseState) const - { - PoseState<T> result; - result.Pose = (*this) * poseState.Pose; - result.LinearVelocity = this->Rotate(poseState.LinearVelocity); - result.LinearAcceleration = this->Rotate(poseState.LinearAcceleration); - result.AngularVelocity = this->Rotate(poseState.AngularVelocity); - result.AngularAcceleration = this->Rotate(poseState.AngularAcceleration); - return result; - } - - Transform Inverted() const + Pose Inverted() const { Quat<T> inv = Rotation.Inverted(); - return Transform(inv, inv.Rotate(-Translation)); + return Pose(inv, inv.Rotate(-Translation)); } }; -typedef Transform<float> Transformf; -typedef Transform<double> Transformd; +typedef Pose<float> Posef; +typedef Pose<double> Posed; //------------------------------------------------------------------------------------- @@ -1241,7 +1420,7 @@ public: M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1; } - explicit Matrix4(const Transform<T>& p) + explicit Matrix4(const Pose<T>& p) { Matrix4 result(p.Rotation); result.SetTranslation(p.Translation); @@ -1271,9 +1450,9 @@ public: return result; } - void ToString(char* dest, UPInt destsize) const + void ToString(char* dest, size_t destsize) const { - UPInt pos = 0; + size_t pos = 0; for (int r=0; r<4; r++) for (int c=0; c<4; c++) pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); @@ -1282,15 +1461,24 @@ public: static Matrix4 FromString(const char* src) { Matrix4 result; + if (src) + { for (int r=0; r<4; r++) + { for (int c=0; c<4; c++) { result.M[r][c] = (T)atof(src); while (src && *src != ' ') + { src++; + } while (src && *src == ' ') + { src++; } + } + } + } return result; } @@ -1304,6 +1492,39 @@ public: M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0; } + void SetXBasis(const Vector3f & v) + { + M[0][0] = v.x; + M[1][0] = v.y; + M[2][0] = v.z; + } + Vector3f GetXBasis() const + { + return Vector3f(M[0][0], M[1][0], M[2][0]); + } + + void SetYBasis(const Vector3f & v) + { + M[0][1] = v.x; + M[1][1] = v.y; + M[2][1] = v.z; + } + Vector3f GetYBasis() const + { + return Vector3f(M[0][1], M[1][1], M[2][1]); + } + + void SetZBasis(const Vector3f & v) + { + M[0][2] = v.x; + M[1][2] = v.y; + M[2][2] = v.z; + } + Vector3f GetZBasis() const + { + return Vector3f(M[0][2], M[1][2], M[2][2]); + } + bool operator== (const Matrix4& b) const { bool isEqual = true; @@ -1404,9 +1625,18 @@ public: Vector3<T> Transform(const Vector3<T>& v) const { - return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3], - M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3], - M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]); + const T rcpW = 1.0f / (M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3]); + return Vector3<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3]) * rcpW, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3]) * rcpW, + (M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]) * rcpW); + } + + Vector4<T> Transform(const Vector4<T>& v) const + { + return Vector4<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3] * v.w, + M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3] * v.w, + M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3] * v.w, + M[3][0] * v.x + M[3][1] * v.y + M[3][2] * v.z + M[3][3] * v.w); } Matrix4 Transposed() const @@ -1423,16 +1653,16 @@ public: } - T SubDet (const UPInt* rows, const UPInt* cols) const + T SubDet (const size_t* rows, const size_t* cols) const { return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]); } - T Cofactor(UPInt I, UPInt J) const + T Cofactor(size_t I, size_t J) const { - const UPInt indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; + const size_t indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); } @@ -1488,7 +1718,7 @@ public: // is followed by rotation c around axis A3 // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> - void ToEulerAngles(T *a, T *b, T *c) + void ToEulerAngles(T *a, T *b, T *c) const { OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); @@ -1500,13 +1730,13 @@ public: if (pm < -1.0f + Math<T>::SingularityRadius) { // South pole singularity *a = 0; - *b = -S*D*Math<T>::PiOver2; + *b = -S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); } else if (pm > 1.0f - Math<T>::SingularityRadius) { // North pole singularity *a = 0; - *b = S*D*Math<T>::PiOver2; + *b = S*D*((T)MATH_DOUBLE_PIOVER2); *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); } else @@ -1526,7 +1756,7 @@ public: // is followed by rotation c around axis A1 // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> - void ToEulerAnglesABA(T *a, T *b, T *c) + void ToEulerAnglesABA(T *a, T *b, T *c) const { OVR_COMPILER_ASSERT(A1 != A2); @@ -1541,7 +1771,7 @@ public: if (c2 < -1 + Math<T>::SingularityRadius) { // South pole singularity *a = 0; - *b = S*D*Math<T>::Pi; + *b = S*D*((T)MATH_DOUBLE_PI); *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); } else if (c2 > 1.0f - Math<T>::SingularityRadius) @@ -1781,19 +2011,20 @@ public: Matrix4 m; T tanHalfFov = tan(yfov * 0.5f); - m.M[0][0] = 1 / (aspect * tanHalfFov); - m.M[1][1] = 1 / tanHalfFov; - m.M[2][2] = zfar / (zfar - znear); - m.M[3][2] = 1; + m.M[0][0] = 1. / (aspect * tanHalfFov); + m.M[1][1] = 1. / tanHalfFov; + m.M[2][2] = zfar / (znear - zfar); + m.M[3][2] = -1.; m.M[2][3] = (zfar * znear) / (znear - zfar); - m.M[3][3] = 0; + m.M[3][3] = 0.; // Note: Post-projection matrix result assumes Left-Handed coordinate system, // with Y up, X right and Z forward. This supports positive z-buffer values. + // This is the case even for RHS coordinate input. return m; } - // PerspectiveRH creates a left-handed perspective projection matrix that can be + // PerspectiveLH creates a left-handed perspective projection matrix that can be // used with the Oculus sample renderer. // yfov - Specifies vertical field of view in radians. // aspect - Screen aspect ration, which is usually width/height for square pixels. @@ -1805,17 +2036,17 @@ public: Matrix4 m; T tanHalfFov = tan(yfov * 0.5f); - m.M[0][0] = 1.0 / (aspect * tanHalfFov); - m.M[1][1] = 1.0 / tanHalfFov; - m.M[2][2] = zfar / (znear - zfar); - // m.M[2][2] = zfar / (zfar - znear); - m.M[3][2] = -1.0; + m.M[0][0] = 1. / (aspect * tanHalfFov); + m.M[1][1] = 1. / tanHalfFov; + //m.M[2][2] = zfar / (znear - zfar); + m.M[2][2] = zfar / (zfar - znear); + m.M[3][2] = -1.; m.M[2][3] = (zfar * znear) / (znear - zfar); - m.M[3][3] = 0.0; + m.M[3][3] = 0.; // Note: Post-projection matrix result assumes Left-Handed coordinate system, // with Y up, X right and Z forward. This supports positive z-buffer values. - // This is the case even for RHS cooridnate input. + // This is the case even for RHS coordinate input. return m; } @@ -1916,7 +2147,7 @@ public: M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0; } - explicit Matrix3(const Transform<T>& p) + explicit Matrix3(const Pose<T>& p) { Matrix3 result(p.Rotation); result.SetTranslation(p.Translation); @@ -1938,7 +2169,7 @@ public: memcpy(M, s.M, sizeof(M)); } - operator typename CompatibleTypes<Matrix3<T> >::Type () const + operator const typename CompatibleTypes<Matrix3<T> >::Type () const { typename CompatibleTypes<Matrix3<T> >::Type result; OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix3)); @@ -1946,9 +2177,9 @@ public: return result; } - void ToString(char* dest, UPInt destsize) const + void ToString(char* dest, size_t destsize) const { - UPInt pos = 0; + size_t pos = 0; for (int r=0; r<3; r++) for (int c=0; c<3; c++) pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); @@ -2108,6 +2339,13 @@ public: return *this; } + Vector2<T> Transform(const Vector2<T>& v) const + { + const float rcpZ = 1.0f / (M[2][0] * v.x + M[2][1] * v.y + M[2][2]); + return Vector2<T>((M[0][0] * v.x + M[0][1] * v.y + M[0][2]) * rcpZ, + (M[1][0] * v.x + M[1][1] * v.y + M[1][2]) * rcpZ); + } + Vector3<T> Transform(const Vector3<T>& v) const { return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z, @@ -2128,7 +2366,7 @@ public: } - T SubDet (const UPInt* rows, const UPInt* cols) const + T SubDet (const size_t* rows, const size_t* cols) const { return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) @@ -2415,10 +2653,10 @@ public: Angle() : a(0) {} // Fix the range to be between -Pi and Pi - Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); } + Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : ((T)MATH_DOUBLE_DEGREETORADFACTOR)) { FixRange(); } - T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; } - void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); } + T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*((T)MATH_DOUBLE_RADTODEGREEFACTOR); } + void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*((T)MATH_DOUBLE_DEGREETORADFACTOR); FixRange(); } int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } T Abs() const { return (a > 0) ? a : -a; } @@ -2440,7 +2678,7 @@ public: Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; } Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; } - T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; } + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= ((T)MATH_DOUBLE_PI)) ? c : ((T)MATH_DOUBLE_TWOPI) - c; } private: @@ -2450,23 +2688,23 @@ private: // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side inline void FastFixRange() { - if (a < -Math<T>::Pi) - a += Math<T>::TwoPi; - else if (a > Math<T>::Pi) - a -= Math<T>::TwoPi; + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); } // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method inline void FixRange() { // do nothing if the value is already in the correct range, since fmod call is expensive - if (a >= -Math<T>::Pi && a <= Math<T>::Pi) + if (a >= -((T)MATH_DOUBLE_PI) && a <= ((T)MATH_DOUBLE_PI)) return; - a = fmod(a,Math<T>::TwoPi); - if (a < -Math<T>::Pi) - a += Math<T>::TwoPi; - else if (a > Math<T>::Pi) - a -= Math<T>::TwoPi; + a = fmod(a,((T)MATH_DOUBLE_TWOPI)); + if (a < -((T)MATH_DOUBLE_PI)) + a += ((T)MATH_DOUBLE_TWOPI); + else if (a > ((T)MATH_DOUBLE_PI)) + a -= ((T)MATH_DOUBLE_TWOPI); } }; @@ -2481,7 +2719,7 @@ typedef Angle<double> Angled; // Consists of a normal vector and distance from the origin where the plane is located. template<class T> -class Plane : public RefCountBase<Plane<T> > +class Plane { public: Vector3<T> N; @@ -2520,6 +2758,8 @@ public: }; typedef Plane<float> Planef; +typedef Plane<double> Planed; + } // Namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_Nullptr.h b/LibOVR/Src/Kernel/OVR_Nullptr.h new file mode 100644 index 0000000..3fd0969 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Nullptr.h @@ -0,0 +1,150 @@ +/************************************************************************************ + +PublicHeader: OVR_Kernel.h +Filename : OVR_Nullptr.h +Content : Implements C++11 nullptr for the case that the compiler doesn't. +Created : June 19, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Nullptr_h +#define OVR_Nullptr_h + +#pragma once + +#include "OVR_Types.h" + + +//----------------------------------------------------------------------------------- +// ***** OVR_HAVE_std_nullptr_t +// +// Identifies if <cstddef.h> includes std::nullptr_t. +// +#if !defined(OVR_HAVE_std_nullptr_t) && defined(OVR_CPP11_ENABLED) + #if defined(OVR_STDLIB_LIBCPP) + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(OVR_STDLIB_LIBSTDCPP) + #if (__GLIBCXX__ >= 20110325) && (__GLIBCXX__ != 20110428) && (__GLIBCXX__ != 20120702) + #define OVR_HAVE_std_nullptr_t 1 + #endif + #elif defined(_MSC_VER) && (_MSC_VER >= 1600) // VS2010+ + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(__clang__) + #define OVR_HAVE_std_nullptr_t 1 + #elif defined(OVR_CPP_GNUC) && (OVR_CPP_VERSION >= 406) // GCC 4.6+ + #define OVR_HAVE_std_nullptr_t 1 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** nullptr / std::nullptr_t +// +// Declares and defines nullptr and related types. +// +#if defined(OVR_CPP_NO_NULLPTR) + namespace std + { + class nullptr_t + { + public: + template <typename T> + operator T*() const + { return 0; } + + template <typename C, typename T> + operator T C::*() const + { return 0; } + + #if OVR_CPP_NO_EXPLICIT_CONVERSION_OPERATORS + typedef void* (nullptr_t::*bool_)() const; // 4.12,p1. We can't portably use operator bool(){ return false; } because bool + operator bool_() const // is convertable to int which breaks other required functionality. + { return false; } + #else + operator bool() const + { return false; } + #endif + + private: + void operator&() const; // 5.2.10,p9 + }; + + inline nullptr_t nullptr_get() + { + nullptr_t n = { }; + return n; + } + + #if !defined(nullptr) + #define nullptr nullptr_get() + #endif + + } // namespace std + + + // 5.9,p2 p4 + // 13.6, p13 + template <typename T> + inline bool operator==(T* pT, const std::nullptr_t) + { return pT == 0; } + + template <typename T> + inline bool operator==(const std::nullptr_t, T* pT) + { return pT == 0; } + + template <typename T, typename U> + inline bool operator==(const std::nullptr_t, T U::* pU) + { return pU == 0; } + + template <typename T, typename U> + inline bool operator==(T U::* pTU, const std::nullptr_t) + { return pTU == 0; } + + inline bool operator==(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator!=(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator>(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator>=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + using std::nullptr_t; + using std::nullptr_get; + +// Some compilers natively support C++11 nullptr but the standard library being used +// doesn't declare std::nullptr_t, in which case we provide one ourselves. +#elif !defined(OVR_HAVE_std_nullptr_t) && !defined(OVR_CPP_NO_DECLTYPE) + namespace std { typedef decltype(nullptr) nullptr_t; } +#endif + + +#endif + diff --git a/LibOVR/Src/Kernel/OVR_Observer.h b/LibOVR/Src/Kernel/OVR_Observer.h new file mode 100644 index 0000000..0f55551 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_Observer.h @@ -0,0 +1,457 @@ +/************************************************************************************ + +PublicHeader: Kernel +Filename : OVR_Observer.h +Content : Observer pattern +Created : June 20, 2014 +Author : Chris Taylor + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Observer_h +#define OVR_Observer_h + +#include "OVR_Types.h" +#include "OVR_Atomic.h" +#include "OVR_RefCount.h" +#include "OVR_Delegates.h" +#include "OVR_Array.h" +#include "OVR_String.h" +#include "OVR_Hash.h" + +namespace OVR { + +template<class DelegateT> class Observer; +template<class DelegateT> class ObserverScope; +template<class DelegateT> class ObserverHash; + + +//----------------------------------------------------------------------------- +// Observer pattern + +// An Observer will observe a Subject. The Subject can emit callbacks that get +// serviced by the Observers. + +// The trickiest part of this is the shutdown code. +// To simplify shutdown, the Observer is a reference-counted object divorced +// from the handler that is called. To avoid misuse, the ObserverScope object +// is provided to ensure that the Shutdown() method is called when it goes out +// of scope. + +// The Observer<> class doubles as the subject class. +// To avoid misuse, assertions are added if a subject tries to observe, or if +// an observer tries to be watched. + +/* + Usage example: + + Say we want to invoke a handler with the signature: + + void MyHandler(int i, bool b); + + The corresponding delegate type is: + + typedef Delegate2<void, int, bool> Handler; + + Note: The return value will be ignored for the Observer pattern. + + For this example there are two classes, one that emits events and another + that listens for events: +*/ + +/* + Event emitter example: + + class MyEmitter + { + ObserverScope<Handler> TheSubject; + + public: + void ClearAllListeners() + { + TheSubject.ReleaseAll(); + } + + void CallListeners(int x, bool y) + { + TheSubject->Call(x, y); + } + + Observer<Handler>* GetSubject() + { + return TheSubject; + } + }; +*/ + +/* + Event listener example: + + class MyListener + { + ObserverScope<Handler> TheObserver; + + void OnEvent(int x, bool y) + { + // Handle event here + } + + public: + MyListener() + { + TheObserver.SetHandler( + Handler::FromMember<MyListener, &MyListener::OnEvent>(this) + ); + } + + void ClearListener() + { + TheObserver.ReleaseAll(); + } + + void ListenTo(Observer<Handler>* emitter) + { + TheObserver->Observe(emitter); + } + }; +*/ + +/* + Usage example: + + MyListener listener; + MyEmitter emitter; + + // To listen to an emitter, + listener.ListenTo(emitter.GetSubject()); + + // To call the listeners, + emitter.CallListeners(22, true); +*/ + +template<class DelegateT> +class Observer : public RefCountBase< Observer<DelegateT> > +{ + friend class ObserverScope<DelegateT>; + friend class ObserverHash<DelegateT>; + +public: + typedef Observer<DelegateT> ThisType; + typedef DelegateT Handler; + +protected: + bool IsShutdown; // Flag to indicate that the object went out of scope + mutable Lock TheLock; // Lock to synchronize calls and shutdown + Array< Ptr< ThisType > > References; // List of observed or observing objects + Handler TheHandler; // Observer-only: Handler for callbacks + + Observer() : + IsShutdown(false) + { + TheHandler.Invalidate(); + } + Observer(Handler handler) : + IsShutdown(false), + TheHandler(handler) + { + } + ~Observer() + { + OVR_ASSERT(References.GetSizeI() == 0); + } + +public: + void SetHandler(Handler handler) + { + OVR_ASSERT(References.GetSizeI() == 0); + TheHandler = handler; + } + + // Release references and prevent further actions + void Shutdown() + { + Lock::Locker locker(&TheLock); + IsShutdown = true; + References.ClearAndRelease(); + } + + // Get count of references held + int GetSizeI() const + { + Lock::Locker locker(&TheLock); + return References.GetSizeI(); + } + + // Observe a subject + bool Observe(ThisType *subject) + { + OVR_ASSERT(TheHandler.IsValid()); + + if (!subject) + { + return false; + } + + Lock::Locker locker(&TheLock); + + if (IsShutdown) + { + return false; + } + + if (!subject->SubjectAddObserver(this)) + { + return false; + } + + References.PushBack(subject); + return true; + } + +protected: + // Subject function: AddObserver() + // Returns true if the observer was added + bool SubjectAddObserver(ThisType* observer) + { + OVR_ASSERT(!TheHandler.IsValid()); + + if (!observer) + { + return true; + } + + Lock::Locker locker(&TheLock); + + if (IsShutdown) + { + return false; + } + + const int count = References.GetSizeI(); + for (int i = 0; i < count; ++i) + { + if (References[i] == observer) + { + // Already watched + return true; + } + } + + References.PushBack(observer); + + return true; + } + +public: + // Subject function: Call() +#define OVR_OBSERVER_CALL_BODY(params) \ + bool callSuccess = false; \ + Lock::Locker locker(&TheLock); \ + int count = References.GetSizeI(); \ + for (int i = 0; i < count; ++i) \ + { \ + if (!References[i]->IsShutdown) \ + { \ + OVR_ASSERT(References[i]->TheHandler.IsValid()); \ + References[i]->TheHandler params; \ + callSuccess = true; \ + } \ + if (References[i]->IsShutdown) \ + { \ + References.RemoveAt(i); \ + --i; --count; \ + } \ + } \ + return callSuccess; + + // Call: Various parameter counts + // Returns true if a call was made + bool Call() + { + OVR_OBSERVER_CALL_BODY(()); + } + template<class Param1> + bool Call(Param1& p1) + { + OVR_OBSERVER_CALL_BODY((p1)); + } + template<class Param1> + bool Call(Param1* p1) + { + OVR_OBSERVER_CALL_BODY((p1)); + } + template<class Param1, class Param2> + bool Call(Param1& p1, Param2& p2) + { + OVR_OBSERVER_CALL_BODY((p1, p2)); + } + template<class Param1, class Param2> + bool Call(Param1* p1, Param2* p2) + { + OVR_OBSERVER_CALL_BODY((p1, p2)); + } + template<class Param1, class Param2, class Param3> + bool Call(Param1& p1, Param2& p2, Param3& p3) + { + OVR_OBSERVER_CALL_BODY((p1, p2, p3)); + } + template<class Param1, class Param2, class Param3> + bool Call(Param1* p1, Param2* p2, Param3* p3) + { + OVR_OBSERVER_CALL_BODY((p1, p2, p3)); + } + +#undef OVR_OBSERVER_CALL_BODY +}; + + +//----------------------------------------------------------------------------- +// ObserverScope + +// Scoped shutdown of the Observer object +template<class DelegateT> +class ObserverScope : public NewOverrideBase +{ + Ptr< Observer<DelegateT> > TheObserver; + DelegateT TheHandler; + + void Shutdown() + { + if (TheObserver) + { + TheObserver->Shutdown(); + TheObserver.Clear(); + } + } + +public: + ObserverScope() + { + TheObserver = *new Observer<DelegateT>; + } + ~ObserverScope() + { + Shutdown(); + } + + // Release all references and recreate it + void ReleaseAll() + { + Shutdown(); + TheObserver = *new Observer<DelegateT>; + if (TheHandler.IsValid()) + { + TheObserver->SetHandler(TheHandler); + } + } + + void SetHandler(DelegateT handler) + { + TheHandler = handler; + TheObserver->SetHandler(handler); + } + + Observer<DelegateT>* GetPtr() + { + return TheObserver.GetPtr(); + } + Observer<DelegateT>* operator->() + { + return TheObserver.GetPtr(); + } + const Observer<DelegateT>* operator->() const + { + return TheObserver.GetPtr(); + } + operator Observer<DelegateT>*() + { + return TheObserver.GetPtr(); + } +}; + + +//----------------------------------------------------------------------------- +// ObserverHash + +// A hash containing Observers +template<class DelegateT> +class ObserverHash : public NewOverrideBase +{ +public: + ObserverHash() {} + ~ObserverHash() {Clear();} + void Clear() + { + Lock::Locker locker(&TheLock); + typename OVR::Hash< String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor >::Iterator it = _Hash.Begin(); + for( it = _Hash.Begin(); it != _Hash.End(); ++it ) + { + Ptr<Observer<DelegateT> > o = it->Second; + o->Shutdown(); + } + } + + Ptr<Observer<DelegateT> > GetSubject(OVR::String key) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *o = _Hash.Get(key); + if (o) + return (*o); + return NULL; + } + + // Add handler to new observer with implicit creation of subject. + void AddObserverToSubject(OVR::String key, Observer<DelegateT> *observer) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); + + if (subjectPtr==NULL) + { + Ptr<Observer<DelegateT> > subject = *new Observer<DelegateT>(); + _Hash.Add(key, subject); + observer->Observe(subject); + } + else + { + observer->Observe(*subjectPtr); + } + } + + void RemoveSubject(OVR::String key) + { + Lock::Locker locker(&TheLock); + Ptr<Observer<DelegateT> > *subjectPtr = _Hash.Get(key); + if (subjectPtr!=NULL) + { + (*subjectPtr)->Shutdown(); + _Hash.Remove(key); + } + } + +protected: + OVR::Hash< OVR::String, Ptr<Observer<DelegateT> >, OVR::String::HashFunctor > _Hash; + Lock TheLock; // Lock to synchronize calls and shutdown +}; + + +} // namespace OVR + +#endif // OVR_Observer_h diff --git a/LibOVR/Src/Kernel/OVR_RefCount.h b/LibOVR/Src/Kernel/OVR_RefCount.h index 775e24c..e6ae936 100644 --- a/LibOVR/Src/Kernel/OVR_RefCount.h +++ b/LibOVR/Src/Kernel/OVR_RefCount.h @@ -413,6 +413,7 @@ public: template<class R> OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src) { + // By design we don't check for src == pObject, as we don't expect that to be the case the large majority of the time. if (src) src->AddRef(); if (pObject) pObject->Release(); pObject = src; diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.cpp b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp new file mode 100644 index 0000000..b314e58 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp @@ -0,0 +1,693 @@ +/************************************************************************************ + +Filename : OVR_SharedMemory.cpp +Content : Inter-process shared memory subsystem +Created : June 1, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "OVR_SharedMemory.h" +#include "OVR_Atomic.h" +#include "OVR_Log.h" +#include "OVR_String.h" +#include "OVR_Array.h" + +#undef new + +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) +#include <Sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor +#endif // OVR_OS_WIN32 + +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) +#include <sys/mman.h> // shm_open(), mmap() +#include <errno.h> // error results for mmap +#include <sys/stat.h> // mode constants +#include <fcntl.h> // O_ constants +#include <unistd.h> // close() +#endif // OVR_OS_LINUX + +OVR_DEFINE_SINGLETON(OVR::SharedMemoryFactory); + +namespace OVR { + + + //// Fake version + +#if defined(OVR_FAKE_SHAREDMEMORY) + + class FakeMemoryBlock : public RefCountBase<FakeMemoryBlock> + { + String Name; + char* Data; + int SizeBytes; + int References; + + public: + FakeMemoryBlock(const String& name, int size) : + Name(name), + Data(NULL), + SizeBytes(size), + References(1) + { + Data = new char[SizeBytes]; + } + ~FakeMemoryBlock() + { + delete[] Data; + } + + bool IsNamed(const String& name) + { + return Name.CompareNoCase(name) == 0; + } + void* GetData() + { + return Data; + } + int GetSizeI() + { + return SizeBytes; + } + void IncrementReferences() + { + ++References; + } + bool DecrementReferences() + { + return --References <= 0; + } + }; + + class SharedMemoryInternal : public NewOverrideBase + { + public: + void* FileView; + Ptr<FakeMemoryBlock> Block; + + void Close(); + + SharedMemoryInternal(FakeMemoryBlock* block) : + Block(block) + { + FileView = Block->GetData(); + } + ~SharedMemoryInternal() + { + Close(); + } + + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); + }; + + + //// FakeMemoryManager + + class FakeMemoryManager : public NewOverrideBase, public SystemSingletonBase<FakeMemoryManager> + { + OVR_DECLARE_SINGLETON(FakeMemoryManager); + + Lock FakeLock; + Array< Ptr<FakeMemoryBlock> > FakeArray; + + public: + SharedMemoryInternal* Open(const char *name, int bytes, bool openOnly) + { + Lock::Locker locker(&FakeLock); + + const int count = FakeArray.GetSizeI(); + for (int ii = 0; ii < count; ++ii) + { + if (FakeArray[ii]->IsNamed(name)) + { + FakeArray[ii]->IncrementReferences(); + return new SharedMemoryInternal(FakeArray[ii]); + } + } + + if (openOnly) + { + return NULL; + } + + Ptr<FakeMemoryBlock> data = *new FakeMemoryBlock(name, bytes); + FakeArray.PushBack(data); + return new SharedMemoryInternal(data); + } + + void Free(FakeMemoryBlock* block) + { + Lock::Locker locker(&FakeLock); + + const int count = FakeArray.GetSizeI(); + for (int ii = 0; ii < count; ++ii) + { + if (FakeArray[ii].GetPtr() == block) + { + // If the reference count hit zero, + if (FakeArray[ii]->DecrementReferences()) + { + // Toast + FakeArray.RemoveAtUnordered(ii); + } + break; + } + } + } + }; + + FakeMemoryManager::FakeMemoryManager() + { + PushDestroyCallbacks(); + } + + FakeMemoryManager::~FakeMemoryManager() + { + OVR_ASSERT(FakeArray.GetSizeI() == 0); + } + + void FakeMemoryManager::OnSystemDestroy() + { + delete this; + } + + +} // namespace OVR + +OVR_DEFINE_SINGLETON(FakeMemoryManager); + +namespace OVR { + + +void SharedMemoryInternal::Close() +{ + FakeMemoryManager::GetInstance()->Free(Block); + Block.Clear(); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + return FakeMemoryManager::GetInstance()->Open(params.globalName, params.minSizeBytes, params.openMode == SharedMemory::OpenMode_OpenOnly); +} + +#endif + + +//// Windows version + +#if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) + +#pragma comment(lib, "advapi32.lib") + +// Hidden implementation class for OS-specific behavior +class SharedMemoryInternal : public NewOverrideBase +{ +public: + HANDLE FileMapping; + void* FileView; + + SharedMemoryInternal(HANDLE fileMapping, void* fileView) : + FileMapping(fileMapping), + FileView(fileView) + { + } + + ~SharedMemoryInternal() + { + // If file view is set, + if (FileView) + { + UnmapViewOfFile(FileView); + FileView = NULL; + } + + // If file mapping is set, + if (FileMapping != NULL) + { + CloseHandle(FileMapping); + FileMapping = NULL; + } + } + + static SharedMemoryInternal* DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize); + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); +}; + +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(HANDLE hFileMapping, const char* fileName, bool openReadOnly, int minSize) +{ + // Interpret the access mode as a map desired access code + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; + + // Map view of the file to this process + void* pFileView = MapViewOfFile(hFileMapping, mapDesiredAccess, 0, 0, minSize); + + // If mapping could not be created, + if (!pFileView) + { + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, GetLastError())); + OVR_UNUSED(fileName); + return NULL; + } + + // Create internal representation + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView); + + // If memory allocation fails, + if (!pimple) + { + UnmapViewOfFile(pFileView); + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); + return NULL; + } + + return pimple; +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) +{ + // Interpret the access mode as a map desired access code + DWORD mapDesiredAccess = openReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE; + + // Open file mapping + HANDLE hFileMapping = OpenFileMappingA(mapDesiredAccess, TRUE, fileName); + + // If file was mapped unsuccessfully, + if (NULL == hFileMapping) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, GetLastError())); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) +{ + // Prepare a SECURITY_ATTRIBUTES object + SECURITY_ATTRIBUTES security; + ZeroMemory(&security, sizeof(security)); + security.nLength = sizeof(security); + + // Security descriptor by DACL strings: + // ACE strings grant Allow(A), Object/Contains Inheritance (OICI) of: + // + Grant All (GA) to System (SY) + // + Grant All (GA) to Built-in Administrators (BA) + // + Grant Read-Only (GR) or Read-Write (GWGR) to Interactive Users (IU) - ie. games + static const char* DACLString_ReadOnly = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)"; + static const char* DACLString_ReadWrite = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)"; + + // Select the remote process access mode + const char* remoteAccessString = + allowRemoteWrite ? DACLString_ReadWrite : DACLString_ReadOnly; + + // Attempt to convert access string to security attributes + // Note: This will allocate the security descriptor with LocalAlloc() and must be freed later + BOOL bConvertOkay = ConvertStringSecurityDescriptorToSecurityDescriptorA( + remoteAccessString, SDDL_REVISION_1, &security.lpSecurityDescriptor, NULL); + + // If conversion fails, + if (!bConvertOkay) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to convert access string, error code = %d", GetLastError())); + return NULL; + } + + // Interpret the access mode as a page protection code + int pageProtectCode = openReadOnly ? PAGE_READONLY : PAGE_READWRITE; + + // Attempt to create a file mapping + HANDLE hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, // From page file + &security, // Security attributes + pageProtectCode, // Read-only? + 0, // High word for size = 0 + minSize, // Low word for size + fileName); // Name of global shared memory file + + // Free the security descriptor buffer + LocalFree(security.lpSecurityDescriptor); + + // If mapping could not be created, + if (NULL == hFileMapping) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, GetLastError())); + return NULL; + } + +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS + // If the file mapping already exists, + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: File mapping at %s already exists", fileName)); + return NULL; + } +#endif + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + SharedMemoryInternal* retval = NULL; + + // Construct the file mapping name in a Windows-specific way + OVR::String fileMappingName = params.globalName; + const char *fileName = fileMappingName.ToCStr(); + + // Is being opened read-only? + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); + + // Try up to 3 times to reduce low-probability failures: + static const int ATTEMPTS_MAX = 3; + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) + { + // If opening should be attempted first, + if (params.openMode != SharedMemory::OpenMode_CreateOnly) + { + // Attempt to open a shared memory map + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); + + // If successful, + if (retval) + { + // Done! + break; + } + } + + // If creating the shared memory is also acceptable, + if (params.openMode != SharedMemory::OpenMode_OpenOnly) + { + // Interpret create mode + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); + + // Attempt to create a shared memory map + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); + + // If successful, + if (retval) + { + // Done! + break; + } + } + } // Re-attempt create/open + + // Note: On Windows the initial contents of the region are guaranteed to be zero. + return retval; +} + +#endif // OVR_OS_WIN32 + + +#if (defined(OVR_OS_LINUX) || defined(OVR_OS_MAC)) && !defined(OVR_FAKE_SHAREDMEMORY) + +// Hidden implementation class for OS-specific behavior +class SharedMemoryInternal +{ +public: + int FileMapping; + void* FileView; + int FileSize; + + SharedMemoryInternal(int fileMapping, void* fileView, int fileSize) : + FileMapping(fileMapping), + FileView(fileView), + FileSize(fileSize) + { + } + + ~SharedMemoryInternal() + { + // If file view is set, + if (FileView) + { + munmap(FileView, FileSize); + FileView = MAP_FAILED; + } + + // If file mapping is set, + if (FileMapping >= 0) + { + close(FileMapping); + FileMapping = -1; + } + } + + static SharedMemoryInternal* DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize); + static SharedMemoryInternal* AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly); + static SharedMemoryInternal* AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite); + static SharedMemoryInternal* CreateSharedMemory(const SharedMemory::OpenParameters& params); +}; + +SharedMemoryInternal* SharedMemoryInternal::DoFileMap(int hFileMapping, const char* fileName, bool openReadOnly, int minSize) +{ + // Calculate the required flags based on read/write mode + int prot = openReadOnly ? PROT_READ : (PROT_READ|PROT_WRITE); + + // Map the file view + void* pFileView = mmap(NULL, minSize, prot, MAP_SHARED, hFileMapping, 0); + + if (pFileView == MAP_FAILED) + { + close(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to map view of file for %s error code = %d", fileName, errno)); + OVR_UNUSED(fileName); + return NULL; + } + + // Create internal representation + SharedMemoryInternal* pimple = new SharedMemoryInternal(hFileMapping, pFileView, minSize); + + // If memory allocation fails, + if (!pimple) + { + munmap(pFileView, minSize); + close(hFileMapping); + + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Out of memory")); + return NULL; + } + + return pimple; +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptOpenSharedMemory(const char* fileName, int minSize, bool openReadOnly) +{ + // Calculate permissions and flags based on read/write mode + int flags = openReadOnly ? O_RDONLY : O_RDWR; + int perms = openReadOnly ? S_IRUSR : (S_IRUSR | S_IWUSR); + + // Attempt to open the shared memory file + int hFileMapping = shm_open(fileName, flags, perms); + + // If file was not opened successfully, + if (hFileMapping < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to open file mapping for %s error code = %d (not necessarily bad)", fileName, errno)); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::AttemptCreateSharedMemory(const char* fileName, int minSize, bool openReadOnly, bool allowRemoteWrite) +{ + // Create mode + // Note: Cannot create the shared memory file read-only because then ftruncate() will fail. + int flags = O_CREAT | O_RDWR; + +#ifndef OVR_ALLOW_CREATE_FILE_MAPPING_IF_EXISTS + // Require exclusive access when creating (seems like a good idea without trying it yet..) + if (shm_unlink(fileName) < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] WARNING: Unable to unlink shared memory file %s error code = %d", fileName, errno)); + } + flags |= O_EXCL; +#endif + + // Set own read/write permissions + int perms = openReadOnly ? S_IRUSR : (S_IRUSR|S_IWUSR); + + // Allow other users to read/write the shared memory file + perms |= allowRemoteWrite ? (S_IWGRP|S_IWOTH|S_IRGRP|S_IROTH) : (S_IRGRP|S_IROTH); + + // Attempt to open the shared memory file + int hFileMapping = shm_open(fileName, flags, perms); + + // If file was not opened successfully, + if (hFileMapping < 0) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to create file mapping for %s error code = %d", fileName, errno)); + return NULL; + } + + int truncRes = ftruncate(hFileMapping, minSize); + + // If file was not opened successfully, + if (truncRes < 0) + { + close(hFileMapping); + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Unable to truncate file for %s to %d error code = %d", fileName, minSize, errno)); + return NULL; + } + + // Map the file + return DoFileMap(hFileMapping, fileName, openReadOnly, minSize); +} + +SharedMemoryInternal* SharedMemoryInternal::CreateSharedMemory(const SharedMemory::OpenParameters& params) +{ + SharedMemoryInternal* retval = NULL; + + // Construct the file mapping name in a Linux-specific way + OVR::String fileMappingName = "/"; + fileMappingName += params.globalName; + const char *fileName = fileMappingName.ToCStr(); + + // Is being opened read-only? + const bool openReadOnly = (params.accessMode == SharedMemory::AccessMode_ReadOnly); + + // Try up to 3 times to reduce low-probability failures: + static const int ATTEMPTS_MAX = 3; + for (int attempts = 0; attempts < ATTEMPTS_MAX; ++attempts) + { + // If opening should be attempted first, + if (params.openMode != SharedMemory::OpenMode_CreateOnly) + { + // Attempt to open a shared memory map + retval = AttemptOpenSharedMemory(fileName, params.minSizeBytes, openReadOnly); + + // If successful, + if (retval) + { + // Done! + break; + } + } + + // If creating the shared memory is also acceptable, + if (params.openMode != SharedMemory::OpenMode_OpenOnly) + { + // Interpret create mode + const bool allowRemoteWrite = (params.remoteMode == SharedMemory::RemoteMode_ReadWrite); + + // Attempt to create a shared memory map + retval = AttemptCreateSharedMemory(fileName, params.minSizeBytes, openReadOnly, allowRemoteWrite); + + // If successful, + if (retval) + { + // Done! + break; + } + } + } // Re-attempt create/open + + // Note: On Windows the initial contents of the region are guaranteed to be zero. + return retval; +} + +#endif // OVR_OS_LINUX + + +//// SharedMemory + +SharedMemory::SharedMemory(int size, void* data, SharedMemoryInternal* pInternal) : + Size(size), + Data(data), + Internal(pInternal) +{ +} +// Call close when it goes out of scope +SharedMemory::~SharedMemory() +{ + Close(); + delete Internal; +} + +void SharedMemory::Close() +{ + if (Internal) + { + delete Internal; + Internal = NULL; + } +} + + +//// SharedMemoryFactory + +Ptr<SharedMemory> SharedMemoryFactory::Open(const SharedMemory::OpenParameters& params) +{ + Ptr<SharedMemory> retval; + + // If no name specified or no size requested, + if (!params.globalName || (params.minSizeBytes <= 0)) + { + OVR_DEBUG_LOG(("[SharedMemory] FAILURE: Invalid parameters to Create()")); + return NULL; + } + + OVR_DEBUG_LOG(("[SharedMemory] Creating shared memory region: %s > %d bytes", + params.globalName, params.minSizeBytes)); + + // Attempt to create a shared memory region from the parameters + SharedMemoryInternal* pInternal = SharedMemoryInternal::CreateSharedMemory(params); + + if (pInternal) + { + // Create the wrapper object + retval = *new SharedMemory(params.minSizeBytes, pInternal->FileView, pInternal); + } + + return retval; +} + +SharedMemoryFactory::SharedMemoryFactory() +{ + OVR_DEBUG_LOG(("[SharedMemory] Creating factory")); + + PushDestroyCallbacks(); +} + +SharedMemoryFactory::~SharedMemoryFactory() +{ + OVR_DEBUG_LOG(("[SharedMemory] Destroying factory")); +} + +void SharedMemoryFactory::OnSystemDestroy() +{ + delete this; +} + + +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.h b/LibOVR/Src/Kernel/OVR_SharedMemory.h new file mode 100644 index 0000000..d18b583 --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.h @@ -0,0 +1,237 @@ +/************************************************************************************ + +PublicHeader: OVR +Filename : OVR_SharedMemory.h +Content : Inter-process shared memory subsystem +Created : June 1, 2014 +Notes : + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_SharedMemory_h +#define OVR_SharedMemory_h + +#include "OVR_Types.h" +#include "OVR_RefCount.h" +#include "OVR_Allocator.h" +#include "OVR_System.h" + +#ifdef OVR_SINGLE_PROCESS /* Everything running in one process usually for debugging */ +#define OVR_FAKE_SHAREDMEMORY /* Single-process version to avoid admin privs */ +#endif + +namespace OVR { + +class SharedMemoryInternal; // Opaque + + +// SharedMemory +// Note: Safe when used between 32-bit and 64-bit processes +class SharedMemory : public RefCountBase<SharedMemory> +{ + friend class SharedMemoryFactory; + + SharedMemory(SharedMemory&) {} + void operator=(SharedMemory&) {} + +public: + // Only constructed by the SharedMemory Factory + SharedMemory(int size, void* data, SharedMemoryInternal* pInternal); + // Call close when it goes out of scope + ~SharedMemory(); + + // Modes for opening a new shared memory region + enum OpenMode + { + // Note: On Windows, Create* requires Administrator priviledges or running as a Service. + OpenMode_CreateOnly, // Must not already exist + OpenMode_OpenOnly, // Must already exist + OpenMode_CreateOrOpen // May exist or not + }; + + // Local access restrictions + enum AccessMode + { + AccessMode_ReadOnly, // Acquire read-only access + AccessMode_ReadWrite, // Acquire read or write access + }; + + // Remote access restrictions + enum RemoteMode + { + RemoteMode_ReadOnly, // Other processes will need to open in read-only mode + RemoteMode_ReadWrite // Other processes can open in read-write mode + }; + + // Modes for opening a new shared memory region + struct OpenParameters + { + OpenParameters() : + globalName(NULL), + minSizeBytes(0), + openMode(SharedMemory::OpenMode_CreateOrOpen), + remoteMode(SharedMemory::RemoteMode_ReadWrite), + accessMode(SharedMemory::AccessMode_ReadWrite) + { + } + + // Creation parameters + const char* globalName; // Name of the shared memory region + int minSizeBytes; // Minimum number of bytes to request + SharedMemory::OpenMode openMode; // Creating the file or opening the file? + SharedMemory::RemoteMode remoteMode; // When creating, what access should other processes get? + SharedMemory::AccessMode accessMode; // When opening/creating, what access should this process get? + }; + +public: + // Returns the size of the shared memory region + int GetSizeI() const + { + return Size; + } + + // Returns the process-local pointer to the shared memory region + // Note: This may be different on different processes + void* GetData() const + { + return Data; + } + +protected: + int Size; // How many shared bytes are shared at the pointer address? + void* Data; // Pointer to the shared memory region. + + // Hidden implementation class for OS-specific behavior + SharedMemoryInternal* Internal; + + // Close and cleanup the shared memory region + // Note: This is called on destruction + void Close(); +}; + + +// SharedMemoryFactory +class SharedMemoryFactory : public NewOverrideBase, public SystemSingletonBase<SharedMemoryFactory> +{ + OVR_DECLARE_SINGLETON(SharedMemoryFactory); + +public: + // Construct a SharedMemory object. + // Note: The new object is reference-counted so it should be stored with Ptr<>. Initial reference count is 1. + Ptr<SharedMemory> Open(const SharedMemory::OpenParameters&); +}; + + +// A shared object +// Its constructor will be called when creating a writer +// Its destructor will not be called +template<class SharedType> +class ISharedObject : public NewOverrideBase +{ +public: + static const int RegionSize = (int)sizeof(SharedType); + +protected: + Ptr<SharedMemory> pSharedMemory; + + bool Open(const char* name, bool readOnly) + { + // Configure open parameters based on read-only mode + SharedMemory::OpenParameters params; + params.globalName = name; + // FIXME: This is a hack. We currently need to open this for read-write even when just reading from + // it because the LocklessUpdater class technically writes to it (increments by 0). + //params.accessMode = readOnly ? SharedMemory::AccessMode_ReadOnly : SharedMemory::AccessMode_ReadWrite; + //params.remoteMode = SharedMemory::RemoteMode_ReadOnly; + params.accessMode = SharedMemory::AccessMode_ReadWrite; + params.remoteMode = SharedMemory::RemoteMode_ReadWrite; + params.minSizeBytes = RegionSize; + params.openMode = readOnly ? SharedMemory::OpenMode_OpenOnly : SharedMemory::OpenMode_CreateOrOpen; + + // Attempt to open the shared memory file + pSharedMemory = SharedMemoryFactory::GetInstance()->Open(params); + + // If it was not able to be opened, + if (pSharedMemory && pSharedMemory->GetSizeI() >= RegionSize && pSharedMemory->GetData()) + { + // If writing, + if (!readOnly) + { + // Construct the object also + Construct<SharedType>(pSharedMemory->GetData()); + } + + return true; + } + + return false; + } + + SharedType* Get() const + { + if (!pSharedMemory) + { + return NULL; + } + + void* data = pSharedMemory->GetData(); + if (!data) + { + return NULL; + } + + return reinterpret_cast<SharedType*>(data); + } +}; + +// Writer specialized shared object: Ctor will be called on Open() +template<class SharedType> +class SharedObjectWriter : public ISharedObject<SharedType> +{ +public: + OVR_FORCE_INLINE bool Open(const char* name) + { + return ISharedObject<SharedType>::Open(name, false); + } + OVR_FORCE_INLINE SharedType* Get() + { + return ISharedObject<SharedType>::Get(); + } +}; + +// Reader specialized shared object: Ctor will not be called +template<class SharedType> +class SharedObjectReader : public ISharedObject<SharedType> +{ +public: + OVR_FORCE_INLINE bool Open(const char* name) + { + return ISharedObject<SharedType>::Open(name, true); + } + OVR_FORCE_INLINE const SharedType* Get() const + { + return ISharedObject<SharedType>::Get(); + } +}; + + +} // namespace OVR + +#endif // OVR_SharedMemory_h diff --git a/LibOVR/Src/Kernel/OVR_Std.cpp b/LibOVR/Src/Kernel/OVR_Std.cpp index 6b5be18..5f47015 100644 --- a/LibOVR/Src/Kernel/OVR_Std.cpp +++ b/LibOVR/Src/Kernel/OVR_Std.cpp @@ -37,7 +37,7 @@ namespace OVR { // Case insensitive compare implemented in platform-specific way. int OVR_CDECL OVR_stricmp(const char* a, const char* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_stricmp(a, b); #else @@ -49,9 +49,9 @@ int OVR_CDECL OVR_stricmp(const char* a, const char* b) #endif } -int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count) +int OVR_CDECL OVR_strnicmp(const char* a, const char* b, size_t count) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_strnicmp(a, b, count); #else @@ -63,7 +63,7 @@ int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count) #endif } -wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src) +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src) { #if defined(OVR_MSVC_SAFESTRING) wcscpy_s(dest, destsize, src); @@ -73,26 +73,26 @@ wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src) wcscpy(dest, src); return dest; #else - UPInt l = OVR_wcslen(src) + 1; // incl term null + size_t l = OVR_wcslen(src) + 1; // incl term null l = (l < destsize) ? l : destsize; memcpy(dest, src, l * sizeof(wchar_t)); return dest; #endif } -wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count) +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count) { #if defined(OVR_MSVC_SAFESTRING) wcsncpy_s(dest, destsize, src, count); return dest; #else - UPInt srclen = OVR_wcslen(src); - UPInt l = Alg::Min(srclen, count); + size_t srclen = OVR_wcslen(src); + size_t l = Alg::Min(srclen, count); l = (l < destsize) ? l : destsize; memcpy(dest, src, l * sizeof(wchar_t)); if (count > srclen) { - UPInt remLen = Alg::Min(destsize - l, (count - srclen)); + size_t remLen = Alg::Min(destsize - l, (count - srclen)); memset(&dest[l], 0, sizeof(wchar_t)*remLen); } else if (l < destsize) @@ -102,7 +102,7 @@ wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src } -wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src) +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src) { #if defined(OVR_MSVC_SAFESTRING) wcscat_s(dest, destsize, src); @@ -112,20 +112,20 @@ wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src) wcscat(dest, src); return dest; #else - UPInt dstlen = OVR_wcslen(dest); // do not incl term null - UPInt srclen = OVR_wcslen(src) + 1; // incl term null - UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; + size_t dstlen = OVR_wcslen(dest); // do not incl term null + size_t srclen = OVR_wcslen(src) + 1; // incl term null + size_t copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; memcpy(dest + dstlen, src, copylen * sizeof(wchar_t)); return dest; #endif } -UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) +size_t OVR_CDECL OVR_wcslen(const wchar_t* str) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) return wcslen(str); #else - UPInt i = 0; + size_t i = 0; while(str[i] != '\0') ++i; return i; @@ -134,7 +134,7 @@ UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) return wcscmp(a, b); #else // not supported, use custom implementation @@ -161,7 +161,7 @@ int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_wcsicmp(a, b); #else @@ -254,7 +254,7 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) // if (isNull(i)) Offsets[i] = 0; // else // if (isFull(i)) Offsets[i] = 1; -// else Offsets[i] = UInt16(offsetCount++ * 16 + 256); +// else Offsets[i] = uint16_t(offsetCount++ * 16 + 256); // } // for(i = 0; i < 16; ++i) // { @@ -280,7 +280,7 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) //private: // bool isNull(unsigned n) const // { -// const UInt16* p = Bits[n]; +// const uint16_t* p = Bits[n]; // for(unsigned i = 0; i < 16; ++i) // if (p[i] != 0) return false; // return true; @@ -288,18 +288,18 @@ double OVR_CDECL OVR_strtod(const char* string, char** tailptr) // // bool isFull(unsigned n) const // { -// const UInt16* p = Bits[n]; +// const uint16_t* p = Bits[n]; // for(unsigned i = 0; i < 16; ++i) // if (p[i] != 0xFFFF) return false; // return true; // } // -// UInt16 Offsets[256]; -// UInt16 Bits[256][16]; +// uint16_t Offsets[256]; +// uint16_t Bits[256][16]; //}; -const UInt16 UnicodeAlnumBits[] = { +const uint16_t UnicodeAlnumBits[] = { 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -354,7 +354,7 @@ const UInt16 UnicodeAlnumBits[] = { 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; -const UInt16 UnicodeAlphaBits[] = { +const uint16_t UnicodeAlphaBits[] = { 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -409,7 +409,7 @@ const UInt16 UnicodeAlphaBits[] = { 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; -const UInt16 UnicodeDigitBits[] = { +const uint16_t UnicodeDigitBits[] = { 256, 0, 0, 0, 0, 0, 272, 0, 0, 288, 304, 320, 336, 352, 368, 384, 400, 0, 0, 416, 0, 0, 0, 432, 448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -441,7 +441,7 @@ const UInt16 UnicodeDigitBits[] = { 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const UInt16 UnicodeSpaceBits[] = { +const uint16_t UnicodeSpaceBits[] = { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -463,7 +463,7 @@ const UInt16 UnicodeSpaceBits[] = { 4095, 0,33536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const UInt16 UnicodeXDigitBits[] = { +const uint16_t UnicodeXDigitBits[] = { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -484,7 +484,7 @@ const UInt16 UnicodeXDigitBits[] = { 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Uncomment if necessary -//const UInt16 UnicodeCntrlBits[] = { +//const uint16_t UnicodeCntrlBits[] = { // 256, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, // 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -508,7 +508,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32768, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3584}; // -//const UInt16 UnicodeGraphBits[] = { +//const uint16_t UnicodeGraphBits[] = { // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -564,7 +564,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191, //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; // -//const UInt16 UnicodePrintBits[] = { +//const uint16_t UnicodePrintBits[] = { // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -620,7 +620,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959, //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; // -//const UInt16 UnicodePunctBits[] = { +//const uint16_t UnicodePunctBits[] = { // 256, 0, 0, 272, 0, 288, 304, 320, 0, 336, 0, 0, 0, 352, 368, 384, // 400, 0, 0, 416, 0, 0, 432, 448, 464, 0, 0, 0, 0, 0, 0, 0, // 480, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -658,7 +658,7 @@ const UInt16 UnicodeXDigitBits[] = { // 0, 0, 0,65535,65055,65527, 3339, 0, 0, 0, 0, 0, 0, 0, 0, 0, //63470,35840, 1,47104, 0,10240, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // -//const UInt16 UnicodeLowerBits[] = { +//const uint16_t UnicodeLowerBits[] = { // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, // 384, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -688,7 +688,7 @@ const UInt16 UnicodeXDigitBits[] = { // 127, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // -//const UInt16 UnicodeUpperBits[] = { +//const uint16_t UnicodeUpperBits[] = { // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, // 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -734,7 +734,7 @@ const UInt16 UnicodeXDigitBits[] = { // they match AS3. -static const UInt16 UnicodeToUpperBits[] = { +static const uint16_t UnicodeToUpperBits[] = { 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 0, 384, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -763,7 +763,7 @@ static const UInt16 UnicodeToUpperBits[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535, 1023, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static const UInt16 UnicodeToLowerBits[] = { +static const uint16_t UnicodeToLowerBits[] = { 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 0, 400, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -795,10 +795,10 @@ static const UInt16 UnicodeToLowerBits[] = { struct GUnicodePairType { - UInt16 Key, Value; + uint16_t Key, Value; }; -static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key) +static inline bool CmpUnicodeKey(const GUnicodePairType& a, uint16_t key) { return a.Key < key; } @@ -1002,11 +1002,11 @@ int OVR_CDECL OVR_towupper(wchar_t charCode) { // To protect from memory overrun in case the character is not found // we use one extra fake element in the table {65536, 0}. - UPInt idx = Alg::LowerBoundSliced( + size_t idx = Alg::LowerBoundSliced( UnicodeToUpperTable, 0, sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1, - (UInt16)charCode, + (uint16_t)charCode, CmpUnicodeKey); return UnicodeToUpperTable[idx].Value; } @@ -1020,11 +1020,11 @@ int OVR_CDECL OVR_towlower(wchar_t charCode) { // To protect from memory overrun in case the character is not found // we use one extra fake element in the table {65536, 0}. - UPInt idx = Alg::LowerBoundSliced( + size_t idx = Alg::LowerBoundSliced( UnicodeToLowerTable, 0, sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1, - (UInt16)charCode, + (uint16_t)charCode, CmpUnicodeKey); return UnicodeToLowerTable[idx].Value; } diff --git a/LibOVR/Src/Kernel/OVR_Std.h b/LibOVR/Src/Kernel/OVR_Std.h index c11f853..d421ca7 100644 --- a/LibOVR/Src/Kernel/OVR_Std.h +++ b/LibOVR/Src/Kernel/OVR_Std.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Std.h Content : Standard C function interface Created : September 19, 2012 @@ -46,8 +46,8 @@ limitations under the License. namespace OVR { -#if defined(OVR_OS_WIN32) -inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix) +#if defined(OVR_OS_WIN32) +inline char* OVR_CDECL OVR_itoa(int val, char *dest, size_t destsize, int radix) { #if defined(OVR_MSVC_SAFESTRING) _itoa_s(val, dest, destsize, radix); @@ -140,12 +140,12 @@ inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) // String functions -inline UPInt OVR_CDECL OVR_strlen(const char* str) +inline size_t OVR_CDECL OVR_strlen(const char* str) { return strlen(str); } -inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src) +inline char* OVR_CDECL OVR_strcpy(char* dest, size_t destsize, const char* src) { #if defined(OVR_MSVC_SAFESTRING) strcpy_s(dest, destsize, src); @@ -156,7 +156,7 @@ inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src) #endif } -inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count) +inline char* OVR_CDECL OVR_strncpy(char* dest, size_t destsize, const char* src, size_t count) { #if defined(OVR_MSVC_SAFESTRING) strncpy_s(dest, destsize, src, count); @@ -167,7 +167,7 @@ inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, #endif } -inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src) +inline char * OVR_CDECL OVR_strcat(char* dest, size_t destsize, const char* src) { #if defined(OVR_MSVC_SAFESTRING) strcat_s(dest, destsize, src); @@ -195,16 +195,16 @@ inline char* OVR_CDECL OVR_strchr(char* str, char c) inline const char* OVR_strrchr(const char* str, char c) { - UPInt len = OVR_strlen(str); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(str); + for (size_t i=len; i>0; i--) if (str[i]==c) return str+i; return 0; } -inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) +inline const uint8_t* OVR_CDECL OVR_memrchr(const uint8_t* str, size_t size, uint8_t c) { - for (SPInt i = (SPInt)size - 1; i >= 0; i--) + for (intptr_t i = (intptr_t)size - 1; i >= 0; i--) { if (str[i] == c) return str + i; @@ -214,8 +214,8 @@ inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) inline char* OVR_CDECL OVR_strrchr(char* str, char c) { - UPInt len = OVR_strlen(str); - for (UPInt i=len; i>0; i--) + size_t len = OVR_strlen(str); + for (size_t i=len; i>0; i--) if (str[i]==c) return str+i; return 0; @@ -234,12 +234,12 @@ inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix) return strtoul(string, tailptr, radix); } -inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size) +inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, size_t size) { return strncmp(ws1, ws2, size); } -inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) +inline uint64_t OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) { #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) return _strtoui64(nptr, endptr, base); @@ -248,7 +248,7 @@ inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) #endif } -inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) +inline int64_t OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) { #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) return _strtoi64(nptr, endptr, base); @@ -258,7 +258,7 @@ inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) } -inline SInt64 OVR_CDECL OVR_atoq(const char* string) +inline int64_t OVR_CDECL OVR_atoq(const char* string) { #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) return _atoi64(string); @@ -267,7 +267,7 @@ inline SInt64 OVR_CDECL OVR_atoq(const char* string) #endif } -inline UInt64 OVR_CDECL OVR_atouq(const char* string) +inline uint64_t OVR_CDECL OVR_atouq(const char* string) { return OVR_strtouq(string, NULL, 10); } @@ -275,13 +275,13 @@ inline UInt64 OVR_CDECL OVR_atouq(const char* string) // Implemented in GStd.cpp in platform-specific manner. int OVR_CDECL OVR_stricmp(const char* dest, const char* src); -int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count); +int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, size_t count); -inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...) +inline size_t OVR_CDECL OVR_sprintf(char *dest, size_t destsize, const char* format, ...) { va_list argList; va_start(argList,format); - UPInt ret; + size_t ret; #if defined(OVR_CC_MSVC) #if defined(OVR_MSVC_SAFESTRING) ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); @@ -301,9 +301,9 @@ inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* forma return ret; } -inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList) +inline size_t OVR_CDECL OVR_vsprintf(char *dest, size_t destsize, const char * format, va_list argList) { - UPInt ret; + size_t ret; #if defined(OVR_CC_MSVC) #if defined(OVR_MSVC_SAFESTRING) dest[0] = '\0'; @@ -314,45 +314,45 @@ inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * for ret = destsize - 1; } else - ret = (UPInt)rv; + ret = (size_t)rv; #else OVR_UNUSED(destsize); int rv = _vsnprintf(dest, destsize - 1, format, argList); OVR_ASSERT(rv != -1); - ret = (UPInt)rv; + ret = (size_t)rv; dest[destsize-1] = 0; #endif #else OVR_UNUSED(destsize); - ret = (UPInt)vsprintf(dest, format, argList); + ret = (size_t)vsprintf(dest, format, argList); OVR_ASSERT(ret < destsize); #endif return ret; } // Returns the number of characters in the formatted string. -inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList) +inline size_t OVR_CDECL OVR_vscprintf(const char * format, va_list argList) { - UPInt ret; + size_t ret; #if defined(OVR_CC_MSVC) - ret = (UPInt) _vscprintf(format, argList); + ret = (size_t) _vscprintf(format, argList); #else - ret = (UPInt) vsnprintf(NULL, 0, format, argList); + ret = (size_t) vsnprintf(NULL, 0, format, argList); #endif return ret; } -wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src); -wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count); -wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src); -UPInt OVR_CDECL OVR_wcslen(const wchar_t* str); +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, size_t destsize, const wchar_t* src); +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, size_t destsize, const wchar_t* src, size_t count); +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src); +size_t OVR_CDECL OVR_wcslen(const wchar_t* str); int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b); int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b); inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_wcsicoll(a, b); #else @@ -366,7 +366,7 @@ inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) return wcscoll(a, b); #else // not supported, use regular wcscmp @@ -376,7 +376,7 @@ inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) #ifndef OVR_NO_WCTYPE -inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) +inline int OVR_CDECL UnicodeCharIs(const uint16_t* table, wchar_t charCode) { unsigned offset = table[charCode >> 8]; if (offset == 0) return 0; @@ -384,19 +384,19 @@ inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0; } -extern const UInt16 UnicodeAlnumBits[]; -extern const UInt16 UnicodeAlphaBits[]; -extern const UInt16 UnicodeDigitBits[]; -extern const UInt16 UnicodeSpaceBits[]; -extern const UInt16 UnicodeXDigitBits[]; +extern const uint16_t UnicodeAlnumBits[]; +extern const uint16_t UnicodeAlphaBits[]; +extern const uint16_t UnicodeDigitBits[]; +extern const uint16_t UnicodeSpaceBits[]; +extern const uint16_t UnicodeXDigitBits[]; // Uncomment if necessary -//extern const UInt16 UnicodeCntrlBits[]; -//extern const UInt16 UnicodeGraphBits[]; -//extern const UInt16 UnicodeLowerBits[]; -//extern const UInt16 UnicodePrintBits[]; -//extern const UInt16 UnicodePunctBits[]; -//extern const UInt16 UnicodeUpperBits[]; +//extern const uint16_t UnicodeCntrlBits[]; +//extern const uint16_t UnicodeGraphBits[]; +//extern const uint16_t UnicodeLowerBits[]; +//extern const uint16_t UnicodePrintBits[]; +//extern const uint16_t UnicodePunctBits[]; +//extern const uint16_t UnicodeUpperBits[]; inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits, charCode); } inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits, charCode); } @@ -473,10 +473,10 @@ inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr) OVR_UNUSED(tailptr); char buffer[64]; char* tp = NULL; - UPInt max = OVR_wcslen(string); + size_t max = OVR_wcslen(string); if (max > 63) max = 63; unsigned char c = 0; - for (UPInt i=0; i < max; i++) + for (size_t i=0; i < max; i++) { c = (unsigned char)string[i]; buffer[i] = ((c) < 128 ? (char)c : '!'); @@ -494,10 +494,10 @@ inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int r OVR_UNUSED(tailptr); char buffer[64]; char* tp = NULL; - UPInt max = OVR_wcslen(string); + size_t max = OVR_wcslen(string); if (max > 63) max = 63; unsigned char c = 0; - for (UPInt i=0; i < max; i++) + for (size_t i=0; i < max; i++) { c = (unsigned char)string[i]; buffer[i] = ((c) < 128 ? (char)c : '!'); diff --git a/LibOVR/Src/Kernel/OVR_String.cpp b/LibOVR/Src/Kernel/OVR_String.cpp index 75b7c0e..9262a3f 100644 --- a/LibOVR/Src/Kernel/OVR_String.cpp +++ b/LibOVR/Src/Kernel/OVR_String.cpp @@ -36,7 +36,7 @@ limitations under the License. namespace OVR { -#define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift) +#define String_LengthIsSize (size_t(1) << String::Flag_LengthIsSizeShift) String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} }; @@ -50,16 +50,16 @@ String::String() String::String(const char* pdata) { // Obtain length in bytes; it doesn't matter if _data is UTF8. - UPInt size = pdata ? OVR_strlen(pdata) : 0; + size_t size = pdata ? OVR_strlen(pdata) : 0; pData = AllocDataCopy1(size, 0, pdata, size); }; String::String(const char* pdata1, const char* pdata2, const char* pdata3) { // Obtain length in bytes; it doesn't matter if _data is UTF8. - UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; - UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; - UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; + size_t size1 = pdata1 ? OVR_strlen(pdata1) : 0; + size_t size2 = pdata2 ? OVR_strlen(pdata2) : 0; + size_t size3 = pdata3 ? OVR_strlen(pdata3) : 0; DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0, pdata1, size1, pdata2, size2); @@ -67,14 +67,14 @@ String::String(const char* pdata1, const char* pdata2, const char* pdata3) pData = pdataDesc; } -String::String(const char* pdata, UPInt size) +String::String(const char* pdata, size_t size) { OVR_ASSERT((size == 0) || (pdata != 0)); pData = AllocDataCopy1(size, 0, pdata, size); }; -String::String(const InitStruct& src, UPInt size) +String::String(const InitStruct& src, size_t size) { pData = AllocData(size, 0); src.InitString(GetData()->Data, size); @@ -101,7 +101,7 @@ String::String(const wchar_t* data) } -String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) +String::DataDesc* String::AllocData(size_t size, size_t lengthIsSize) { String::DataDesc* pdesc; @@ -120,17 +120,17 @@ String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) } -String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize, - const char* pdata, UPInt copySize) +String::DataDesc* String::AllocDataCopy1(size_t size, size_t lengthIsSize, + const char* pdata, size_t copySize) { String::DataDesc* pdesc = AllocData(size, lengthIsSize); memcpy(pdesc->Data, pdata, copySize); return pdesc; } -String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, - const char* pdata1, UPInt copySize1, - const char* pdata2, UPInt copySize2) +String::DataDesc* String::AllocDataCopy2(size_t size, size_t lengthIsSize, + const char* pdata1, size_t copySize1, + const char* pdata2, size_t copySize2) { String::DataDesc* pdesc = AllocData(size, lengthIsSize); memcpy(pdesc->Data, pdata1, copySize1); @@ -139,16 +139,16 @@ String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, } -UPInt String::GetLength() const +size_t String::GetLength() const { // Optimize length accesses for non-UTF8 character strings. DataDesc* pdata = GetData(); - UPInt length, size = pdata->GetSize(); + size_t length, size = pdata->GetSize(); if (pdata->LengthIsSize()) return size; - length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size); + length = (size_t)UTF8Util::GetLength(pdata->Data, (size_t)size); if (length == size) pdata->Size |= String_LengthIsSize; @@ -157,15 +157,15 @@ UPInt String::GetLength() const } -//static UInt32 String_CharSearch(const char* buf, ) +//static uint32_t String_CharSearch(const char* buf, ) -UInt32 String::GetCharAt(UPInt index) const +uint32_t String::GetCharAt(size_t index) const { - SPInt i = (SPInt) index; + intptr_t i = (intptr_t) index; DataDesc* pdata = GetData(); const char* buf = pdata->Data; - UInt32 c; + uint32_t c; if (pdata->LengthIsSize()) { @@ -178,13 +178,13 @@ UInt32 String::GetCharAt(UPInt index) const return c; } -UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const +uint32_t String::GetFirstCharAt(size_t index, const char** offset) const { DataDesc* pdata = GetData(); - SPInt i = (SPInt) index; + intptr_t i = (intptr_t) index; const char* buf = pdata->Data; const char* end = buf + pdata->GetSize(); - UInt32 c; + uint32_t c; do { @@ -204,40 +204,40 @@ UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const return c; } -UInt32 String::GetNextChar(const char** offset) const +uint32_t String::GetNextChar(const char** offset) const { return UTF8Util::DecodeNextChar(offset); } -void String::AppendChar(UInt32 ch) +void String::AppendChar(uint32_t ch) { DataDesc* pdata = GetData(); - UPInt size = pdata->GetSize(); + size_t size = pdata->GetSize(); char buff[8]; - SPInt encodeSize = 0; + intptr_t encodeSize = 0; // Converts ch into UTF8 string and fills it into buff. UTF8Util::EncodeChar(buff, &encodeSize, ch); OVR_ASSERT(encodeSize >= 0); - SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0, - pdata->Data, size, buff, (UPInt)encodeSize)); + SetData(AllocDataCopy2(size + (size_t)encodeSize, 0, + pdata->Data, size, buff, (size_t)encodeSize)); pdata->Release(); } -void String::AppendString(const wchar_t* pstr, SPInt len) +void String::AppendString(const wchar_t* pstr, intptr_t len) { if (!pstr) return; DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); - UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len); + size_t oldSize = pdata->GetSize(); + size_t encodeSize = (size_t)UTF8Util::GetEncodeStringSize(pstr, len); - DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0, + DataDesc* pnewData = AllocDataCopy1(oldSize + (size_t)encodeSize, 0, pdata->Data, oldSize); UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len); @@ -246,22 +246,22 @@ void String::AppendString(const wchar_t* pstr, SPInt len) } -void String::AppendString(const char* putf8str, SPInt utf8StrSz) +void String::AppendString(const char* putf8str, intptr_t utf8StrSz) { if (!putf8str || !utf8StrSz) return; if (utf8StrSz == -1) - utf8StrSz = (SPInt)OVR_strlen(putf8str); + utf8StrSz = (intptr_t)OVR_strlen(putf8str); DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); + size_t oldSize = pdata->GetSize(); - SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0, - pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz)); + SetData(AllocDataCopy2(oldSize + (size_t)utf8StrSz, 0, + pdata->Data, oldSize, putf8str, (size_t)utf8StrSz)); pdata->Release(); } -void String::AssignString(const InitStruct& src, UPInt size) +void String::AssignString(const InitStruct& src, size_t size) { DataDesc* poldData = GetData(); DataDesc* pnewData = AllocData(size, 0); @@ -270,7 +270,7 @@ void String::AssignString(const InitStruct& src, UPInt size) poldData->Release(); } -void String::AssignString(const char* putf8str, UPInt size) +void String::AssignString(const char* putf8str, size_t size) { DataDesc* poldData = GetData(); SetData(AllocDataCopy1(size, 0, putf8str, size)); @@ -285,7 +285,7 @@ void String::operator = (const char* pstr) void String::operator = (const wchar_t* pwstr) { DataDesc* poldData = GetData(); - UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0; + size_t size = pwstr ? (size_t)UTF8Util::GetEncodeStringSize(pwstr) : 0; DataDesc* pnewData = AllocData(size, 0); UTF8Util::EncodeString(pnewData->Data, pwstr); @@ -316,9 +316,9 @@ void String::operator += (const String& src) { DataDesc *pourData = GetData(), *psrcData = src.GetData(); - UPInt ourSize = pourData->GetSize(), + size_t ourSize = pourData->GetSize(), srcSize = psrcData->GetSize(); - UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); + size_t lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); SetData(AllocDataCopy2(ourSize + srcSize, lflag, pourData->Data, ourSize, psrcData->Data, srcSize)); @@ -340,12 +340,12 @@ String String::operator + (const String& src) const return tmp1; } -void String::Remove(UPInt posAt, SPInt removeLength) +void String::Remove(size_t posAt, intptr_t removeLength) { DataDesc* pdata = GetData(); - UPInt oldSize = pdata->GetSize(); + size_t oldSize = pdata->GetSize(); // Length indicates the number of characters to remove. - UPInt length = GetLength(); + size_t length = GetLength(); // If index is past the string, nothing to remove. if (posAt >= length) @@ -355,8 +355,8 @@ void String::Remove(UPInt posAt, SPInt removeLength) removeLength = length - posAt; // Get the byte position of the UTF8 char at position posAt. - SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); - SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); + intptr_t bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); + intptr_t removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(), pdata->Data, bytePos, @@ -365,9 +365,9 @@ void String::Remove(UPInt posAt, SPInt removeLength) } -String String::Substring(UPInt start, UPInt end) const +String String::Substring(size_t start, size_t end) const { - UPInt length = GetLength(); + size_t length = GetLength(); if ((start >= length) || (start >= end)) return String(); @@ -378,9 +378,9 @@ String String::Substring(UPInt start, UPInt end) const return String(pdata->Data + start, end - start); // Get position of starting character. - SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); - SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); - return String(pdata->Data + byteStart, (UPInt)byteSize); + intptr_t byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); + intptr_t byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); + return String(pdata->Data + byteStart, (size_t)byteSize); } void String::Clear() @@ -393,11 +393,11 @@ void String::Clear() String String::ToUpper() const { - UInt32 c; + uint32_t c; const char* psource = GetData()->Data; const char* pend = psource + GetData()->GetSize(); String str; - SPInt bufferOffset = 0; + intptr_t bufferOffset = 0; char buffer[512]; while(psource < pend) @@ -405,7 +405,7 @@ String String::ToUpper() const do { c = UTF8Util::DecodeNextChar_Advance0(&psource); UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c))); - } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); // Append string a piece at a time. str.AppendString(buffer, bufferOffset); @@ -417,11 +417,11 @@ String String::ToUpper() const String String::ToLower() const { - UInt32 c; + uint32_t c; const char* psource = GetData()->Data; const char* pend = psource + GetData()->GetSize(); String str; - SPInt bufferOffset = 0; + intptr_t bufferOffset = 0; char buffer[512]; while(psource < pend) @@ -429,7 +429,7 @@ String String::ToLower() const do { c = UTF8Util::DecodeNextChar_Advance0(&psource); UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c))); - } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); + } while ((psource < pend) && (bufferOffset < intptr_t(sizeof(buffer)-8))); // Append string a piece at a time. str.AppendString(buffer, bufferOffset); @@ -441,13 +441,13 @@ String String::ToLower() const -String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) +String& String::Insert(const char* substr, size_t posAt, intptr_t strSize) { DataDesc* poldData = GetData(); - UPInt oldSize = poldData->GetSize(); - UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize; - UPInt byteIndex = (poldData->LengthIsSize()) ? - posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); + size_t oldSize = poldData->GetSize(); + size_t insertSize = (strSize < 0) ? OVR_strlen(substr) : (size_t)strSize; + size_t byteIndex = (poldData->LengthIsSize()) ? + posAt : (size_t)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); OVR_ASSERT(byteIndex <= oldSize); @@ -461,27 +461,27 @@ String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) } /* -String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len) +String& String::Insert(const uint32_t* substr, size_t posAt, intptr_t len) { - for (SPInt i = 0; i < len; ++i) + for (intptr_t i = 0; i < len; ++i) { - UPInt charw = InsertCharAt(substr[i], posAt); + size_t charw = InsertCharAt(substr[i], posAt); posAt += charw; } return *this; } */ -UPInt String::InsertCharAt(UInt32 c, UPInt posAt) +size_t String::InsertCharAt(uint32_t c, size_t posAt) { - char buf[8]; - SPInt index = 0; + char buf[8]; + intptr_t index = 0; UTF8Util::EncodeChar(buf, &index, c); OVR_ASSERT(index >= 0); - buf[(UPInt)index] = 0; + buf[(size_t)index] = 0; Insert(buf, posAt, index); - return (UPInt)index; + return (size_t)index; } @@ -490,22 +490,22 @@ int String::CompareNoCase(const char* a, const char* b) return OVR_stricmp(a, b); } -int String::CompareNoCase(const char* a, const char* b, SPInt len) +int String::CompareNoCase(const char* a, const char* b, intptr_t len) { if (len) { - SPInt f,l; - SPInt slen = len; + intptr_t f,l; + intptr_t slen = len; const char *s = b; do { - f = (SPInt)OVR_tolower((int)(*(a++))); - l = (SPInt)OVR_tolower((int)(*(b++))); + f = (intptr_t)OVR_tolower((int)(*(a++))); + l = (intptr_t)OVR_tolower((int)(*(b++))); } while (--len && f && (f == l) && *b != 0); if (f == l && (len != 0 || *b != 0)) { - f = (SPInt)slen; - l = (SPInt)OVR_strlen(s); + f = (intptr_t)slen; + l = (intptr_t)OVR_strlen(s); return int(f - l); } @@ -518,10 +518,10 @@ int String::CompareNoCase(const char* a, const char* b, SPInt len) // ***** Implement hash static functions // Hash function -UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) +size_t String::BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed) { - const UByte* pdata = (const UByte*) pdataIn; - UPInt h = seed; + const uint8_t* pdata = (const uint8_t*) pdataIn; + size_t h = seed; while (size > 0) { size--; @@ -532,10 +532,10 @@ UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) } // Hash function, case-insensitive -UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed) +size_t String::BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed) { - const UByte* pdata = (const UByte*) pdataIn; - UPInt h = seed; + const uint8_t* pdata = (const uint8_t*) pdataIn; + size_t h = seed; while (size > 0) { size--; @@ -560,7 +560,7 @@ StringBuffer::StringBuffer() { } -StringBuffer::StringBuffer(UPInt growSize) +StringBuffer::StringBuffer(size_t growSize) : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) { SetGrowSize(growSize); @@ -572,7 +572,7 @@ StringBuffer::StringBuffer(const char* data) AppendString(data); } -StringBuffer::StringBuffer(const char* data, UPInt dataSize) +StringBuffer::StringBuffer(const char* data, size_t dataSize) : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) { AppendString(data, dataSize); @@ -601,32 +601,32 @@ StringBuffer::~StringBuffer() if (pData) OVR_FREE(pData); } -void StringBuffer::SetGrowSize(UPInt growSize) +void StringBuffer::SetGrowSize(size_t growSize) { if (growSize <= 16) GrowSize = 16; else { - UByte bits = Alg::UpperBit(UInt32(growSize-1)); - UPInt size = 1<<bits; + uint8_t bits = Alg::UpperBit(uint32_t(growSize-1)); + size_t size = (size_t)1 << bits; GrowSize = size == growSize ? growSize : size; } } -UPInt StringBuffer::GetLength() const +size_t StringBuffer::GetLength() const { - UPInt length, size = GetSize(); + size_t length, size = GetSize(); if (LengthIsSize) return size; - length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize()); + length = (size_t)UTF8Util::GetLength(pData, (size_t)GetSize()); if (length == GetSize()) LengthIsSize = true; return length; } -void StringBuffer::Reserve(UPInt _size) +void StringBuffer::Reserve(size_t _size) { if (_size >= BufferSize) // >= because of trailing zero! (!AB) { @@ -637,7 +637,7 @@ void StringBuffer::Reserve(UPInt _size) pData = (char*)OVR_REALLOC(pData, BufferSize); } } -void StringBuffer::Resize(UPInt _size) +void StringBuffer::Resize(size_t _size) { Reserve(_size); LengthIsSize = false; @@ -660,45 +660,45 @@ void StringBuffer::Clear() */ } // Appends a character -void StringBuffer::AppendChar(UInt32 ch) +void StringBuffer::AppendChar(uint32_t ch) { char buff[8]; - UPInt origSize = GetSize(); + size_t origSize = GetSize(); // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes // in the UTF8 string. - SPInt srcSize = 0; + intptr_t srcSize = 0; UTF8Util::EncodeChar(buff, &srcSize, ch); OVR_ASSERT(srcSize >= 0); - UPInt size = origSize + srcSize; + size_t size = origSize + srcSize; Resize(size); memcpy(pData + origSize, buff, srcSize); } // Append a string -void StringBuffer::AppendString(const wchar_t* pstr, SPInt len) +void StringBuffer::AppendString(const wchar_t* pstr, intptr_t len) { if (!pstr) return; - SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len); - UPInt origSize = GetSize(); - UPInt size = srcSize + origSize; + intptr_t srcSize = UTF8Util::GetEncodeStringSize(pstr, len); + size_t origSize = GetSize(); + size_t size = srcSize + origSize; Resize(size); UTF8Util::EncodeString(pData + origSize, pstr, len); } -void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz) +void StringBuffer::AppendString(const char* putf8str, intptr_t utf8StrSz) { if (!putf8str || !utf8StrSz) return; if (utf8StrSz == -1) - utf8StrSz = (SPInt)OVR_strlen(putf8str); + utf8StrSz = (intptr_t)OVR_strlen(putf8str); - UPInt origSize = GetSize(); - UPInt size = utf8StrSz + origSize; + size_t origSize = GetSize(); + size_t size = utf8StrSz + origSize; Resize(size); memcpy(pData + origSize, putf8str, utf8StrSz); @@ -708,7 +708,7 @@ void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz) void StringBuffer::operator = (const char* pstr) { pstr = pstr ? pstr : ""; - UPInt size = OVR_strlen(pstr); + size_t size = OVR_strlen(pstr); Resize(size); memcpy(pData, pstr, size); } @@ -716,7 +716,7 @@ void StringBuffer::operator = (const char* pstr) void StringBuffer::operator = (const wchar_t* pstr) { pstr = pstr ? pstr : L""; - UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr); + size_t size = (size_t)UTF8Util::GetEncodeStringSize(pstr); Resize(size); UTF8Util::EncodeString(pData, pstr); } @@ -735,12 +735,12 @@ void StringBuffer::operator = (const StringBuffer& src) // Inserts substr at posAt -void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) +void StringBuffer::Insert(const char* substr, size_t posAt, intptr_t len) { - UPInt oldSize = Size; - UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len; - UPInt byteIndex = LengthIsSize ? posAt : - (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size); + size_t oldSize = Size; + size_t insertSize = (len < 0) ? OVR_strlen(substr) : (size_t)len; + size_t byteIndex = LengthIsSize ? posAt : + (size_t)UTF8Util::GetByteIndex(posAt, pData, (intptr_t)Size); OVR_ASSERT(byteIndex <= oldSize); Reserve(oldSize + insertSize); @@ -753,16 +753,16 @@ void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) } // Inserts character at posAt -UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt) +size_t StringBuffer::InsertCharAt(uint32_t c, size_t posAt) { char buf[8]; - SPInt len = 0; + intptr_t len = 0; UTF8Util::EncodeChar(buf, &len, c); OVR_ASSERT(len >= 0); - buf[(UPInt)len] = 0; + buf[(size_t)len] = 0; Insert(buf, posAt, len); - return (UPInt)len; + return (size_t)len; } } // OVR diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h index 0866968..25c4b68 100644 --- a/LibOVR/Src/Kernel/OVR_String.h +++ b/LibOVR/Src/Kernel/OVR_String.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_String.h Content : String UTF8 string implementation with copy-on-write semantics (thread-safe for assignment but not modification). @@ -59,7 +59,7 @@ protected: //Flag_GetLength = 0x7FFFFFFF, // This flag is set if GetLength() == GetSize() for a string. // Avoid extra scanning is Substring and indexing logic. - Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1) + Flag_LengthIsSizeShift = (sizeof(size_t)*8 - 1) }; @@ -68,13 +68,13 @@ protected: { // Number of bytes. Will be the same as the number of chars if the characters // are ascii, may not be equal to number of chars in case string data is UTF8. - UPInt Size; - volatile SInt32 RefCount; + size_t Size; + volatile int32_t RefCount; char Data[1]; void AddRef() { - AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1); + AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, 1); } // Decrement ref count. This needs to be thread-safe, since // a different thread could have also decremented the ref count. @@ -88,13 +88,13 @@ protected: // checking against 0 needs to made an atomic operation. void Release() { - if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) + if ((AtomicOps<int32_t>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) OVR_FREE(this); } - static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; } - UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; } - UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); } + static size_t GetLengthFlagBit() { return size_t(1) << Flag_LengthIsSizeShift; } + size_t GetSize() const { return Size & ~GetLengthFlagBit() ; } + size_t GetLengthFlag() const { return Size & GetLengthFlagBit(); } bool LengthIsSize() const { return GetLengthFlag() != 0; } }; @@ -109,11 +109,11 @@ protected: union { DataDesc* pData; - UPInt HeapTypeBits; + size_t HeapTypeBits; }; typedef union { DataDesc* pData; - UPInt HeapTypeBits; + size_t HeapTypeBits; } DataDescUnion; inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); } @@ -122,7 +122,7 @@ protected: { DataDescUnion u; u.pData = pData; - u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask); + u.HeapTypeBits = (u.HeapTypeBits & ~(size_t)HT_Mask); return u.pData; } @@ -135,12 +135,12 @@ protected: } - DataDesc* AllocData(UPInt size, UPInt lengthIsSize); - DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize, - const char* pdata, UPInt copySize); - DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize, - const char* pdata1, UPInt copySize1, - const char* pdata2, UPInt copySize2); + DataDesc* AllocData(size_t size, size_t lengthIsSize); + DataDesc* AllocDataCopy1(size_t size, size_t lengthIsSize, + const char* pdata, size_t copySize); + DataDesc* AllocDataCopy2(size_t size, size_t lengthIsSize, + const char* pdata1, size_t copySize1, + const char* pdata2, size_t copySize2); // Special constructor to avoid data initalization when used in derived class. struct NoConstructor { }; @@ -152,7 +152,7 @@ public: struct InitStruct { virtual ~InitStruct() { } - virtual void InitString(char* pbuffer, UPInt size) const = 0; + virtual void InitString(char* pbuffer, size_t size) const = 0; }; @@ -160,10 +160,10 @@ public: String(); String(const char* data); String(const char* data1, const char* pdata2, const char* pdata3 = 0); - String(const char* data, UPInt buflen); + String(const char* data, size_t buflen); String(const String& src); String(const StringBuffer& src); - String(const InitStruct& src, UPInt size); + String(const InitStruct& src, size_t size); explicit String(const wchar_t* data); // Destructor (Captain Obvious guarantees!) @@ -186,68 +186,68 @@ public: const char* ToCStr() const { return GetData()->Data; } // Returns number of bytes - UPInt GetSize() const { return GetData()->GetSize() ; } + size_t GetSize() const { return GetData()->GetSize() ; } // Tells whether or not the string is empty bool IsEmpty() const { return GetSize() == 0; } // Returns number of characters - UPInt GetLength() const; + size_t GetLength() const; // Returns character at the specified index - UInt32 GetCharAt(UPInt index) const; - UInt32 GetFirstCharAt(UPInt index, const char** offset) const; - UInt32 GetNextChar(const char** offset) const; + uint32_t GetCharAt(size_t index) const; + uint32_t GetFirstCharAt(size_t index, const char** offset) const; + uint32_t GetNextChar(const char** offset) const; // Appends a character - void AppendChar(UInt32 ch); + void AppendChar(uint32_t ch); // Append a string - void AppendString(const wchar_t* pstr, SPInt len = -1); - void AppendString(const char* putf8str, SPInt utf8StrSz = -1); + void AppendString(const wchar_t* pstr, intptr_t len = -1); + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); // Assigned a string with dynamic data (copied through initializer). - void AssignString(const InitStruct& src, UPInt size); + void AssignString(const InitStruct& src, size_t size); // Assigns string with known size. - void AssignString(const char* putf8str, UPInt size); + void AssignString(const char* putf8str, size_t size); // Resize the string to the new size -// void Resize(UPInt _size); +// void Resize(size_t _size); // Removes the character at posAt - void Remove(UPInt posAt, SPInt len = 1); + void Remove(size_t posAt, intptr_t len = 1); // Returns a String that's a substring of this. // -start is the index of the first UTF8 character you want to include. // -end is the index one past the last UTF8 character you want to include. - String Substring(UPInt start, UPInt end) const; + String Substring(size_t start, size_t end) const; // Case-conversion String ToUpper() const; String ToLower() const; // Inserts substr at posAt - String& Insert (const char* substr, UPInt posAt, SPInt len = -1); + String& Insert (const char* substr, size_t posAt, intptr_t len = -1); // Inserts character at posAt - UPInt InsertCharAt(UInt32 c, UPInt posAt); + size_t InsertCharAt(uint32_t c, size_t posAt); // Inserts substr at posAt, which is an index of a character (not byte). // Of size is specified, it is in bytes. -// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1); +// String& Insert(const uint32_t* substr, size_t posAt, intptr_t size = -1); // Get Byte index of the character at position = index - UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); } + size_t GetByteIndex(size_t index) const { return (size_t)UTF8Util::GetByteIndex(index, GetData()->Data); } // Utility: case-insensitive string compare. stricmp() & strnicmp() are not // ANSI or POSIX, do not seem to appear in Linux. static int OVR_STDCALL CompareNoCase(const char* a, const char* b); - static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len); + static int OVR_STDCALL CompareNoCase(const char* a, const char* b, intptr_t len); // Hash function, case-insensitive - static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381); + static size_t OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, size_t size, size_t seed = 5381); // Hash function, case-sensitive - static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381); + static size_t OVR_STDCALL BernsteinHashFunction(const void* pdataIn, size_t size, size_t seed = 5381); // ***** File path parsing helper functions. @@ -343,10 +343,10 @@ public: // Accesses raw bytes const char& operator [] (int index) const { - OVR_ASSERT(index >= 0 && (UPInt)index < GetSize()); + OVR_ASSERT(index >= 0 && (size_t)index < GetSize()); return GetData()->Data[index]; } - const char& operator [] (UPInt index) const + const char& operator [] (size_t index) const { OVR_ASSERT(index < GetSize()); return GetData()->Data[index]; @@ -373,9 +373,9 @@ public: // Hash functor used for strings. struct HashFunctor { - UPInt operator()(const String& data) const + size_t operator()(const String& data) const { - UPInt size = data.GetSize(); + size_t size = data.GetSize(); return String::BernsteinHashFunction((const char*)data, size); } }; @@ -383,14 +383,14 @@ public: // lookup based on NoCaseKey. struct NoCaseHashFunctor { - UPInt operator()(const String& data) const + size_t operator()(const String& data) const { - UPInt size = data.GetSize(); + size_t size = data.GetSize(); return String::BernsteinHashFunctionCIS((const char*)data, size); } - UPInt operator()(const NoCaseKey& data) const + size_t operator()(const NoCaseKey& data) const { - UPInt size = data.pStr->GetSize(); + size_t size = data.pStr->GetSize(); return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size); } }; @@ -404,18 +404,18 @@ public: class StringBuffer { char* pData; - UPInt Size; - UPInt BufferSize; - UPInt GrowSize; + size_t Size; + size_t BufferSize; + size_t GrowSize; mutable bool LengthIsSize; public: // Constructors / Destructor. StringBuffer(); - explicit StringBuffer(UPInt growSize); + explicit StringBuffer(size_t growSize); StringBuffer(const char* data); - StringBuffer(const char* data, UPInt buflen); + StringBuffer(const char* data, size_t buflen); StringBuffer(const String& src); StringBuffer(const StringBuffer& src); explicit StringBuffer(const wchar_t* data); @@ -423,8 +423,8 @@ public: // Modify grow size used for growing/shrinking the buffer. - UPInt GetGrowSize() const { return GrowSize; } - void SetGrowSize(UPInt growSize); + size_t GetGrowSize() const { return GrowSize; } + void SetGrowSize(size_t growSize); // *** General Functions @@ -437,38 +437,38 @@ public: const char* ToCStr() const { return (pData) ? pData : ""; } // Returns number of bytes. - UPInt GetSize() const { return Size ; } + size_t GetSize() const { return Size ; } // Tells whether or not the string is empty. bool IsEmpty() const { return GetSize() == 0; } // Returns number of characters - UPInt GetLength() const; + size_t GetLength() const; // Returns character at the specified index - UInt32 GetCharAt(UPInt index) const; - UInt32 GetFirstCharAt(UPInt index, const char** offset) const; - UInt32 GetNextChar(const char** offset) const; + uint32_t GetCharAt(size_t index) const; + uint32_t GetFirstCharAt(size_t index, const char** offset) const; + uint32_t GetNextChar(const char** offset) const; // Resize the string to the new size - void Resize(UPInt _size); - void Reserve(UPInt _size); + void Resize(size_t _size); + void Reserve(size_t _size); // Appends a character - void AppendChar(UInt32 ch); + void AppendChar(uint32_t ch); // Append a string - void AppendString(const wchar_t* pstr, SPInt len = -1); - void AppendString(const char* putf8str, SPInt utf8StrSz = -1); + void AppendString(const wchar_t* pstr, intptr_t len = -1); + void AppendString(const char* putf8str, intptr_t utf8StrSz = -1); void AppendFormat(const char* format, ...); // Assigned a string with dynamic data (copied through initializer). - //void AssignString(const InitStruct& src, UPInt size); + //void AssignString(const InitStruct& src, size_t size); // Inserts substr at posAt - void Insert (const char* substr, UPInt posAt, SPInt len = -1); + void Insert (const char* substr, size_t posAt, intptr_t len = -1); // Inserts character at posAt - UPInt InsertCharAt(UInt32 c, UPInt posAt); + size_t InsertCharAt(uint32_t c, size_t posAt); // Assignment void operator = (const char* str); @@ -487,10 +487,10 @@ public: // Accesses raw bytes char& operator [] (int index) { - OVR_ASSERT(((UPInt)index) < GetSize()); + OVR_ASSERT(((size_t)index) < GetSize()); return pData[index]; } - char& operator [] (UPInt index) + char& operator [] (size_t index) { OVR_ASSERT(index < GetSize()); return pData[index]; @@ -498,10 +498,10 @@ public: const char& operator [] (int index) const { - OVR_ASSERT(((UPInt)index) < GetSize()); + OVR_ASSERT(((size_t)index) < GetSize()); return pData[index]; } - const char& operator [] (UPInt index) const + const char& operator [] (size_t index) const { OVR_ASSERT(index < GetSize()); return pData[index]; @@ -520,7 +520,7 @@ public: StringDataPtr() : pStr(NULL), Size(0) {} StringDataPtr(const StringDataPtr& p) : pStr(p.pStr), Size(p.Size) {} - StringDataPtr(const char* pstr, UPInt sz) + StringDataPtr(const char* pstr, size_t sz) : pStr(pstr), Size(sz) {} StringDataPtr(const char* pstr) : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {} @@ -532,7 +532,7 @@ public: public: const char* ToCStr() const { return pStr; } - UPInt GetSize() const { return Size; } + size_t GetSize() const { return Size; } bool IsEmpty() const { return GetSize() == 0; } // value is a prefix of this string @@ -550,33 +550,33 @@ public: // Find first character. // init_ind - initial index. - SPInt FindChar(char c, UPInt init_ind = 0) const + intptr_t FindChar(char c, size_t init_ind = 0) const { - for (UPInt i = init_ind; i < GetSize(); ++i) + for (size_t i = init_ind; i < GetSize(); ++i) if (pStr[i] == c) - return static_cast<SPInt>(i); + return static_cast<intptr_t>(i); return -1; } // Find last character. // init_ind - initial index. - SPInt FindLastChar(char c, UPInt init_ind = ~0) const + intptr_t FindLastChar(char c, size_t init_ind = ~0) const { - if (init_ind == (UPInt)~0 || init_ind > GetSize()) + if (init_ind == (size_t)~0 || init_ind > GetSize()) init_ind = GetSize(); else ++init_ind; - for (UPInt i = init_ind; i > 0; --i) + for (size_t i = init_ind; i > 0; --i) if (pStr[i - 1] == c) - return static_cast<SPInt>(i - 1); + return static_cast<intptr_t>(i - 1); return -1; } // Create new object and trim size bytes from the left. - StringDataPtr GetTrimLeft(UPInt size) const + StringDataPtr GetTrimLeft(size_t size) const { // Limit trim size to the size of the string. size = Alg::PMin(GetSize(), size); @@ -584,7 +584,7 @@ public: return StringDataPtr(ToCStr() + size, GetSize() - size); } // Create new object and trim size bytes from the right. - StringDataPtr GetTrimRight(UPInt size) const + StringDataPtr GetTrimRight(size_t size) const { // Limit trim to the size of the string. size = Alg::PMin(GetSize(), size); @@ -596,7 +596,7 @@ public: // Useful for parsing. StringDataPtr GetNextToken(char separator = ':') const { - UPInt cur_pos = 0; + size_t cur_pos = 0; const char* cur_str = ToCStr(); for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos) @@ -611,7 +611,7 @@ public: } // Trim size bytes from the left. - StringDataPtr& TrimLeft(UPInt size) + StringDataPtr& TrimLeft(size_t size) { // Limit trim size to the size of the string. size = Alg::PMin(GetSize(), size); @@ -621,7 +621,7 @@ public: return *this; } // Trim size bytes from the right. - StringDataPtr& TrimRight(UPInt size) + StringDataPtr& TrimRight(size_t size) { // Limit trim to the size of the string. size = Alg::PMin(GetSize(), size); @@ -636,7 +636,7 @@ public: // Hash functor used string data pointers struct HashFunctor { - UPInt operator()(const StringDataPtr& data) const + size_t operator()(const StringDataPtr& data) const { return String::BernsteinHashFunction(data.ToCStr(), data.GetSize()); } @@ -649,7 +649,7 @@ public: protected: const char* pStr; - UPInt Size; + size_t Size; }; } // OVR diff --git a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp index e196dd7..a47ca4e 100644 --- a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp +++ b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp @@ -34,13 +34,13 @@ void StringBuffer::AppendFormat(const char* format, ...) va_list argList; va_start(argList, format); - UPInt size = OVR_vscprintf(format, argList); + size_t size = OVR_vscprintf(format, argList); va_end(argList); char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1)); va_start(argList, format); - UPInt result = OVR_vsprintf(buffer, size+1, format, argList); + size_t result = OVR_vsprintf(buffer, size+1, format, argList); OVR_UNUSED1(result); va_end(argList); OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf")); diff --git a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp index 02abe15..c954083 100644 --- a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp +++ b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp @@ -39,7 +39,7 @@ void ScanFilePath(const char* url, const char** pfilename, const char** pext) const char *filename = 0; const char *lastDot = 0; - UInt32 charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal = UTF8Util::DecodeNextChar(&url); while (charVal != 0) { @@ -76,8 +76,8 @@ void ScanFilePath(const char* url, const char** pfilename, const char** pext) // - protocol: 'file://', 'http://' const char* ScanPathProtocol(const char* url) { - UInt32 charVal = UTF8Util::DecodeNextChar(&url); - UInt32 charVal2; + uint32_t charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal2; while (charVal != 0) { @@ -118,7 +118,7 @@ bool String::HasAbsolutePath(const char* url) if (!url || !*url) return true; // Treat empty strings as absolute. - UInt32 charVal = UTF8Util::DecodeNextChar(&url); + uint32_t charVal = UTF8Util::DecodeNextChar(&url); // Fist character of '/' or '\\' means absolute url. if ((charVal == '/') || (charVal == '\\')) diff --git a/LibOVR/Src/Kernel/OVR_SysFile.cpp b/LibOVR/Src/Kernel/OVR_SysFile.cpp index 604527a..d08dbb2 100644 --- a/LibOVR/Src/Kernel/OVR_SysFile.cpp +++ b/LibOVR/Src/Kernel/OVR_SysFile.cpp @@ -51,21 +51,21 @@ public: // Return position / file size virtual int Tell() { return 0; } - virtual SInt64 LTell() { return 0; } + virtual int64_t LTell() { return 0; } virtual int GetLength() { return 0; } - virtual SInt64 LGetLength() { return 0; } + virtual int64_t LGetLength() { return 0; } // virtual bool Stat(FileStats *pfs) { return 0; } virtual int GetErrorCode() { return Error_FileNotFound; } // ** Stream implementation & I/O - virtual int Write(const UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } - virtual int Read(UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } + virtual int Write(const uint8_t *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } + virtual int Read(uint8_t *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } virtual int SkipBytes(int numBytes) { return 0; OVR_UNUSED(numBytes); } virtual int BytesAvailable() { return 0; } virtual bool Flush() { return 0; } virtual int Seek(int offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } - virtual SInt64 LSeek(SInt64 offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } + virtual int64_t LSeek(int64_t offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } virtual int CopyFromStream(File *pstream, int byteSize) { return -1; OVR_UNUSED2(pstream, byteSize); } virtual bool Close() { return 0; } diff --git a/LibOVR/Src/Kernel/OVR_SysFile.h b/LibOVR/Src/Kernel/OVR_SysFile.h index 61ad6e8..7bd0162 100644 --- a/LibOVR/Src/Kernel/OVR_SysFile.h +++ b/LibOVR/Src/Kernel/OVR_SysFile.h @@ -48,9 +48,9 @@ class SysFile; struct FileStat { // No change or create time because they are not available on most systems - SInt64 ModifyTime; - SInt64 AccessTime; - SInt64 FileSize; + int64_t ModifyTime; + int64_t AccessTime; + int64_t FileSize; bool operator== (const FileStat& stat) const { diff --git a/LibOVR/Src/Kernel/OVR_System.cpp b/LibOVR/Src/Kernel/OVR_System.cpp index 3144ade..8d5d201 100644 --- a/LibOVR/Src/Kernel/OVR_System.cpp +++ b/LibOVR/Src/Kernel/OVR_System.cpp @@ -28,10 +28,27 @@ limitations under the License. #include "OVR_System.h" #include "OVR_Threads.h" #include "OVR_Timer.h" +#include "../Displays/OVR_Display.h" +#ifdef OVR_OS_WIN32 +#include "../Displays/OVR_Win32_ShimFunctions.h" +#endif namespace OVR { -// ***** OVR::System Implementation + +// Stack of destroy listeners (push/pop semantics) +static SystemSingletonInternal *SystemShutdownListenerStack = 0; +static Lock stackLock; + +void SystemSingletonInternal::PushDestroyCallbacks() +{ + Lock::Locker locker(&stackLock); + + // Push listener onto the stack + NextSingleton = SystemShutdownListenerStack; + SystemShutdownListenerStack = this; +} + // Initializes System core, installing allocator. void System::Init(Log* log, Allocator *palloc) @@ -41,6 +58,29 @@ void System::Init(Log* log, Allocator *palloc) Log::SetGlobalLog(log); Timer::initializeTimerSystem(); Allocator::setInstance(palloc); + Display::Initialize(); +#ifdef OVR_OS_WIN32 + // This code will look for the first display. If it's a display + // that's extending the destkop, the code will assume we're in + // compatibility mode. Compatibility mode prevents shim loading + // and renders only to extended Rifts. + // If we find a display and it's application exclusive, + // we load the shim so we can render to it. + // If no display is available, we revert to whatever the + // driver tells us we're in + Ptr<DisplaySearchHandle> searchHandle = *Display::GetDisplaySearchHandle(); + Ptr<Display> pDisplay = NULL; + + if (Display::GetDisplayCount(searchHandle) > 0) + { + pDisplay = Display::GetDisplay(0, searchHandle); + } + + if( pDisplay == NULL ) + Win32::DisplayShim::GetInstance().Initialize(Display::InCompatibilityMode()); + else + Win32::DisplayShim::GetInstance().Initialize(!pDisplay->ApplicationExclusive); +#endif } else { @@ -52,13 +92,33 @@ void System::Destroy() { if (Allocator::GetInstance()) { - // Wait for all threads to finish; this must be done so that memory - // allocator and all destructors finalize correctly. +#ifdef OVR_OS_WIN32 + Win32::DisplayShim::GetInstance().Shutdown(); +#endif + + // Invoke all of the post-finish callbacks (normal case) + for (SystemSingletonInternal *listener = SystemShutdownListenerStack; listener; listener = listener->NextSingleton) + { + listener->OnThreadDestroy(); + } + #ifdef OVR_ENABLE_THREADS - Thread::FinishAllThreads(); + // Wait for all threads to finish; this must be done so that memory + // allocator and all destructors finalize correctly. + Thread::FinishAllThreads(); #endif - // Shutdown heap and destroy SysAlloc singleton, if any. + // Invoke all of the post-finish callbacks (normal case) + for (SystemSingletonInternal *next, *listener = SystemShutdownListenerStack; listener; listener = next) + { + next = listener->NextSingleton; + + listener->OnSystemDestroy(); + } + + SystemShutdownListenerStack = 0; + + // Shutdown heap and destroy SysAlloc singleton, if any. Allocator::GetInstance()->onSystemShutdown(); Allocator::setInstance(0); @@ -77,5 +137,5 @@ bool System::IsInitialized() return Allocator::GetInstance() != 0; } -} // OVR +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h index 253fe19..a85cd49 100644 --- a/LibOVR/Src/Kernel/OVR_System.h +++ b/LibOVR/Src/Kernel/OVR_System.h @@ -31,9 +31,102 @@ limitations under the License. #include "OVR_Allocator.h" #include "OVR_Log.h" +#include "OVR_Atomic.h" namespace OVR { + +//----------------------------------------------------------------------------- +// SystemSingleton + +// Subsystems are implemented using the Singleton pattern. +// To avoid code duplication in all the places where Singletons are defined, +// The pattern is defined once here and used everywhere. + +class SystemSingletonInternal +{ + friend class System; + + SystemSingletonInternal* NextSingleton; + + // No copying allowed + SystemSingletonInternal(const SystemSingletonInternal&) {} + void operator=(const SystemSingletonInternal&) {} + +protected: + SystemSingletonInternal() : + NextSingleton(0) + { + } + + // Call this to register the destroy events + // Destroy callbacks will be called in the reverse order they were registered + // Note: As a rule of thumb, call this at the end of the singleton class constructor. + void PushDestroyCallbacks(); + + // Required: Invoked when the System object is shutting down + // Called after threads are stopped + // Called before Log, Allocator, and Timer subsystems are stopped + // Listeners are called in the opposite order they were registered + virtual void OnSystemDestroy() = 0; + + // Called just before waiting for threads to die + // Listeners are called in the opposite order they were registered + // Useful to start terminating threads at the right time + // Note: The singleton must not delete itself here. + virtual void OnThreadDestroy() {} +}; + +// Singletons derive from this class +template<class T> +class SystemSingletonBase : public SystemSingletonInternal +{ + static AtomicPtr<T> SingletonInstance; + static T* SlowGetInstance(); + +protected: + ~SystemSingletonBase() + { + // Make sure the instance gets set to zero on dtor + if (SingletonInstance == this) + SingletonInstance = 0; + } + +public: + static OVR_FORCE_INLINE T* GetInstance() + { + // Fast version + // Note: The singleton instance is stored in an AtomicPtr<> to allow it to be accessed + // atomically from multiple threads without locks. + T* instance = SingletonInstance; + return instance ? instance : SlowGetInstance(); + } +}; + +// For reference, see N3337 14.5.1.3 (Static data members of class templates): +template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstance; + +// Place this in the singleton class in the header file +#define OVR_DECLARE_SINGLETON(T) \ + friend class OVR::SystemSingletonBase<T>; \ +private: \ + T(); \ + ~T(); \ + virtual void OnSystemDestroy(); + +// Place this in the singleton class source file +#define OVR_DEFINE_SINGLETON(T) \ + namespace OVR { \ + template<> T* SystemSingletonBase<T>::SlowGetInstance() \ + { \ + static OVR::Lock lock; \ + OVR::Lock::Locker locker(&lock); \ + if (!SingletonInstance) SingletonInstance = new T; \ + return SingletonInstance; \ + } \ + } + + // ***** System Core Initialization class // System initialization must take place before any other OVR_Kernel objects are used; @@ -47,14 +140,12 @@ namespace OVR { class System { public: - // System constructor expects allocator to be specified, if it is being substituted. System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), Allocator* palloc = DefaultAllocator::InitSystemSingleton()) { Init(log, palloc); } - ~System() { Destroy(); @@ -68,11 +159,12 @@ public: static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), Allocator *palloc = DefaultAllocator::InitSystemSingleton()); - // De-initializes System more, finalizing the threading system and destroying + // De-initializes System more, finalizing the threading system and destroying // the global memory allocator. - static void OVR_CDECL Destroy(); + static void OVR_CDECL Destroy(); }; -} // OVR + +} // namespace OVR #endif diff --git a/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp new file mode 100644 index 0000000..56b68ff --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.cpp @@ -0,0 +1,401 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_ThreadCommandQueue.cpp +Content : Command queue for operations executed on a thread +Created : October 29, 2012 + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "OVR_ThreadCommandQueue.h" + +namespace OVR { + + +//------------------------------------------------------------------------ +// ***** CircularBuffer + +// CircularBuffer is a FIFO buffer implemented in a single block of memory, +// which allows writing and reading variable-size data chucks. Write fails +// if buffer is full. + +class CircularBuffer +{ + enum { + AlignSize = 16, + AlignMask = AlignSize - 1 + }; + + uint8_t* pBuffer; + size_t Size; + size_t Tail; // Byte offset of next item to be popped. + size_t Head; // Byte offset of where next push will take place. + size_t End; // When Head < Tail, this is used instead of Size. + + inline size_t roundUpSize(size_t size) + { return (size + AlignMask) & ~(size_t)AlignMask; } + +public: + + CircularBuffer(size_t size) + : Size(size), Tail(0), Head(0), End(0) + { + pBuffer = (uint8_t*)OVR_ALLOC_ALIGNED(roundUpSize(size), AlignSize); + } + ~CircularBuffer() + { + // For ThreadCommands, we must consume everything before shutdown. + OVR_ASSERT(IsEmpty()); + OVR_FREE_ALIGNED(pBuffer); + } + + bool IsEmpty() const { return (Head == Tail); } + + // Allocates a state block of specified size and advances pointers, + // returning 0 if buffer is full. + uint8_t* Write(size_t size); + + // Returns a pointer to next available data block; 0 if none available. + uint8_t* ReadBegin() + { return (Head != Tail) ? (pBuffer + Tail) : 0; } + // Consumes data of specified size; this must match size passed to Write. + void ReadEnd(size_t size); +}; + + +// Allocates a state block of specified size and advances pointers, +// returning 0 if buffer is full. +uint8_t* CircularBuffer::Write(size_t size) +{ + uint8_t* p = 0; + + size = roundUpSize(size); + // Since this is circular buffer, always allow at least one item. + OVR_ASSERT(size < Size/2); + + if (Head >= Tail) + { + OVR_ASSERT(End == 0); + + if (size <= (Size - Head)) + { + p = pBuffer + Head; + Head += size; + } + else if (size < Tail) + { + p = pBuffer; + End = Head; + Head = size; + OVR_ASSERT(Head != Tail); + } + } + else + { + OVR_ASSERT(End != 0); + + if ((Tail - Head) > size) + { + p = pBuffer + Head; + Head += size; + OVR_ASSERT(Head != Tail); + } + } + + return p; +} + +void CircularBuffer::ReadEnd(size_t size) +{ + OVR_ASSERT(Head != Tail); + size = roundUpSize(size); + + Tail += size; + if (Tail == End) + { + Tail = End = 0; + } + else if (Tail == Head) + { + OVR_ASSERT(End == 0); + Tail = Head = 0; + } +} + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommand + +ThreadCommand::PopBuffer::~PopBuffer() +{ + if (Size) { + Destruct<ThreadCommand>(toCommand()); + } +} + +void ThreadCommand::PopBuffer::InitFromBuffer(void* data) +{ + ThreadCommand* cmd = (ThreadCommand*)data; + OVR_ASSERT(cmd->Size <= MaxSize); + + if (Size) { + Destruct<ThreadCommand>(toCommand()); + } + Size = cmd->Size; + memcpy(Buffer, (void*)cmd, Size); +} + +void ThreadCommand::PopBuffer::Execute() +{ + ThreadCommand* command = toCommand(); + OVR_ASSERT(command); + command->Execute(); + if (NeedsWait()) { + GetEvent()->PulseEvent(); + } +} + +//------------------------------------------------------------------------------------- + +class ThreadCommandQueueImpl : public NewOverrideBase +{ + typedef ThreadCommand::NotifyEvent NotifyEvent; + friend class ThreadCommandQueue; + +public: + + ThreadCommandQueueImpl(ThreadCommandQueue* queue) : + pQueue(queue), + ExitEnqueued(false), + ExitProcessed(false), + CommandBuffer(2048), + PullThreadId(0) + { + } + ~ThreadCommandQueueImpl(); + + + bool PushCommand(const ThreadCommand& command); + bool PopCommand(ThreadCommand::PopBuffer* popBuffer); + + + // ExitCommand is used by notify us that Thread is shutting down. + struct ExitCommand : public ThreadCommand + { + ThreadCommandQueueImpl* pImpl; + + ExitCommand(ThreadCommandQueueImpl* impl, bool wait) + : ThreadCommand(sizeof(ExitCommand), wait, true), pImpl(impl) { } + + virtual void Execute() const + { + Lock::Locker lock(&pImpl->QueueLock); + pImpl->ExitProcessed = true; + } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ExitCommand>(p, *this); } + }; + + + NotifyEvent* AllocNotifyEvent_NTS() + { + NotifyEvent* p = AvailableEvents.GetFirst(); + + if (!AvailableEvents.IsNull(p)) + p->RemoveNode(); + else + p = new NotifyEvent; + return p; + } + + void FreeNotifyEvent_NTS(NotifyEvent* p) + { + AvailableEvents.PushBack(p); + } + + void FreeNotifyEvents_NTS() + { + while(!AvailableEvents.IsEmpty()) + { + NotifyEvent* p = AvailableEvents.GetFirst(); + p->RemoveNode(); + delete p; + } + } + + ThreadCommandQueue* pQueue; + Lock QueueLock; + volatile bool ExitEnqueued; + volatile bool ExitProcessed; + List<NotifyEvent> AvailableEvents; + List<NotifyEvent> BlockedProducers; + CircularBuffer CommandBuffer; + + // The pull thread id is set to the last thread that pulled commands. + // Since this thread command queue is designed for a single thread, + // reentrant behavior that would cause a dead-lock for messages that + // wait for completion can be avoided by simply comparing the + // thread id of the last pull. + OVR::ThreadId PullThreadId; +}; + +ThreadCommandQueueImpl::~ThreadCommandQueueImpl() +{ + Lock::Locker lock(&QueueLock); + OVR_ASSERT(BlockedProducers.IsEmpty()); + FreeNotifyEvents_NTS(); +} + +bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command) +{ + if (command.NeedsWait() && PullThreadId == OVR::GetCurrentThreadId()) + { + command.Execute(); + return true; + } + + ThreadCommand::NotifyEvent* completeEvent = 0; + ThreadCommand::NotifyEvent* queueAvailableEvent = 0; + + // Repeat writing command into buffer until it is available. + for (;;) { + { // Lock Scope + Lock::Locker lock(&QueueLock); + + if (queueAvailableEvent) { + FreeNotifyEvent_NTS(queueAvailableEvent); + queueAvailableEvent = 0; + } + + // Don't allow any commands after PushExitCommand() is called. + if (ExitEnqueued && !command.ExitFlag) { + return false; + } + + bool bufferWasEmpty = CommandBuffer.IsEmpty(); + uint8_t* buffer = CommandBuffer.Write(command.GetSize()); + + if (buffer) { + ThreadCommand* c = command.CopyConstruct(buffer); + + if (c->NeedsWait()) { + completeEvent = c->pEvent = AllocNotifyEvent_NTS(); + } + + // Signal-waker consumer when we add data to buffer. + if (bufferWasEmpty) { + pQueue->OnPushNonEmpty_Locked(); + } + + break; + } + + queueAvailableEvent = AllocNotifyEvent_NTS(); + BlockedProducers.PushBack(queueAvailableEvent); + } // Lock Scope + + queueAvailableEvent->Wait(); + } // Intentional infinite loop + + // Command was enqueued, wait if necessary. + if (completeEvent) { + completeEvent->Wait(); + Lock::Locker lock(&QueueLock); + FreeNotifyEvent_NTS(completeEvent); + } + + return true; +} + + +// Pops the next command from the thread queue, if any is available. +bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer) +{ + PullThreadId = OVR::GetCurrentThreadId(); + + Lock::Locker lock(&QueueLock); + + uint8_t* buffer = CommandBuffer.ReadBegin(); + if (!buffer) + { + // Notify thread while in lock scope, enabling initialization of wait. + pQueue->OnPopEmpty_Locked(); + return false; + } + + popBuffer->InitFromBuffer(buffer); + CommandBuffer.ReadEnd(popBuffer->GetSize()); + + if (!BlockedProducers.IsEmpty()) + { + ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst(); + queueAvailableEvent->RemoveNode(); + queueAvailableEvent->PulseEvent(); + // Event is freed later by waiter. + } + return true; +} + + +//------------------------------------------------------------------------------------- + +ThreadCommandQueue::ThreadCommandQueue() +{ + pImpl = new ThreadCommandQueueImpl(this); +} +ThreadCommandQueue::~ThreadCommandQueue() +{ + delete pImpl; +} + +bool ThreadCommandQueue::PushCommand(const ThreadCommand& command) +{ + return pImpl->PushCommand(command); +} + +bool ThreadCommandQueue::PopCommand(ThreadCommand::PopBuffer* popBuffer) +{ + return pImpl->PopCommand(popBuffer); +} + +void ThreadCommandQueue::PushExitCommand(bool wait) +{ + // Exit is processed in two stages: + // - First, ExitEnqueued flag is set to block further commands from queuing up. + // - Second, the actual exit call is processed on the consumer thread, flushing + // any prior commands. + // IsExiting() only returns true after exit has flushed. + { + Lock::Locker lock(&pImpl->QueueLock); + if (pImpl->ExitEnqueued) + return; + pImpl->ExitEnqueued = true; + } + + PushCommand(ThreadCommandQueueImpl::ExitCommand(pImpl, wait)); +} + +bool ThreadCommandQueue::IsExiting() const +{ + return pImpl->ExitProcessed; +} + + +} // namespace OVR diff --git a/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h new file mode 100644 index 0000000..31b836f --- /dev/null +++ b/LibOVR/Src/Kernel/OVR_ThreadCommandQueue.h @@ -0,0 +1,318 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_ThreadCommandQueue.h +Content : Command queue for operations executed on a thread +Created : October 29, 2012 +Author : Michael Antonov + +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. + +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +http://www.oculusvr.com/licenses/LICENSE-3.1 + +Unless required by applicable law or agreed to in writing, the Oculus VR SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_ThreadCommandQueue_h +#define OVR_ThreadCommandQueue_h + +#include "../Kernel/OVR_Types.h" +#include "../Kernel/OVR_List.h" +#include "../Kernel/OVR_Atomic.h" +#include "../Kernel/OVR_Threads.h" + +namespace OVR { + +class ThreadCommand; +class ThreadCommandQueue; + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommand + +// ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue. +class ThreadCommand +{ +public: + // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the + // calling (producer) thread when command is completed or queue slot is available. + class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase + { + Event E; + public: + NotifyEvent() { } + + void Wait() { E.Wait(); } + void PulseEvent() { E.PulseEvent(); } + }; + + // ThreadCommand::PopBuffer is temporary storage for a command popped off + // by ThreadCommandQueue::PopCommand. + class PopBuffer + { + enum { MaxSize = 256 }; + + size_t Size; + union { + uint8_t Buffer[MaxSize]; + size_t Align; + }; + + ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; } + + public: + PopBuffer() : Size(0) { } + ~PopBuffer(); + + void InitFromBuffer(void* data); + + bool HasCommand() const { return Size != 0; } + size_t GetSize() const { return Size; } + bool NeedsWait() const { return toCommand()->NeedsWait(); } + NotifyEvent* GetEvent() const { return toCommand()->pEvent; } + + // Execute the command and also notifies caller to finish waiting, + // if necessary. + void Execute(); + }; + + uint16_t Size; + bool WaitFlag; + bool ExitFlag; // Marks the last exit command. + NotifyEvent* pEvent; + + ThreadCommand(size_t size, bool waitFlag, bool exitFlag = false) + : Size((uint16_t)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { } + virtual ~ThreadCommand() { } + + bool NeedsWait() const { return WaitFlag; } + size_t GetSize() const { return Size; } + + virtual void Execute() const = 0; + // Copy constructor used for serializing this to memory buffer. + virtual ThreadCommand* CopyConstruct(void* p) const = 0; +}; + + +//------------------------------------------------------------------------------------- + +// CleanType is a template that strips 'const' and '&' modifiers from the argument type; +// for example, typename CleanType<A&>::Type is equivalent to A. +template<class T> struct CleanType { typedef T Type; }; +template<class T> struct CleanType<T&> { typedef T Type; }; +template<class T> struct CleanType<const T> { typedef T Type; }; +template<class T> struct CleanType<const T&> { typedef T Type; }; + +// SelfType is a template that yields the argument type. This helps avoid conflicts with +// automatic template argument deduction for function calls when identical argument +// is already defined. +template<class T> struct SelfType { typedef T Type; }; + + + +//------------------------------------------------------------------------------------- +// ThreadCommand specializations for member functions with different number of +// arguments and argument types. + +// Used to return nothing from a ThreadCommand, to avoid problems with 'void'. +struct Void +{ + Void() {} + Void(int) {} +}; + +// ThreadCommand for member function with 0 arguments. +template<class C, class R> +class ThreadCommandMF0 : public ThreadCommand +{ + typedef R (C::*FnPtr)(); + C* pClass; + FnPtr pFn; + R* pRet; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)()) : + (void)(pClass->*pFn)(); + } + +public: + ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF0), needsWait), + pClass(pclass), pFn(fn), pRet(ret) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF0>(p, *this); } +}; + + +// ThreadCommand for member function with 1 argument. +template<class C, class R, class A0> +class ThreadCommandMF1 : public ThreadCommand +{ + typedef R (C::*FnPtr)(A0); + C* pClass; + FnPtr pFn; + R* pRet; + typename CleanType<A0>::Type AVal0; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) : + (void)(pClass->*pFn)(AVal0); + } + +public: + ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF1), needsWait), + pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF1>(p, *this); } +}; + +// ThreadCommand for member function with 2 arguments. +template<class C, class R, class A0, class A1> +class ThreadCommandMF2 : public ThreadCommand +{ + typedef R (C::*FnPtr)(A0, A1); + C* pClass; + FnPtr pFn; + R* pRet; + typename CleanType<A0>::Type AVal0; + typename CleanType<A1>::Type AVal1; + + void executeImpl() const + { + pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) : + (void)(pClass->*pFn)(AVal0, AVal1); + } + +public: + ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait) + : ThreadCommand(sizeof(ThreadCommandMF2), needsWait), + pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { } + + virtual void Execute() const { executeImpl(); } + virtual ThreadCommand* CopyConstruct(void* p) const + { return Construct<ThreadCommandMF2>(p, *this); } +}; + + +//------------------------------------------------------------------------------------- +// ***** ThreadCommandQueue + +// ThreadCommandQueue is a queue of executable function-call commands intended to be +// serviced by a single consumer thread. Commands are added to the queue with PushCall +// and removed with PopCall; they are processed in FIFO order. Multiple producer threads +// are supported and will be blocked if internal data buffer is full. + +class ThreadCommandQueue +{ +public: + + ThreadCommandQueue(); + virtual ~ThreadCommandQueue(); + + + // Pops the next command from the thread queue, if any is available. + // The command should be executed by calling popBuffer->Execute(). + // Returns 'false' if no command is available at the time of the call. + bool PopCommand(ThreadCommand::PopBuffer* popBuffer); + + // Generic implementaion of PushCommand; enqueues a command for execution. + // Returns 'false' if push failed, usually indicating thread shutdown. + bool PushCommand(const ThreadCommand& command); + + // + void PushExitCommand(bool wait); + + // Returns 'true' once ExitCommand has been processed, so the thread can shut down. + bool IsExiting() const; + + + // These two virtual functions serve as notifications for derived + // thread waiting. + virtual void OnPushNonEmpty_Locked() { } + virtual void OnPopEmpty_Locked() { } + + + // *** PushCall with no result + + // Enqueue a member function of 'this' class to be called on consumer thread. + // By default the function returns immediately; set 'wait' argument to 'true' to + // wait for completion. + template<class C, class R> + bool PushCall(R (C::*fn)(), bool wait = false) + { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); } + template<class C, class R, class A0> + bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false) + { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); } + template<class C, class R, class A0, class A1> + bool PushCall(R (C::*fn)(A0, A1), + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); } + // Enqueue a specified member function call of class C. + // By default the function returns immediately; set 'wait' argument to 'true' to + // wait for completion. + template<class C, class R> + bool PushCall(C* p, R (C::*fn)(), bool wait = false) + { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); } + template<class C, class R, class A0> + bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false) + { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); } + template<class C, class R, class A0, class A1> + bool PushCall(C* p, R (C::*fn)(A0, A1), + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); } + + + // *** PushCall with Result + + // Enqueue a member function of 'this' class call and wait for call to complete + // on consumer thread before returning. + template<class C, class R> + bool PushCallAndWaitResult(R (C::*fn)(), R* ret) + { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); } + template<class C, class R, class A0> + bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0) + { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); } + template<class C, class R, class A0, class A1> + bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret, + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); } + // Enqueue a member function call for class C and wait for the call to complete + // on consumer thread before returning. + template<class C, class R> + bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret) + { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); } + template<class C, class R, class A0> + bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0) + { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); } + template<class C, class R, class A0, class A1> + bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret, + typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1) + { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); } + +private: + class ThreadCommandQueueImpl* pImpl; +}; + + +} // namespace OVR + +#endif // OVR_ThreadCommandQueue_h diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h index 307f107..0ecc152 100644 --- a/LibOVR/Src/Kernel/OVR_Threads.h +++ b/LibOVR/Src/Kernel/OVR_Threads.h @@ -196,9 +196,7 @@ typedef void* ThreadId; class Thread : public RefCountBase<Thread> { // NOTE: Waitable must be the first base since it implements RefCountImpl. - public: - // *** Callback functions, can be used instead of overriding Run // Run function prototypes. @@ -234,30 +232,31 @@ public: // Thread constructor parameters struct CreateParams { - CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, + CreateParams(ThreadFn func = 0, void* hand = 0, size_t ssize = 128 * 1024, int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) : threadFunction(func), userHandle(hand), stackSize(ssize), processor(proc), initialState(state), priority(prior) {} ThreadFn threadFunction; // Thread function void* userHandle; // User handle passes to a thread - UPInt stackSize; // Thread stack size + size_t stackSize; // Thread stack size int processor; // Thread hardware processor ThreadState initialState; // ThreadPriority priority; // Thread priority }; + // *** Constructors // A default constructor always creates a thread in NotRunning state, because // the derived class has not yet been initialized. The derived class can call Start explicitly. // "processor" parameter specifies which hardware processor this thread will be run on. // -1 means OS decides this. Implemented only on Win32 - Thread(UPInt stackSize = 128 * 1024, int processor = -1); + Thread(size_t stackSize = 128 * 1024, int processor = -1); // Constructors that initialize the thread with a pointer to function. // An option to start a thread is available, but it should not be used if classes are derived from Thread. // "processor" parameter specifies which hardware processor this thread will be run on. // -1 means OS decides this. Implemented only on Win32 - Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024, + Thread(ThreadFn threadFunction, void* userHandle = 0, size_t stackSize = 128 * 1024, int processor = -1, ThreadState initialState = NotRunning); // Constructors that initialize the thread with a create parameters structure. explicit Thread(const CreateParams& params); @@ -314,6 +313,11 @@ public: // Returns current thread state ThreadState GetThreadState() const; + // Wait for thread to finish for a maxmimum number of milliseconds + // For maxWaitMs = 0 it simply polls and then returns if the thread is not finished + // For maxWaitMs < 0 it will wait forever + bool Join(int maxWaitMs = -1) const; + // Returns the number of available CPUs on the system static int GetCPUCount(); @@ -321,13 +325,13 @@ public: // and set to the return value if Run function after the thread is finished. inline int GetExitCode() const { return ExitCode; } // Returns an OS handle -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) void* GetOSHandle() const { return ThreadHandle; } #else pthread_t GetOSHandle() const { return ThreadHandle; } #endif -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) ThreadId GetThreadId() const { return IdValue; } #else ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } @@ -343,16 +347,11 @@ public: // *** Debugging functionality -#if defined(OVR_OS_WIN32) virtual void SetThreadName( const char* name ); -#else - virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); } -#endif private: #if defined(OVR_OS_WIN32) - friend unsigned WINAPI Thread_Win32StartFn(void *pthread); - + friend unsigned WINAPI Thread_Win32StartFn(void *phandle); #else friend void *Thread_PthreadStartFn(void * phandle); @@ -362,15 +361,15 @@ private: protected: // Thread state flags - AtomicInt<UInt32> ThreadFlags; - AtomicInt<SInt32> SuspendCount; - UPInt StackSize; + AtomicInt<uint32_t> ThreadFlags; + AtomicInt<int32_t> SuspendCount; + size_t StackSize; // Hardware processor which this thread is running on. int Processor; ThreadPriority Priority; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) void* ThreadHandle; volatile ThreadId IdValue; diff --git a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp deleted file mode 100644 index da483d5..0000000 --- a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/************************************************************************************ - -Filename : OVR_ThreadsPthread.cpp -Content : -Created : -Notes : - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -************************************************************************************/ - -#include "OVR_Threads.h" -#include "OVR_Hash.h" - -#ifdef OVR_ENABLE_THREADS - -#include "OVR_Timer.h" -#include "OVR_Log.h" - -#include <pthread.h> -#include <time.h> -#include <unistd.h> -#include <sys/time.h> -#include <errno.h> - - -namespace OVR { - -// ***** Mutex implementation - - -// *** Internal Mutex implementation structure - -class MutexImpl : public NewOverrideBase -{ - // System mutex or semaphore - pthread_mutex_t SMutex; - bool Recursive; - unsigned LockCount; - pthread_t LockedBy; - - friend class WaitConditionImpl; - -public: - // Constructor/destructor - MutexImpl(Mutex* pmutex, bool recursive = 1); - ~MutexImpl(); - - // Locking functions - void DoLock(); - bool TryLock(); - void Unlock(Mutex* pmutex); - // Returns 1 if the mutes is currently locked - bool IsLockedByAnotherThread(Mutex* pmutex); - bool IsSignaled() const; -}; - -pthread_mutexattr_t Lock::RecursiveAttr; -bool Lock::RecursiveAttrInit = 0; - -// *** Constructor/destructor -MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) -{ - OVR_UNUSED(pmutex); - Recursive = recursive; - LockCount = 0; - - if (Recursive) - { - if (!Lock::RecursiveAttrInit) - { - pthread_mutexattr_init(&Lock::RecursiveAttr); - pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); - Lock::RecursiveAttrInit = 1; - } - - pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); - } - else - pthread_mutex_init(&SMutex, 0); -} - -MutexImpl::~MutexImpl() -{ - pthread_mutex_destroy(&SMutex); -} - - -// Lock and try lock -void MutexImpl::DoLock() -{ - while (pthread_mutex_lock(&SMutex)) - ; - LockCount++; - LockedBy = pthread_self(); -} - -bool MutexImpl::TryLock() -{ - if (!pthread_mutex_trylock(&SMutex)) - { - LockCount++; - LockedBy = pthread_self(); - return 1; - } - - return 0; -} - -void MutexImpl::Unlock(Mutex* pmutex) -{ - OVR_UNUSED(pmutex); - OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); - - unsigned lockCount; - LockCount--; - lockCount = LockCount; - - pthread_mutex_unlock(&SMutex); -} - -bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) -{ - OVR_UNUSED(pmutex); - // There could be multiple interpretations of IsLocked with respect to current thread - if (LockCount == 0) - return 0; - if (pthread_self() != LockedBy) - return 1; - return 0; -} - -bool MutexImpl::IsSignaled() const -{ - // An mutex is signaled if it is not locked ANYWHERE - // Note that this is different from IsLockedByAnotherThread function, - // that takes current thread into account - return LockCount == 0; -} - - -// *** Actual Mutex class implementation - -Mutex::Mutex(bool recursive) -{ - // NOTE: RefCount mode already thread-safe for all waitables. - pImpl = new MutexImpl(this, recursive); -} - -Mutex::~Mutex() -{ - delete pImpl; -} - -// Lock and try lock -void Mutex::DoLock() -{ - pImpl->DoLock(); -} -bool Mutex::TryLock() -{ - return pImpl->TryLock(); -} -void Mutex::Unlock() -{ - pImpl->Unlock(this); -} -bool Mutex::IsLockedByAnotherThread() -{ - return pImpl->IsLockedByAnotherThread(this); -} - - - -//----------------------------------------------------------------------------------- -// ***** Event - -bool Event::Wait(unsigned delay) -{ - Mutex::Locker lock(&StateMutex); - - // Do the correct amount of waiting - if (delay == OVR_WAIT_INFINITE) - { - while(!State) - StateWaitCondition.Wait(&StateMutex); - } - else if (delay) - { - if (!State) - StateWaitCondition.Wait(&StateMutex, delay); - } - - bool state = State; - // Take care of temporary 'pulsing' of a state - if (Temporary) - { - Temporary = false; - State = false; - } - return state; -} - -void Event::updateState(bool newState, bool newTemp, bool mustNotify) -{ - Mutex::Locker lock(&StateMutex); - State = newState; - Temporary = newTemp; - if (mustNotify) - StateWaitCondition.NotifyAll(); -} - - - -// ***** Wait Condition Implementation - -// Internal implementation class -class WaitConditionImpl : public NewOverrideBase -{ - pthread_mutex_t SMutex; - pthread_cond_t Condv; - -public: - - // Constructor/destructor - WaitConditionImpl(); - ~WaitConditionImpl(); - - // Release mutex and wait for condition. The mutex is re-aqured after the wait. - bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); - - // Notify a condition, releasing at one object waiting - void Notify(); - // Notify a condition, releasing all objects waiting - void NotifyAll(); -}; - - -WaitConditionImpl::WaitConditionImpl() -{ - pthread_mutex_init(&SMutex, 0); - pthread_cond_init(&Condv, 0); -} - -WaitConditionImpl::~WaitConditionImpl() -{ - pthread_mutex_destroy(&SMutex); - pthread_cond_destroy(&Condv); -} - -bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) -{ - bool result = 1; - unsigned lockCount = pmutex->pImpl->LockCount; - - // Mutex must have been locked - if (lockCount == 0) - return 0; - - pthread_mutex_lock(&SMutex); - - // Finally, release a mutex or semaphore - if (pmutex->pImpl->Recursive) - { - // Release the recursive mutex N times - pmutex->pImpl->LockCount = 0; - for(unsigned i=0; i<lockCount; i++) - pthread_mutex_unlock(&pmutex->pImpl->SMutex); - } - else - { - pmutex->pImpl->LockCount = 0; - pthread_mutex_unlock(&pmutex->pImpl->SMutex); - } - - // Note that there is a gap here between mutex.Unlock() and Wait(). - // The other mutex protects this gap. - - if (delay == OVR_WAIT_INFINITE) - pthread_cond_wait(&Condv,&SMutex); - else - { - timespec ts; - - struct timeval tv; - gettimeofday(&tv, 0); - - ts.tv_sec = tv.tv_sec + (delay / 1000); - ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000; - - if (ts.tv_nsec > 999999999) - { - ts.tv_sec++; - ts.tv_nsec -= 1000000000; - } - int r = pthread_cond_timedwait(&Condv,&SMutex, &ts); - OVR_ASSERT(r == 0 || r == ETIMEDOUT); - if (r) - result = 0; - } - - pthread_mutex_unlock(&SMutex); - - // Re-aquire the mutex - for(unsigned i=0; i<lockCount; i++) - pmutex->DoLock(); - - // Return the result - return result; -} - -// Notify a condition, releasing the least object in a queue -void WaitConditionImpl::Notify() -{ - pthread_mutex_lock(&SMutex); - pthread_cond_signal(&Condv); - pthread_mutex_unlock(&SMutex); -} - -// Notify a condition, releasing all objects waiting -void WaitConditionImpl::NotifyAll() -{ - pthread_mutex_lock(&SMutex); - pthread_cond_broadcast(&Condv); - pthread_mutex_unlock(&SMutex); -} - - - -// *** Actual implementation of WaitCondition - -WaitCondition::WaitCondition() -{ - pImpl = new WaitConditionImpl; -} -WaitCondition::~WaitCondition() -{ - delete pImpl; -} - -bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) -{ - return pImpl->Wait(pmutex, delay); -} -// Notification -void WaitCondition::Notify() -{ - pImpl->Notify(); -} -void WaitCondition::NotifyAll() -{ - pImpl->NotifyAll(); -} - - -// ***** Current thread - -// Per-thread variable -/* -static __thread Thread* pCurrentThread = 0; - -// Static function to return a pointer to the current thread -void Thread::InitCurrentThread(Thread *pthread) -{ - pCurrentThread = pthread; -} - -// Static function to return a pointer to the current thread -Thread* Thread::GetThread() -{ - return pCurrentThread; -} -*/ - - -// *** Thread constructors. - -Thread::Thread(UPInt stackSize, int processor) -{ - // NOTE: RefCount mode already thread-safe for all Waitable objects. - CreateParams params; - params.stackSize = stackSize; - params.processor = processor; - Init(params); -} - -Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, - int processor, Thread::ThreadState initialState) -{ - CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); - Init(params); -} - -Thread::Thread(const CreateParams& params) -{ - Init(params); -} - -void Thread::Init(const CreateParams& params) -{ - // Clear the variables - ThreadFlags = 0; - ThreadHandle = 0; - ExitCode = 0; - SuspendCount = 0; - StackSize = params.stackSize; - Processor = params.processor; - Priority = params.priority; - - // Clear Function pointers - ThreadFunction = params.threadFunction; - UserHandle = params.userHandle; - if (params.initialState != NotRunning) - Start(params.initialState); -} - -Thread::~Thread() -{ - // Thread should not running while object is being destroyed, - // this would indicate ref-counting issue. - //OVR_ASSERT(IsRunning() == 0); - - // Clean up thread. - ThreadHandle = 0; -} - - - -// *** Overridable User functions. - -// Default Run implementation -int Thread::Run() -{ - // Call pointer to function, if available. - return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; -} -void Thread::OnExit() -{ -} - - -// Finishes the thread and releases internal reference to it. -void Thread::FinishAndRelease() -{ - // Note: thread must be US. - ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); - ThreadFlags |= OVR_THREAD_FINISHED; - - // Release our reference; this is equivalent to 'delete this' - // from the point of view of our thread. - Release(); -} - - - -// *** ThreadList - used to track all created threads - -class ThreadList : public NewOverrideBase -{ - //------------------------------------------------------------------------ - struct ThreadHashOp - { - size_t operator()(const Thread* ptr) - { - return (((size_t)ptr) >> 6) ^ (size_t)ptr; - } - }; - - HashSet<Thread*, ThreadHashOp> ThreadSet; - Mutex ThreadMutex; - WaitCondition ThreadsEmpty; - // Track the root thread that created us. - pthread_t RootThreadId; - - static ThreadList* volatile pRunningThreads; - - void addThread(Thread *pthread) - { - Mutex::Locker lock(&ThreadMutex); - ThreadSet.Add(pthread); - } - - void removeThread(Thread *pthread) - { - Mutex::Locker lock(&ThreadMutex); - ThreadSet.Remove(pthread); - if (ThreadSet.GetSize() == 0) - ThreadsEmpty.Notify(); - } - - void finishAllThreads() - { - // Only original root thread can call this. - OVR_ASSERT(pthread_self() == RootThreadId); - - Mutex::Locker lock(&ThreadMutex); - while (ThreadSet.GetSize() != 0) - ThreadsEmpty.Wait(&ThreadMutex); - } - -public: - - ThreadList() - { - RootThreadId = pthread_self(); - } - ~ThreadList() { } - - - static void AddRunningThread(Thread *pthread) - { - // Non-atomic creation ok since only the root thread - if (!pRunningThreads) - { - pRunningThreads = new ThreadList; - OVR_ASSERT(pRunningThreads); - } - pRunningThreads->addThread(pthread); - } - - // NOTE: 'pthread' might be a dead pointer when this is - // called so it should not be accessed; it is only used - // for removal. - static void RemoveRunningThread(Thread *pthread) - { - OVR_ASSERT(pRunningThreads); - pRunningThreads->removeThread(pthread); - } - - static void FinishAllThreads() - { - // This is ok because only root thread can wait for other thread finish. - if (pRunningThreads) - { - pRunningThreads->finishAllThreads(); - delete pRunningThreads; - pRunningThreads = 0; - } - } -}; - -// By default, we have no thread list. -ThreadList* volatile ThreadList::pRunningThreads = 0; - - -// FinishAllThreads - exposed publicly in Thread. -void Thread::FinishAllThreads() -{ - ThreadList::FinishAllThreads(); -} - -// *** Run override - -int Thread::PRun() -{ - // Suspend us on start, if requested - if (ThreadFlags & OVR_THREAD_START_SUSPENDED) - { - Suspend(); - ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; - } - - // Call the virtual run function - ExitCode = Run(); - return ExitCode; -} - - - - -// *** User overridables - -bool Thread::GetExitFlag() const -{ - return (ThreadFlags & OVR_THREAD_EXIT) != 0; -} - -void Thread::SetExitFlag(bool exitFlag) -{ - // The below is atomic since ThreadFlags is AtomicInt. - if (exitFlag) - ThreadFlags |= OVR_THREAD_EXIT; - else - ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; -} - - -// Determines whether the thread was running and is now finished -bool Thread::IsFinished() const -{ - return (ThreadFlags & OVR_THREAD_FINISHED) != 0; -} -// Determines whether the thread is suspended -bool Thread::IsSuspended() const -{ - return SuspendCount > 0; -} -// Returns current thread state -Thread::ThreadState Thread::GetThreadState() const -{ - if (IsSuspended()) - return Suspended; - if (ThreadFlags & OVR_THREAD_STARTED) - return Running; - return NotRunning; -} -/* -static const char* mapsched_policy(int policy) -{ - switch(policy) - { - case SCHED_OTHER: - return "SCHED_OTHER"; - case SCHED_RR: - return "SCHED_RR"; - case SCHED_FIFO: - return "SCHED_FIFO"; - - } - return "UNKNOWN"; -} - int policy; - sched_param sparam; - pthread_getschedparam(pthread_self(), &policy, &sparam); - int max_prior = sched_get_priority_max(policy); - int min_prior = sched_get_priority_min(policy); - printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior); -#include <stdio.h> -*/ -// ***** Thread management - -// The actual first function called on thread start -void* Thread_PthreadStartFn(void* phandle) -{ - Thread* pthread = (Thread*)phandle; - int result = pthread->PRun(); - // Signal the thread as done and release it atomically. - pthread->FinishAndRelease(); - // At this point Thread object might be dead; however we can still pass - // it to RemoveRunningThread since it is only used as a key there. - ThreadList::RemoveRunningThread(pthread); - return reinterpret_cast<void*>(result); -} - -int Thread::InitAttr = 0; -pthread_attr_t Thread::Attr; - -/* static */ -int Thread::GetOSPriority(ThreadPriority p) -//static inline int MapToSystemPrority(Thread::ThreadPriority p) -{ - OVR_UNUSED(p); - return -1; -} - -bool Thread::Start(ThreadState initialState) -{ - if (initialState == NotRunning) - return 0; - if (GetThreadState() != NotRunning) - { - OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); - return 0; - } - - if (!InitAttr) - { - pthread_attr_init(&Attr); - pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&Attr, 128 * 1024); - sched_param sparam; - sparam.sched_priority = Thread::GetOSPriority(NormalPriority); - pthread_attr_setschedparam(&Attr, &sparam); - InitAttr = 1; - } - - ExitCode = 0; - SuspendCount = 0; - ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; - - // AddRef to us until the thread is finished - AddRef(); - ThreadList::AddRunningThread(this); - - int result; - if (StackSize != 128 * 1024 || Priority != NormalPriority) - { - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&attr, StackSize); - sched_param sparam; - sparam.sched_priority = Thread::GetOSPriority(Priority); - pthread_attr_setschedparam(&attr, &sparam); - result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this); - pthread_attr_destroy(&attr); - } - else - result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this); - - if (result) - { - ThreadFlags = 0; - Release(); - ThreadList::RemoveRunningThread(this); - return 0; - } - return 1; -} - - -// Suspend the thread until resumed -bool Thread::Suspend() -{ - OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system")); - return 0; -} - -// Resumes currently suspended thread -bool Thread::Resume() -{ - return 0; -} - - -// Quits with an exit code -void Thread::Exit(int exitCode) -{ - // Can only exist the current thread - // if (GetThread() != this) - // return; - - // Call the virtual OnExit function - OnExit(); - - // Signal this thread object as done and release it's references. - FinishAndRelease(); - ThreadList::RemoveRunningThread(this); - - pthread_exit(reinterpret_cast<void*>(exitCode)); -} - -ThreadId GetCurrentThreadId() -{ - return (void*)pthread_self(); -} - -// *** Sleep functions - -/* static */ -bool Thread::Sleep(unsigned secs) -{ - sleep(secs); - return 1; -} -/* static */ -bool Thread::MSleep(unsigned msecs) -{ - usleep(msecs*1000); - return 1; -} - -/* static */ -int Thread::GetCPUCount() -{ - return 1; -} - -} - -#endif // OVR_ENABLE_THREADS diff --git a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp index 663d859..25c4d2b 100644 --- a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp +++ b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp @@ -28,6 +28,7 @@ limitations under the License. #include "OVR_Threads.h" #include "OVR_Hash.h" #include "OVR_Log.h" +#include "OVR_Timer.h" #ifdef OVR_ENABLE_THREADS @@ -541,7 +542,7 @@ __declspec(thread) Thread* pCurrentThread = 0; // *** Thread constructors. -Thread::Thread(UPInt stackSize, int processor) +Thread::Thread(size_t stackSize, int processor) { CreateParams params; params.stackSize = stackSize; @@ -549,7 +550,7 @@ Thread::Thread(UPInt stackSize, int processor) Init(params); } -Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, +Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, size_t stackSize, int processor, Thread::ThreadState initialState) { CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); @@ -597,9 +598,14 @@ Thread::~Thread() // Default Run implementation int Thread::Run() { - // Call pointer to function, if available. - return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; + if (!ThreadFunction) + return 0; + + int ret = ThreadFunction(this, UserHandle); + + return ret; } + void Thread::OnExit() { } @@ -608,7 +614,7 @@ void Thread::OnExit() void Thread::FinishAndRelease() { // Note: thread must be US. - ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); + ThreadFlags &= (uint32_t)~(OVR_THREAD_STARTED); ThreadFlags |= OVR_THREAD_FINISHED; // Release our reference; this is equivalent to 'delete this' @@ -624,9 +630,9 @@ class ThreadList : public NewOverrideBase //------------------------------------------------------------------------ struct ThreadHashOp { - UPInt operator()(const Thread* ptr) + size_t operator()(const Thread* ptr) { - return (((UPInt)ptr) >> 6) ^ (UPInt)ptr; + return (((size_t)ptr) >> 6) ^ (size_t)ptr; } }; @@ -722,11 +728,12 @@ int Thread::PRun() if (ThreadFlags & OVR_THREAD_START_SUSPENDED) { Suspend(); - ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; + ThreadFlags &= (uint32_t)~OVR_THREAD_START_SUSPENDED; } // Call the virtual run function ExitCode = Run(); + return ExitCode; } @@ -761,7 +768,7 @@ void Thread::SetExitFlag(bool exitFlag) if (exitFlag) ThreadFlags |= OVR_THREAD_EXIT; else - ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; + ThreadFlags &= (uint32_t) ~OVR_THREAD_EXIT; } @@ -779,12 +786,39 @@ bool Thread::IsSuspended() const Thread::ThreadState Thread::GetThreadState() const { if (IsSuspended()) - return Suspended; + return Suspended; if (ThreadFlags & OVR_THREAD_STARTED) - return Running; + return Running; return NotRunning; } +// Join thread +bool Thread::Join(int maxWaitMs) const +{ + // If polling, + if (maxWaitMs == 0) + { + // Just return if finished + return IsFinished(); + } + // If waiting forever, + else if (maxWaitMs > 0) + { + // Try waiting once + WaitForSingleObject(ThreadHandle, maxWaitMs); + + // Return if the wait succeeded + return IsFinished(); + } + // While not finished, + while (!IsFinished()) + { + // Wait for the thread handle to signal + WaitForSingleObject(ThreadHandle, INFINITE); + } + + return true; +} // ***** Thread management @@ -852,8 +886,9 @@ bool Thread::Start(ThreadState initialState) ExitCode = 0; SuspendCount = 0; ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; + ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize, - Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); + Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); // Failed? Fail the function if (ThreadHandle == 0) @@ -890,13 +925,15 @@ bool Thread::Resume() return 0; // Decrement count, and resume thread if it is 0 - SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1); + int32_t oldCount = SuspendCount.ExchangeAdd_Acquire(-1); if (oldCount >= 1) { if (oldCount == 1) { - if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF) - return 1; + if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF) + { + return 1; + } } else { @@ -922,7 +959,7 @@ void Thread::Exit(int exitCode) FinishAndRelease(); ThreadList::RemoveRunningThread(this); - // Call the exit function. + // Call the exit function. _endthreadex((unsigned)exitCode); } @@ -979,6 +1016,7 @@ void Thread::SetThreadName( const char* name ) } __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER ) { + return; } #endif // OVR_BUILD_SHIPPING } @@ -1001,5 +1039,3 @@ ThreadId GetCurrentThreadId() } // OVR #endif - - diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp index a8de47d..5269106 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.cpp +++ b/LibOVR/Src/Kernel/OVR_Timer.cpp @@ -27,8 +27,10 @@ limitations under the License. #include "OVR_Timer.h" #include "OVR_Log.h" -#if defined (OVR_OS_WIN32) +#if defined (OVR_OS_WIN32) +#define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <MMSystem.h> #elif defined(OVR_OS_ANDROID) #include <time.h> #include <android/log.h> @@ -57,7 +59,7 @@ double Timer::GetSeconds() } -#ifndef OVR_OS_WIN32 +#if !defined(OVR_OS_WIN32) // Unused on OSs other then Win32. void Timer::initializeTimerSystem() @@ -76,10 +78,10 @@ void Timer::shutdownTimerSystem() #if defined(OVR_OS_ANDROID) -UInt64 Timer::GetTicksNanos() +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); // Choreographer vsync timestamp is based on. struct timespec tp; @@ -89,7 +91,7 @@ UInt64 Timer::GetTicksNanos() { OVR_DEBUG_LOG(("clock_gettime status=%i", status )); } - const UInt64 result = (UInt64)tp.tv_sec * (UInt64)(1000 * 1000 * 1000) + UInt64(tp.tv_nsec); + const uint64_t result = (uint64_t)tp.tv_sec * (uint64_t)(1000 * 1000 * 1000) + uint64_t(tp.tv_nsec); return result; } @@ -97,7 +99,7 @@ UInt64 Timer::GetTicksNanos() //------------------------------------------------------------------------ // *** Win32 Specific Timer -#elif defined (OVR_OS_WIN32) +#elif defined (OVR_OS_WIN32) // This helper class implements high-resolution wrapper that combines timeGetTime() output @@ -117,7 +119,7 @@ struct PerformanceTimer void Initialize(); void Shutdown(); - UInt64 GetTimeNanos(); + uint64_t GetTimeNanos(); UINT64 getFrequency() @@ -131,19 +133,20 @@ struct PerformanceTimer return PrefFrequency; } + bool UsingVista; CRITICAL_SECTION TimeCS; // timeGetTime() support with wrap. - UInt32 OldMMTimeMs; - UInt32 MMTimeWrapCounter; + uint32_t OldMMTimeMs; + uint32_t MMTimeWrapCounter; // Cached performance frequency result. - UInt64 PrefFrequency; + uint64_t PrefFrequency; // Computed as (perfCounterNanos - ticksCounterNanos) initially, // and used to adjust timing. - UInt64 PerfMinusTicksDeltaNanos; + uint64_t PerfMinusTicksDeltaNanos; // Last returned value in nanoseconds, to ensure we don't back-step in time. - UInt64 LastResultNanos; + uint64_t LastResultNanos; }; PerformanceTimer Win32_PerfTimer; @@ -151,23 +154,55 @@ PerformanceTimer Win32_PerfTimer; void PerformanceTimer::Initialize() { - timeBeginPeriod(1); + + MMRESULT mmr = timeBeginPeriod(1); + OVR_ASSERT(TIMERR_NOERROR == mmr); + OVR_UNUSED(mmr); + InitializeCriticalSection(&TimeCS); MMTimeWrapCounter = 0; getFrequency(); + + // Set Vista flag. On Vista, we can just use QPC() without all the extra work + UsingVista = false; + OSVERSIONINFOA vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionExA(&vi)) + { + UsingVista = vi.dwMajorVersion >= 6; + } + + OVR_DEBUG_LOG(("Performance timer Vista flag = %d", (int)UsingVista)); } void PerformanceTimer::Shutdown() { DeleteCriticalSection(&TimeCS); - timeEndPeriod(1); + + MMRESULT mmr = timeEndPeriod(1); + OVR_ASSERT(TIMERR_NOERROR == mmr); + OVR_UNUSED(mmr); } -UInt64 PerformanceTimer::GetTimeNanos() +uint64_t PerformanceTimer::GetTimeNanos() { - UInt64 resultNanos; + uint64_t resultNanos; LARGE_INTEGER li; - DWORD mmTimeMs; + + // If on Vista, + if (UsingVista) + { + // Then we can use QPC() directly without all that extra work + QueryPerformanceCounter(&li); + + uint64_t frequency = getFrequency(); + uint64_t perfCounterSeconds = (uint64_t)li.QuadPart / frequency; + uint64_t perfRemainderNanos = (((uint64_t)li.QuadPart - perfCounterSeconds * frequency) * + Timer::NanosPerSecond) / frequency; + resultNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos; + } + else + { // On Win32 QueryPerformanceFrequency is unreliable due to SMP and // performance levels, so use this logic to detect wrapping and track @@ -175,25 +210,23 @@ UInt64 PerformanceTimer::GetTimeNanos() ::EnterCriticalSection(&TimeCS); // Get raw value and perf counter "At the same time". - mmTimeMs = timeGetTime(); QueryPerformanceCounter(&li); - + DWORD mmTimeMs = timeGetTime(); if (OldMMTimeMs > mmTimeMs) MMTimeWrapCounter++; OldMMTimeMs = mmTimeMs; // Normalize to nanoseconds. - UInt64 mmCounterNanos = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000; - UInt64 frequency = getFrequency(); - UInt64 perfCounterSeconds = UInt64(li.QuadPart) / frequency; - UInt64 perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) * + uint64_t frequency = getFrequency(); + uint64_t perfCounterSeconds = uint64_t(li.QuadPart) / frequency; + uint64_t perfRemainderNanos = ( (uint64_t(li.QuadPart) - perfCounterSeconds * frequency) * Timer::NanosPerSecond ) / frequency; - UInt64 perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos; + uint64_t perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos; + uint64_t mmCounterNanos = ((uint64_t(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000; if (PerfMinusTicksDeltaNanos == 0) PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos; - // Compute result before snapping. // // On first call, this evaluates to: @@ -225,22 +258,23 @@ UInt64 PerformanceTimer::GetTimeNanos() LastResultNanos = resultNanos; ::LeaveCriticalSection(&TimeCS); + } //Tom's addition, to keep precision - static UInt64 initial_time = 0; - if (!initial_time) initial_time = resultNanos; - resultNanos -= initial_time; - + //static uint64_t initial_time = 0; + //if (!initial_time) initial_time = resultNanos; + //resultNanos -= initial_time; + // FIXME: This cannot be used for cross-process timestamps return resultNanos; } // Delegate to PerformanceTimer. -UInt64 Timer::GetTicksNanos() +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); return Win32_PerfTimer.GetTimeNanos(); } @@ -260,20 +294,20 @@ void Timer::shutdownTimerSystem() //------------------------------------------------------------------------ // *** Standard OS Timer -UInt64 Timer::GetTicksNanos() +uint64_t Timer::GetTicksNanos() { if (useFakeSeconds) - return (UInt64) (FakeSeconds * NanosPerSecond); + return (uint64_t) (FakeSeconds * NanosPerSecond); // TODO: prefer rdtsc when available? - UInt64 result; + uint64_t result; // Return microseconds. struct timeval tv; gettimeofday(&tv, 0); - result = (UInt64)tv.tv_sec * 1000000; + result = (uint64_t)tv.tv_sec * 1000000; result += tv.tv_usec; return result * 1000; diff --git a/LibOVR/Src/Kernel/OVR_Timer.h b/LibOVR/Src/Kernel/OVR_Timer.h index 12cba3b..ca585b2 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.h +++ b/LibOVR/Src/Kernel/OVR_Timer.h @@ -56,13 +56,13 @@ public: static double OVR_STDCALL GetSeconds(); // Returns time in Nanoseconds, using highest possible system resolution. - static UInt64 OVR_STDCALL GetTicksNanos(); + static uint64_t OVR_STDCALL GetTicksNanos(); // Kept for compatibility. // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 49.2 days. // Use either time difference of two values of GetTicks to avoid wrap-around. - static UInt32 OVR_STDCALL GetTicksMs() - { return UInt32(GetTicksNanos() / 1000000); } + static uint32_t OVR_STDCALL GetTicksMs() + { return uint32_t(GetTicksNanos() / 1000000); } // for recorded data playback static void SetFakeSeconds(double fakeSeconds) diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h index 8f2b3f3..9126f78 100644 --- a/LibOVR/Src/Kernel/OVR_Types.h +++ b/LibOVR/Src/Kernel/OVR_Types.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_Types.h Content : Standard library defines and simple types Created : September 19, 2012 @@ -28,6 +28,16 @@ limitations under the License. #ifndef OVR_Types_H #define OVR_Types_H +#include "OVR_Compiler.h" + +// Unsupported compiler configurations +#if _MSC_VER == 0x1600 +# if _MSC_FULL_VER < 160040219 +# error "Oculus does not support VS2010 without SP1 installed: It will crash in Release mode" +# endif +#endif + + //----------------------------------------------------------------------------------- // ****** Operating System // @@ -115,47 +125,6 @@ limitations under the License. //----------------------------------------------------------------------------------- -// ***** Compiler -// -// The following compilers are defined: (OVR_CC_x) -// -// MSVC - Microsoft Visual C/C++ -// INTEL - Intel C++ for Linux / Windows -// GNU - GNU C++ -// ARM - ARM C/C++ - -#if defined(__INTEL_COMPILER) -// Intel 4.0 = 400 -// Intel 5.0 = 500 -// Intel 6.0 = 600 -// Intel 8.0 = 800 -// Intel 9.0 = 900 -# define OVR_CC_INTEL __INTEL_COMPILER - -#elif defined(_MSC_VER) -// MSVC 5.0 = 1100 -// MSVC 6.0 = 1200 -// MSVC 7.0 (VC2002) = 1300 -// MSVC 7.1 (VC2003) = 1310 -// MSVC 8.0 (VC2005) = 1400 -// MSVC 9.0 (VC2008) = 1500 -// MSVC 10.0 (VC2010) = 1600 -// MSVC 11.0 (VC2012) = 1700 -// MSVC 12.0 (VC2013) = 1800 -# define OVR_CC_MSVC _MSC_VER - -#elif defined(__GNUC__) -# define OVR_CC_GNU - -#elif defined(__CC_ARM) -# define OVR_CC_ARM - -#else -# error "Oculus does not support this Compiler" -#endif - - -//----------------------------------------------------------------------------------- // ***** Compiler Warnings // Disable MSVC warnings @@ -208,6 +177,23 @@ limitations under the License. //----------------------------------------------------------------------------------- +// ***** int8_t, int16_t, etc. + +#if defined(OVR_CC_MSVC) && (OVR_CC_VER <= 1500) // VS2008 and earlier + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; +#else + #include <stdint.h> +#endif + + +//----------------------------------------------------------------------------------- // ***** Type definitions for Common Systems namespace OVR { @@ -219,7 +205,7 @@ typedef size_t UPInt; typedef ptrdiff_t SPInt; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) typedef char SByte; // 8 bit Integer (Byte) typedef unsigned char UByte; @@ -256,32 +242,50 @@ typedef uint64_t UInt64; #endif +struct OVR_GUID +{ + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +}; -// ***** BaseTypes Namespace -// BaseTypes namespace is explicitly declared to allow base types to be used -// by customers directly without other contents of OVR namespace. -// -// Its is expected that OVR samples will declare 'using namespace OVR::BaseTypes' -// to allow using these directly without polluting the target scope with other -// OVR declarations, such as Ptr<>, String or Mutex. -namespace BaseTypes -{ - using OVR::UPInt; - using OVR::SPInt; - using OVR::UByte; - using OVR::SByte; - using OVR::UInt16; - using OVR::SInt16; - using OVR::UInt32; - using OVR::SInt32; - using OVR::UInt64; - using OVR::SInt64; -} // OVR::BaseTypes } // OVR + +//----------------------------------------------------------------------------------- +// ****** Standard C/C++ Library +// +// Identifies which standard library is currently being used. +// +// LIBSTDCPP - GNU libstdc++, used by GCC. +// LIBCPP - LLVM libc++, typically used by clang and GCC. +// DINKUMWARE - Used by Microsoft and various non-Microsoft compilers (e.g. Sony clang). + +#if !defined(OVR_STDLIB_LIBSTDCPP) + #if defined(__GLIBCXX__) + #define OVR_STDLIB_LIBSTDCPP 1 + #endif +#endif + +#if !defined(OVR_STDLIB_LIBCPP) + #if defined(__clang__) + #if defined(__cplusplus) && __has_include(<__config>) + #define OVR_STDLIB_LIBCPP 1 + #endif + #endif +#endif + +#if !defined(OVR_STDLIB_DINKUMWARE) + #if defined(_YVALS) // Dinkumware globally #defines _YVALS from the #includes above. + #define OVR_STDLIB_DINKUMWARE 1 + #endif +#endif + + //----------------------------------------------------------------------------------- // ***** Macro Definitions // @@ -302,17 +306,7 @@ namespace BaseTypes #define OVR_BIG_ENDIAN 2 -// Force inline substitute - goes before function declaration -#if defined(OVR_CC_MSVC) -# define OVR_FORCE_INLINE __forceinline -#elif defined(OVR_CC_GNU) -# define OVR_FORCE_INLINE __attribute__((always_inline)) inline -#else -# define OVR_FORCE_INLINE inline -#endif // OVR_CC_MSVC - - -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) // ***** Win32 @@ -369,6 +363,137 @@ namespace BaseTypes #endif // defined(OVR_OS_WIN32) +//----------------------------------------------------------------------------------- +// ***** OVR_PTR_SIZE +// +// Specifies the byte size of pointers (same as sizeof void*). + +#if !defined(OVR_PTR_SIZE) + #if defined(__WORDSIZE) + #define OVR_PTR_SIZE ((__WORDSIZE) / 8) + #elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__64BIT__) || defined(__Ptr_Is_64) + #define OVR_PTR_SIZE 8 + #elif defined(__CC_ARM) && (__sizeof_ptr == 8) + #define OVR_PTR_SIZE 8 + #else + #define OVR_PTR_SIZE 4 + #endif +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_WORD_SIZE +// +// Specifies the byte size of a machine word/register. Not necessarily the same as +// the size of pointers, but usually >= the size of pointers. + +#if !defined(OVR_WORD_SIZE) + #define OVR_WORD_SIZE OVR_PTR_SIZE // For our currently supported platforms these are equal. +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_FORCE_INLINE +// +// Force inline substitute - goes before function declaration +// Example usage: +// OVR_FORCE_INLINE void Test(); + +#if !defined(OVR_FORCE_INLINE) + #if defined(OVR_CC_MSVC) + #define OVR_FORCE_INLINE __forceinline + #elif defined(OVR_CC_GNU) + #define OVR_FORCE_INLINE __attribute__((always_inline)) inline + #else + #define OVR_FORCE_INLINE inline + #endif // OVR_CC_MSVC +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_NO_INLINE +// +// Cannot be used with inline or OVR_FORCE_INLINE. +// Example usage: +// OVR_NO_INLINE void Test(); + +#if !defined(OVR_NO_INLINE) + #if defined(OVR_CC_MSVC) && (_MSC_VER >= 1500) // VS2008+ + #define OVR_NO_INLINE __declspec(noinline) + #elif !defined(OVR_CC_MSVC) + #define OVR_NO_INLINE __attribute__((noinline)) + #endif +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_STRINGIZE +// +// Converts a preprocessor symbol to a string. +// +// Example usage: +// printf("Line: %s", OVR_STRINGIZE(__LINE__)); +// +#if !defined(OVR_STRINGIFY) + #define OVR_STRINGIZEIMPL(x) #x + #define OVR_STRINGIZE(x) OVR_STRINGIZEIMPL(x) +#endif + + +// ----------------------------------------------------------------------------------- +// ***** OVR_JOIN +// +// Joins two preprocessing symbols together. Supports the case when either or the +// the symbols are macros themselves. +// +// Example usage: +// char OVR_JOIN(unique_, __LINE__); // Results in (e.g.) char unique_123; +// +#if !defined(OVR_JOIN) + #define OVR_JOIN(a, b) OVR_JOIN1(a, b) + #define OVR_JOIN1(a, b) OVR_JOIN2(a, b) + #define OVR_JOIN2(a, b) a##b +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_OFFSETOF +// +// Portable implementation of offsetof for structs and classes. offsetof and GCC's +// __builtin_offsetof work only with POD types (standard-layout types under C++11), +// despite that it can safely work with a number of types that aren't POD. This +// version works with more types without generating compiler warnings or errors. +// Returns the offset as a size_t, as per offsetof. +// +// Example usage: +// struct Test{ int i; float f; }; +// size_t fPos = OVR_OFFSETOF(Test, f); + +#if defined(OVR_CC_GNU) + #define OVR_OFFSETOF(class_, member_) ((size_t)(((uintptr_t)&reinterpret_cast<const volatile char&>((((class_*)65536)->member_))) - 65536)) +#else + #define OVR_OFFSETOF(class_, member_) offsetof(class_, member_) +#endif + + +//----------------------------------------------------------------------------------- +// ***** OVR_SIZEOF_MEMBER +// +// Implements a portable way to determine the size of struct or class data member. +// C++11 allows this directly via sizeof (see OVR_CPP_NO_EXTENDED_SIZEOF), and this +// macro exists to handle pre-C++11 compilers. +// Returns the offset as a size_t, as per sizeof. +// +// Example usage: +// struct Test{ int i; float f; }; +// size_t fSize = OVR_SIZEOF_MEMBER(Test, f); +// +#if defined(OVR_CPP_NO_EXTENDED_SIZEOF) + #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(((class_*)0)->member_)) +#else + #define OVR_SIZEOF_MEMBER(class_, member_) (sizeof(class_::member_)) +#endif + //----------------------------------------------------------------------------------- // ***** OVR_DEBUG_BREAK, OVR_ASSERT @@ -376,14 +501,14 @@ namespace BaseTypes // If not in debug build, macros do nothing #ifndef OVR_BUILD_DEBUG -# define OVR_DEBUG_CODE(c) c +# define OVR_DEBUG_CODE(c) # define OVR_DEBUG_BREAK ((void)0) # define OVR_ASSERT(p) ((void)0) #else // Microsoft Win32 specific debugging support -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) # ifdef OVR_CPU_X86 # if defined(__cplusplus_cli) # define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) @@ -402,7 +527,7 @@ namespace BaseTypes # define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0) #endif -#define OVR_DEBUG_CODE(c) +#define OVR_DEBUG_CODE(c) c // This will cause compiler breakpoint #define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; } } while(0) @@ -410,15 +535,137 @@ namespace BaseTypes #endif // OVR_BUILD_DEBUG -// Compile-time assert; produces compiler error if condition is false -#define OVR_COMPILER_ASSERT(x) { int zero = 0; switch(zero) {case 0: case x:;} } +// ------------------------------------------------------------------------ +// ***** OVR_COMPILER_ASSERT +// +// Compile-time assert; produces compiler error if condition is false. +// The expression must be a compile-time constant expression. +// +// Example usage: +// OVR_COMPILER_ASSERT(sizeof(int32_t == 4)); + +#if OVR_CPP_NO_STATIC_ASSERT + #define OVR_COMPILER_ASSERT(x) { int zero = 0; switch(zero) {case 0: case x:;} } +#else + #define OVR_COMPILER_ASSERT(x) static_assert((x), #x) +#endif + + +// ------------------------------------------------------------------------ +// ***** static_assert +// +// Portable support for C++11 static_assert. +// Acts as if the following were declared: +// void static_assert(bool const_expression, const char* msg); +// +// Example usage: +// static_assert(sizeof(int32_t) == 4, "int32_t expected to be 4 bytes."); + +#if defined(OVR_CPP_NO_STATIC_ASSERT) + #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #define OVR_SA_UNUSED __attribute__((unused)) + #else + #define OVR_SA_UNUSED + #endif + #define OVR_SA_PASTE(a,b) a##b + #define OVR_SA_HELP(a,b) OVR_SA_PASTE(a,b) + + #if defined(__COUNTER__) + #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __COUNTER__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #else + #define static_assert(expression, msg) typedef char OVR_SA_HELP(compileTimeAssert, __LINE__) [((expression) != 0) ? 1 : -1] OVR_SA_UNUSED + #endif +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_ARRAY_COUNT +// +// Returns the element count of a C array. +// +// Example usage: +// float itemArray[16]; +// for(size_t i = 0; i < OVR_ARRAY_COUNT(itemArray); i++) { ... } + +#if defined(OVR_CPP_NO_CONSTEXPR) + #ifndef OVR_ARRAY_COUNT + #define OVR_ARRAY_COUNT(x) (sizeof(x) / sizeof(x[0])) + #endif +#else + // Smarter C++11 version which knows the difference between arrays and pointers. + template <typename T, size_t N> + char (&OVRArrayCountHelper(T (&x)[N]))[N]; + #define OVR_ARRAY_COUNT(x) (sizeof(OVRArrayCountHelper(x))) +#endif + + +// ------------------------------------------------------------------------ +// ***** OVR_CURRENT_FUNCTION +// +// Portable wrapper for __PRETTY_FUNCTION__, C99 __func__, __FUNCTION__. +// This represents the most expressive version available. +// Acts as if the following were declared: +// static const char OVR_CURRENT_FUNCTION[] = "function-name"; +// +// Example usage: +// void Test() { printf("%s", OVR_CURRENT_FUNCTION); } + +#if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) || (defined(__ICC) && (__ICC >= 600)) // GCC, clang, Intel + #define OVR_CURRENT_FUNCTION __PRETTY_FUNCTION__ +#elif defined(__FUNCSIG__) // VC++ + #define OVR_CURRENT_FUNCTION __FUNCSIG__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) // C99 compilers + #define OVR_CURRENT_FUNCTION __func__ +#else + #define OVR_CURRENT_FUNCTION __FUNCTION__ +#endif + +//----------------------------------------------------------------------------------- +// ***** OVR_DEPRECATED / OVR_DEPRECATED_MSG +// +// Portably annotates a function or struct as deprecated. +// Note that clang supports __deprecated_enum_msg, which may be useful to support. +// +// Example usage: +// OVR_DEPRECATED void Test(); // Use on the function declaration, as opposed to definition. +// +// struct OVR_DEPRECATED Test{ ... }; +// +// OVR_DEPRECATED_MSG("Test is deprecated") +// void Test(); + +#if !defined(OVR_DEPRECATED) + #if defined(OVR_CC_MSVC) && (OVR_CC_VERSION > 1400) // VS2005+ + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __declspec(deprecated(msg)) + #elif defined(OVR_CC_CLANG) && OVR_CC_HAS_FEATURE(attribute_deprecated_with_message) + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) + #elif defined(OVR_CC_GNU) && (OVR_CC_VERSION >= 405) + #define OVR_DEPRECATED __declspec(deprecated) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) + #elif !defined(OVR_CC_MSVC) + #define OVR_DEPRECATED __attribute__((deprecated)) + #define OVR_DEPRECATED_MSG(msg) __attribute__((deprecated)) + #else + #define OVR_DEPRECATED + #define OVR_DEPRECATED_MSG(msg) + #endif +#endif //----------------------------------------------------------------------------------- // ***** OVR_UNUSED - Unused Argument handling - // Macro to quiet compiler warnings about unused parameters/variables. +// +// Example usage: +// void Test() { +// int x = SomeFunction(); +// OVR_UNUSED(x); +// } +// + #if defined(OVR_CC_GNU) # define OVR_UNUSED(a) do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0) #else @@ -438,8 +685,10 @@ namespace BaseTypes //----------------------------------------------------------------------------------- // ***** Configuration Macros +// +// Expands to the current build type as a const char string literal. +// Acts as the following declaration: const char OVR_BUILD_STRING[]; -// SF Build type #ifdef OVR_BUILD_DEBUG # define OVR_BUILD_STRING "Debug" #else @@ -471,4 +720,5 @@ namespace BaseTypes // + #endif // OVR_Types_h diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp index f8aa697..0e8f0e6 100644 --- a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp @@ -30,10 +30,10 @@ limitations under the License. namespace OVR { namespace UTF8Util { -SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) +intptr_t OVR_STDCALL GetLength(const char* buf, intptr_t buflen) { const char* p = buf; - SPInt length = 0; + intptr_t length = 0; if (buflen != -1) { @@ -53,10 +53,10 @@ SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) return length; } -UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length) { const char* buf = putf8str; - UInt32 c = 0; + uint32_t c = 0; if (length != -1) { @@ -87,7 +87,7 @@ UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) return c; } -SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char *putf8str, intptr_t length) { const char* buf = putf8str; @@ -104,7 +104,7 @@ SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) while (index > 0) { - UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf); + uint32_t c = UTF8Util::DecodeNextChar_Advance0(&buf); index--; if (c == 0) @@ -114,7 +114,7 @@ SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) return buf-putf8str; } -int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) +int OVR_STDCALL GetEncodeCharSize(uint32_t ucs_character) { if (ucs_character <= 0x7F) return 1; @@ -132,9 +132,9 @@ int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) return 0; } -UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) { - UInt32 uc; + uint32_t uc; char c; // Security considerations: @@ -171,7 +171,7 @@ UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) if (c == 0) return 0; // End of buffer. - if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII. + if ((c & 0x80) == 0) return (uint32_t) c; // Conventional 7-bit ASCII. // Multi-byte sequences. if ((c & 0xE0) == 0xC0) @@ -236,7 +236,7 @@ UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) } -void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) +void OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* pindex, uint32_t ucs_character) { if (ucs_character <= 0x7F) { @@ -289,9 +289,9 @@ void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) } } -SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length) { - SPInt len = 0; + intptr_t len = 0; if (length != -1) for (int i = 0; i < length; i++) { @@ -307,9 +307,9 @@ SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) return len; } -void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length) { - SPInt ofs = 0; + intptr_t ofs = 0; if (length != -1) { for (int i = 0; i < length; i++) @@ -329,14 +329,14 @@ void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) pbuff[ofs] = 0; } -UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen) +size_t OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen) { wchar_t *pbegin = pbuff; if (bytesLen == -1) { while (1) { - UInt32 ch = DecodeNextChar_Advance0(&putf8str); + uint32_t ch = DecodeNextChar_Advance0(&putf8str); if (ch == 0) break; else if (ch >= 0xFFFF) @@ -349,7 +349,7 @@ UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytes const char* p = putf8str; while ((p - putf8str) < bytesLen) { - UInt32 ch = DecodeNextChar_Advance0(&p); + uint32_t ch = DecodeNextChar_Advance0(&p); if (ch >= 0xFFFF) ch = 0xFFFD; *pbuff++ = wchar_t(ch); @@ -384,12 +384,12 @@ UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytes #include <stdio.h> -bool check_equal(const char* utf8_in, const UInt32* ucs_in) +bool check_equal(const char* utf8_in, const uint32_t* ucs_in) { for (;;) { - UInt32 next_ucs = *ucs_in++; - UInt32 next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); + uint32_t next_ucs = *ucs_in++; + uint32_t next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); if (next_ucs != next_ucs_from_utf8) { return false; @@ -429,11 +429,11 @@ void log_ascii(const char* line) } -void log_ucs(const UInt32* line) +void log_ucs(const uint32_t* line) { for (;;) { - UInt32 uc = *line++; + uint32_t uc = *line++; if (uc == 0) { // End of line. @@ -458,7 +458,7 @@ int main(int argc, const char* argv[]) { { const char* test8 = "Ignacio CastaƱo"; - const UInt32 test32[] = + const uint32_t test32[] = { 0x49, 0x67, 0x6E, 0x61, 0x63, 0x69, 0x6F, 0x20, 0x43, 0x61, @@ -484,7 +484,7 @@ int main(int argc, const char* argv[]) const int LINE_SIZE = 200; // max line size char line_buffer_utf8[LINE_SIZE]; char reencoded_utf8[6 * LINE_SIZE]; - UInt32 line_buffer_ucs[LINE_SIZE]; + uint32_t line_buffer_ucs[LINE_SIZE]; int byte_counter = 0; for (;;) @@ -503,10 +503,10 @@ int main(int argc, const char* argv[]) // Decode into UCS. const char* p = line_buffer_utf8; - UInt32* q = line_buffer_ucs; + uint32_t* q = line_buffer_ucs; for (;;) { - UInt32 uc = UTF8Util::DecodeNextChar(&p); + uint32_t uc = UTF8Util::DecodeNextChar(&p); *q++ = uc; OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE); @@ -520,7 +520,7 @@ int main(int argc, const char* argv[]) int index = 0; for (;;) { - UInt32 uc = *q++; + uint32_t uc = *q++; OVR_ASSERT(index < LINE_SIZE * 6 - 6); int last_index = index; UTF8Util::EncodeChar(reencoded_utf8, &index, uc); diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.h b/LibOVR/Src/Kernel/OVR_UTF8Util.h index 6a596012..f80edfe 100644 --- a/LibOVR/Src/Kernel/OVR_UTF8Util.h +++ b/LibOVR/Src/Kernel/OVR_UTF8Util.h @@ -1,6 +1,6 @@ /************************************************************************************ -PublicHeader: OVR.h +PublicHeader: OVR_Kernel.h Filename : OVR_UTF8Util.h Content : UTF8 Unicode character encoding/decoding support Created : September 19, 2012 @@ -38,56 +38,56 @@ namespace OVR { namespace UTF8Util { // Determines the length of UTF8 string in characters. // If source length is specified (in bytes), null 0 character is counted properly. -SPInt OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1); +intptr_t OVR_STDCALL GetLength(const char* putf8str, intptr_t length = -1); // Gets a decoded UTF8 character at index; you can access up to the index returned // by GetLength. 0 will be returned for out of bounds access. -UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1); +uint32_t OVR_STDCALL GetCharAt(intptr_t index, const char* putf8str, intptr_t length = -1); // Converts UTF8 character index into byte offset. // -1 is returned if index was out of bounds. -SPInt OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1); +intptr_t OVR_STDCALL GetByteIndex(intptr_t index, const char* putf8str, intptr_t length = -1); // *** 16-bit Unicode string Encoding/Decoding routines. // Determines the number of bytes necessary to encode a string. // Does not count the terminating 0 (null) character. -SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1); +intptr_t OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, intptr_t length = -1); // Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at // least GetEncodeStringSize() + 1. -void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1); +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, intptr_t length = -1); // Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available. // Characters over 0xFFFF are replaced with 0xFFFD. // Returns the length of resulting string (number of characters) -UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1); +size_t OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, intptr_t bytesLen = -1); // *** Individual character Encoding/Decoding. // Determined the number of bytes necessary to encode a UCS character. -int OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter); +int OVR_STDCALL GetEncodeCharSize(uint32_t ucsCharacter); // Encodes the given UCS character into the given UTF-8 buffer. // Writes the data starting at buffer[offset], and // increments offset by the number of bytes written. // May write up to 6 bytes, so make sure there's room in the buffer -void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter); +void OVR_STDCALL EncodeChar(char* pbuffer, intptr_t* poffset, uint32_t ucsCharacter); // Return the next Unicode character in the UTF-8 encoded buffer. // Invalid UTF-8 sequences produce a U+FFFD character as output. // Advances *utf8_buffer past the character returned. Pointer advance // occurs even if the terminating 0 character is hit, since that allows // strings with middle '\0' characters to be supported. -UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); +uint32_t OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); // Safer version of DecodeNextChar, which doesn't advance pointer if // null character is hit. -inline UInt32 DecodeNextChar(const char** putf8Buffer) +inline uint32_t DecodeNextChar(const char** putf8Buffer) { - UInt32 ch = DecodeNextChar_Advance0(putf8Buffer); + uint32_t ch = DecodeNextChar_Advance0(putf8Buffer); if (ch == 0) (*putf8Buffer)--; return ch; |