oculus1
changeset 3:b069a5c27388
added a couple more stuff, fixed all the LibOVR line endings
line diff
1.1 --- a/libovr/Src/Kernel/OVR_Alg.cpp Sat Sep 14 17:51:03 2013 +0300 1.2 +++ b/libovr/Src/Kernel/OVR_Alg.cpp Sun Sep 15 04:10:05 2013 +0300 1.3 @@ -1,1 +1,46 @@ 1.4 -/************************************************************************************ 1.5 1.6 Filename : OVR_Alg.cpp 1.7 Content : Static lookup tables for Alg functions 1.8 Created : September 19, 2012 1.9 Notes : 1.10 1.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.12 1.13 Use of this software is subject to the terms of the Oculus license 1.14 agreement provided at the time of installation or download, or which 1.15 otherwise accompanies this software in either electronic or hard copy form. 1.16 1.17 ************************************************************************************/ 1.18 1.19 #include "OVR_Types.h" 1.20 1.21 namespace OVR { namespace Alg { 1.22 1.23 //------------------------------------------------------------------------ 1.24 extern const UByte UpperBitTable[256] = 1.25 { 1.26 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, 1.27 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, 1.28 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 1.29 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 1.30 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, 1.31 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, 1.32 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, 1.33 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 1.34 }; 1.35 1.36 extern const UByte LowerBitTable[256] = 1.37 { 1.38 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, 1.39 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, 1.40 6,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, 1.41 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, 1.42 7,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, 1.43 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, 1.44 6,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, 1.45 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 1.46 }; 1.47 1.48 1.49 }} // OVE::Alg 1.50 \ No newline at end of file 1.51 +/************************************************************************************ 1.52 + 1.53 +Filename : OVR_Alg.cpp 1.54 +Content : Static lookup tables for Alg functions 1.55 +Created : September 19, 2012 1.56 +Notes : 1.57 + 1.58 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.59 + 1.60 +Use of this software is subject to the terms of the Oculus license 1.61 +agreement provided at the time of installation or download, or which 1.62 +otherwise accompanies this software in either electronic or hard copy form. 1.63 + 1.64 +************************************************************************************/ 1.65 + 1.66 +#include "OVR_Types.h" 1.67 + 1.68 +namespace OVR { namespace Alg { 1.69 + 1.70 +//------------------------------------------------------------------------ 1.71 +extern const UByte UpperBitTable[256] = 1.72 +{ 1.73 + 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, 1.74 + 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, 1.75 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 1.76 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 1.77 + 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, 1.78 + 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, 1.79 + 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, 1.80 + 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 1.81 +}; 1.82 + 1.83 +extern const UByte LowerBitTable[256] = 1.84 +{ 1.85 + 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, 1.86 + 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, 1.87 + 6,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, 1.88 + 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, 1.89 + 7,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, 1.90 + 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, 1.91 + 6,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, 1.92 + 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 1.93 +}; 1.94 + 1.95 + 1.96 +}} // OVE::Alg
2.1 --- a/libovr/Src/Kernel/OVR_Alg.h Sat Sep 14 17:51:03 2013 +0300 2.2 +++ b/libovr/Src/Kernel/OVR_Alg.h Sun Sep 15 04:10:05 2013 +0300 2.3 @@ -1,1 +1,953 @@ 2.4 -/************************************************************************************ 2.5 2.6 PublicHeader: OVR.h 2.7 Filename : OVR_Alg.h 2.8 Content : Simple general purpose algorithms: Sort, Binary Search, etc. 2.9 Created : September 19, 2012 2.10 Notes : 2.11 2.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 2.13 2.14 Use of this software is subject to the terms of the Oculus license 2.15 agreement provided at the time of installation or download, or which 2.16 otherwise accompanies this software in either electronic or hard copy form. 2.17 2.18 ************************************************************************************/ 2.19 2.20 #ifndef OVR_Alg_h 2.21 #define OVR_Alg_h 2.22 2.23 #include "OVR_Types.h" 2.24 #include <string.h> 2.25 2.26 namespace OVR { namespace Alg { 2.27 2.28 2.29 //----------------------------------------------------------------------------------- 2.30 // ***** Operator extensions 2.31 2.32 template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) 2.33 { T temp(a); a = b; b = temp; } 2.34 2.35 2.36 // ***** min/max are not implemented in Visual Studio 6 standard STL 2.37 2.38 template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b) 2.39 { return (a < b) ? a : b; } 2.40 2.41 template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b) 2.42 { return (b < a) ? a : b; } 2.43 2.44 template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal) 2.45 { return Max<T>(minVal, Min<T>(v, maxVal)); } 2.46 2.47 template <typename T> OVR_FORCE_INLINE int Chop(T f) 2.48 { return (int)f; } 2.49 2.50 template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f) 2.51 { return (b - a) * f + a; } 2.52 2.53 2.54 // These functions stand to fix a stupid VC++ warning (with /Wp64 on): 2.55 // "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data" 2.56 // Use these functions instead of gmin/gmax if the argument has size 2.57 // of the pointer to avoid the warning. Though, functionally they are 2.58 // absolutelly the same as regular gmin/gmax. 2.59 template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b) 2.60 { 2.61 OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); 2.62 return (a < b) ? a : b; 2.63 } 2.64 template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b) 2.65 { 2.66 OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); 2.67 return (b < a) ? a : b; 2.68 } 2.69 2.70 2.71 template <typename T> OVR_FORCE_INLINE const T Abs(const T v) 2.72 { return (v>=0) ? v : -v; } 2.73 2.74 2.75 //----------------------------------------------------------------------------------- 2.76 // ***** OperatorLess 2.77 // 2.78 template<class T> struct OperatorLess 2.79 { 2.80 static bool Compare(const T& a, const T& b) 2.81 { 2.82 return a < b; 2.83 } 2.84 }; 2.85 2.86 2.87 //----------------------------------------------------------------------------------- 2.88 // ***** QuickSortSliced 2.89 // 2.90 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.91 // The range is specified with start, end, where "end" is exclusive! 2.92 // The comparison predicate must be specified. 2.93 template<class Array, class Less> 2.94 void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) 2.95 { 2.96 enum 2.97 { 2.98 Threshold = 9 2.99 }; 2.100 2.101 if(end - start < 2) return; 2.102 2.103 SPInt stack[80]; 2.104 SPInt* top = stack; 2.105 SPInt base = (SPInt)start; 2.106 SPInt limit = (SPInt)end; 2.107 2.108 for(;;) 2.109 { 2.110 SPInt len = limit - base; 2.111 SPInt i, j, pivot; 2.112 2.113 if(len > Threshold) 2.114 { 2.115 // we use base + len/2 as the pivot 2.116 pivot = base + len / 2; 2.117 Swap(arr[base], arr[pivot]); 2.118 2.119 i = base + 1; 2.120 j = limit - 1; 2.121 2.122 // now ensure that *i <= *base <= *j 2.123 if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); 2.124 if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); 2.125 if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); 2.126 2.127 for(;;) 2.128 { 2.129 do i++; while( less(arr[i], arr[base]) ); 2.130 do j--; while( less(arr[base], arr[j]) ); 2.131 2.132 if( i > j ) 2.133 { 2.134 break; 2.135 } 2.136 2.137 Swap(arr[i], arr[j]); 2.138 } 2.139 2.140 Swap(arr[base], arr[j]); 2.141 2.142 // now, push the largest sub-array 2.143 if(j - base > limit - i) 2.144 { 2.145 top[0] = base; 2.146 top[1] = j; 2.147 base = i; 2.148 } 2.149 else 2.150 { 2.151 top[0] = i; 2.152 top[1] = limit; 2.153 limit = j; 2.154 } 2.155 top += 2; 2.156 } 2.157 else 2.158 { 2.159 // the sub-array is small, perform insertion sort 2.160 j = base; 2.161 i = j + 1; 2.162 2.163 for(; i < limit; j = i, i++) 2.164 { 2.165 for(; less(arr[j + 1], arr[j]); j--) 2.166 { 2.167 Swap(arr[j + 1], arr[j]); 2.168 if(j == base) 2.169 { 2.170 break; 2.171 } 2.172 } 2.173 } 2.174 if(top > stack) 2.175 { 2.176 top -= 2; 2.177 base = top[0]; 2.178 limit = top[1]; 2.179 } 2.180 else 2.181 { 2.182 break; 2.183 } 2.184 } 2.185 } 2.186 } 2.187 2.188 2.189 //----------------------------------------------------------------------------------- 2.190 // ***** QuickSortSliced 2.191 // 2.192 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.193 // The range is specified with start, end, where "end" is exclusive! 2.194 // The data type must have a defined "<" operator. 2.195 template<class Array> 2.196 void QuickSortSliced(Array& arr, UPInt start, UPInt end) 2.197 { 2.198 typedef typename Array::ValueType ValueType; 2.199 QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); 2.200 } 2.201 2.202 // Same as corresponding G_QuickSortSliced but with checking array limits to avoid 2.203 // crash in the case of wrong comparator functor. 2.204 template<class Array, class Less> 2.205 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) 2.206 { 2.207 enum 2.208 { 2.209 Threshold = 9 2.210 }; 2.211 2.212 if(end - start < 2) return true; 2.213 2.214 SPInt stack[80]; 2.215 SPInt* top = stack; 2.216 SPInt base = (SPInt)start; 2.217 SPInt limit = (SPInt)end; 2.218 2.219 for(;;) 2.220 { 2.221 SPInt len = limit - base; 2.222 SPInt i, j, pivot; 2.223 2.224 if(len > Threshold) 2.225 { 2.226 // we use base + len/2 as the pivot 2.227 pivot = base + len / 2; 2.228 Swap(arr[base], arr[pivot]); 2.229 2.230 i = base + 1; 2.231 j = limit - 1; 2.232 2.233 // now ensure that *i <= *base <= *j 2.234 if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); 2.235 if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); 2.236 if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); 2.237 2.238 for(;;) 2.239 { 2.240 do 2.241 { 2.242 i++; 2.243 if (i >= limit) 2.244 return false; 2.245 } while( less(arr[i], arr[base]) ); 2.246 do 2.247 { 2.248 j--; 2.249 if (j < 0) 2.250 return false; 2.251 } while( less(arr[base], arr[j]) ); 2.252 2.253 if( i > j ) 2.254 { 2.255 break; 2.256 } 2.257 2.258 Swap(arr[i], arr[j]); 2.259 } 2.260 2.261 Swap(arr[base], arr[j]); 2.262 2.263 // now, push the largest sub-array 2.264 if(j - base > limit - i) 2.265 { 2.266 top[0] = base; 2.267 top[1] = j; 2.268 base = i; 2.269 } 2.270 else 2.271 { 2.272 top[0] = i; 2.273 top[1] = limit; 2.274 limit = j; 2.275 } 2.276 top += 2; 2.277 } 2.278 else 2.279 { 2.280 // the sub-array is small, perform insertion sort 2.281 j = base; 2.282 i = j + 1; 2.283 2.284 for(; i < limit; j = i, i++) 2.285 { 2.286 for(; less(arr[j + 1], arr[j]); j--) 2.287 { 2.288 Swap(arr[j + 1], arr[j]); 2.289 if(j == base) 2.290 { 2.291 break; 2.292 } 2.293 } 2.294 } 2.295 if(top > stack) 2.296 { 2.297 top -= 2; 2.298 base = top[0]; 2.299 limit = top[1]; 2.300 } 2.301 else 2.302 { 2.303 break; 2.304 } 2.305 } 2.306 } 2.307 return true; 2.308 } 2.309 2.310 template<class Array> 2.311 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end) 2.312 { 2.313 typedef typename Array::ValueType ValueType; 2.314 return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare); 2.315 } 2.316 2.317 //----------------------------------------------------------------------------------- 2.318 // ***** QuickSort 2.319 // 2.320 // Sort an array Array, ArrayPaged, ArrayUnsafe. 2.321 // The array must have GetSize() function. 2.322 // The comparison predicate must be specified. 2.323 template<class Array, class Less> 2.324 void QuickSort(Array& arr, Less less) 2.325 { 2.326 QuickSortSliced(arr, 0, arr.GetSize(), less); 2.327 } 2.328 2.329 // checks for boundaries 2.330 template<class Array, class Less> 2.331 bool QuickSortSafe(Array& arr, Less less) 2.332 { 2.333 return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less); 2.334 } 2.335 2.336 2.337 //----------------------------------------------------------------------------------- 2.338 // ***** QuickSort 2.339 // 2.340 // Sort an array Array, ArrayPaged, ArrayUnsafe. 2.341 // The array must have GetSize() function. 2.342 // The data type must have a defined "<" operator. 2.343 template<class Array> 2.344 void QuickSort(Array& arr) 2.345 { 2.346 typedef typename Array::ValueType ValueType; 2.347 QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.348 } 2.349 2.350 template<class Array> 2.351 bool QuickSortSafe(Array& arr) 2.352 { 2.353 typedef typename Array::ValueType ValueType; 2.354 return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.355 } 2.356 2.357 //----------------------------------------------------------------------------------- 2.358 // ***** InsertionSortSliced 2.359 // 2.360 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.361 // The range is specified with start, end, where "end" is exclusive! 2.362 // The comparison predicate must be specified. 2.363 // Unlike Quick Sort, the Insertion Sort works much slower in average, 2.364 // but may be much faster on almost sorted arrays. Besides, it guarantees 2.365 // that the elements will not be swapped if not necessary. For example, 2.366 // an array with all equal elements will remain "untouched", while 2.367 // Quick Sort will considerably shuffle the elements in this case. 2.368 template<class Array, class Less> 2.369 void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) 2.370 { 2.371 UPInt j = start; 2.372 UPInt i = j + 1; 2.373 UPInt limit = end; 2.374 2.375 for(; i < limit; j = i, i++) 2.376 { 2.377 for(; less(arr[j + 1], arr[j]); j--) 2.378 { 2.379 Swap(arr[j + 1], arr[j]); 2.380 if(j <= start) 2.381 { 2.382 break; 2.383 } 2.384 } 2.385 } 2.386 } 2.387 2.388 2.389 //----------------------------------------------------------------------------------- 2.390 // ***** InsertionSortSliced 2.391 // 2.392 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.393 // The range is specified with start, end, where "end" is exclusive! 2.394 // The data type must have a defined "<" operator. 2.395 template<class Array> 2.396 void InsertionSortSliced(Array& arr, UPInt start, UPInt end) 2.397 { 2.398 typedef typename Array::ValueType ValueType; 2.399 InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); 2.400 } 2.401 2.402 //----------------------------------------------------------------------------------- 2.403 // ***** InsertionSort 2.404 // 2.405 // Sort an array Array, ArrayPaged, ArrayUnsafe. 2.406 // The array must have GetSize() function. 2.407 // The comparison predicate must be specified. 2.408 2.409 template<class Array, class Less> 2.410 void InsertionSort(Array& arr, Less less) 2.411 { 2.412 InsertionSortSliced(arr, 0, arr.GetSize(), less); 2.413 } 2.414 2.415 //----------------------------------------------------------------------------------- 2.416 // ***** InsertionSort 2.417 // 2.418 // Sort an array Array, ArrayPaged, ArrayUnsafe. 2.419 // The array must have GetSize() function. 2.420 // The data type must have a defined "<" operator. 2.421 template<class Array> 2.422 void InsertionSort(Array& arr) 2.423 { 2.424 typedef typename Array::ValueType ValueType; 2.425 InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.426 } 2.427 2.428 2.429 2.430 //----------------------------------------------------------------------------------- 2.431 // ***** LowerBoundSliced 2.432 // 2.433 template<class Array, class Value, class Less> 2.434 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) 2.435 { 2.436 SPInt first = (SPInt)start; 2.437 SPInt len = (SPInt)(end - start); 2.438 SPInt half; 2.439 SPInt middle; 2.440 2.441 while(len > 0) 2.442 { 2.443 half = len >> 1; 2.444 middle = first + half; 2.445 if(less(arr[middle], val)) 2.446 { 2.447 first = middle + 1; 2.448 len = len - half - 1; 2.449 } 2.450 else 2.451 { 2.452 len = half; 2.453 } 2.454 } 2.455 return (UPInt)first; 2.456 } 2.457 2.458 2.459 //----------------------------------------------------------------------------------- 2.460 // ***** LowerBoundSliced 2.461 // 2.462 template<class Array, class Value> 2.463 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) 2.464 { 2.465 return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); 2.466 } 2.467 2.468 //----------------------------------------------------------------------------------- 2.469 // ***** LowerBoundSized 2.470 // 2.471 template<class Array, class Value> 2.472 UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) 2.473 { 2.474 return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); 2.475 } 2.476 2.477 //----------------------------------------------------------------------------------- 2.478 // ***** LowerBound 2.479 // 2.480 template<class Array, class Value, class Less> 2.481 UPInt LowerBound(const Array& arr, const Value& val, Less less) 2.482 { 2.483 return LowerBoundSliced(arr, 0, arr.GetSize(), val, less); 2.484 } 2.485 2.486 2.487 //----------------------------------------------------------------------------------- 2.488 // ***** LowerBound 2.489 // 2.490 template<class Array, class Value> 2.491 UPInt LowerBound(const Array& arr, const Value& val) 2.492 { 2.493 return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); 2.494 } 2.495 2.496 2.497 2.498 //----------------------------------------------------------------------------------- 2.499 // ***** UpperBoundSliced 2.500 // 2.501 template<class Array, class Value, class Less> 2.502 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) 2.503 { 2.504 SPInt first = (SPInt)start; 2.505 SPInt len = (SPInt)(end - start); 2.506 SPInt half; 2.507 SPInt middle; 2.508 2.509 while(len > 0) 2.510 { 2.511 half = len >> 1; 2.512 middle = first + half; 2.513 if(less(val, arr[middle])) 2.514 { 2.515 len = half; 2.516 } 2.517 else 2.518 { 2.519 first = middle + 1; 2.520 len = len - half - 1; 2.521 } 2.522 } 2.523 return (UPInt)first; 2.524 } 2.525 2.526 2.527 //----------------------------------------------------------------------------------- 2.528 // ***** UpperBoundSliced 2.529 // 2.530 template<class Array, class Value> 2.531 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) 2.532 { 2.533 return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); 2.534 } 2.535 2.536 2.537 //----------------------------------------------------------------------------------- 2.538 // ***** UpperBoundSized 2.539 // 2.540 template<class Array, class Value> 2.541 UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) 2.542 { 2.543 return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); 2.544 } 2.545 2.546 2.547 //----------------------------------------------------------------------------------- 2.548 // ***** UpperBound 2.549 // 2.550 template<class Array, class Value, class Less> 2.551 UPInt UpperBound(const Array& arr, const Value& val, Less less) 2.552 { 2.553 return UpperBoundSliced(arr, 0, arr.GetSize(), val, less); 2.554 } 2.555 2.556 2.557 //----------------------------------------------------------------------------------- 2.558 // ***** UpperBound 2.559 // 2.560 template<class Array, class Value> 2.561 UPInt UpperBound(const Array& arr, const Value& val) 2.562 { 2.563 return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); 2.564 } 2.565 2.566 2.567 //----------------------------------------------------------------------------------- 2.568 // ***** ReverseArray 2.569 // 2.570 template<class Array> void ReverseArray(Array& arr) 2.571 { 2.572 SPInt from = 0; 2.573 SPInt to = arr.GetSize() - 1; 2.574 while(from < to) 2.575 { 2.576 Swap(arr[from], arr[to]); 2.577 ++from; 2.578 --to; 2.579 } 2.580 } 2.581 2.582 2.583 // ***** AppendArray 2.584 // 2.585 template<class CDst, class CSrc> 2.586 void AppendArray(CDst& dst, const CSrc& src) 2.587 { 2.588 UPInt i; 2.589 for(i = 0; i < src.GetSize(); i++) 2.590 dst.PushBack(src[i]); 2.591 } 2.592 2.593 //----------------------------------------------------------------------------------- 2.594 // ***** ArrayAdaptor 2.595 // 2.596 // A simple adapter that provides the GetSize() method and overloads 2.597 // operator []. Used to wrap plain arrays in QuickSort and such. 2.598 template<class T> class ArrayAdaptor 2.599 { 2.600 public: 2.601 typedef T ValueType; 2.602 ArrayAdaptor() : Data(0), Size(0) {} 2.603 ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {} 2.604 UPInt GetSize() const { return Size; } 2.605 const T& operator [] (UPInt i) const { return Data[i]; } 2.606 T& operator [] (UPInt i) { return Data[i]; } 2.607 private: 2.608 T* Data; 2.609 UPInt Size; 2.610 }; 2.611 2.612 2.613 //----------------------------------------------------------------------------------- 2.614 // ***** GConstArrayAdaptor 2.615 // 2.616 // A simple const adapter that provides the GetSize() method and overloads 2.617 // operator []. Used to wrap plain arrays in LowerBound and such. 2.618 template<class T> class ConstArrayAdaptor 2.619 { 2.620 public: 2.621 typedef T ValueType; 2.622 ConstArrayAdaptor() : Data(0), Size(0) {} 2.623 ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {} 2.624 UPInt GetSize() const { return Size; } 2.625 const T& operator [] (UPInt i) const { return Data[i]; } 2.626 private: 2.627 const T* Data; 2.628 UPInt Size; 2.629 }; 2.630 2.631 2.632 2.633 //----------------------------------------------------------------------------------- 2.634 extern const UByte UpperBitTable[256]; 2.635 extern const UByte LowerBitTable[256]; 2.636 2.637 2.638 2.639 //----------------------------------------------------------------------------------- 2.640 inline UByte UpperBit(UPInt val) 2.641 { 2.642 #ifndef OVR_64BIT_POINTERS 2.643 2.644 if (val & 0xFFFF0000) 2.645 { 2.646 return (val & 0xFF000000) ? 2.647 UpperBitTable[(val >> 24) ] + 24: 2.648 UpperBitTable[(val >> 16) & 0xFF] + 16; 2.649 } 2.650 return (val & 0xFF00) ? 2.651 UpperBitTable[(val >> 8) & 0xFF] + 8: 2.652 UpperBitTable[(val ) & 0xFF]; 2.653 2.654 #else 2.655 2.656 if (val & 0xFFFFFFFF00000000) 2.657 { 2.658 if (val & 0xFFFF000000000000) 2.659 { 2.660 return (val & 0xFF00000000000000) ? 2.661 UpperBitTable[(val >> 56) ] + 56: 2.662 UpperBitTable[(val >> 48) & 0xFF] + 48; 2.663 } 2.664 return (val & 0xFF0000000000) ? 2.665 UpperBitTable[(val >> 40) & 0xFF] + 40: 2.666 UpperBitTable[(val >> 32) & 0xFF] + 32; 2.667 } 2.668 else 2.669 { 2.670 if (val & 0xFFFF0000) 2.671 { 2.672 return (val & 0xFF000000) ? 2.673 UpperBitTable[(val >> 24) ] + 24: 2.674 UpperBitTable[(val >> 16) & 0xFF] + 16; 2.675 } 2.676 return (val & 0xFF00) ? 2.677 UpperBitTable[(val >> 8) & 0xFF] + 8: 2.678 UpperBitTable[(val ) & 0xFF]; 2.679 } 2.680 2.681 #endif 2.682 } 2.683 2.684 //----------------------------------------------------------------------------------- 2.685 inline UByte LowerBit(UPInt val) 2.686 { 2.687 #ifndef OVR_64BIT_POINTERS 2.688 2.689 if (val & 0xFFFF) 2.690 { 2.691 return (val & 0xFF) ? 2.692 LowerBitTable[ val & 0xFF]: 2.693 LowerBitTable[(val >> 8) & 0xFF] + 8; 2.694 } 2.695 return (val & 0xFF0000) ? 2.696 LowerBitTable[(val >> 16) & 0xFF] + 16: 2.697 LowerBitTable[(val >> 24) & 0xFF] + 24; 2.698 2.699 #else 2.700 2.701 if (val & 0xFFFFFFFF) 2.702 { 2.703 if (val & 0xFFFF) 2.704 { 2.705 return (val & 0xFF) ? 2.706 LowerBitTable[ val & 0xFF]: 2.707 LowerBitTable[(val >> 8) & 0xFF] + 8; 2.708 } 2.709 return (val & 0xFF0000) ? 2.710 LowerBitTable[(val >> 16) & 0xFF] + 16: 2.711 LowerBitTable[(val >> 24) & 0xFF] + 24; 2.712 } 2.713 else 2.714 { 2.715 if (val & 0xFFFF00000000) 2.716 { 2.717 return (val & 0xFF00000000) ? 2.718 LowerBitTable[(val >> 32) & 0xFF] + 32: 2.719 LowerBitTable[(val >> 40) & 0xFF] + 40; 2.720 } 2.721 return (val & 0xFF000000000000) ? 2.722 LowerBitTable[(val >> 48) & 0xFF] + 48: 2.723 LowerBitTable[(val >> 56) & 0xFF] + 56; 2.724 } 2.725 2.726 #endif 2.727 } 2.728 2.729 2.730 2.731 // ******* Special (optimized) memory routines 2.732 // Note: null (bad) pointer is not tested 2.733 class MemUtil 2.734 { 2.735 public: 2.736 2.737 // Memory compare 2.738 static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } 2.739 static int Cmp16(const void* p1, const void* p2, UPInt int16Count); 2.740 static int Cmp32(const void* p1, const void* p2, UPInt int32Count); 2.741 static int Cmp64(const void* p1, const void* p2, UPInt int64Count); 2.742 }; 2.743 2.744 // ** Inline Implementation 2.745 2.746 inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) 2.747 { 2.748 SInt16* pa = (SInt16*)p1; 2.749 SInt16* pb = (SInt16*)p2; 2.750 unsigned ic = 0; 2.751 if (int16Count == 0) 2.752 return 0; 2.753 while (pa[ic] == pb[ic]) 2.754 if (++ic==int16Count) 2.755 return 0; 2.756 return pa[ic] > pb[ic] ? 1 : -1; 2.757 } 2.758 inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) 2.759 { 2.760 SInt32* pa = (SInt32*)p1; 2.761 SInt32* pb = (SInt32*)p2; 2.762 unsigned ic = 0; 2.763 if (int32Count == 0) 2.764 return 0; 2.765 while (pa[ic] == pb[ic]) 2.766 if (++ic==int32Count) 2.767 return 0; 2.768 return pa[ic] > pb[ic] ? 1 : -1; 2.769 } 2.770 inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) 2.771 { 2.772 SInt64* pa = (SInt64*)p1; 2.773 SInt64* pb = (SInt64*)p2; 2.774 unsigned ic = 0; 2.775 if (int64Count == 0) 2.776 return 0; 2.777 while (pa[ic] == pb[ic]) 2.778 if (++ic==int64Count) 2.779 return 0; 2.780 return pa[ic] > pb[ic] ? 1 : -1; 2.781 } 2.782 2.783 // ** End Inline Implementation 2.784 2.785 2.786 //----------------------------------------------------------------------------------- 2.787 // ******* Byte Order Conversions 2.788 namespace ByteUtil { 2.789 2.790 // *** Swap Byte Order 2.791 2.792 // Swap the byte order of a byte array 2.793 inline void SwapOrder(void* pv, int size) 2.794 { 2.795 UByte* pb = (UByte*)pv; 2.796 UByte temp; 2.797 for (int i = 0; i < size>>1; i++) 2.798 { 2.799 temp = pb[size-1-i]; 2.800 pb[size-1-i] = pb[i]; 2.801 pb[i] = temp; 2.802 } 2.803 } 2.804 2.805 // Swap the byte order of primitive types 2.806 inline UByte SwapOrder(UByte v) { return v; } 2.807 inline SByte SwapOrder(SByte v) { return v; } 2.808 inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } 2.809 inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } 2.810 inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } 2.811 inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } 2.812 inline UInt64 SwapOrder(UInt64 v) 2.813 { 2.814 return (v>>56) | 2.815 ((v&UInt64(0x00FF000000000000))>>40) | 2.816 ((v&UInt64(0x0000FF0000000000))>>24) | 2.817 ((v&UInt64(0x000000FF00000000))>>8) | 2.818 ((v&UInt64(0x00000000FF000000))<<8) | 2.819 ((v&UInt64(0x0000000000FF0000))<<24) | 2.820 ((v&UInt64(0x000000000000FF00))<<40) | 2.821 (v<<56); 2.822 } 2.823 inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } 2.824 inline float SwapOrder(float p) 2.825 { 2.826 union { 2.827 float p; 2.828 UInt32 v; 2.829 } u; 2.830 u.p = p; 2.831 u.v = SwapOrder(u.v); 2.832 return u.p; 2.833 } 2.834 2.835 inline double SwapOrder(double p) 2.836 { 2.837 union { 2.838 double p; 2.839 UInt64 v; 2.840 } u; 2.841 u.p = p; 2.842 u.v = SwapOrder(u.v); 2.843 return u.p; 2.844 } 2.845 2.846 // *** Byte-order conversion 2.847 2.848 #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN) 2.849 // Little Endian to System (LE) 2.850 inline UByte LEToSystem(UByte v) { return v; } 2.851 inline SByte LEToSystem(SByte v) { return v; } 2.852 inline UInt16 LEToSystem(UInt16 v) { return v; } 2.853 inline SInt16 LEToSystem(SInt16 v) { return v; } 2.854 inline UInt32 LEToSystem(UInt32 v) { return v; } 2.855 inline SInt32 LEToSystem(SInt32 v) { return v; } 2.856 inline UInt64 LEToSystem(UInt64 v) { return v; } 2.857 inline SInt64 LEToSystem(SInt64 v) { return v; } 2.858 inline float LEToSystem(float v) { return v; } 2.859 inline double LEToSystem(double v) { return v; } 2.860 2.861 // Big Endian to System (LE) 2.862 inline UByte BEToSystem(UByte v) { return SwapOrder(v); } 2.863 inline SByte BEToSystem(SByte v) { return SwapOrder(v); } 2.864 inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } 2.865 inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } 2.866 inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } 2.867 inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } 2.868 inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } 2.869 inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } 2.870 inline float BEToSystem(float v) { return SwapOrder(v); } 2.871 inline double BEToSystem(double v) { return SwapOrder(v); } 2.872 2.873 // System (LE) to Little Endian 2.874 inline UByte SystemToLE(UByte v) { return v; } 2.875 inline SByte SystemToLE(SByte v) { return v; } 2.876 inline UInt16 SystemToLE(UInt16 v) { return v; } 2.877 inline SInt16 SystemToLE(SInt16 v) { return v; } 2.878 inline UInt32 SystemToLE(UInt32 v) { return v; } 2.879 inline SInt32 SystemToLE(SInt32 v) { return v; } 2.880 inline UInt64 SystemToLE(UInt64 v) { return v; } 2.881 inline SInt64 SystemToLE(SInt64 v) { return v; } 2.882 inline float SystemToLE(float v) { return v; } 2.883 inline double SystemToLE(double v) { return v; } 2.884 2.885 // System (LE) to Big Endian 2.886 inline UByte SystemToBE(UByte v) { return SwapOrder(v); } 2.887 inline SByte SystemToBE(SByte v) { return SwapOrder(v); } 2.888 inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } 2.889 inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } 2.890 inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } 2.891 inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } 2.892 inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } 2.893 inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } 2.894 inline float SystemToBE(float v) { return SwapOrder(v); } 2.895 inline double SystemToBE(double v) { return SwapOrder(v); } 2.896 2.897 #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN) 2.898 // Little Endian to System (BE) 2.899 inline UByte LEToSystem(UByte v) { return SwapOrder(v); } 2.900 inline SByte LEToSystem(SByte v) { return SwapOrder(v); } 2.901 inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } 2.902 inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } 2.903 inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } 2.904 inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } 2.905 inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } 2.906 inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } 2.907 inline float LEToSystem(float v) { return SwapOrder(v); } 2.908 inline double LEToSystem(double v) { return SwapOrder(v); } 2.909 2.910 // Big Endian to System (BE) 2.911 inline UByte BEToSystem(UByte v) { return v; } 2.912 inline SByte BEToSystem(SByte v) { return v; } 2.913 inline UInt16 BEToSystem(UInt16 v) { return v; } 2.914 inline SInt16 BEToSystem(SInt16 v) { return v; } 2.915 inline UInt32 BEToSystem(UInt32 v) { return v; } 2.916 inline SInt32 BEToSystem(SInt32 v) { return v; } 2.917 inline UInt64 BEToSystem(UInt64 v) { return v; } 2.918 inline SInt64 BEToSystem(SInt64 v) { return v; } 2.919 inline float BEToSystem(float v) { return v; } 2.920 inline double BEToSystem(double v) { return v; } 2.921 2.922 // System (BE) to Little Endian 2.923 inline UByte SystemToLE(UByte v) { return SwapOrder(v); } 2.924 inline SByte SystemToLE(SByte v) { return SwapOrder(v); } 2.925 inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } 2.926 inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } 2.927 inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } 2.928 inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } 2.929 inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } 2.930 inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } 2.931 inline float SystemToLE(float v) { return SwapOrder(v); } 2.932 inline double SystemToLE(double v) { return SwapOrder(v); } 2.933 2.934 // System (BE) to Big Endian 2.935 inline UByte SystemToBE(UByte v) { return v; } 2.936 inline SByte SystemToBE(SByte v) { return v; } 2.937 inline UInt16 SystemToBE(UInt16 v) { return v; } 2.938 inline SInt16 SystemToBE(SInt16 v) { return v; } 2.939 inline UInt32 SystemToBE(UInt32 v) { return v; } 2.940 inline SInt32 SystemToBE(SInt32 v) { return v; } 2.941 inline UInt64 SystemToBE(UInt64 v) { return v; } 2.942 inline SInt64 SystemToBE(SInt64 v) { return v; } 2.943 inline float SystemToBE(float v) { return v; } 2.944 inline double SystemToBE(double v) { return v; } 2.945 2.946 #else 2.947 #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN" 2.948 #endif 2.949 2.950 } // namespace ByteUtil 2.951 2.952 2.953 2.954 }} // OVR::Alg 2.955 2.956 #endif 2.957 \ No newline at end of file 2.958 +/************************************************************************************ 2.959 + 2.960 +PublicHeader: OVR.h 2.961 +Filename : OVR_Alg.h 2.962 +Content : Simple general purpose algorithms: Sort, Binary Search, etc. 2.963 +Created : September 19, 2012 2.964 +Notes : 2.965 + 2.966 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 2.967 + 2.968 +Use of this software is subject to the terms of the Oculus license 2.969 +agreement provided at the time of installation or download, or which 2.970 +otherwise accompanies this software in either electronic or hard copy form. 2.971 + 2.972 +************************************************************************************/ 2.973 + 2.974 +#ifndef OVR_Alg_h 2.975 +#define OVR_Alg_h 2.976 + 2.977 +#include "OVR_Types.h" 2.978 +#include <string.h> 2.979 + 2.980 +namespace OVR { namespace Alg { 2.981 + 2.982 + 2.983 +//----------------------------------------------------------------------------------- 2.984 +// ***** Operator extensions 2.985 + 2.986 +template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) 2.987 +{ T temp(a); a = b; b = temp; } 2.988 + 2.989 + 2.990 +// ***** min/max are not implemented in Visual Studio 6 standard STL 2.991 + 2.992 +template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b) 2.993 +{ return (a < b) ? a : b; } 2.994 + 2.995 +template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b) 2.996 +{ return (b < a) ? a : b; } 2.997 + 2.998 +template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal) 2.999 +{ return Max<T>(minVal, Min<T>(v, maxVal)); } 2.1000 + 2.1001 +template <typename T> OVR_FORCE_INLINE int Chop(T f) 2.1002 +{ return (int)f; } 2.1003 + 2.1004 +template <typename T> OVR_FORCE_INLINE T Lerp(T a, T b, T f) 2.1005 +{ return (b - a) * f + a; } 2.1006 + 2.1007 + 2.1008 +// These functions stand to fix a stupid VC++ warning (with /Wp64 on): 2.1009 +// "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data" 2.1010 +// Use these functions instead of gmin/gmax if the argument has size 2.1011 +// of the pointer to avoid the warning. Though, functionally they are 2.1012 +// absolutelly the same as regular gmin/gmax. 2.1013 +template <typename T> OVR_FORCE_INLINE const T PMin(const T a, const T b) 2.1014 +{ 2.1015 + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); 2.1016 + return (a < b) ? a : b; 2.1017 +} 2.1018 +template <typename T> OVR_FORCE_INLINE const T PMax(const T a, const T b) 2.1019 +{ 2.1020 + OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt)); 2.1021 + return (b < a) ? a : b; 2.1022 +} 2.1023 + 2.1024 + 2.1025 +template <typename T> OVR_FORCE_INLINE const T Abs(const T v) 2.1026 +{ return (v>=0) ? v : -v; } 2.1027 + 2.1028 + 2.1029 +//----------------------------------------------------------------------------------- 2.1030 +// ***** OperatorLess 2.1031 +// 2.1032 +template<class T> struct OperatorLess 2.1033 +{ 2.1034 + static bool Compare(const T& a, const T& b) 2.1035 + { 2.1036 + return a < b; 2.1037 + } 2.1038 +}; 2.1039 + 2.1040 + 2.1041 +//----------------------------------------------------------------------------------- 2.1042 +// ***** QuickSortSliced 2.1043 +// 2.1044 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.1045 +// The range is specified with start, end, where "end" is exclusive! 2.1046 +// The comparison predicate must be specified. 2.1047 +template<class Array, class Less> 2.1048 +void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less) 2.1049 +{ 2.1050 + enum 2.1051 + { 2.1052 + Threshold = 9 2.1053 + }; 2.1054 + 2.1055 + if(end - start < 2) return; 2.1056 + 2.1057 + SPInt stack[80]; 2.1058 + SPInt* top = stack; 2.1059 + SPInt base = (SPInt)start; 2.1060 + SPInt limit = (SPInt)end; 2.1061 + 2.1062 + for(;;) 2.1063 + { 2.1064 + SPInt len = limit - base; 2.1065 + SPInt i, j, pivot; 2.1066 + 2.1067 + if(len > Threshold) 2.1068 + { 2.1069 + // we use base + len/2 as the pivot 2.1070 + pivot = base + len / 2; 2.1071 + Swap(arr[base], arr[pivot]); 2.1072 + 2.1073 + i = base + 1; 2.1074 + j = limit - 1; 2.1075 + 2.1076 + // now ensure that *i <= *base <= *j 2.1077 + if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); 2.1078 + if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); 2.1079 + if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); 2.1080 + 2.1081 + for(;;) 2.1082 + { 2.1083 + do i++; while( less(arr[i], arr[base]) ); 2.1084 + do j--; while( less(arr[base], arr[j]) ); 2.1085 + 2.1086 + if( i > j ) 2.1087 + { 2.1088 + break; 2.1089 + } 2.1090 + 2.1091 + Swap(arr[i], arr[j]); 2.1092 + } 2.1093 + 2.1094 + Swap(arr[base], arr[j]); 2.1095 + 2.1096 + // now, push the largest sub-array 2.1097 + if(j - base > limit - i) 2.1098 + { 2.1099 + top[0] = base; 2.1100 + top[1] = j; 2.1101 + base = i; 2.1102 + } 2.1103 + else 2.1104 + { 2.1105 + top[0] = i; 2.1106 + top[1] = limit; 2.1107 + limit = j; 2.1108 + } 2.1109 + top += 2; 2.1110 + } 2.1111 + else 2.1112 + { 2.1113 + // the sub-array is small, perform insertion sort 2.1114 + j = base; 2.1115 + i = j + 1; 2.1116 + 2.1117 + for(; i < limit; j = i, i++) 2.1118 + { 2.1119 + for(; less(arr[j + 1], arr[j]); j--) 2.1120 + { 2.1121 + Swap(arr[j + 1], arr[j]); 2.1122 + if(j == base) 2.1123 + { 2.1124 + break; 2.1125 + } 2.1126 + } 2.1127 + } 2.1128 + if(top > stack) 2.1129 + { 2.1130 + top -= 2; 2.1131 + base = top[0]; 2.1132 + limit = top[1]; 2.1133 + } 2.1134 + else 2.1135 + { 2.1136 + break; 2.1137 + } 2.1138 + } 2.1139 + } 2.1140 +} 2.1141 + 2.1142 + 2.1143 +//----------------------------------------------------------------------------------- 2.1144 +// ***** QuickSortSliced 2.1145 +// 2.1146 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.1147 +// The range is specified with start, end, where "end" is exclusive! 2.1148 +// The data type must have a defined "<" operator. 2.1149 +template<class Array> 2.1150 +void QuickSortSliced(Array& arr, UPInt start, UPInt end) 2.1151 +{ 2.1152 + typedef typename Array::ValueType ValueType; 2.1153 + QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); 2.1154 +} 2.1155 + 2.1156 +// Same as corresponding G_QuickSortSliced but with checking array limits to avoid 2.1157 +// crash in the case of wrong comparator functor. 2.1158 +template<class Array, class Less> 2.1159 +bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less) 2.1160 +{ 2.1161 + enum 2.1162 + { 2.1163 + Threshold = 9 2.1164 + }; 2.1165 + 2.1166 + if(end - start < 2) return true; 2.1167 + 2.1168 + SPInt stack[80]; 2.1169 + SPInt* top = stack; 2.1170 + SPInt base = (SPInt)start; 2.1171 + SPInt limit = (SPInt)end; 2.1172 + 2.1173 + for(;;) 2.1174 + { 2.1175 + SPInt len = limit - base; 2.1176 + SPInt i, j, pivot; 2.1177 + 2.1178 + if(len > Threshold) 2.1179 + { 2.1180 + // we use base + len/2 as the pivot 2.1181 + pivot = base + len / 2; 2.1182 + Swap(arr[base], arr[pivot]); 2.1183 + 2.1184 + i = base + 1; 2.1185 + j = limit - 1; 2.1186 + 2.1187 + // now ensure that *i <= *base <= *j 2.1188 + if(less(arr[j], arr[i])) Swap(arr[j], arr[i]); 2.1189 + if(less(arr[base], arr[i])) Swap(arr[base], arr[i]); 2.1190 + if(less(arr[j], arr[base])) Swap(arr[j], arr[base]); 2.1191 + 2.1192 + for(;;) 2.1193 + { 2.1194 + do 2.1195 + { 2.1196 + i++; 2.1197 + if (i >= limit) 2.1198 + return false; 2.1199 + } while( less(arr[i], arr[base]) ); 2.1200 + do 2.1201 + { 2.1202 + j--; 2.1203 + if (j < 0) 2.1204 + return false; 2.1205 + } while( less(arr[base], arr[j]) ); 2.1206 + 2.1207 + if( i > j ) 2.1208 + { 2.1209 + break; 2.1210 + } 2.1211 + 2.1212 + Swap(arr[i], arr[j]); 2.1213 + } 2.1214 + 2.1215 + Swap(arr[base], arr[j]); 2.1216 + 2.1217 + // now, push the largest sub-array 2.1218 + if(j - base > limit - i) 2.1219 + { 2.1220 + top[0] = base; 2.1221 + top[1] = j; 2.1222 + base = i; 2.1223 + } 2.1224 + else 2.1225 + { 2.1226 + top[0] = i; 2.1227 + top[1] = limit; 2.1228 + limit = j; 2.1229 + } 2.1230 + top += 2; 2.1231 + } 2.1232 + else 2.1233 + { 2.1234 + // the sub-array is small, perform insertion sort 2.1235 + j = base; 2.1236 + i = j + 1; 2.1237 + 2.1238 + for(; i < limit; j = i, i++) 2.1239 + { 2.1240 + for(; less(arr[j + 1], arr[j]); j--) 2.1241 + { 2.1242 + Swap(arr[j + 1], arr[j]); 2.1243 + if(j == base) 2.1244 + { 2.1245 + break; 2.1246 + } 2.1247 + } 2.1248 + } 2.1249 + if(top > stack) 2.1250 + { 2.1251 + top -= 2; 2.1252 + base = top[0]; 2.1253 + limit = top[1]; 2.1254 + } 2.1255 + else 2.1256 + { 2.1257 + break; 2.1258 + } 2.1259 + } 2.1260 + } 2.1261 + return true; 2.1262 +} 2.1263 + 2.1264 +template<class Array> 2.1265 +bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end) 2.1266 +{ 2.1267 + typedef typename Array::ValueType ValueType; 2.1268 + return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare); 2.1269 +} 2.1270 + 2.1271 +//----------------------------------------------------------------------------------- 2.1272 +// ***** QuickSort 2.1273 +// 2.1274 +// Sort an array Array, ArrayPaged, ArrayUnsafe. 2.1275 +// The array must have GetSize() function. 2.1276 +// The comparison predicate must be specified. 2.1277 +template<class Array, class Less> 2.1278 +void QuickSort(Array& arr, Less less) 2.1279 +{ 2.1280 + QuickSortSliced(arr, 0, arr.GetSize(), less); 2.1281 +} 2.1282 + 2.1283 +// checks for boundaries 2.1284 +template<class Array, class Less> 2.1285 +bool QuickSortSafe(Array& arr, Less less) 2.1286 +{ 2.1287 + return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less); 2.1288 +} 2.1289 + 2.1290 + 2.1291 +//----------------------------------------------------------------------------------- 2.1292 +// ***** QuickSort 2.1293 +// 2.1294 +// Sort an array Array, ArrayPaged, ArrayUnsafe. 2.1295 +// The array must have GetSize() function. 2.1296 +// The data type must have a defined "<" operator. 2.1297 +template<class Array> 2.1298 +void QuickSort(Array& arr) 2.1299 +{ 2.1300 + typedef typename Array::ValueType ValueType; 2.1301 + QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.1302 +} 2.1303 + 2.1304 +template<class Array> 2.1305 +bool QuickSortSafe(Array& arr) 2.1306 +{ 2.1307 + typedef typename Array::ValueType ValueType; 2.1308 + return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.1309 +} 2.1310 + 2.1311 +//----------------------------------------------------------------------------------- 2.1312 +// ***** InsertionSortSliced 2.1313 +// 2.1314 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.1315 +// The range is specified with start, end, where "end" is exclusive! 2.1316 +// The comparison predicate must be specified. 2.1317 +// Unlike Quick Sort, the Insertion Sort works much slower in average, 2.1318 +// but may be much faster on almost sorted arrays. Besides, it guarantees 2.1319 +// that the elements will not be swapped if not necessary. For example, 2.1320 +// an array with all equal elements will remain "untouched", while 2.1321 +// Quick Sort will considerably shuffle the elements in this case. 2.1322 +template<class Array, class Less> 2.1323 +void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less) 2.1324 +{ 2.1325 + UPInt j = start; 2.1326 + UPInt i = j + 1; 2.1327 + UPInt limit = end; 2.1328 + 2.1329 + for(; i < limit; j = i, i++) 2.1330 + { 2.1331 + for(; less(arr[j + 1], arr[j]); j--) 2.1332 + { 2.1333 + Swap(arr[j + 1], arr[j]); 2.1334 + if(j <= start) 2.1335 + { 2.1336 + break; 2.1337 + } 2.1338 + } 2.1339 + } 2.1340 +} 2.1341 + 2.1342 + 2.1343 +//----------------------------------------------------------------------------------- 2.1344 +// ***** InsertionSortSliced 2.1345 +// 2.1346 +// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe. 2.1347 +// The range is specified with start, end, where "end" is exclusive! 2.1348 +// The data type must have a defined "<" operator. 2.1349 +template<class Array> 2.1350 +void InsertionSortSliced(Array& arr, UPInt start, UPInt end) 2.1351 +{ 2.1352 + typedef typename Array::ValueType ValueType; 2.1353 + InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare); 2.1354 +} 2.1355 + 2.1356 +//----------------------------------------------------------------------------------- 2.1357 +// ***** InsertionSort 2.1358 +// 2.1359 +// Sort an array Array, ArrayPaged, ArrayUnsafe. 2.1360 +// The array must have GetSize() function. 2.1361 +// The comparison predicate must be specified. 2.1362 + 2.1363 +template<class Array, class Less> 2.1364 +void InsertionSort(Array& arr, Less less) 2.1365 +{ 2.1366 + InsertionSortSliced(arr, 0, arr.GetSize(), less); 2.1367 +} 2.1368 + 2.1369 +//----------------------------------------------------------------------------------- 2.1370 +// ***** InsertionSort 2.1371 +// 2.1372 +// Sort an array Array, ArrayPaged, ArrayUnsafe. 2.1373 +// The array must have GetSize() function. 2.1374 +// The data type must have a defined "<" operator. 2.1375 +template<class Array> 2.1376 +void InsertionSort(Array& arr) 2.1377 +{ 2.1378 + typedef typename Array::ValueType ValueType; 2.1379 + InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare); 2.1380 +} 2.1381 + 2.1382 + 2.1383 + 2.1384 +//----------------------------------------------------------------------------------- 2.1385 +// ***** LowerBoundSliced 2.1386 +// 2.1387 +template<class Array, class Value, class Less> 2.1388 +UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) 2.1389 +{ 2.1390 + SPInt first = (SPInt)start; 2.1391 + SPInt len = (SPInt)(end - start); 2.1392 + SPInt half; 2.1393 + SPInt middle; 2.1394 + 2.1395 + while(len > 0) 2.1396 + { 2.1397 + half = len >> 1; 2.1398 + middle = first + half; 2.1399 + if(less(arr[middle], val)) 2.1400 + { 2.1401 + first = middle + 1; 2.1402 + len = len - half - 1; 2.1403 + } 2.1404 + else 2.1405 + { 2.1406 + len = half; 2.1407 + } 2.1408 + } 2.1409 + return (UPInt)first; 2.1410 +} 2.1411 + 2.1412 + 2.1413 +//----------------------------------------------------------------------------------- 2.1414 +// ***** LowerBoundSliced 2.1415 +// 2.1416 +template<class Array, class Value> 2.1417 +UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) 2.1418 +{ 2.1419 + return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); 2.1420 +} 2.1421 + 2.1422 +//----------------------------------------------------------------------------------- 2.1423 +// ***** LowerBoundSized 2.1424 +// 2.1425 +template<class Array, class Value> 2.1426 +UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val) 2.1427 +{ 2.1428 + return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); 2.1429 +} 2.1430 + 2.1431 +//----------------------------------------------------------------------------------- 2.1432 +// ***** LowerBound 2.1433 +// 2.1434 +template<class Array, class Value, class Less> 2.1435 +UPInt LowerBound(const Array& arr, const Value& val, Less less) 2.1436 +{ 2.1437 + return LowerBoundSliced(arr, 0, arr.GetSize(), val, less); 2.1438 +} 2.1439 + 2.1440 + 2.1441 +//----------------------------------------------------------------------------------- 2.1442 +// ***** LowerBound 2.1443 +// 2.1444 +template<class Array, class Value> 2.1445 +UPInt LowerBound(const Array& arr, const Value& val) 2.1446 +{ 2.1447 + return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); 2.1448 +} 2.1449 + 2.1450 + 2.1451 + 2.1452 +//----------------------------------------------------------------------------------- 2.1453 +// ***** UpperBoundSliced 2.1454 +// 2.1455 +template<class Array, class Value, class Less> 2.1456 +UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less) 2.1457 +{ 2.1458 + SPInt first = (SPInt)start; 2.1459 + SPInt len = (SPInt)(end - start); 2.1460 + SPInt half; 2.1461 + SPInt middle; 2.1462 + 2.1463 + while(len > 0) 2.1464 + { 2.1465 + half = len >> 1; 2.1466 + middle = first + half; 2.1467 + if(less(val, arr[middle])) 2.1468 + { 2.1469 + len = half; 2.1470 + } 2.1471 + else 2.1472 + { 2.1473 + first = middle + 1; 2.1474 + len = len - half - 1; 2.1475 + } 2.1476 + } 2.1477 + return (UPInt)first; 2.1478 +} 2.1479 + 2.1480 + 2.1481 +//----------------------------------------------------------------------------------- 2.1482 +// ***** UpperBoundSliced 2.1483 +// 2.1484 +template<class Array, class Value> 2.1485 +UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val) 2.1486 +{ 2.1487 + return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare); 2.1488 +} 2.1489 + 2.1490 + 2.1491 +//----------------------------------------------------------------------------------- 2.1492 +// ***** UpperBoundSized 2.1493 +// 2.1494 +template<class Array, class Value> 2.1495 +UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val) 2.1496 +{ 2.1497 + return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare); 2.1498 +} 2.1499 + 2.1500 + 2.1501 +//----------------------------------------------------------------------------------- 2.1502 +// ***** UpperBound 2.1503 +// 2.1504 +template<class Array, class Value, class Less> 2.1505 +UPInt UpperBound(const Array& arr, const Value& val, Less less) 2.1506 +{ 2.1507 + return UpperBoundSliced(arr, 0, arr.GetSize(), val, less); 2.1508 +} 2.1509 + 2.1510 + 2.1511 +//----------------------------------------------------------------------------------- 2.1512 +// ***** UpperBound 2.1513 +// 2.1514 +template<class Array, class Value> 2.1515 +UPInt UpperBound(const Array& arr, const Value& val) 2.1516 +{ 2.1517 + return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare); 2.1518 +} 2.1519 + 2.1520 + 2.1521 +//----------------------------------------------------------------------------------- 2.1522 +// ***** ReverseArray 2.1523 +// 2.1524 +template<class Array> void ReverseArray(Array& arr) 2.1525 +{ 2.1526 + SPInt from = 0; 2.1527 + SPInt to = arr.GetSize() - 1; 2.1528 + while(from < to) 2.1529 + { 2.1530 + Swap(arr[from], arr[to]); 2.1531 + ++from; 2.1532 + --to; 2.1533 + } 2.1534 +} 2.1535 + 2.1536 + 2.1537 +// ***** AppendArray 2.1538 +// 2.1539 +template<class CDst, class CSrc> 2.1540 +void AppendArray(CDst& dst, const CSrc& src) 2.1541 +{ 2.1542 + UPInt i; 2.1543 + for(i = 0; i < src.GetSize(); i++) 2.1544 + dst.PushBack(src[i]); 2.1545 +} 2.1546 + 2.1547 +//----------------------------------------------------------------------------------- 2.1548 +// ***** ArrayAdaptor 2.1549 +// 2.1550 +// A simple adapter that provides the GetSize() method and overloads 2.1551 +// operator []. Used to wrap plain arrays in QuickSort and such. 2.1552 +template<class T> class ArrayAdaptor 2.1553 +{ 2.1554 +public: 2.1555 + typedef T ValueType; 2.1556 + ArrayAdaptor() : Data(0), Size(0) {} 2.1557 + ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {} 2.1558 + UPInt GetSize() const { return Size; } 2.1559 + const T& operator [] (UPInt i) const { return Data[i]; } 2.1560 + T& operator [] (UPInt i) { return Data[i]; } 2.1561 +private: 2.1562 + T* Data; 2.1563 + UPInt Size; 2.1564 +}; 2.1565 + 2.1566 + 2.1567 +//----------------------------------------------------------------------------------- 2.1568 +// ***** GConstArrayAdaptor 2.1569 +// 2.1570 +// A simple const adapter that provides the GetSize() method and overloads 2.1571 +// operator []. Used to wrap plain arrays in LowerBound and such. 2.1572 +template<class T> class ConstArrayAdaptor 2.1573 +{ 2.1574 +public: 2.1575 + typedef T ValueType; 2.1576 + ConstArrayAdaptor() : Data(0), Size(0) {} 2.1577 + ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {} 2.1578 + UPInt GetSize() const { return Size; } 2.1579 + const T& operator [] (UPInt i) const { return Data[i]; } 2.1580 +private: 2.1581 + const T* Data; 2.1582 + UPInt Size; 2.1583 +}; 2.1584 + 2.1585 + 2.1586 + 2.1587 +//----------------------------------------------------------------------------------- 2.1588 +extern const UByte UpperBitTable[256]; 2.1589 +extern const UByte LowerBitTable[256]; 2.1590 + 2.1591 + 2.1592 + 2.1593 +//----------------------------------------------------------------------------------- 2.1594 +inline UByte UpperBit(UPInt val) 2.1595 +{ 2.1596 +#ifndef OVR_64BIT_POINTERS 2.1597 + 2.1598 + if (val & 0xFFFF0000) 2.1599 + { 2.1600 + return (val & 0xFF000000) ? 2.1601 + UpperBitTable[(val >> 24) ] + 24: 2.1602 + UpperBitTable[(val >> 16) & 0xFF] + 16; 2.1603 + } 2.1604 + return (val & 0xFF00) ? 2.1605 + UpperBitTable[(val >> 8) & 0xFF] + 8: 2.1606 + UpperBitTable[(val ) & 0xFF]; 2.1607 + 2.1608 +#else 2.1609 + 2.1610 + if (val & 0xFFFFFFFF00000000) 2.1611 + { 2.1612 + if (val & 0xFFFF000000000000) 2.1613 + { 2.1614 + return (val & 0xFF00000000000000) ? 2.1615 + UpperBitTable[(val >> 56) ] + 56: 2.1616 + UpperBitTable[(val >> 48) & 0xFF] + 48; 2.1617 + } 2.1618 + return (val & 0xFF0000000000) ? 2.1619 + UpperBitTable[(val >> 40) & 0xFF] + 40: 2.1620 + UpperBitTable[(val >> 32) & 0xFF] + 32; 2.1621 + } 2.1622 + else 2.1623 + { 2.1624 + if (val & 0xFFFF0000) 2.1625 + { 2.1626 + return (val & 0xFF000000) ? 2.1627 + UpperBitTable[(val >> 24) ] + 24: 2.1628 + UpperBitTable[(val >> 16) & 0xFF] + 16; 2.1629 + } 2.1630 + return (val & 0xFF00) ? 2.1631 + UpperBitTable[(val >> 8) & 0xFF] + 8: 2.1632 + UpperBitTable[(val ) & 0xFF]; 2.1633 + } 2.1634 + 2.1635 +#endif 2.1636 +} 2.1637 + 2.1638 +//----------------------------------------------------------------------------------- 2.1639 +inline UByte LowerBit(UPInt val) 2.1640 +{ 2.1641 +#ifndef OVR_64BIT_POINTERS 2.1642 + 2.1643 + if (val & 0xFFFF) 2.1644 + { 2.1645 + return (val & 0xFF) ? 2.1646 + LowerBitTable[ val & 0xFF]: 2.1647 + LowerBitTable[(val >> 8) & 0xFF] + 8; 2.1648 + } 2.1649 + return (val & 0xFF0000) ? 2.1650 + LowerBitTable[(val >> 16) & 0xFF] + 16: 2.1651 + LowerBitTable[(val >> 24) & 0xFF] + 24; 2.1652 + 2.1653 +#else 2.1654 + 2.1655 + if (val & 0xFFFFFFFF) 2.1656 + { 2.1657 + if (val & 0xFFFF) 2.1658 + { 2.1659 + return (val & 0xFF) ? 2.1660 + LowerBitTable[ val & 0xFF]: 2.1661 + LowerBitTable[(val >> 8) & 0xFF] + 8; 2.1662 + } 2.1663 + return (val & 0xFF0000) ? 2.1664 + LowerBitTable[(val >> 16) & 0xFF] + 16: 2.1665 + LowerBitTable[(val >> 24) & 0xFF] + 24; 2.1666 + } 2.1667 + else 2.1668 + { 2.1669 + if (val & 0xFFFF00000000) 2.1670 + { 2.1671 + return (val & 0xFF00000000) ? 2.1672 + LowerBitTable[(val >> 32) & 0xFF] + 32: 2.1673 + LowerBitTable[(val >> 40) & 0xFF] + 40; 2.1674 + } 2.1675 + return (val & 0xFF000000000000) ? 2.1676 + LowerBitTable[(val >> 48) & 0xFF] + 48: 2.1677 + LowerBitTable[(val >> 56) & 0xFF] + 56; 2.1678 + } 2.1679 + 2.1680 +#endif 2.1681 +} 2.1682 + 2.1683 + 2.1684 + 2.1685 +// ******* Special (optimized) memory routines 2.1686 +// Note: null (bad) pointer is not tested 2.1687 +class MemUtil 2.1688 +{ 2.1689 +public: 2.1690 + 2.1691 + // Memory compare 2.1692 + static int Cmp (const void* p1, const void* p2, UPInt byteCount) { return memcmp(p1, p2, byteCount); } 2.1693 + static int Cmp16(const void* p1, const void* p2, UPInt int16Count); 2.1694 + static int Cmp32(const void* p1, const void* p2, UPInt int32Count); 2.1695 + static int Cmp64(const void* p1, const void* p2, UPInt int64Count); 2.1696 +}; 2.1697 + 2.1698 +// ** Inline Implementation 2.1699 + 2.1700 +inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count) 2.1701 +{ 2.1702 + SInt16* pa = (SInt16*)p1; 2.1703 + SInt16* pb = (SInt16*)p2; 2.1704 + unsigned ic = 0; 2.1705 + if (int16Count == 0) 2.1706 + return 0; 2.1707 + while (pa[ic] == pb[ic]) 2.1708 + if (++ic==int16Count) 2.1709 + return 0; 2.1710 + return pa[ic] > pb[ic] ? 1 : -1; 2.1711 +} 2.1712 +inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count) 2.1713 +{ 2.1714 + SInt32* pa = (SInt32*)p1; 2.1715 + SInt32* pb = (SInt32*)p2; 2.1716 + unsigned ic = 0; 2.1717 + if (int32Count == 0) 2.1718 + return 0; 2.1719 + while (pa[ic] == pb[ic]) 2.1720 + if (++ic==int32Count) 2.1721 + return 0; 2.1722 + return pa[ic] > pb[ic] ? 1 : -1; 2.1723 +} 2.1724 +inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count) 2.1725 +{ 2.1726 + SInt64* pa = (SInt64*)p1; 2.1727 + SInt64* pb = (SInt64*)p2; 2.1728 + unsigned ic = 0; 2.1729 + if (int64Count == 0) 2.1730 + return 0; 2.1731 + while (pa[ic] == pb[ic]) 2.1732 + if (++ic==int64Count) 2.1733 + return 0; 2.1734 + return pa[ic] > pb[ic] ? 1 : -1; 2.1735 +} 2.1736 + 2.1737 +// ** End Inline Implementation 2.1738 + 2.1739 + 2.1740 +//----------------------------------------------------------------------------------- 2.1741 +// ******* Byte Order Conversions 2.1742 +namespace ByteUtil { 2.1743 + 2.1744 + // *** Swap Byte Order 2.1745 + 2.1746 + // Swap the byte order of a byte array 2.1747 + inline void SwapOrder(void* pv, int size) 2.1748 + { 2.1749 + UByte* pb = (UByte*)pv; 2.1750 + UByte temp; 2.1751 + for (int i = 0; i < size>>1; i++) 2.1752 + { 2.1753 + temp = pb[size-1-i]; 2.1754 + pb[size-1-i] = pb[i]; 2.1755 + pb[i] = temp; 2.1756 + } 2.1757 + } 2.1758 + 2.1759 + // Swap the byte order of primitive types 2.1760 + inline UByte SwapOrder(UByte v) { return v; } 2.1761 + inline SByte SwapOrder(SByte v) { return v; } 2.1762 + inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); } 2.1763 + inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); } 2.1764 + inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); } 2.1765 + inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); } 2.1766 + inline UInt64 SwapOrder(UInt64 v) 2.1767 + { 2.1768 + return (v>>56) | 2.1769 + ((v&UInt64(0x00FF000000000000))>>40) | 2.1770 + ((v&UInt64(0x0000FF0000000000))>>24) | 2.1771 + ((v&UInt64(0x000000FF00000000))>>8) | 2.1772 + ((v&UInt64(0x00000000FF000000))<<8) | 2.1773 + ((v&UInt64(0x0000000000FF0000))<<24) | 2.1774 + ((v&UInt64(0x000000000000FF00))<<40) | 2.1775 + (v<<56); 2.1776 + } 2.1777 + inline SInt64 SwapOrder(SInt64 v) { return (SInt64)SwapOrder(UInt64(v)); } 2.1778 + inline float SwapOrder(float p) 2.1779 + { 2.1780 + union { 2.1781 + float p; 2.1782 + UInt32 v; 2.1783 + } u; 2.1784 + u.p = p; 2.1785 + u.v = SwapOrder(u.v); 2.1786 + return u.p; 2.1787 + } 2.1788 + 2.1789 + inline double SwapOrder(double p) 2.1790 + { 2.1791 + union { 2.1792 + double p; 2.1793 + UInt64 v; 2.1794 + } u; 2.1795 + u.p = p; 2.1796 + u.v = SwapOrder(u.v); 2.1797 + return u.p; 2.1798 + } 2.1799 + 2.1800 + // *** Byte-order conversion 2.1801 + 2.1802 +#if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN) 2.1803 + // Little Endian to System (LE) 2.1804 + inline UByte LEToSystem(UByte v) { return v; } 2.1805 + inline SByte LEToSystem(SByte v) { return v; } 2.1806 + inline UInt16 LEToSystem(UInt16 v) { return v; } 2.1807 + inline SInt16 LEToSystem(SInt16 v) { return v; } 2.1808 + inline UInt32 LEToSystem(UInt32 v) { return v; } 2.1809 + inline SInt32 LEToSystem(SInt32 v) { return v; } 2.1810 + inline UInt64 LEToSystem(UInt64 v) { return v; } 2.1811 + inline SInt64 LEToSystem(SInt64 v) { return v; } 2.1812 + inline float LEToSystem(float v) { return v; } 2.1813 + inline double LEToSystem(double v) { return v; } 2.1814 + 2.1815 + // Big Endian to System (LE) 2.1816 + inline UByte BEToSystem(UByte v) { return SwapOrder(v); } 2.1817 + inline SByte BEToSystem(SByte v) { return SwapOrder(v); } 2.1818 + inline UInt16 BEToSystem(UInt16 v) { return SwapOrder(v); } 2.1819 + inline SInt16 BEToSystem(SInt16 v) { return SwapOrder(v); } 2.1820 + inline UInt32 BEToSystem(UInt32 v) { return SwapOrder(v); } 2.1821 + inline SInt32 BEToSystem(SInt32 v) { return SwapOrder(v); } 2.1822 + inline UInt64 BEToSystem(UInt64 v) { return SwapOrder(v); } 2.1823 + inline SInt64 BEToSystem(SInt64 v) { return SwapOrder(v); } 2.1824 + inline float BEToSystem(float v) { return SwapOrder(v); } 2.1825 + inline double BEToSystem(double v) { return SwapOrder(v); } 2.1826 + 2.1827 + // System (LE) to Little Endian 2.1828 + inline UByte SystemToLE(UByte v) { return v; } 2.1829 + inline SByte SystemToLE(SByte v) { return v; } 2.1830 + inline UInt16 SystemToLE(UInt16 v) { return v; } 2.1831 + inline SInt16 SystemToLE(SInt16 v) { return v; } 2.1832 + inline UInt32 SystemToLE(UInt32 v) { return v; } 2.1833 + inline SInt32 SystemToLE(SInt32 v) { return v; } 2.1834 + inline UInt64 SystemToLE(UInt64 v) { return v; } 2.1835 + inline SInt64 SystemToLE(SInt64 v) { return v; } 2.1836 + inline float SystemToLE(float v) { return v; } 2.1837 + inline double SystemToLE(double v) { return v; } 2.1838 + 2.1839 + // System (LE) to Big Endian 2.1840 + inline UByte SystemToBE(UByte v) { return SwapOrder(v); } 2.1841 + inline SByte SystemToBE(SByte v) { return SwapOrder(v); } 2.1842 + inline UInt16 SystemToBE(UInt16 v) { return SwapOrder(v); } 2.1843 + inline SInt16 SystemToBE(SInt16 v) { return SwapOrder(v); } 2.1844 + inline UInt32 SystemToBE(UInt32 v) { return SwapOrder(v); } 2.1845 + inline SInt32 SystemToBE(SInt32 v) { return SwapOrder(v); } 2.1846 + inline UInt64 SystemToBE(UInt64 v) { return SwapOrder(v); } 2.1847 + inline SInt64 SystemToBE(SInt64 v) { return SwapOrder(v); } 2.1848 + inline float SystemToBE(float v) { return SwapOrder(v); } 2.1849 + inline double SystemToBE(double v) { return SwapOrder(v); } 2.1850 + 2.1851 +#elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN) 2.1852 + // Little Endian to System (BE) 2.1853 + inline UByte LEToSystem(UByte v) { return SwapOrder(v); } 2.1854 + inline SByte LEToSystem(SByte v) { return SwapOrder(v); } 2.1855 + inline UInt16 LEToSystem(UInt16 v) { return SwapOrder(v); } 2.1856 + inline SInt16 LEToSystem(SInt16 v) { return SwapOrder(v); } 2.1857 + inline UInt32 LEToSystem(UInt32 v) { return SwapOrder(v); } 2.1858 + inline SInt32 LEToSystem(SInt32 v) { return SwapOrder(v); } 2.1859 + inline UInt64 LEToSystem(UInt64 v) { return SwapOrder(v); } 2.1860 + inline SInt64 LEToSystem(SInt64 v) { return SwapOrder(v); } 2.1861 + inline float LEToSystem(float v) { return SwapOrder(v); } 2.1862 + inline double LEToSystem(double v) { return SwapOrder(v); } 2.1863 + 2.1864 + // Big Endian to System (BE) 2.1865 + inline UByte BEToSystem(UByte v) { return v; } 2.1866 + inline SByte BEToSystem(SByte v) { return v; } 2.1867 + inline UInt16 BEToSystem(UInt16 v) { return v; } 2.1868 + inline SInt16 BEToSystem(SInt16 v) { return v; } 2.1869 + inline UInt32 BEToSystem(UInt32 v) { return v; } 2.1870 + inline SInt32 BEToSystem(SInt32 v) { return v; } 2.1871 + inline UInt64 BEToSystem(UInt64 v) { return v; } 2.1872 + inline SInt64 BEToSystem(SInt64 v) { return v; } 2.1873 + inline float BEToSystem(float v) { return v; } 2.1874 + inline double BEToSystem(double v) { return v; } 2.1875 + 2.1876 + // System (BE) to Little Endian 2.1877 + inline UByte SystemToLE(UByte v) { return SwapOrder(v); } 2.1878 + inline SByte SystemToLE(SByte v) { return SwapOrder(v); } 2.1879 + inline UInt16 SystemToLE(UInt16 v) { return SwapOrder(v); } 2.1880 + inline SInt16 SystemToLE(SInt16 v) { return SwapOrder(v); } 2.1881 + inline UInt32 SystemToLE(UInt32 v) { return SwapOrder(v); } 2.1882 + inline SInt32 SystemToLE(SInt32 v) { return SwapOrder(v); } 2.1883 + inline UInt64 SystemToLE(UInt64 v) { return SwapOrder(v); } 2.1884 + inline SInt64 SystemToLE(SInt64 v) { return SwapOrder(v); } 2.1885 + inline float SystemToLE(float v) { return SwapOrder(v); } 2.1886 + inline double SystemToLE(double v) { return SwapOrder(v); } 2.1887 + 2.1888 + // System (BE) to Big Endian 2.1889 + inline UByte SystemToBE(UByte v) { return v; } 2.1890 + inline SByte SystemToBE(SByte v) { return v; } 2.1891 + inline UInt16 SystemToBE(UInt16 v) { return v; } 2.1892 + inline SInt16 SystemToBE(SInt16 v) { return v; } 2.1893 + inline UInt32 SystemToBE(UInt32 v) { return v; } 2.1894 + inline SInt32 SystemToBE(SInt32 v) { return v; } 2.1895 + inline UInt64 SystemToBE(UInt64 v) { return v; } 2.1896 + inline SInt64 SystemToBE(SInt64 v) { return v; } 2.1897 + inline float SystemToBE(float v) { return v; } 2.1898 + inline double SystemToBE(double v) { return v; } 2.1899 + 2.1900 +#else 2.1901 + #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN" 2.1902 +#endif 2.1903 + 2.1904 +} // namespace ByteUtil 2.1905 + 2.1906 + 2.1907 + 2.1908 +}} // OVR::Alg 2.1909 + 2.1910 +#endif
3.1 --- a/libovr/Src/Kernel/OVR_Allocator.cpp Sat Sep 14 17:51:03 2013 +0300 3.2 +++ b/libovr/Src/Kernel/OVR_Allocator.cpp Sun Sep 15 04:10:05 2013 +0300 3.3 @@ -1,1 +1,84 @@ 3.4 -/************************************************************************************ 3.5 3.6 Filename : OVR_Allocator.cpp 3.7 Content : Installable memory allocator implementation 3.8 Created : September 19, 2012 3.9 Notes : 3.10 3.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 3.12 3.13 Use of this software is subject to the terms of the Oculus license 3.14 agreement provided at the time of installation or download, or which 3.15 otherwise accompanies this software in either electronic or hard copy form. 3.16 3.17 ************************************************************************************/ 3.18 3.19 #include "OVR_Allocator.h" 3.20 #ifdef OVR_OS_MAC 3.21 #include <stdlib.h> 3.22 #else 3.23 #include <malloc.h> 3.24 #endif 3.25 3.26 namespace OVR { 3.27 3.28 //----------------------------------------------------------------------------------- 3.29 // ***** Allocator 3.30 3.31 Allocator* Allocator::pInstance = 0; 3.32 3.33 // Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding. 3.34 void* Allocator::AllocAligned(UPInt size, UPInt align) 3.35 { 3.36 OVR_ASSERT((align & (align-1)) == 0); 3.37 align = (align > sizeof(UPInt)) ? align : sizeof(UPInt); 3.38 UPInt p = (UPInt)Alloc(size+align); 3.39 UPInt aligned = 0; 3.40 if (p) 3.41 { 3.42 aligned = (UPInt(p) + align-1) & ~(align-1); 3.43 if (aligned == p) 3.44 aligned += align; 3.45 *(((UPInt*)aligned)-1) = aligned-p; 3.46 } 3.47 return (void*)aligned; 3.48 } 3.49 3.50 void Allocator::FreeAligned(void* p) 3.51 { 3.52 UPInt src = UPInt(p) - *(((UPInt*)p)-1); 3.53 Free((void*)src); 3.54 } 3.55 3.56 3.57 //------------------------------------------------------------------------ 3.58 // ***** Default Allocator 3.59 3.60 // This allocator is created and used if no other allocator is installed. 3.61 // Default allocator delegates to system malloc. 3.62 3.63 void* DefaultAllocator::Alloc(UPInt size) 3.64 { 3.65 return malloc(size); 3.66 } 3.67 void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line) 3.68 { 3.69 #if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC) 3.70 return _malloc_dbg(size, _NORMAL_BLOCK, file, line); 3.71 #else 3.72 OVR_UNUSED2(file, line); 3.73 return malloc(size); 3.74 #endif 3.75 } 3.76 3.77 void* DefaultAllocator::Realloc(void* p, UPInt newSize) 3.78 { 3.79 return realloc(p, newSize); 3.80 } 3.81 void DefaultAllocator::Free(void *p) 3.82 { 3.83 return free(p); 3.84 } 3.85 3.86 3.87 } // OVR 3.88 \ No newline at end of file 3.89 +/************************************************************************************ 3.90 + 3.91 +Filename : OVR_Allocator.cpp 3.92 +Content : Installable memory allocator implementation 3.93 +Created : September 19, 2012 3.94 +Notes : 3.95 + 3.96 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 3.97 + 3.98 +Use of this software is subject to the terms of the Oculus license 3.99 +agreement provided at the time of installation or download, or which 3.100 +otherwise accompanies this software in either electronic or hard copy form. 3.101 + 3.102 +************************************************************************************/ 3.103 + 3.104 +#include "OVR_Allocator.h" 3.105 +#ifdef OVR_OS_MAC 3.106 + #include <stdlib.h> 3.107 +#else 3.108 + #include <malloc.h> 3.109 +#endif 3.110 + 3.111 +namespace OVR { 3.112 + 3.113 +//----------------------------------------------------------------------------------- 3.114 +// ***** Allocator 3.115 + 3.116 +Allocator* Allocator::pInstance = 0; 3.117 + 3.118 +// Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding. 3.119 +void* Allocator::AllocAligned(UPInt size, UPInt align) 3.120 +{ 3.121 + OVR_ASSERT((align & (align-1)) == 0); 3.122 + align = (align > sizeof(UPInt)) ? align : sizeof(UPInt); 3.123 + UPInt p = (UPInt)Alloc(size+align); 3.124 + UPInt aligned = 0; 3.125 + if (p) 3.126 + { 3.127 + aligned = (UPInt(p) + align-1) & ~(align-1); 3.128 + if (aligned == p) 3.129 + aligned += align; 3.130 + *(((UPInt*)aligned)-1) = aligned-p; 3.131 + } 3.132 + return (void*)aligned; 3.133 +} 3.134 + 3.135 +void Allocator::FreeAligned(void* p) 3.136 +{ 3.137 + UPInt src = UPInt(p) - *(((UPInt*)p)-1); 3.138 + Free((void*)src); 3.139 +} 3.140 + 3.141 + 3.142 +//------------------------------------------------------------------------ 3.143 +// ***** Default Allocator 3.144 + 3.145 +// This allocator is created and used if no other allocator is installed. 3.146 +// Default allocator delegates to system malloc. 3.147 + 3.148 +void* DefaultAllocator::Alloc(UPInt size) 3.149 +{ 3.150 + return malloc(size); 3.151 +} 3.152 +void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line) 3.153 +{ 3.154 +#if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC) 3.155 + return _malloc_dbg(size, _NORMAL_BLOCK, file, line); 3.156 +#else 3.157 + OVR_UNUSED2(file, line); 3.158 + return malloc(size); 3.159 +#endif 3.160 +} 3.161 + 3.162 +void* DefaultAllocator::Realloc(void* p, UPInt newSize) 3.163 +{ 3.164 + return realloc(p, newSize); 3.165 +} 3.166 +void DefaultAllocator::Free(void *p) 3.167 +{ 3.168 + return free(p); 3.169 +} 3.170 + 3.171 + 3.172 +} // OVR
4.1 --- a/libovr/Src/Kernel/OVR_Allocator.h Sat Sep 14 17:51:03 2013 +0300 4.2 +++ b/libovr/Src/Kernel/OVR_Allocator.h Sun Sep 15 04:10:05 2013 +0300 4.3 @@ -1,1 +1,336 @@ 4.4 -/************************************************************************************ 4.5 4.6 PublicHeader: OVR.h 4.7 Filename : OVR_Allocator.h 4.8 Content : Installable memory allocator 4.9 Created : September 19, 2012 4.10 Notes : 4.11 4.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 4.13 4.14 Use of this software is subject to the terms of the Oculus license 4.15 agreement provided at the time of installation or download, or which 4.16 otherwise accompanies this software in either electronic or hard copy form. 4.17 4.18 ************************************************************************************/ 4.19 4.20 #ifndef OVR_Allocator_h 4.21 #define OVR_Allocator_h 4.22 4.23 #include "OVR_Types.h" 4.24 4.25 //----------------------------------------------------------------------------------- 4.26 4.27 // ***** Disable template-unfriendly MS VC++ warnings 4.28 #if defined(OVR_CC_MSVC) 4.29 // Pragma to prevent long name warnings in in VC++ 4.30 #pragma warning(disable : 4503) 4.31 #pragma warning(disable : 4786) 4.32 // In MSVC 7.1, warning about placement new POD default initializer 4.33 #pragma warning(disable : 4345) 4.34 #endif 4.35 4.36 // Un-define new so that placement constructors work 4.37 #undef new 4.38 4.39 4.40 //----------------------------------------------------------------------------------- 4.41 // ***** Placement new overrides 4.42 4.43 // Calls constructor on own memory created with "new(ptr) type" 4.44 #ifndef __PLACEMENT_NEW_INLINE 4.45 #define __PLACEMENT_NEW_INLINE 4.46 4.47 # if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU) 4.48 # include <new> 4.49 # else 4.50 // Useful on MSVC 4.51 OVR_FORCE_INLINE void* operator new (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } 4.52 OVR_FORCE_INLINE void operator delete (void *, void *) { } 4.53 # endif 4.54 4.55 #endif // __PLACEMENT_NEW_INLINE 4.56 4.57 4.58 4.59 //------------------------------------------------------------------------ 4.60 // ***** Macros to redefine class new/delete operators 4.61 4.62 // Types specifically declared to allow disambiguation of address in 4.63 // class member operator new. 4.64 4.65 #define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \ 4.66 void* operator new(UPInt sz) \ 4.67 { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \ 4.68 void* operator new(UPInt sz, const char* file, int line) \ 4.69 { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \ 4.70 void operator delete(void *p) \ 4.71 { check_delete(class_name, p); OVR_FREE(p); } \ 4.72 void operator delete(void *p, const char*, int) \ 4.73 { check_delete(class_name, p); OVR_FREE(p); } 4.74 4.75 #define OVR_MEMORY_DEFINE_PLACEMENT_NEW \ 4.76 void* operator new (UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } \ 4.77 void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); } 4.78 4.79 4.80 #define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p) 4.81 4.82 // Redefined all delete/new operators in a class without custom memory initialization 4.83 #define OVR_MEMORY_REDEFINE_NEW(class_name) \ 4.84 OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE) 4.85 4.86 4.87 namespace OVR { 4.88 4.89 //----------------------------------------------------------------------------------- 4.90 // ***** Construct / Destruct 4.91 4.92 // Construct/Destruct functions are useful when new is redefined, as they can 4.93 // be called instead of placement new constructors. 4.94 4.95 4.96 template <class T> 4.97 OVR_FORCE_INLINE T* Construct(void *p) 4.98 { 4.99 return ::new(p) T; 4.100 } 4.101 4.102 template <class T> 4.103 OVR_FORCE_INLINE T* Construct(void *p, const T& source) 4.104 { 4.105 return ::new(p) T(source); 4.106 } 4.107 4.108 // Same as above, but allows for a different type of constructor. 4.109 template <class T, class S> 4.110 OVR_FORCE_INLINE T* ConstructAlt(void *p, const S& source) 4.111 { 4.112 return ::new(p) T(source); 4.113 } 4.114 4.115 template <class T, class S1, class S2> 4.116 OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2) 4.117 { 4.118 return ::new(p) T(src1, src2); 4.119 } 4.120 4.121 template <class T> 4.122 OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count) 4.123 { 4.124 UByte *pdata = (UByte*)p; 4.125 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 4.126 { 4.127 Construct<T>(pdata); 4.128 } 4.129 } 4.130 4.131 template <class T> 4.132 OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source) 4.133 { 4.134 UByte *pdata = (UByte*)p; 4.135 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 4.136 { 4.137 Construct<T>(pdata, source); 4.138 } 4.139 } 4.140 4.141 template <class T> 4.142 OVR_FORCE_INLINE void Destruct(T *pobj) 4.143 { 4.144 pobj->~T(); 4.145 OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning. 4.146 } 4.147 4.148 template <class T> 4.149 OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count) 4.150 { 4.151 for (UPInt i=0; i<count; ++i, ++pobj) 4.152 pobj->~T(); 4.153 } 4.154 4.155 4.156 //----------------------------------------------------------------------------------- 4.157 // ***** Allocator 4.158 4.159 // Allocator defines a memory allocation interface that developers can override 4.160 // to to provide memory for OVR; an instance of this class is typically created on 4.161 // application startup and passed into System or OVR::System constructor. 4.162 // 4.163 // 4.164 // Users implementing this interface must provide three functions: Alloc, Free, 4.165 // and Realloc. Implementations of these functions must honor the requested alignment. 4.166 // Although arbitrary alignment requests are possible, requested alignment will 4.167 // typically be small, such as 16 bytes or less. 4.168 4.169 class Allocator 4.170 { 4.171 friend class System; 4.172 public: 4.173 4.174 // *** Standard Alignment Alloc/Free 4.175 4.176 // Allocate memory of specified size with default alignment. 4.177 // Alloc of size==0 will allocate a tiny block & return a valid pointer; 4.178 // this makes it suitable for new operator. 4.179 virtual void* Alloc(UPInt size) = 0; 4.180 // Same as Alloc, but provides an option of passing debug data. 4.181 virtual void* AllocDebug(UPInt size, const char* file, unsigned line) 4.182 { OVR_UNUSED2(file, line); return Alloc(size); } 4.183 4.184 // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to 4.185 // new memory block, which may be the same as original pointer. Will return 0 if reallocation 4.186 // failed, in which case previous memory is still valid. 4.187 // Realloc to decrease size will never fail. 4.188 // Realloc of pointer == 0 is equivalent to Alloc 4.189 // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free(). 4.190 virtual void* Realloc(void* p, UPInt newSize) = 0; 4.191 4.192 // Frees memory allocated by Alloc/Realloc. 4.193 // Free of null pointer is valid and will do nothing. 4.194 virtual void Free(void *p) = 0; 4.195 4.196 4.197 // *** Standard Alignment Alloc/Free 4.198 4.199 // Allocate memory of specified alignment. 4.200 // Memory allocated with AllocAligned MUST be freed with FreeAligned. 4.201 // Default implementation will delegate to Alloc/Free after doing rounding. 4.202 virtual void* AllocAligned(UPInt size, UPInt align); 4.203 // Frees memory allocated with AllocAligned. 4.204 virtual void FreeAligned(void* p); 4.205 4.206 // Returns the pointer to the current globally installed Allocator instance. 4.207 // This pointer is used for most of the memory allocations. 4.208 static Allocator* GetInstance() { return pInstance; } 4.209 4.210 4.211 protected: 4.212 // onSystemShutdown is called on the allocator during System::Shutdown. 4.213 // At this point, all allocations should've been freed. 4.214 virtual void onSystemShutdown() { } 4.215 4.216 public: 4.217 static void setInstance(Allocator* palloc) 4.218 { 4.219 OVR_ASSERT((pInstance == 0) || (palloc == 0)); 4.220 pInstance = palloc; 4.221 } 4.222 4.223 private: 4.224 4.225 static Allocator* pInstance; 4.226 }; 4.227 4.228 4.229 4.230 //------------------------------------------------------------------------ 4.231 // ***** Allocator_SingletonSupport 4.232 4.233 // Allocator_SingletonSupport is a Allocator wrapper class that implements 4.234 // the InitSystemSingleton static function, used to create a global singleton 4.235 // used for the OVR::System default argument initialization. 4.236 // 4.237 // End users implementing custom Allocator interface don't need to make use of this base 4.238 // class; they can just create an instance of their own class on stack and pass it to System. 4.239 4.240 template<class D> 4.241 class Allocator_SingletonSupport : public Allocator 4.242 { 4.243 struct AllocContainer 4.244 { 4.245 UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)]; 4.246 bool Initialized; 4.247 AllocContainer() : Initialized(0) { } 4.248 }; 4.249 4.250 AllocContainer* pContainer; 4.251 4.252 public: 4.253 Allocator_SingletonSupport() : pContainer(0) { } 4.254 4.255 // Creates a singleton instance of this Allocator class used 4.256 // on OVR_DEFAULT_ALLOCATOR during System initialization. 4.257 static D* InitSystemSingleton() 4.258 { 4.259 static AllocContainer Container; 4.260 OVR_ASSERT(Container.Initialized == false); 4.261 4.262 Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data); 4.263 presult->pContainer = &Container; 4.264 Container.Initialized = true; 4.265 return (D*)presult; 4.266 } 4.267 4.268 protected: 4.269 virtual void onSystemShutdown() 4.270 { 4.271 Allocator::onSystemShutdown(); 4.272 if (pContainer) 4.273 { 4.274 pContainer->Initialized = false; 4.275 Destruct((D*)this); 4.276 pContainer = 0; 4.277 } 4.278 } 4.279 }; 4.280 4.281 //------------------------------------------------------------------------ 4.282 // ***** Default Allocator 4.283 4.284 // This allocator is created and used if no other allocator is installed. 4.285 // Default allocator delegates to system malloc. 4.286 4.287 class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator> 4.288 { 4.289 public: 4.290 virtual void* Alloc(UPInt size); 4.291 virtual void* AllocDebug(UPInt size, const char* file, unsigned line); 4.292 virtual void* Realloc(void* p, UPInt newSize); 4.293 virtual void Free(void *p); 4.294 }; 4.295 4.296 4.297 //------------------------------------------------------------------------ 4.298 // ***** Memory Allocation Macros 4.299 4.300 // These macros should be used for global allocation. In the future, these 4.301 // macros will allows allocation to be extended with debug file/line information 4.302 // if necessary. 4.303 4.304 #define OVR_REALLOC(p,s) OVR::Allocator::GetInstance()->Realloc((p),(s)) 4.305 #define OVR_FREE(p) OVR::Allocator::GetInstance()->Free((p)) 4.306 #define OVR_ALLOC_ALIGNED(s,a) OVR::Allocator::GetInstance()->AllocAligned((s),(a)) 4.307 #define OVR_FREE_ALIGNED(p) OVR::Allocator::GetInstance()->FreeAligned((p)) 4.308 4.309 #ifdef OVR_BUILD_DEBUG 4.310 #define OVR_ALLOC(s) OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__) 4.311 #define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->AllocDebug((s), f, l) 4.312 #else 4.313 #define OVR_ALLOC(s) OVR::Allocator::GetInstance()->Alloc((s)) 4.314 #define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->Alloc((s)) 4.315 #endif 4.316 4.317 //------------------------------------------------------------------------ 4.318 4.319 // Base class that overrides the new and delete operators. 4.320 // Deriving from this class, even as a multiple base, incurs no space overhead. 4.321 class NewOverrideBase 4.322 { 4.323 public: 4.324 4.325 // Redefine all new & delete operators. 4.326 OVR_MEMORY_REDEFINE_NEW(NewOverrideBase) 4.327 }; 4.328 4.329 4.330 } // OVR 4.331 4.332 4.333 // Redefine operator 'new' if necessary. 4.334 #if defined(OVR_DEFINE_NEW) 4.335 #define new OVR_DEFINE_NEW 4.336 #endif 4.337 4.338 4.339 #endif // OVR_Memory 4.340 \ No newline at end of file 4.341 +/************************************************************************************ 4.342 + 4.343 +PublicHeader: OVR.h 4.344 +Filename : OVR_Allocator.h 4.345 +Content : Installable memory allocator 4.346 +Created : September 19, 2012 4.347 +Notes : 4.348 + 4.349 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 4.350 + 4.351 +Use of this software is subject to the terms of the Oculus license 4.352 +agreement provided at the time of installation or download, or which 4.353 +otherwise accompanies this software in either electronic or hard copy form. 4.354 + 4.355 +************************************************************************************/ 4.356 + 4.357 +#ifndef OVR_Allocator_h 4.358 +#define OVR_Allocator_h 4.359 + 4.360 +#include "OVR_Types.h" 4.361 + 4.362 +//----------------------------------------------------------------------------------- 4.363 + 4.364 +// ***** Disable template-unfriendly MS VC++ warnings 4.365 +#if defined(OVR_CC_MSVC) 4.366 +// Pragma to prevent long name warnings in in VC++ 4.367 +#pragma warning(disable : 4503) 4.368 +#pragma warning(disable : 4786) 4.369 +// In MSVC 7.1, warning about placement new POD default initializer 4.370 +#pragma warning(disable : 4345) 4.371 +#endif 4.372 + 4.373 +// Un-define new so that placement constructors work 4.374 +#undef new 4.375 + 4.376 + 4.377 +//----------------------------------------------------------------------------------- 4.378 +// ***** Placement new overrides 4.379 + 4.380 +// Calls constructor on own memory created with "new(ptr) type" 4.381 +#ifndef __PLACEMENT_NEW_INLINE 4.382 +#define __PLACEMENT_NEW_INLINE 4.383 + 4.384 +# if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU) 4.385 +# include <new> 4.386 +# else 4.387 + // Useful on MSVC 4.388 + OVR_FORCE_INLINE void* operator new (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } 4.389 + OVR_FORCE_INLINE void operator delete (void *, void *) { } 4.390 +# endif 4.391 + 4.392 +#endif // __PLACEMENT_NEW_INLINE 4.393 + 4.394 + 4.395 + 4.396 +//------------------------------------------------------------------------ 4.397 +// ***** Macros to redefine class new/delete operators 4.398 + 4.399 +// Types specifically declared to allow disambiguation of address in 4.400 +// class member operator new. 4.401 + 4.402 +#define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete) \ 4.403 + void* operator new(UPInt sz) \ 4.404 + { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; } \ 4.405 + void* operator new(UPInt sz, const char* file, int line) \ 4.406 + { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; } \ 4.407 + void operator delete(void *p) \ 4.408 + { check_delete(class_name, p); OVR_FREE(p); } \ 4.409 + void operator delete(void *p, const char*, int) \ 4.410 + { check_delete(class_name, p); OVR_FREE(p); } 4.411 + 4.412 +#define OVR_MEMORY_DEFINE_PLACEMENT_NEW \ 4.413 + void* operator new (UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; } \ 4.414 + void operator delete (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); } 4.415 + 4.416 + 4.417 +#define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p) 4.418 + 4.419 +// Redefined all delete/new operators in a class without custom memory initialization 4.420 +#define OVR_MEMORY_REDEFINE_NEW(class_name) \ 4.421 + OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE) 4.422 + 4.423 + 4.424 +namespace OVR { 4.425 + 4.426 +//----------------------------------------------------------------------------------- 4.427 +// ***** Construct / Destruct 4.428 + 4.429 +// Construct/Destruct functions are useful when new is redefined, as they can 4.430 +// be called instead of placement new constructors. 4.431 + 4.432 + 4.433 +template <class T> 4.434 +OVR_FORCE_INLINE T* Construct(void *p) 4.435 +{ 4.436 + return ::new(p) T; 4.437 +} 4.438 + 4.439 +template <class T> 4.440 +OVR_FORCE_INLINE T* Construct(void *p, const T& source) 4.441 +{ 4.442 + return ::new(p) T(source); 4.443 +} 4.444 + 4.445 +// Same as above, but allows for a different type of constructor. 4.446 +template <class T, class S> 4.447 +OVR_FORCE_INLINE T* ConstructAlt(void *p, const S& source) 4.448 +{ 4.449 + return ::new(p) T(source); 4.450 +} 4.451 + 4.452 +template <class T, class S1, class S2> 4.453 +OVR_FORCE_INLINE T* ConstructAlt(void *p, const S1& src1, const S2& src2) 4.454 +{ 4.455 + return ::new(p) T(src1, src2); 4.456 +} 4.457 + 4.458 +template <class T> 4.459 +OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count) 4.460 +{ 4.461 + UByte *pdata = (UByte*)p; 4.462 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 4.463 + { 4.464 + Construct<T>(pdata); 4.465 + } 4.466 +} 4.467 + 4.468 +template <class T> 4.469 +OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source) 4.470 +{ 4.471 + UByte *pdata = (UByte*)p; 4.472 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 4.473 + { 4.474 + Construct<T>(pdata, source); 4.475 + } 4.476 +} 4.477 + 4.478 +template <class T> 4.479 +OVR_FORCE_INLINE void Destruct(T *pobj) 4.480 +{ 4.481 + pobj->~T(); 4.482 + OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning. 4.483 +} 4.484 + 4.485 +template <class T> 4.486 +OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count) 4.487 +{ 4.488 + for (UPInt i=0; i<count; ++i, ++pobj) 4.489 + pobj->~T(); 4.490 +} 4.491 + 4.492 + 4.493 +//----------------------------------------------------------------------------------- 4.494 +// ***** Allocator 4.495 + 4.496 +// Allocator defines a memory allocation interface that developers can override 4.497 +// to to provide memory for OVR; an instance of this class is typically created on 4.498 +// application startup and passed into System or OVR::System constructor. 4.499 +// 4.500 +// 4.501 +// Users implementing this interface must provide three functions: Alloc, Free, 4.502 +// and Realloc. Implementations of these functions must honor the requested alignment. 4.503 +// Although arbitrary alignment requests are possible, requested alignment will 4.504 +// typically be small, such as 16 bytes or less. 4.505 + 4.506 +class Allocator 4.507 +{ 4.508 + friend class System; 4.509 +public: 4.510 + 4.511 + // *** Standard Alignment Alloc/Free 4.512 + 4.513 + // Allocate memory of specified size with default alignment. 4.514 + // Alloc of size==0 will allocate a tiny block & return a valid pointer; 4.515 + // this makes it suitable for new operator. 4.516 + virtual void* Alloc(UPInt size) = 0; 4.517 + // Same as Alloc, but provides an option of passing debug data. 4.518 + virtual void* AllocDebug(UPInt size, const char* file, unsigned line) 4.519 + { OVR_UNUSED2(file, line); return Alloc(size); } 4.520 + 4.521 + // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to 4.522 + // new memory block, which may be the same as original pointer. Will return 0 if reallocation 4.523 + // failed, in which case previous memory is still valid. 4.524 + // Realloc to decrease size will never fail. 4.525 + // Realloc of pointer == 0 is equivalent to Alloc 4.526 + // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free(). 4.527 + virtual void* Realloc(void* p, UPInt newSize) = 0; 4.528 + 4.529 + // Frees memory allocated by Alloc/Realloc. 4.530 + // Free of null pointer is valid and will do nothing. 4.531 + virtual void Free(void *p) = 0; 4.532 + 4.533 + 4.534 + // *** Standard Alignment Alloc/Free 4.535 + 4.536 + // Allocate memory of specified alignment. 4.537 + // Memory allocated with AllocAligned MUST be freed with FreeAligned. 4.538 + // Default implementation will delegate to Alloc/Free after doing rounding. 4.539 + virtual void* AllocAligned(UPInt size, UPInt align); 4.540 + // Frees memory allocated with AllocAligned. 4.541 + virtual void FreeAligned(void* p); 4.542 + 4.543 + // Returns the pointer to the current globally installed Allocator instance. 4.544 + // This pointer is used for most of the memory allocations. 4.545 + static Allocator* GetInstance() { return pInstance; } 4.546 + 4.547 + 4.548 +protected: 4.549 + // onSystemShutdown is called on the allocator during System::Shutdown. 4.550 + // At this point, all allocations should've been freed. 4.551 + virtual void onSystemShutdown() { } 4.552 + 4.553 +public: 4.554 + static void setInstance(Allocator* palloc) 4.555 + { 4.556 + OVR_ASSERT((pInstance == 0) || (palloc == 0)); 4.557 + pInstance = palloc; 4.558 + } 4.559 + 4.560 +private: 4.561 + 4.562 + static Allocator* pInstance; 4.563 +}; 4.564 + 4.565 + 4.566 + 4.567 +//------------------------------------------------------------------------ 4.568 +// ***** Allocator_SingletonSupport 4.569 + 4.570 +// Allocator_SingletonSupport is a Allocator wrapper class that implements 4.571 +// the InitSystemSingleton static function, used to create a global singleton 4.572 +// used for the OVR::System default argument initialization. 4.573 +// 4.574 +// End users implementing custom Allocator interface don't need to make use of this base 4.575 +// class; they can just create an instance of their own class on stack and pass it to System. 4.576 + 4.577 +template<class D> 4.578 +class Allocator_SingletonSupport : public Allocator 4.579 +{ 4.580 + struct AllocContainer 4.581 + { 4.582 + UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)]; 4.583 + bool Initialized; 4.584 + AllocContainer() : Initialized(0) { } 4.585 + }; 4.586 + 4.587 + AllocContainer* pContainer; 4.588 + 4.589 +public: 4.590 + Allocator_SingletonSupport() : pContainer(0) { } 4.591 + 4.592 + // Creates a singleton instance of this Allocator class used 4.593 + // on OVR_DEFAULT_ALLOCATOR during System initialization. 4.594 + static D* InitSystemSingleton() 4.595 + { 4.596 + static AllocContainer Container; 4.597 + OVR_ASSERT(Container.Initialized == false); 4.598 + 4.599 + Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data); 4.600 + presult->pContainer = &Container; 4.601 + Container.Initialized = true; 4.602 + return (D*)presult; 4.603 + } 4.604 + 4.605 +protected: 4.606 + virtual void onSystemShutdown() 4.607 + { 4.608 + Allocator::onSystemShutdown(); 4.609 + if (pContainer) 4.610 + { 4.611 + pContainer->Initialized = false; 4.612 + Destruct((D*)this); 4.613 + pContainer = 0; 4.614 + } 4.615 + } 4.616 +}; 4.617 + 4.618 +//------------------------------------------------------------------------ 4.619 +// ***** Default Allocator 4.620 + 4.621 +// This allocator is created and used if no other allocator is installed. 4.622 +// Default allocator delegates to system malloc. 4.623 + 4.624 +class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator> 4.625 +{ 4.626 +public: 4.627 + virtual void* Alloc(UPInt size); 4.628 + virtual void* AllocDebug(UPInt size, const char* file, unsigned line); 4.629 + virtual void* Realloc(void* p, UPInt newSize); 4.630 + virtual void Free(void *p); 4.631 +}; 4.632 + 4.633 + 4.634 +//------------------------------------------------------------------------ 4.635 +// ***** Memory Allocation Macros 4.636 + 4.637 +// These macros should be used for global allocation. In the future, these 4.638 +// macros will allows allocation to be extended with debug file/line information 4.639 +// if necessary. 4.640 + 4.641 +#define OVR_REALLOC(p,s) OVR::Allocator::GetInstance()->Realloc((p),(s)) 4.642 +#define OVR_FREE(p) OVR::Allocator::GetInstance()->Free((p)) 4.643 +#define OVR_ALLOC_ALIGNED(s,a) OVR::Allocator::GetInstance()->AllocAligned((s),(a)) 4.644 +#define OVR_FREE_ALIGNED(p) OVR::Allocator::GetInstance()->FreeAligned((p)) 4.645 + 4.646 +#ifdef OVR_BUILD_DEBUG 4.647 +#define OVR_ALLOC(s) OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__) 4.648 +#define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->AllocDebug((s), f, l) 4.649 +#else 4.650 +#define OVR_ALLOC(s) OVR::Allocator::GetInstance()->Alloc((s)) 4.651 +#define OVR_ALLOC_DEBUG(s,f,l) OVR::Allocator::GetInstance()->Alloc((s)) 4.652 +#endif 4.653 + 4.654 +//------------------------------------------------------------------------ 4.655 + 4.656 +// Base class that overrides the new and delete operators. 4.657 +// Deriving from this class, even as a multiple base, incurs no space overhead. 4.658 +class NewOverrideBase 4.659 +{ 4.660 +public: 4.661 + 4.662 + // Redefine all new & delete operators. 4.663 + OVR_MEMORY_REDEFINE_NEW(NewOverrideBase) 4.664 +}; 4.665 + 4.666 + 4.667 +} // OVR 4.668 + 4.669 + 4.670 +// Redefine operator 'new' if necessary. 4.671 +#if defined(OVR_DEFINE_NEW) 4.672 +#define new OVR_DEFINE_NEW 4.673 +#endif 4.674 + 4.675 + 4.676 +#endif // OVR_Memory
5.1 --- a/libovr/Src/Kernel/OVR_Array.h Sat Sep 14 17:51:03 2013 +0300 5.2 +++ b/libovr/Src/Kernel/OVR_Array.h Sun Sep 15 04:10:05 2013 +0300 5.3 @@ -1,1 +1,793 @@ 5.4 -/************************************************************************************ 5.5 5.6 PublicHeader: OVR.h 5.7 Filename : OVR_Array.h 5.8 Content : Template implementation for Array 5.9 Created : September 19, 2012 5.10 Notes : 5.11 5.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 5.13 5.14 Use of this software is subject to the terms of the Oculus license 5.15 agreement provided at the time of installation or download, or which 5.16 otherwise accompanies this software in either electronic or hard copy form. 5.17 5.18 ************************************************************************************/ 5.19 5.20 #ifndef OVR_Array_h 5.21 #define OVR_Array_h 5.22 5.23 #include "OVR_ContainerAllocator.h" 5.24 5.25 namespace OVR { 5.26 5.27 //----------------------------------------------------------------------------------- 5.28 // ***** ArrayDefaultPolicy 5.29 // 5.30 // Default resize behavior. No minimal capacity, Granularity=4, 5.31 // Shrinking as needed. ArrayConstPolicy actually is the same as 5.32 // ArrayDefaultPolicy, but parametrized with constants. 5.33 // This struct is used only in order to reduce the template "matroska". 5.34 struct ArrayDefaultPolicy 5.35 { 5.36 ArrayDefaultPolicy() : Capacity(0) {} 5.37 ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {} 5.38 5.39 UPInt GetMinCapacity() const { return 0; } 5.40 UPInt GetGranularity() const { return 4; } 5.41 bool NeverShrinking() const { return 0; } 5.42 5.43 UPInt GetCapacity() const { return Capacity; } 5.44 void SetCapacity(UPInt capacity) { Capacity = capacity; } 5.45 private: 5.46 UPInt Capacity; 5.47 }; 5.48 5.49 5.50 //----------------------------------------------------------------------------------- 5.51 // ***** ArrayConstPolicy 5.52 // 5.53 // Statically parametrized resizing behavior: 5.54 // MinCapacity, Granularity, and Shrinking flag. 5.55 template<int MinCapacity=0, int Granularity=4, bool NeverShrink=false> 5.56 struct ArrayConstPolicy 5.57 { 5.58 typedef ArrayConstPolicy<MinCapacity, Granularity, NeverShrink> SelfType; 5.59 5.60 ArrayConstPolicy() : Capacity(0) {} 5.61 ArrayConstPolicy(const SelfType&) : Capacity(0) {} 5.62 5.63 UPInt GetMinCapacity() const { return MinCapacity; } 5.64 UPInt GetGranularity() const { return Granularity; } 5.65 bool NeverShrinking() const { return NeverShrink; } 5.66 5.67 UPInt GetCapacity() const { return Capacity; } 5.68 void SetCapacity(UPInt capacity) { Capacity = capacity; } 5.69 private: 5.70 UPInt Capacity; 5.71 }; 5.72 5.73 //----------------------------------------------------------------------------------- 5.74 // ***** ArrayDataBase 5.75 // 5.76 // Basic operations with array data: Reserve, Resize, Free, ArrayPolicy. 5.77 // For internal use only: ArrayData,ArrayDataCC and others. 5.78 template<class T, class Allocator, class SizePolicy> 5.79 struct ArrayDataBase 5.80 { 5.81 typedef T ValueType; 5.82 typedef Allocator AllocatorType; 5.83 typedef SizePolicy SizePolicyType; 5.84 typedef ArrayDataBase<T, Allocator, SizePolicy> SelfType; 5.85 5.86 ArrayDataBase() 5.87 : Data(0), Size(0), Policy() {} 5.88 5.89 ArrayDataBase(const SizePolicy& p) 5.90 : Data(0), Size(0), Policy(p) {} 5.91 5.92 ~ArrayDataBase() 5.93 { 5.94 Allocator::DestructArray(Data, Size); 5.95 Allocator::Free(Data); 5.96 } 5.97 5.98 UPInt GetCapacity() const 5.99 { 5.100 return Policy.GetCapacity(); 5.101 } 5.102 5.103 void ClearAndRelease() 5.104 { 5.105 Allocator::DestructArray(Data, Size); 5.106 Allocator::Free(Data); 5.107 Data = 0; 5.108 Size = 0; 5.109 Policy.SetCapacity(0); 5.110 } 5.111 5.112 void Reserve(UPInt newCapacity) 5.113 { 5.114 if (Policy.NeverShrinking() && newCapacity < GetCapacity()) 5.115 return; 5.116 5.117 if (newCapacity < Policy.GetMinCapacity()) 5.118 newCapacity = Policy.GetMinCapacity(); 5.119 5.120 // Resize the buffer. 5.121 if (newCapacity == 0) 5.122 { 5.123 if (Data) 5.124 { 5.125 Allocator::Free(Data); 5.126 Data = 0; 5.127 } 5.128 Policy.SetCapacity(0); 5.129 } 5.130 else 5.131 { 5.132 UPInt gran = Policy.GetGranularity(); 5.133 newCapacity = (newCapacity + gran - 1) / gran * gran; 5.134 if (Data) 5.135 { 5.136 if (Allocator::IsMovable()) 5.137 { 5.138 Data = (T*)Allocator::Realloc(Data, sizeof(T) * newCapacity); 5.139 } 5.140 else 5.141 { 5.142 T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity); 5.143 UPInt i, s; 5.144 s = (Size < newCapacity) ? Size : newCapacity; 5.145 for (i = 0; i < s; ++i) 5.146 { 5.147 Allocator::Construct(&newData[i], Data[i]); 5.148 Allocator::Destruct(&Data[i]); 5.149 } 5.150 for (i = s; i < Size; ++i) 5.151 { 5.152 Allocator::Destruct(&Data[i]); 5.153 } 5.154 Allocator::Free(Data); 5.155 Data = newData; 5.156 } 5.157 } 5.158 else 5.159 { 5.160 Data = (T*)Allocator::Alloc(sizeof(T) * newCapacity); 5.161 //memset(Buffer, 0, (sizeof(ValueType) * newSize)); // Do we need this? 5.162 } 5.163 Policy.SetCapacity(newCapacity); 5.164 // OVR_ASSERT(Data); // need to throw (or something) on alloc failure! 5.165 } 5.166 } 5.167 5.168 // This version of Resize DOES NOT construct the elements. 5.169 // It's done to optimize PushBack, which uses a copy constructor 5.170 // instead of the default constructor and assignment 5.171 void ResizeNoConstruct(UPInt newSize) 5.172 { 5.173 UPInt oldSize = Size; 5.174 5.175 if (newSize < oldSize) 5.176 { 5.177 Allocator::DestructArray(Data + newSize, oldSize - newSize); 5.178 if (newSize < (Policy.GetCapacity() >> 1)) 5.179 { 5.180 Reserve(newSize); 5.181 } 5.182 } 5.183 else if(newSize >= Policy.GetCapacity()) 5.184 { 5.185 Reserve(newSize + (newSize >> 2)); 5.186 } 5.187 //! IMPORTANT to modify Size only after Reserve completes, because garbage collectable 5.188 // array may use this array and may traverse it during Reserve (in the case, if 5.189 // collection occurs because of heap limit exceeded). 5.190 Size = newSize; 5.191 } 5.192 5.193 ValueType* Data; 5.194 UPInt Size; 5.195 SizePolicy Policy; 5.196 }; 5.197 5.198 5.199 5.200 //----------------------------------------------------------------------------------- 5.201 // ***** ArrayData 5.202 // 5.203 // General purpose array data. 5.204 // For internal use only in Array, ArrayLH, ArrayPOD and so on. 5.205 template<class T, class Allocator, class SizePolicy> 5.206 struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> 5.207 { 5.208 typedef T ValueType; 5.209 typedef Allocator AllocatorType; 5.210 typedef SizePolicy SizePolicyType; 5.211 typedef ArrayDataBase<T, Allocator, SizePolicy> BaseType; 5.212 typedef ArrayData <T, Allocator, SizePolicy> SelfType; 5.213 5.214 ArrayData() 5.215 : BaseType() { } 5.216 5.217 ArrayData(int size) 5.218 : BaseType() { Resize(size); } 5.219 5.220 ArrayData(const SelfType& a) 5.221 : BaseType(a.Policy) { Append(a.Data, a.Size); } 5.222 5.223 5.224 void Resize(UPInt newSize) 5.225 { 5.226 UPInt oldSize = this->Size; 5.227 BaseType::ResizeNoConstruct(newSize); 5.228 if(newSize > oldSize) 5.229 Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize); 5.230 } 5.231 5.232 void PushBack(const ValueType& val) 5.233 { 5.234 BaseType::ResizeNoConstruct(this->Size + 1); 5.235 Allocator::Construct(this->Data + this->Size - 1, val); 5.236 } 5.237 5.238 template<class S> 5.239 void PushBackAlt(const S& val) 5.240 { 5.241 BaseType::ResizeNoConstruct(this->Size + 1); 5.242 Allocator::ConstructAlt(this->Data + this->Size - 1, val); 5.243 } 5.244 5.245 // Append the given data to the array. 5.246 void Append(const ValueType other[], UPInt count) 5.247 { 5.248 if (count) 5.249 { 5.250 UPInt oldSize = this->Size; 5.251 BaseType::ResizeNoConstruct(this->Size + count); 5.252 Allocator::ConstructArray(this->Data + oldSize, count, other); 5.253 } 5.254 } 5.255 }; 5.256 5.257 5.258 5.259 //----------------------------------------------------------------------------------- 5.260 // ***** ArrayDataCC 5.261 // 5.262 // A modification of ArrayData that always copy-constructs new elements 5.263 // using a specified DefaultValue. For internal use only in ArrayCC. 5.264 template<class T, class Allocator, class SizePolicy> 5.265 struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> 5.266 { 5.267 typedef T ValueType; 5.268 typedef Allocator AllocatorType; 5.269 typedef SizePolicy SizePolicyType; 5.270 typedef ArrayDataBase<T, Allocator, SizePolicy> BaseType; 5.271 typedef ArrayDataCC <T, Allocator, SizePolicy> SelfType; 5.272 5.273 ArrayDataCC(const ValueType& defval) 5.274 : BaseType(), DefaultValue(defval) { } 5.275 5.276 ArrayDataCC(const ValueType& defval, int size) 5.277 : BaseType(), DefaultValue(defval) { Resize(size); } 5.278 5.279 ArrayDataCC(const SelfType& a) 5.280 : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); } 5.281 5.282 5.283 void Resize(UPInt newSize) 5.284 { 5.285 UPInt oldSize = this->Size; 5.286 BaseType::ResizeNoConstruct(newSize); 5.287 if(newSize > oldSize) 5.288 Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue); 5.289 } 5.290 5.291 void PushBack(const ValueType& val) 5.292 { 5.293 BaseType::ResizeNoConstruct(this->Size + 1); 5.294 Allocator::Construct(this->Data + this->Size - 1, val); 5.295 } 5.296 5.297 template<class S> 5.298 void PushBackAlt(const S& val) 5.299 { 5.300 BaseType::ResizeNoConstruct(this->Size + 1); 5.301 Allocator::ConstructAlt(this->Data + this->Size - 1, val); 5.302 } 5.303 5.304 // Append the given data to the array. 5.305 void Append(const ValueType other[], UPInt count) 5.306 { 5.307 if (count) 5.308 { 5.309 UPInt oldSize = this->Size; 5.310 BaseType::ResizeNoConstruct(this->Size + count); 5.311 Allocator::ConstructArray(this->Data + oldSize, count, other); 5.312 } 5.313 } 5.314 5.315 ValueType DefaultValue; 5.316 }; 5.317 5.318 5.319 5.320 5.321 5.322 //----------------------------------------------------------------------------------- 5.323 // ***** ArrayBase 5.324 // 5.325 // Resizable array. The behavior can be POD (suffix _POD) and 5.326 // Movable (no suffix) depending on the allocator policy. 5.327 // In case of _POD the constructors and destructors are not called. 5.328 // 5.329 // Arrays can't handle non-movable objects! Don't put anything in here 5.330 // that can't be moved around by bitwise copy. 5.331 // 5.332 // The addresses of elements are not persistent! Don't keep the address 5.333 // of an element; the array contents will move around as it gets resized. 5.334 template<class ArrayData> 5.335 class ArrayBase 5.336 { 5.337 public: 5.338 typedef typename ArrayData::ValueType ValueType; 5.339 typedef typename ArrayData::AllocatorType AllocatorType; 5.340 typedef typename ArrayData::SizePolicyType SizePolicyType; 5.341 typedef ArrayBase<ArrayData> SelfType; 5.342 5.343 5.344 #undef new 5.345 OVR_MEMORY_REDEFINE_NEW(ArrayBase) 5.346 // Redefine operator 'new' if necessary. 5.347 #if defined(OVR_DEFINE_NEW) 5.348 #define new OVR_DEFINE_NEW 5.349 #endif 5.350 5.351 5.352 ArrayBase() 5.353 : Data() {} 5.354 ArrayBase(int size) 5.355 : Data(size) {} 5.356 ArrayBase(const SelfType& a) 5.357 : Data(a.Data) {} 5.358 5.359 ArrayBase(const ValueType& defval) 5.360 : Data(defval) {} 5.361 ArrayBase(const ValueType& defval, int size) 5.362 : Data(defval, size) {} 5.363 5.364 SizePolicyType* GetSizePolicy() const { return Data.Policy; } 5.365 void SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; } 5.366 5.367 bool NeverShrinking()const { return Data.Policy.NeverShrinking(); } 5.368 UPInt GetSize() const { return Data.Size; } 5.369 bool IsEmpty() const { return Data.Size == 0; } 5.370 UPInt GetCapacity() const { return Data.GetCapacity(); } 5.371 UPInt GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } 5.372 5.373 void ClearAndRelease() { Data.ClearAndRelease(); } 5.374 void Clear() { Data.Resize(0); } 5.375 void Resize(UPInt newSize) { Data.Resize(newSize); } 5.376 5.377 // Reserve can only increase the capacity 5.378 void Reserve(UPInt newCapacity) 5.379 { 5.380 if (newCapacity > Data.GetCapacity()) 5.381 Data.Reserve(newCapacity); 5.382 } 5.383 5.384 // Basic access. 5.385 ValueType& At(UPInt index) 5.386 { 5.387 OVR_ASSERT(index < Data.Size); 5.388 return Data.Data[index]; 5.389 } 5.390 const ValueType& At(UPInt index) const 5.391 { 5.392 OVR_ASSERT(index < Data.Size); 5.393 return Data.Data[index]; 5.394 } 5.395 5.396 ValueType ValueAt(UPInt index) const 5.397 { 5.398 OVR_ASSERT(index < Data.Size); 5.399 return Data.Data[index]; 5.400 } 5.401 5.402 // Basic access. 5.403 ValueType& operator [] (UPInt index) 5.404 { 5.405 OVR_ASSERT(index < Data.Size); 5.406 return Data.Data[index]; 5.407 } 5.408 const ValueType& operator [] (UPInt index) const 5.409 { 5.410 OVR_ASSERT(index < Data.Size); 5.411 return Data.Data[index]; 5.412 } 5.413 5.414 // Raw pointer to the data. Use with caution! 5.415 const ValueType* GetDataPtr() const { return Data.Data; } 5.416 ValueType* GetDataPtr() { return Data.Data; } 5.417 5.418 // Insert the given element at the end of the array. 5.419 void PushBack(const ValueType& val) 5.420 { 5.421 // DO NOT pass elements of your own vector into 5.422 // push_back()! Since we're using references, 5.423 // resize() may munge the element storage! 5.424 // OVR_ASSERT(&val < &Buffer[0] || &val > &Buffer[BufferSize]); 5.425 Data.PushBack(val); 5.426 } 5.427 5.428 template<class S> 5.429 void PushBackAlt(const S& val) 5.430 { 5.431 Data.PushBackAlt(val); 5.432 } 5.433 5.434 // Remove the last element. 5.435 void PopBack(UPInt count = 1) 5.436 { 5.437 OVR_ASSERT(Data.Size >= count); 5.438 Data.Resize(Data.Size - count); 5.439 } 5.440 5.441 ValueType& PushDefault() 5.442 { 5.443 Data.PushBack(ValueType()); 5.444 return Back(); 5.445 } 5.446 5.447 ValueType Pop() 5.448 { 5.449 ValueType t = Back(); 5.450 PopBack(); 5.451 return t; 5.452 } 5.453 5.454 5.455 // Access the first element. 5.456 ValueType& Front() { return At(0); } 5.457 const ValueType& Front() const { return At(0); } 5.458 5.459 // Access the last element. 5.460 ValueType& Back() { return At(Data.Size - 1); } 5.461 const ValueType& Back() const { return At(Data.Size - 1); } 5.462 5.463 // Array copy. Copies the contents of a into this array. 5.464 const SelfType& operator = (const SelfType& a) 5.465 { 5.466 Resize(a.GetSize()); 5.467 for (UPInt i = 0; i < Data.Size; i++) { 5.468 *(Data.Data + i) = a[i]; 5.469 } 5.470 return *this; 5.471 } 5.472 5.473 // Removing multiple elements from the array. 5.474 void RemoveMultipleAt(UPInt index, UPInt num) 5.475 { 5.476 OVR_ASSERT(index + num <= Data.Size); 5.477 if (Data.Size == num) 5.478 { 5.479 Clear(); 5.480 } 5.481 else 5.482 { 5.483 AllocatorType::DestructArray(Data.Data + index, num); 5.484 AllocatorType::CopyArrayForward( 5.485 Data.Data + index, 5.486 Data.Data + index + num, 5.487 Data.Size - num - index); 5.488 Data.Size -= num; 5.489 } 5.490 } 5.491 5.492 // Removing an element from the array is an expensive operation! 5.493 // It compacts only after removing the last element. 5.494 void RemoveAt(UPInt index) 5.495 { 5.496 OVR_ASSERT(index < Data.Size); 5.497 if (Data.Size == 1) 5.498 { 5.499 Clear(); 5.500 } 5.501 else 5.502 { 5.503 AllocatorType::Destruct(Data.Data + index); 5.504 AllocatorType::CopyArrayForward( 5.505 Data.Data + index, 5.506 Data.Data + index + 1, 5.507 Data.Size - 1 - index); 5.508 --Data.Size; 5.509 } 5.510 } 5.511 5.512 // Insert the given object at the given index shifting all the elements up. 5.513 void InsertAt(UPInt index, const ValueType& val = ValueType()) 5.514 { 5.515 OVR_ASSERT(index <= Data.Size); 5.516 5.517 Data.Resize(Data.Size + 1); 5.518 if (index < Data.Size - 1) 5.519 { 5.520 AllocatorType::CopyArrayBackward( 5.521 Data.Data + index + 1, 5.522 Data.Data + index, 5.523 Data.Size - 1 - index); 5.524 } 5.525 AllocatorType::Construct(Data.Data + index, val); 5.526 } 5.527 5.528 // Insert the given object at the given index shifting all the elements up. 5.529 void InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType()) 5.530 { 5.531 OVR_ASSERT(index <= Data.Size); 5.532 5.533 Data.Resize(Data.Size + num); 5.534 if (index < Data.Size - num) 5.535 { 5.536 AllocatorType::CopyArrayBackward( 5.537 Data.Data + index + num, 5.538 Data.Data + index, 5.539 Data.Size - num - index); 5.540 } 5.541 for (UPInt i = 0; i < num; ++i) 5.542 AllocatorType::Construct(Data.Data + index + i, val); 5.543 } 5.544 5.545 // Append the given data to the array. 5.546 void Append(const SelfType& other) 5.547 { 5.548 Append(other.Data.Data, other.GetSize()); 5.549 } 5.550 5.551 // Append the given data to the array. 5.552 void Append(const ValueType other[], UPInt count) 5.553 { 5.554 Data.Append(other, count); 5.555 } 5.556 5.557 class Iterator 5.558 { 5.559 SelfType* pArray; 5.560 SPInt CurIndex; 5.561 5.562 public: 5.563 Iterator() : pArray(0), CurIndex(-1) {} 5.564 Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} 5.565 5.566 bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } 5.567 bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } 5.568 5.569 Iterator& operator++() 5.570 { 5.571 if (pArray) 5.572 { 5.573 if (CurIndex < (SPInt)pArray->GetSize()) 5.574 ++CurIndex; 5.575 } 5.576 return *this; 5.577 } 5.578 Iterator operator++(int) 5.579 { 5.580 Iterator it(*this); 5.581 operator++(); 5.582 return it; 5.583 } 5.584 Iterator& operator--() 5.585 { 5.586 if (pArray) 5.587 { 5.588 if (CurIndex >= 0) 5.589 --CurIndex; 5.590 } 5.591 return *this; 5.592 } 5.593 Iterator operator--(int) 5.594 { 5.595 Iterator it(*this); 5.596 operator--(); 5.597 return it; 5.598 } 5.599 Iterator operator+(int delta) const 5.600 { 5.601 return Iterator(pArray, CurIndex + delta); 5.602 } 5.603 Iterator operator-(int delta) const 5.604 { 5.605 return Iterator(pArray, CurIndex - delta); 5.606 } 5.607 SPInt operator-(const Iterator& right) const 5.608 { 5.609 OVR_ASSERT(pArray == right.pArray); 5.610 return CurIndex - right.CurIndex; 5.611 } 5.612 ValueType& operator*() const { OVR_ASSERT(pArray); return (*pArray)[CurIndex]; } 5.613 ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.614 ValueType* GetPtr() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.615 5.616 bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } 5.617 5.618 void Remove() 5.619 { 5.620 if (!IsFinished()) 5.621 pArray->RemoveAt(CurIndex); 5.622 } 5.623 5.624 SPInt GetIndex() const { return CurIndex; } 5.625 }; 5.626 5.627 Iterator Begin() { return Iterator(this); } 5.628 Iterator End() { return Iterator(this, (SPInt)GetSize()); } 5.629 Iterator Last() { return Iterator(this, (SPInt)GetSize() - 1); } 5.630 5.631 class ConstIterator 5.632 { 5.633 const SelfType* pArray; 5.634 SPInt CurIndex; 5.635 5.636 public: 5.637 ConstIterator() : pArray(0), CurIndex(-1) {} 5.638 ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} 5.639 5.640 bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } 5.641 bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } 5.642 5.643 ConstIterator& operator++() 5.644 { 5.645 if (pArray) 5.646 { 5.647 if (CurIndex < (int)pArray->GetSize()) 5.648 ++CurIndex; 5.649 } 5.650 return *this; 5.651 } 5.652 ConstIterator operator++(int) 5.653 { 5.654 ConstIterator it(*this); 5.655 operator++(); 5.656 return it; 5.657 } 5.658 ConstIterator& operator--() 5.659 { 5.660 if (pArray) 5.661 { 5.662 if (CurIndex >= 0) 5.663 --CurIndex; 5.664 } 5.665 return *this; 5.666 } 5.667 ConstIterator operator--(int) 5.668 { 5.669 ConstIterator it(*this); 5.670 operator--(); 5.671 return it; 5.672 } 5.673 ConstIterator operator+(int delta) const 5.674 { 5.675 return ConstIterator(pArray, CurIndex + delta); 5.676 } 5.677 ConstIterator operator-(int delta) const 5.678 { 5.679 return ConstIterator(pArray, CurIndex - delta); 5.680 } 5.681 SPInt operator-(const ConstIterator& right) const 5.682 { 5.683 OVR_ASSERT(pArray == right.pArray); 5.684 return CurIndex - right.CurIndex; 5.685 } 5.686 const ValueType& operator*() const { OVR_ASSERT(pArray); return (*pArray)[CurIndex]; } 5.687 const ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.688 const ValueType* GetPtr() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.689 5.690 bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } 5.691 5.692 SPInt GetIndex() const { return CurIndex; } 5.693 }; 5.694 ConstIterator Begin() const { return ConstIterator(this); } 5.695 ConstIterator End() const { return ConstIterator(this, (SPInt)GetSize()); } 5.696 ConstIterator Last() const { return ConstIterator(this, (SPInt)GetSize() - 1); } 5.697 5.698 protected: 5.699 ArrayData Data; 5.700 }; 5.701 5.702 5.703 5.704 //----------------------------------------------------------------------------------- 5.705 // ***** Array 5.706 // 5.707 // General purpose array for movable objects that require explicit 5.708 // construction/destruction. 5.709 template<class T, class SizePolicy=ArrayDefaultPolicy> 5.710 class Array : public ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > 5.711 { 5.712 public: 5.713 typedef T ValueType; 5.714 typedef ContainerAllocator<T> AllocatorType; 5.715 typedef SizePolicy SizePolicyType; 5.716 typedef Array<T, SizePolicy> SelfType; 5.717 typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType; 5.718 5.719 Array() : BaseType() {} 5.720 Array(int size) : BaseType(size) {} 5.721 Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.722 Array(const SelfType& a) : BaseType(a) {} 5.723 const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.724 }; 5.725 5.726 // ***** ArrayPOD 5.727 // 5.728 // General purpose array for movable objects that DOES NOT require 5.729 // construction/destruction. Constructors and destructors are not called! 5.730 // Global heap is in use. 5.731 template<class T, class SizePolicy=ArrayDefaultPolicy> 5.732 class ArrayPOD : public ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > 5.733 { 5.734 public: 5.735 typedef T ValueType; 5.736 typedef ContainerAllocator_POD<T> AllocatorType; 5.737 typedef SizePolicy SizePolicyType; 5.738 typedef ArrayPOD<T, SizePolicy> SelfType; 5.739 typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType; 5.740 5.741 ArrayPOD() : BaseType() {} 5.742 ArrayPOD(int size) : BaseType(size) {} 5.743 ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.744 ArrayPOD(const SelfType& a) : BaseType(a) {} 5.745 const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.746 }; 5.747 5.748 5.749 // ***** ArrayCPP 5.750 // 5.751 // General purpose, fully C++ compliant array. Can be used with non-movable data. 5.752 // Global heap is in use. 5.753 template<class T, class SizePolicy=ArrayDefaultPolicy> 5.754 class ArrayCPP : public ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > 5.755 { 5.756 public: 5.757 typedef T ValueType; 5.758 typedef ContainerAllocator_CPP<T> AllocatorType; 5.759 typedef SizePolicy SizePolicyType; 5.760 typedef ArrayCPP<T, SizePolicy> SelfType; 5.761 typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType; 5.762 5.763 ArrayCPP() : BaseType() {} 5.764 ArrayCPP(int size) : BaseType(size) {} 5.765 ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.766 ArrayCPP(const SelfType& a) : BaseType(a) {} 5.767 const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.768 }; 5.769 5.770 5.771 // ***** ArrayCC 5.772 // 5.773 // A modification of the array that uses the given default value to 5.774 // construct the elements. The constructors and destructors are 5.775 // properly called, the objects must be movable. 5.776 5.777 template<class T, class SizePolicy=ArrayDefaultPolicy> 5.778 class ArrayCC : public ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > 5.779 { 5.780 public: 5.781 typedef T ValueType; 5.782 typedef ContainerAllocator<T> AllocatorType; 5.783 typedef SizePolicy SizePolicyType; 5.784 typedef ArrayCC<T, SizePolicy> SelfType; 5.785 typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > BaseType; 5.786 5.787 ArrayCC(const ValueType& defval) : BaseType(defval) {} 5.788 ArrayCC(const ValueType& defval, int size) : BaseType(defval, size) {} 5.789 ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); } 5.790 ArrayCC(const SelfType& a) : BaseType(a) {} 5.791 const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.792 }; 5.793 5.794 } // OVR 5.795 5.796 #endif 5.797 \ No newline at end of file 5.798 +/************************************************************************************ 5.799 + 5.800 +PublicHeader: OVR.h 5.801 +Filename : OVR_Array.h 5.802 +Content : Template implementation for Array 5.803 +Created : September 19, 2012 5.804 +Notes : 5.805 + 5.806 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 5.807 + 5.808 +Use of this software is subject to the terms of the Oculus license 5.809 +agreement provided at the time of installation or download, or which 5.810 +otherwise accompanies this software in either electronic or hard copy form. 5.811 + 5.812 +************************************************************************************/ 5.813 + 5.814 +#ifndef OVR_Array_h 5.815 +#define OVR_Array_h 5.816 + 5.817 +#include "OVR_ContainerAllocator.h" 5.818 + 5.819 +namespace OVR { 5.820 + 5.821 +//----------------------------------------------------------------------------------- 5.822 +// ***** ArrayDefaultPolicy 5.823 +// 5.824 +// Default resize behavior. No minimal capacity, Granularity=4, 5.825 +// Shrinking as needed. ArrayConstPolicy actually is the same as 5.826 +// ArrayDefaultPolicy, but parametrized with constants. 5.827 +// This struct is used only in order to reduce the template "matroska". 5.828 +struct ArrayDefaultPolicy 5.829 +{ 5.830 + ArrayDefaultPolicy() : Capacity(0) {} 5.831 + ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {} 5.832 + 5.833 + UPInt GetMinCapacity() const { return 0; } 5.834 + UPInt GetGranularity() const { return 4; } 5.835 + bool NeverShrinking() const { return 0; } 5.836 + 5.837 + UPInt GetCapacity() const { return Capacity; } 5.838 + void SetCapacity(UPInt capacity) { Capacity = capacity; } 5.839 +private: 5.840 + UPInt Capacity; 5.841 +}; 5.842 + 5.843 + 5.844 +//----------------------------------------------------------------------------------- 5.845 +// ***** ArrayConstPolicy 5.846 +// 5.847 +// Statically parametrized resizing behavior: 5.848 +// MinCapacity, Granularity, and Shrinking flag. 5.849 +template<int MinCapacity=0, int Granularity=4, bool NeverShrink=false> 5.850 +struct ArrayConstPolicy 5.851 +{ 5.852 + typedef ArrayConstPolicy<MinCapacity, Granularity, NeverShrink> SelfType; 5.853 + 5.854 + ArrayConstPolicy() : Capacity(0) {} 5.855 + ArrayConstPolicy(const SelfType&) : Capacity(0) {} 5.856 + 5.857 + UPInt GetMinCapacity() const { return MinCapacity; } 5.858 + UPInt GetGranularity() const { return Granularity; } 5.859 + bool NeverShrinking() const { return NeverShrink; } 5.860 + 5.861 + UPInt GetCapacity() const { return Capacity; } 5.862 + void SetCapacity(UPInt capacity) { Capacity = capacity; } 5.863 +private: 5.864 + UPInt Capacity; 5.865 +}; 5.866 + 5.867 +//----------------------------------------------------------------------------------- 5.868 +// ***** ArrayDataBase 5.869 +// 5.870 +// Basic operations with array data: Reserve, Resize, Free, ArrayPolicy. 5.871 +// For internal use only: ArrayData,ArrayDataCC and others. 5.872 +template<class T, class Allocator, class SizePolicy> 5.873 +struct ArrayDataBase 5.874 +{ 5.875 + typedef T ValueType; 5.876 + typedef Allocator AllocatorType; 5.877 + typedef SizePolicy SizePolicyType; 5.878 + typedef ArrayDataBase<T, Allocator, SizePolicy> SelfType; 5.879 + 5.880 + ArrayDataBase() 5.881 + : Data(0), Size(0), Policy() {} 5.882 + 5.883 + ArrayDataBase(const SizePolicy& p) 5.884 + : Data(0), Size(0), Policy(p) {} 5.885 + 5.886 + ~ArrayDataBase() 5.887 + { 5.888 + Allocator::DestructArray(Data, Size); 5.889 + Allocator::Free(Data); 5.890 + } 5.891 + 5.892 + UPInt GetCapacity() const 5.893 + { 5.894 + return Policy.GetCapacity(); 5.895 + } 5.896 + 5.897 + void ClearAndRelease() 5.898 + { 5.899 + Allocator::DestructArray(Data, Size); 5.900 + Allocator::Free(Data); 5.901 + Data = 0; 5.902 + Size = 0; 5.903 + Policy.SetCapacity(0); 5.904 + } 5.905 + 5.906 + void Reserve(UPInt newCapacity) 5.907 + { 5.908 + if (Policy.NeverShrinking() && newCapacity < GetCapacity()) 5.909 + return; 5.910 + 5.911 + if (newCapacity < Policy.GetMinCapacity()) 5.912 + newCapacity = Policy.GetMinCapacity(); 5.913 + 5.914 + // Resize the buffer. 5.915 + if (newCapacity == 0) 5.916 + { 5.917 + if (Data) 5.918 + { 5.919 + Allocator::Free(Data); 5.920 + Data = 0; 5.921 + } 5.922 + Policy.SetCapacity(0); 5.923 + } 5.924 + else 5.925 + { 5.926 + UPInt gran = Policy.GetGranularity(); 5.927 + newCapacity = (newCapacity + gran - 1) / gran * gran; 5.928 + if (Data) 5.929 + { 5.930 + if (Allocator::IsMovable()) 5.931 + { 5.932 + Data = (T*)Allocator::Realloc(Data, sizeof(T) * newCapacity); 5.933 + } 5.934 + else 5.935 + { 5.936 + T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity); 5.937 + UPInt i, s; 5.938 + s = (Size < newCapacity) ? Size : newCapacity; 5.939 + for (i = 0; i < s; ++i) 5.940 + { 5.941 + Allocator::Construct(&newData[i], Data[i]); 5.942 + Allocator::Destruct(&Data[i]); 5.943 + } 5.944 + for (i = s; i < Size; ++i) 5.945 + { 5.946 + Allocator::Destruct(&Data[i]); 5.947 + } 5.948 + Allocator::Free(Data); 5.949 + Data = newData; 5.950 + } 5.951 + } 5.952 + else 5.953 + { 5.954 + Data = (T*)Allocator::Alloc(sizeof(T) * newCapacity); 5.955 + //memset(Buffer, 0, (sizeof(ValueType) * newSize)); // Do we need this? 5.956 + } 5.957 + Policy.SetCapacity(newCapacity); 5.958 + // OVR_ASSERT(Data); // need to throw (or something) on alloc failure! 5.959 + } 5.960 + } 5.961 + 5.962 + // This version of Resize DOES NOT construct the elements. 5.963 + // It's done to optimize PushBack, which uses a copy constructor 5.964 + // instead of the default constructor and assignment 5.965 + void ResizeNoConstruct(UPInt newSize) 5.966 + { 5.967 + UPInt oldSize = Size; 5.968 + 5.969 + if (newSize < oldSize) 5.970 + { 5.971 + Allocator::DestructArray(Data + newSize, oldSize - newSize); 5.972 + if (newSize < (Policy.GetCapacity() >> 1)) 5.973 + { 5.974 + Reserve(newSize); 5.975 + } 5.976 + } 5.977 + else if(newSize >= Policy.GetCapacity()) 5.978 + { 5.979 + Reserve(newSize + (newSize >> 2)); 5.980 + } 5.981 + //! IMPORTANT to modify Size only after Reserve completes, because garbage collectable 5.982 + // array may use this array and may traverse it during Reserve (in the case, if 5.983 + // collection occurs because of heap limit exceeded). 5.984 + Size = newSize; 5.985 + } 5.986 + 5.987 + ValueType* Data; 5.988 + UPInt Size; 5.989 + SizePolicy Policy; 5.990 +}; 5.991 + 5.992 + 5.993 + 5.994 +//----------------------------------------------------------------------------------- 5.995 +// ***** ArrayData 5.996 +// 5.997 +// General purpose array data. 5.998 +// For internal use only in Array, ArrayLH, ArrayPOD and so on. 5.999 +template<class T, class Allocator, class SizePolicy> 5.1000 +struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy> 5.1001 +{ 5.1002 + typedef T ValueType; 5.1003 + typedef Allocator AllocatorType; 5.1004 + typedef SizePolicy SizePolicyType; 5.1005 + typedef ArrayDataBase<T, Allocator, SizePolicy> BaseType; 5.1006 + typedef ArrayData <T, Allocator, SizePolicy> SelfType; 5.1007 + 5.1008 + ArrayData() 5.1009 + : BaseType() { } 5.1010 + 5.1011 + ArrayData(int size) 5.1012 + : BaseType() { Resize(size); } 5.1013 + 5.1014 + ArrayData(const SelfType& a) 5.1015 + : BaseType(a.Policy) { Append(a.Data, a.Size); } 5.1016 + 5.1017 + 5.1018 + void Resize(UPInt newSize) 5.1019 + { 5.1020 + UPInt oldSize = this->Size; 5.1021 + BaseType::ResizeNoConstruct(newSize); 5.1022 + if(newSize > oldSize) 5.1023 + Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize); 5.1024 + } 5.1025 + 5.1026 + void PushBack(const ValueType& val) 5.1027 + { 5.1028 + BaseType::ResizeNoConstruct(this->Size + 1); 5.1029 + Allocator::Construct(this->Data + this->Size - 1, val); 5.1030 + } 5.1031 + 5.1032 + template<class S> 5.1033 + void PushBackAlt(const S& val) 5.1034 + { 5.1035 + BaseType::ResizeNoConstruct(this->Size + 1); 5.1036 + Allocator::ConstructAlt(this->Data + this->Size - 1, val); 5.1037 + } 5.1038 + 5.1039 + // Append the given data to the array. 5.1040 + void Append(const ValueType other[], UPInt count) 5.1041 + { 5.1042 + if (count) 5.1043 + { 5.1044 + UPInt oldSize = this->Size; 5.1045 + BaseType::ResizeNoConstruct(this->Size + count); 5.1046 + Allocator::ConstructArray(this->Data + oldSize, count, other); 5.1047 + } 5.1048 + } 5.1049 +}; 5.1050 + 5.1051 + 5.1052 + 5.1053 +//----------------------------------------------------------------------------------- 5.1054 +// ***** ArrayDataCC 5.1055 +// 5.1056 +// A modification of ArrayData that always copy-constructs new elements 5.1057 +// using a specified DefaultValue. For internal use only in ArrayCC. 5.1058 +template<class T, class Allocator, class SizePolicy> 5.1059 +struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy> 5.1060 +{ 5.1061 + typedef T ValueType; 5.1062 + typedef Allocator AllocatorType; 5.1063 + typedef SizePolicy SizePolicyType; 5.1064 + typedef ArrayDataBase<T, Allocator, SizePolicy> BaseType; 5.1065 + typedef ArrayDataCC <T, Allocator, SizePolicy> SelfType; 5.1066 + 5.1067 + ArrayDataCC(const ValueType& defval) 5.1068 + : BaseType(), DefaultValue(defval) { } 5.1069 + 5.1070 + ArrayDataCC(const ValueType& defval, int size) 5.1071 + : BaseType(), DefaultValue(defval) { Resize(size); } 5.1072 + 5.1073 + ArrayDataCC(const SelfType& a) 5.1074 + : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); } 5.1075 + 5.1076 + 5.1077 + void Resize(UPInt newSize) 5.1078 + { 5.1079 + UPInt oldSize = this->Size; 5.1080 + BaseType::ResizeNoConstruct(newSize); 5.1081 + if(newSize > oldSize) 5.1082 + Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue); 5.1083 + } 5.1084 + 5.1085 + void PushBack(const ValueType& val) 5.1086 + { 5.1087 + BaseType::ResizeNoConstruct(this->Size + 1); 5.1088 + Allocator::Construct(this->Data + this->Size - 1, val); 5.1089 + } 5.1090 + 5.1091 + template<class S> 5.1092 + void PushBackAlt(const S& val) 5.1093 + { 5.1094 + BaseType::ResizeNoConstruct(this->Size + 1); 5.1095 + Allocator::ConstructAlt(this->Data + this->Size - 1, val); 5.1096 + } 5.1097 + 5.1098 + // Append the given data to the array. 5.1099 + void Append(const ValueType other[], UPInt count) 5.1100 + { 5.1101 + if (count) 5.1102 + { 5.1103 + UPInt oldSize = this->Size; 5.1104 + BaseType::ResizeNoConstruct(this->Size + count); 5.1105 + Allocator::ConstructArray(this->Data + oldSize, count, other); 5.1106 + } 5.1107 + } 5.1108 + 5.1109 + ValueType DefaultValue; 5.1110 +}; 5.1111 + 5.1112 + 5.1113 + 5.1114 + 5.1115 + 5.1116 +//----------------------------------------------------------------------------------- 5.1117 +// ***** ArrayBase 5.1118 +// 5.1119 +// Resizable array. The behavior can be POD (suffix _POD) and 5.1120 +// Movable (no suffix) depending on the allocator policy. 5.1121 +// In case of _POD the constructors and destructors are not called. 5.1122 +// 5.1123 +// Arrays can't handle non-movable objects! Don't put anything in here 5.1124 +// that can't be moved around by bitwise copy. 5.1125 +// 5.1126 +// The addresses of elements are not persistent! Don't keep the address 5.1127 +// of an element; the array contents will move around as it gets resized. 5.1128 +template<class ArrayData> 5.1129 +class ArrayBase 5.1130 +{ 5.1131 +public: 5.1132 + typedef typename ArrayData::ValueType ValueType; 5.1133 + typedef typename ArrayData::AllocatorType AllocatorType; 5.1134 + typedef typename ArrayData::SizePolicyType SizePolicyType; 5.1135 + typedef ArrayBase<ArrayData> SelfType; 5.1136 + 5.1137 + 5.1138 +#undef new 5.1139 + OVR_MEMORY_REDEFINE_NEW(ArrayBase) 5.1140 +// Redefine operator 'new' if necessary. 5.1141 +#if defined(OVR_DEFINE_NEW) 5.1142 +#define new OVR_DEFINE_NEW 5.1143 +#endif 5.1144 + 5.1145 + 5.1146 + ArrayBase() 5.1147 + : Data() {} 5.1148 + ArrayBase(int size) 5.1149 + : Data(size) {} 5.1150 + ArrayBase(const SelfType& a) 5.1151 + : Data(a.Data) {} 5.1152 + 5.1153 + ArrayBase(const ValueType& defval) 5.1154 + : Data(defval) {} 5.1155 + ArrayBase(const ValueType& defval, int size) 5.1156 + : Data(defval, size) {} 5.1157 + 5.1158 + SizePolicyType* GetSizePolicy() const { return Data.Policy; } 5.1159 + void SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; } 5.1160 + 5.1161 + bool NeverShrinking()const { return Data.Policy.NeverShrinking(); } 5.1162 + UPInt GetSize() const { return Data.Size; } 5.1163 + bool IsEmpty() const { return Data.Size == 0; } 5.1164 + UPInt GetCapacity() const { return Data.GetCapacity(); } 5.1165 + UPInt GetNumBytes() const { return Data.GetCapacity() * sizeof(ValueType); } 5.1166 + 5.1167 + void ClearAndRelease() { Data.ClearAndRelease(); } 5.1168 + void Clear() { Data.Resize(0); } 5.1169 + void Resize(UPInt newSize) { Data.Resize(newSize); } 5.1170 + 5.1171 + // Reserve can only increase the capacity 5.1172 + void Reserve(UPInt newCapacity) 5.1173 + { 5.1174 + if (newCapacity > Data.GetCapacity()) 5.1175 + Data.Reserve(newCapacity); 5.1176 + } 5.1177 + 5.1178 + // Basic access. 5.1179 + ValueType& At(UPInt index) 5.1180 + { 5.1181 + OVR_ASSERT(index < Data.Size); 5.1182 + return Data.Data[index]; 5.1183 + } 5.1184 + const ValueType& At(UPInt index) const 5.1185 + { 5.1186 + OVR_ASSERT(index < Data.Size); 5.1187 + return Data.Data[index]; 5.1188 + } 5.1189 + 5.1190 + ValueType ValueAt(UPInt index) const 5.1191 + { 5.1192 + OVR_ASSERT(index < Data.Size); 5.1193 + return Data.Data[index]; 5.1194 + } 5.1195 + 5.1196 + // Basic access. 5.1197 + ValueType& operator [] (UPInt index) 5.1198 + { 5.1199 + OVR_ASSERT(index < Data.Size); 5.1200 + return Data.Data[index]; 5.1201 + } 5.1202 + const ValueType& operator [] (UPInt index) const 5.1203 + { 5.1204 + OVR_ASSERT(index < Data.Size); 5.1205 + return Data.Data[index]; 5.1206 + } 5.1207 + 5.1208 + // Raw pointer to the data. Use with caution! 5.1209 + const ValueType* GetDataPtr() const { return Data.Data; } 5.1210 + ValueType* GetDataPtr() { return Data.Data; } 5.1211 + 5.1212 + // Insert the given element at the end of the array. 5.1213 + void PushBack(const ValueType& val) 5.1214 + { 5.1215 + // DO NOT pass elements of your own vector into 5.1216 + // push_back()! Since we're using references, 5.1217 + // resize() may munge the element storage! 5.1218 + // OVR_ASSERT(&val < &Buffer[0] || &val > &Buffer[BufferSize]); 5.1219 + Data.PushBack(val); 5.1220 + } 5.1221 + 5.1222 + template<class S> 5.1223 + void PushBackAlt(const S& val) 5.1224 + { 5.1225 + Data.PushBackAlt(val); 5.1226 + } 5.1227 + 5.1228 + // Remove the last element. 5.1229 + void PopBack(UPInt count = 1) 5.1230 + { 5.1231 + OVR_ASSERT(Data.Size >= count); 5.1232 + Data.Resize(Data.Size - count); 5.1233 + } 5.1234 + 5.1235 + ValueType& PushDefault() 5.1236 + { 5.1237 + Data.PushBack(ValueType()); 5.1238 + return Back(); 5.1239 + } 5.1240 + 5.1241 + ValueType Pop() 5.1242 + { 5.1243 + ValueType t = Back(); 5.1244 + PopBack(); 5.1245 + return t; 5.1246 + } 5.1247 + 5.1248 + 5.1249 + // Access the first element. 5.1250 + ValueType& Front() { return At(0); } 5.1251 + const ValueType& Front() const { return At(0); } 5.1252 + 5.1253 + // Access the last element. 5.1254 + ValueType& Back() { return At(Data.Size - 1); } 5.1255 + const ValueType& Back() const { return At(Data.Size - 1); } 5.1256 + 5.1257 + // Array copy. Copies the contents of a into this array. 5.1258 + const SelfType& operator = (const SelfType& a) 5.1259 + { 5.1260 + Resize(a.GetSize()); 5.1261 + for (UPInt i = 0; i < Data.Size; i++) { 5.1262 + *(Data.Data + i) = a[i]; 5.1263 + } 5.1264 + return *this; 5.1265 + } 5.1266 + 5.1267 + // Removing multiple elements from the array. 5.1268 + void RemoveMultipleAt(UPInt index, UPInt num) 5.1269 + { 5.1270 + OVR_ASSERT(index + num <= Data.Size); 5.1271 + if (Data.Size == num) 5.1272 + { 5.1273 + Clear(); 5.1274 + } 5.1275 + else 5.1276 + { 5.1277 + AllocatorType::DestructArray(Data.Data + index, num); 5.1278 + AllocatorType::CopyArrayForward( 5.1279 + Data.Data + index, 5.1280 + Data.Data + index + num, 5.1281 + Data.Size - num - index); 5.1282 + Data.Size -= num; 5.1283 + } 5.1284 + } 5.1285 + 5.1286 + // Removing an element from the array is an expensive operation! 5.1287 + // It compacts only after removing the last element. 5.1288 + void RemoveAt(UPInt index) 5.1289 + { 5.1290 + OVR_ASSERT(index < Data.Size); 5.1291 + if (Data.Size == 1) 5.1292 + { 5.1293 + Clear(); 5.1294 + } 5.1295 + else 5.1296 + { 5.1297 + AllocatorType::Destruct(Data.Data + index); 5.1298 + AllocatorType::CopyArrayForward( 5.1299 + Data.Data + index, 5.1300 + Data.Data + index + 1, 5.1301 + Data.Size - 1 - index); 5.1302 + --Data.Size; 5.1303 + } 5.1304 + } 5.1305 + 5.1306 + // Insert the given object at the given index shifting all the elements up. 5.1307 + void InsertAt(UPInt index, const ValueType& val = ValueType()) 5.1308 + { 5.1309 + OVR_ASSERT(index <= Data.Size); 5.1310 + 5.1311 + Data.Resize(Data.Size + 1); 5.1312 + if (index < Data.Size - 1) 5.1313 + { 5.1314 + AllocatorType::CopyArrayBackward( 5.1315 + Data.Data + index + 1, 5.1316 + Data.Data + index, 5.1317 + Data.Size - 1 - index); 5.1318 + } 5.1319 + AllocatorType::Construct(Data.Data + index, val); 5.1320 + } 5.1321 + 5.1322 + // Insert the given object at the given index shifting all the elements up. 5.1323 + void InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType()) 5.1324 + { 5.1325 + OVR_ASSERT(index <= Data.Size); 5.1326 + 5.1327 + Data.Resize(Data.Size + num); 5.1328 + if (index < Data.Size - num) 5.1329 + { 5.1330 + AllocatorType::CopyArrayBackward( 5.1331 + Data.Data + index + num, 5.1332 + Data.Data + index, 5.1333 + Data.Size - num - index); 5.1334 + } 5.1335 + for (UPInt i = 0; i < num; ++i) 5.1336 + AllocatorType::Construct(Data.Data + index + i, val); 5.1337 + } 5.1338 + 5.1339 + // Append the given data to the array. 5.1340 + void Append(const SelfType& other) 5.1341 + { 5.1342 + Append(other.Data.Data, other.GetSize()); 5.1343 + } 5.1344 + 5.1345 + // Append the given data to the array. 5.1346 + void Append(const ValueType other[], UPInt count) 5.1347 + { 5.1348 + Data.Append(other, count); 5.1349 + } 5.1350 + 5.1351 + class Iterator 5.1352 + { 5.1353 + SelfType* pArray; 5.1354 + SPInt CurIndex; 5.1355 + 5.1356 + public: 5.1357 + Iterator() : pArray(0), CurIndex(-1) {} 5.1358 + Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} 5.1359 + 5.1360 + bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } 5.1361 + bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } 5.1362 + 5.1363 + Iterator& operator++() 5.1364 + { 5.1365 + if (pArray) 5.1366 + { 5.1367 + if (CurIndex < (SPInt)pArray->GetSize()) 5.1368 + ++CurIndex; 5.1369 + } 5.1370 + return *this; 5.1371 + } 5.1372 + Iterator operator++(int) 5.1373 + { 5.1374 + Iterator it(*this); 5.1375 + operator++(); 5.1376 + return it; 5.1377 + } 5.1378 + Iterator& operator--() 5.1379 + { 5.1380 + if (pArray) 5.1381 + { 5.1382 + if (CurIndex >= 0) 5.1383 + --CurIndex; 5.1384 + } 5.1385 + return *this; 5.1386 + } 5.1387 + Iterator operator--(int) 5.1388 + { 5.1389 + Iterator it(*this); 5.1390 + operator--(); 5.1391 + return it; 5.1392 + } 5.1393 + Iterator operator+(int delta) const 5.1394 + { 5.1395 + return Iterator(pArray, CurIndex + delta); 5.1396 + } 5.1397 + Iterator operator-(int delta) const 5.1398 + { 5.1399 + return Iterator(pArray, CurIndex - delta); 5.1400 + } 5.1401 + SPInt operator-(const Iterator& right) const 5.1402 + { 5.1403 + OVR_ASSERT(pArray == right.pArray); 5.1404 + return CurIndex - right.CurIndex; 5.1405 + } 5.1406 + ValueType& operator*() const { OVR_ASSERT(pArray); return (*pArray)[CurIndex]; } 5.1407 + ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.1408 + ValueType* GetPtr() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.1409 + 5.1410 + bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } 5.1411 + 5.1412 + void Remove() 5.1413 + { 5.1414 + if (!IsFinished()) 5.1415 + pArray->RemoveAt(CurIndex); 5.1416 + } 5.1417 + 5.1418 + SPInt GetIndex() const { return CurIndex; } 5.1419 + }; 5.1420 + 5.1421 + Iterator Begin() { return Iterator(this); } 5.1422 + Iterator End() { return Iterator(this, (SPInt)GetSize()); } 5.1423 + Iterator Last() { return Iterator(this, (SPInt)GetSize() - 1); } 5.1424 + 5.1425 + class ConstIterator 5.1426 + { 5.1427 + const SelfType* pArray; 5.1428 + SPInt CurIndex; 5.1429 + 5.1430 + public: 5.1431 + ConstIterator() : pArray(0), CurIndex(-1) {} 5.1432 + ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {} 5.1433 + 5.1434 + bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; } 5.1435 + bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; } 5.1436 + 5.1437 + ConstIterator& operator++() 5.1438 + { 5.1439 + if (pArray) 5.1440 + { 5.1441 + if (CurIndex < (int)pArray->GetSize()) 5.1442 + ++CurIndex; 5.1443 + } 5.1444 + return *this; 5.1445 + } 5.1446 + ConstIterator operator++(int) 5.1447 + { 5.1448 + ConstIterator it(*this); 5.1449 + operator++(); 5.1450 + return it; 5.1451 + } 5.1452 + ConstIterator& operator--() 5.1453 + { 5.1454 + if (pArray) 5.1455 + { 5.1456 + if (CurIndex >= 0) 5.1457 + --CurIndex; 5.1458 + } 5.1459 + return *this; 5.1460 + } 5.1461 + ConstIterator operator--(int) 5.1462 + { 5.1463 + ConstIterator it(*this); 5.1464 + operator--(); 5.1465 + return it; 5.1466 + } 5.1467 + ConstIterator operator+(int delta) const 5.1468 + { 5.1469 + return ConstIterator(pArray, CurIndex + delta); 5.1470 + } 5.1471 + ConstIterator operator-(int delta) const 5.1472 + { 5.1473 + return ConstIterator(pArray, CurIndex - delta); 5.1474 + } 5.1475 + SPInt operator-(const ConstIterator& right) const 5.1476 + { 5.1477 + OVR_ASSERT(pArray == right.pArray); 5.1478 + return CurIndex - right.CurIndex; 5.1479 + } 5.1480 + const ValueType& operator*() const { OVR_ASSERT(pArray); return (*pArray)[CurIndex]; } 5.1481 + const ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.1482 + const ValueType* GetPtr() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; } 5.1483 + 5.1484 + bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); } 5.1485 + 5.1486 + SPInt GetIndex() const { return CurIndex; } 5.1487 + }; 5.1488 + ConstIterator Begin() const { return ConstIterator(this); } 5.1489 + ConstIterator End() const { return ConstIterator(this, (SPInt)GetSize()); } 5.1490 + ConstIterator Last() const { return ConstIterator(this, (SPInt)GetSize() - 1); } 5.1491 + 5.1492 +protected: 5.1493 + ArrayData Data; 5.1494 +}; 5.1495 + 5.1496 + 5.1497 + 5.1498 +//----------------------------------------------------------------------------------- 5.1499 +// ***** Array 5.1500 +// 5.1501 +// General purpose array for movable objects that require explicit 5.1502 +// construction/destruction. 5.1503 +template<class T, class SizePolicy=ArrayDefaultPolicy> 5.1504 +class Array : public ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > 5.1505 +{ 5.1506 +public: 5.1507 + typedef T ValueType; 5.1508 + typedef ContainerAllocator<T> AllocatorType; 5.1509 + typedef SizePolicy SizePolicyType; 5.1510 + typedef Array<T, SizePolicy> SelfType; 5.1511 + typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType; 5.1512 + 5.1513 + Array() : BaseType() {} 5.1514 + Array(int size) : BaseType(size) {} 5.1515 + Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.1516 + Array(const SelfType& a) : BaseType(a) {} 5.1517 + const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.1518 +}; 5.1519 + 5.1520 +// ***** ArrayPOD 5.1521 +// 5.1522 +// General purpose array for movable objects that DOES NOT require 5.1523 +// construction/destruction. Constructors and destructors are not called! 5.1524 +// Global heap is in use. 5.1525 +template<class T, class SizePolicy=ArrayDefaultPolicy> 5.1526 +class ArrayPOD : public ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > 5.1527 +{ 5.1528 +public: 5.1529 + typedef T ValueType; 5.1530 + typedef ContainerAllocator_POD<T> AllocatorType; 5.1531 + typedef SizePolicy SizePolicyType; 5.1532 + typedef ArrayPOD<T, SizePolicy> SelfType; 5.1533 + typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType; 5.1534 + 5.1535 + ArrayPOD() : BaseType() {} 5.1536 + ArrayPOD(int size) : BaseType(size) {} 5.1537 + ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.1538 + ArrayPOD(const SelfType& a) : BaseType(a) {} 5.1539 + const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.1540 +}; 5.1541 + 5.1542 + 5.1543 +// ***** ArrayCPP 5.1544 +// 5.1545 +// General purpose, fully C++ compliant array. Can be used with non-movable data. 5.1546 +// Global heap is in use. 5.1547 +template<class T, class SizePolicy=ArrayDefaultPolicy> 5.1548 +class ArrayCPP : public ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > 5.1549 +{ 5.1550 +public: 5.1551 + typedef T ValueType; 5.1552 + typedef ContainerAllocator_CPP<T> AllocatorType; 5.1553 + typedef SizePolicy SizePolicyType; 5.1554 + typedef ArrayCPP<T, SizePolicy> SelfType; 5.1555 + typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType; 5.1556 + 5.1557 + ArrayCPP() : BaseType() {} 5.1558 + ArrayCPP(int size) : BaseType(size) {} 5.1559 + ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); } 5.1560 + ArrayCPP(const SelfType& a) : BaseType(a) {} 5.1561 + const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.1562 +}; 5.1563 + 5.1564 + 5.1565 +// ***** ArrayCC 5.1566 +// 5.1567 +// A modification of the array that uses the given default value to 5.1568 +// construct the elements. The constructors and destructors are 5.1569 +// properly called, the objects must be movable. 5.1570 + 5.1571 +template<class T, class SizePolicy=ArrayDefaultPolicy> 5.1572 +class ArrayCC : public ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > 5.1573 +{ 5.1574 +public: 5.1575 + typedef T ValueType; 5.1576 + typedef ContainerAllocator<T> AllocatorType; 5.1577 + typedef SizePolicy SizePolicyType; 5.1578 + typedef ArrayCC<T, SizePolicy> SelfType; 5.1579 + typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > BaseType; 5.1580 + 5.1581 + ArrayCC(const ValueType& defval) : BaseType(defval) {} 5.1582 + ArrayCC(const ValueType& defval, int size) : BaseType(defval, size) {} 5.1583 + ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); } 5.1584 + ArrayCC(const SelfType& a) : BaseType(a) {} 5.1585 + const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; } 5.1586 +}; 5.1587 + 5.1588 +} // OVR 5.1589 + 5.1590 +#endif
6.1 --- a/libovr/Src/Kernel/OVR_Atomic.cpp Sat Sep 14 17:51:03 2013 +0300 6.2 +++ b/libovr/Src/Kernel/OVR_Atomic.cpp Sun Sep 15 04:10:05 2013 +0300 6.3 @@ -1,1 +1,82 @@ 6.4 -/************************************************************************************ 6.5 6.6 Filename : OVR_Atomic.cpp 6.7 Content : Contains atomic operations and inline fastest locking 6.8 functionality. Will contain #ifdefs for OS efficiency. 6.9 Have non-thread-safe implementation if not available. 6.10 Created : September 19, 2012 6.11 Notes : 6.12 6.13 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 6.14 6.15 Use of this software is subject to the terms of the Oculus license 6.16 agreement provided at the time of installation or download, or which 6.17 otherwise accompanies this software in either electronic or hard copy form. 6.18 6.19 ************************************************************************************/ 6.20 6.21 #include "OVR_Atomic.h" 6.22 6.23 #ifdef OVR_ENABLE_THREADS 6.24 6.25 // Include Windows 8-Metro compatible Synchronization API 6.26 #if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) 6.27 #include <synchapi.h> 6.28 #endif 6.29 6.30 6.31 namespace OVR { 6.32 6.33 // ***** Windows Lock implementation 6.34 6.35 #if defined(OVR_OS_WIN32) 6.36 6.37 // ***** Standard Win32 Lock implementation 6.38 6.39 // Constructors 6.40 Lock::Lock(unsigned spinCount) 6.41 { 6.42 #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) 6.43 // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility 6.44 InitializeCriticalSectionEx(&cs, spinCount, 6.45 OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO)); 6.46 #else 6.47 // Spin count init critical section function prototype for Window NT 6.48 typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount) 6.49 (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount); 6.50 6.51 6.52 // Try to load function dynamically so that we don't require NT 6.53 // On Windows NT we will use InitializeCriticalSectionAndSpinCount 6.54 static bool initTried = 0; 6.55 static Function_InitializeCriticalSectionAndSpinCount pInitFn = 0; 6.56 6.57 if (!initTried) 6.58 { 6.59 HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll")); 6.60 pInitFn = (Function_InitializeCriticalSectionAndSpinCount) 6.61 ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount"); 6.62 initTried = true; 6.63 } 6.64 6.65 // Initialize the critical section 6.66 if (pInitFn) 6.67 pInitFn(&cs, spinCount); 6.68 else 6.69 ::InitializeCriticalSection(&cs); 6.70 #endif 6.71 6.72 } 6.73 6.74 6.75 Lock::~Lock() 6.76 { 6.77 DeleteCriticalSection(&cs); 6.78 } 6.79 6.80 6.81 #endif 6.82 6.83 } // OVR 6.84 6.85 #endif // OVR_ENABLE_THREADS 6.86 \ No newline at end of file 6.87 +/************************************************************************************ 6.88 + 6.89 +Filename : OVR_Atomic.cpp 6.90 +Content : Contains atomic operations and inline fastest locking 6.91 + functionality. Will contain #ifdefs for OS efficiency. 6.92 + Have non-thread-safe implementation if not available. 6.93 +Created : September 19, 2012 6.94 +Notes : 6.95 + 6.96 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 6.97 + 6.98 +Use of this software is subject to the terms of the Oculus license 6.99 +agreement provided at the time of installation or download, or which 6.100 +otherwise accompanies this software in either electronic or hard copy form. 6.101 + 6.102 +************************************************************************************/ 6.103 + 6.104 +#include "OVR_Atomic.h" 6.105 + 6.106 +#ifdef OVR_ENABLE_THREADS 6.107 + 6.108 +// Include Windows 8-Metro compatible Synchronization API 6.109 +#if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) 6.110 +#include <synchapi.h> 6.111 +#endif 6.112 + 6.113 + 6.114 +namespace OVR { 6.115 + 6.116 +// ***** Windows Lock implementation 6.117 + 6.118 +#if defined(OVR_OS_WIN32) 6.119 + 6.120 +// ***** Standard Win32 Lock implementation 6.121 + 6.122 +// Constructors 6.123 +Lock::Lock(unsigned spinCount) 6.124 +{ 6.125 +#if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8) 6.126 + // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility 6.127 + InitializeCriticalSectionEx(&cs, spinCount, 6.128 + OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO)); 6.129 +#else 6.130 + // Spin count init critical section function prototype for Window NT 6.131 + typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount) 6.132 + (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount); 6.133 + 6.134 + 6.135 + // Try to load function dynamically so that we don't require NT 6.136 + // On Windows NT we will use InitializeCriticalSectionAndSpinCount 6.137 + static bool initTried = 0; 6.138 + static Function_InitializeCriticalSectionAndSpinCount pInitFn = 0; 6.139 + 6.140 + if (!initTried) 6.141 + { 6.142 + HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll")); 6.143 + pInitFn = (Function_InitializeCriticalSectionAndSpinCount) 6.144 + ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount"); 6.145 + initTried = true; 6.146 + } 6.147 + 6.148 + // Initialize the critical section 6.149 + if (pInitFn) 6.150 + pInitFn(&cs, spinCount); 6.151 + else 6.152 + ::InitializeCriticalSection(&cs); 6.153 +#endif 6.154 + 6.155 +} 6.156 + 6.157 + 6.158 +Lock::~Lock() 6.159 +{ 6.160 + DeleteCriticalSection(&cs); 6.161 +} 6.162 + 6.163 + 6.164 +#endif 6.165 + 6.166 +} // OVR 6.167 + 6.168 +#endif // OVR_ENABLE_THREADS
7.1 --- a/libovr/Src/Kernel/OVR_Atomic.h Sat Sep 14 17:51:03 2013 +0300 7.2 +++ b/libovr/Src/Kernel/OVR_Atomic.h Sun Sep 15 04:10:05 2013 +0300 7.3 @@ -1,1 +1,859 @@ 7.4 -/************************************************************************************ 7.5 7.6 PublicHeader: OVR.h 7.7 Filename : OVR_Atomic.h 7.8 Content : Contains atomic operations and inline fastest locking 7.9 functionality. Will contain #ifdefs for OS efficiency. 7.10 Have non-thread-safe implementaion if not available. 7.11 Created : September 19, 2012 7.12 Notes : 7.13 7.14 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 7.15 7.16 Use of this software is subject to the terms of the Oculus license 7.17 agreement provided at the time of installation or download, or which 7.18 otherwise accompanies this software in either electronic or hard copy form. 7.19 7.20 ************************************************************************************/ 7.21 #ifndef OVR_Atomic_h 7.22 #define OVR_Atomic_h 7.23 7.24 #include "OVR_Types.h" 7.25 7.26 // Include System thread functionality. 7.27 #if defined(OVR_OS_WIN32) 7.28 #include <windows.h> 7.29 #else 7.30 #include <pthread.h> 7.31 #endif 7.32 7.33 7.34 namespace OVR { 7.35 7.36 7.37 // ****** Declared classes 7.38 7.39 // If there is NO thread support we implement AtomicOps and 7.40 // Lock objects as no-ops. The other classes are not defined. 7.41 template<class C> class AtomicOps; 7.42 template<class T> class AtomicInt; 7.43 template<class T> class AtomicPtr; 7.44 7.45 class Lock; 7.46 7.47 7.48 //----------------------------------------------------------------------------------- 7.49 // ***** AtomicOps 7.50 7.51 // Atomic operations are provided by the AtomicOps templates class, 7.52 // implemented through system-specific AtomicOpsRaw specializations. 7.53 // It provides several fundamental operations such as Exchange, ExchangeAdd 7.54 // CompareAndSet, and Store_Release. Each function includes several memory 7.55 // synchronization versions, important for multiprocessing CPUs with weak 7.56 // memory consistency. The following memory fencing strategies are supported: 7.57 // 7.58 // - NoSync. No memory synchronization is done for atomic op. 7.59 // - Release. All other memory writes are completed before atomic op 7.60 // writes its results. 7.61 // - Acquire. Further memory reads are forced to wait until atomic op 7.62 // executes, guaranteeing that the right values will be seen. 7.63 // - Sync. A combination of Release and Acquire. 7.64 7.65 7.66 // *** AtomicOpsRaw 7.67 7.68 // AtomicOpsRaw is a specialized template that provides atomic operations 7.69 // used by AtomicOps. This class has two fundamental qualities: (1) it 7.70 // defines a type T of correct size, and (2) provides operations that work 7.71 // atomically, such as Exchange_Sync and CompareAndSet_Release. 7.72 7.73 // AtomicOpsRawBase class contains shared constants/classes for AtomicOpsRaw. 7.74 // The primary thing is does is define sync class objects, whose destructor and 7.75 // constructor provide places to insert appropriate synchronization calls, on 7.76 // systems where such calls are necessary. So far, the breakdown is as follows: 7.77 // 7.78 // - X86 systems don't need custom syncs, since their exchange/atomic 7.79 // instructions are implicitly synchronized. 7.80 // - PowerPC requires lwsync/isync instructions that can use this mechanism. 7.81 // - If some other systems require a mechanism where syncing type is associated 7.82 // with a particular instruction, the default implementation (which implements 7.83 // all Sync, Acquire, and Release modes in terms of NoSync and fence) may not 7.84 // work. Ii that case it will need to be #ifdef-ed conditionally. 7.85 7.86 struct AtomicOpsRawBase 7.87 { 7.88 #if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_OS_WIN32) || defined(OVR_OS_IPHONE) 7.89 // Need to have empty constructor to avoid class 'unused' variable warning. 7.90 struct FullSync { inline FullSync() { } }; 7.91 struct AcquireSync { inline AcquireSync() { } }; 7.92 struct ReleaseSync { inline ReleaseSync() { } }; 7.93 7.94 #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) 7.95 struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("isync\n"); } }; 7.96 struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("isync\n"); } }; 7.97 struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } }; 7.98 7.99 #elif defined(OVR_CPU_MIPS) 7.100 struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("sync\n"); } }; 7.101 struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } }; 7.102 struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } }; 7.103 7.104 #elif defined(OVR_CPU_ARM) 7.105 struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } }; 7.106 struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } }; 7.107 struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } }; 7.108 7.109 7.110 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4) 7.111 // __sync functions are already full sync 7.112 struct FullSync { inline FullSync() { } }; 7.113 struct AcquireSync { inline AcquireSync() { } }; 7.114 struct ReleaseSync { inline ReleaseSync() { } }; 7.115 #endif 7.116 }; 7.117 7.118 7.119 // 4-Byte raw data atomic op implementation class. 7.120 struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase 7.121 { 7.122 #if !defined(OVR_ENABLE_THREADS) 7.123 7.124 // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. 7.125 typedef UInt32 T; 7.126 7.127 // *** Thread - Safe Atomic Versions. 7.128 7.129 #elif defined(OVR_OS_WIN32) 7.130 7.131 // Use special defined for VC6, where volatile is not used and 7.132 // InterlockedCompareExchange is declared incorrectly. 7.133 typedef LONG T; 7.134 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC < 1300) 7.135 typedef T* InterlockTPtr; 7.136 typedef LPVOID ET; 7.137 typedef ET* InterlockETPtr; 7.138 #else 7.139 typedef volatile T* InterlockTPtr; 7.140 typedef T ET; 7.141 typedef InterlockTPtr InterlockETPtr; 7.142 #endif 7.143 inline static T Exchange_NoSync(volatile T* p, T val) { return InterlockedExchange((InterlockTPtr)p, val); } 7.144 inline static T ExchangeAdd_NoSync(volatile T* p, T val) { return InterlockedExchangeAdd((InterlockTPtr)p, val); } 7.145 inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; } 7.146 7.147 #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) 7.148 typedef UInt32 T; 7.149 static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.150 { 7.151 UInt32 ret; 7.152 7.153 asm volatile("1:\n\t" 7.154 "lwarx %[r],0,%[i]\n\t" 7.155 "stwcx. %[j],0,%[i]\n\t" 7.156 "bne- 1b\n" 7.157 : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [j] "b" (j) : "cc", "memory"); 7.158 7.159 return ret; 7.160 } 7.161 7.162 static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.163 { 7.164 UInt32 dummy, ret; 7.165 7.166 asm volatile("1:\n\t" 7.167 "lwarx %[r],0,%[i]\n\t" 7.168 "add %[o],%[r],%[j]\n\t" 7.169 "stwcx. %[o],0,%[i]\n\t" 7.170 "bne- 1b\n" 7.171 : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc", "memory"); 7.172 7.173 return ret; 7.174 } 7.175 7.176 static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.177 { 7.178 UInt32 ret; 7.179 7.180 asm volatile("1:\n\t" 7.181 "lwarx %[r],0,%[i]\n\t" 7.182 "cmpw 0,%[r],%[cmp]\n\t" 7.183 "mfcr %[r]\n\t" 7.184 "bne- 2f\n\t" 7.185 "stwcx. %[val],0,%[i]\n\t" 7.186 "bne- 1b\n\t" 7.187 "2:\n" 7.188 : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc", "memory"); 7.189 7.190 return (ret & 0x20000000) ? 1 : 0; 7.191 } 7.192 7.193 #elif defined(OVR_CPU_MIPS) 7.194 typedef UInt32 T; 7.195 7.196 static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.197 { 7.198 UInt32 ret; 7.199 7.200 asm volatile("1:\n\t" 7.201 "ll %[r],0(%[i])\n\t" 7.202 "sc %[j],0(%[i])\n\t" 7.203 "beq %[j],$0,1b\n\t" 7.204 "nop \n" 7.205 : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory"); 7.206 7.207 return ret; 7.208 } 7.209 7.210 static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.211 { 7.212 UInt32 ret; 7.213 7.214 asm volatile("1:\n\t" 7.215 "ll %[r],0(%[i])\n\t" 7.216 "addu %[j],%[r],%[j]\n\t" 7.217 "sc %[j],0(%[i])\n\t" 7.218 "beq %[j],$0,1b\n\t" 7.219 "nop \n" 7.220 : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory"); 7.221 7.222 return ret; 7.223 } 7.224 7.225 static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.226 { 7.227 UInt32 ret, dummy; 7.228 7.229 asm volatile("1:\n\t" 7.230 "move %[r],$0\n\t" 7.231 "ll %[o],0(%[i])\n\t" 7.232 "bne %[o],%[c],2f\n\t" 7.233 "move %[r],%[v]\n\t" 7.234 "sc %[r],0(%[i])\n\t" 7.235 "beq %[r],$0,1b\n\t" 7.236 "nop \n\t" 7.237 "2:\n" 7.238 : "+m" (*i),[r] "=&d" (ret), [o] "=&d" (dummy) : [i] "d" (i), [c] "d" (c), [v] "d" (value) 7.239 : "cc", "memory"); 7.240 7.241 return ret; 7.242 } 7.243 7.244 #elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM) 7.245 typedef UInt32 T; 7.246 7.247 static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.248 { 7.249 for(;;) 7.250 { 7.251 T r = __ldrex(i); 7.252 if (__strex(j, i) == 0) 7.253 return r; 7.254 } 7.255 } 7.256 static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.257 { 7.258 for(;;) 7.259 { 7.260 T r = __ldrex(i); 7.261 if (__strex(r + j, i) == 0) 7.262 return r; 7.263 } 7.264 } 7.265 7.266 static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.267 { 7.268 for(;;) 7.269 { 7.270 T r = __ldrex(i); 7.271 if (r != c) 7.272 return 0; 7.273 if (__strex(value, i) == 0) 7.274 return 1; 7.275 } 7.276 } 7.277 7.278 #elif defined(OVR_CPU_ARM) 7.279 typedef UInt32 T; 7.280 7.281 static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.282 { 7.283 UInt32 ret, dummy; 7.284 7.285 asm volatile("1:\n\t" 7.286 "ldrex %[r],[%[i]]\n\t" 7.287 "strex %[t],%[j],[%[i]]\n\t" 7.288 "cmp %[t],#0\n\t" 7.289 "bne 1b\n\t" 7.290 : "+m" (*i), [r] "=&r" (ret), [t] "=&r" (dummy) : [i] "r" (i), [j] "r" (j) : "cc", "memory"); 7.291 7.292 return ret; 7.293 } 7.294 7.295 static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.296 { 7.297 UInt32 ret, dummy, test; 7.298 7.299 asm volatile("1:\n\t" 7.300 "ldrex %[r],[%[i]]\n\t" 7.301 "add %[o],%[r],%[j]\n\t" 7.302 "strex %[t],%[o],[%[i]]\n\t" 7.303 "cmp %[t],#0\n\t" 7.304 "bne 1b\n\t" 7.305 : "+m" (*i), [r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [j] "r" (j) : "cc", "memory"); 7.306 7.307 return ret; 7.308 } 7.309 7.310 static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.311 { 7.312 UInt32 ret = 1, dummy, test; 7.313 7.314 asm volatile("1:\n\t" 7.315 "ldrex %[o],[%[i]]\n\t" 7.316 "cmp %[o],%[c]\n\t" 7.317 "bne 2f\n\t" 7.318 "strex %[r],%[v],[%[i]]\n\t" 7.319 "cmp %[r],#0\n\t" 7.320 "bne 1b\n\t" 7.321 "2:\n" 7.322 : "+m" (*i),[r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [c] "r" (c), [v] "r" (value) 7.323 : "cc", "memory"); 7.324 7.325 return !ret; 7.326 } 7.327 7.328 #elif defined(OVR_CPU_X86) 7.329 typedef UInt32 T; 7.330 7.331 static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.332 { 7.333 asm volatile("xchgl %1,%[i]\n" 7.334 : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory"); 7.335 7.336 return j; 7.337 } 7.338 7.339 static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.340 { 7.341 asm volatile("lock; xaddl %1,%[i]\n" 7.342 : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory"); 7.343 7.344 return j; 7.345 } 7.346 7.347 static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.348 { 7.349 UInt32 ret; 7.350 7.351 asm volatile("lock; cmpxchgl %[v],%[i]\n" 7.352 : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory"); 7.353 7.354 return (ret == c); 7.355 } 7.356 7.357 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) 7.358 7.359 typedef UInt32 T; 7.360 7.361 static inline T Exchange_NoSync(volatile T *i, T j) 7.362 { 7.363 T v; 7.364 do { 7.365 v = *i; 7.366 } while (!__sync_bool_compare_and_swap(i, v, j)); 7.367 return v; 7.368 } 7.369 7.370 static inline T ExchangeAdd_NoSync(volatile T *i, T j) 7.371 { 7.372 return __sync_fetch_and_add(i, j); 7.373 } 7.374 7.375 static inline bool CompareAndSet_NoSync(volatile T *i, T c, T value) 7.376 { 7.377 return __sync_bool_compare_and_swap(i, c, value); 7.378 } 7.379 7.380 #endif // OS 7.381 }; 7.382 7.383 7.384 // 8-Byte raw data data atomic op implementation class. 7.385 // Currently implementation is provided only on systems with 64-bit pointers. 7.386 struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase 7.387 { 7.388 #if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS) 7.389 7.390 // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. 7.391 typedef UInt64 T; 7.392 7.393 // *** Thread - Safe OS specific versions. 7.394 #elif defined(OVR_OS_WIN32) 7.395 7.396 // This is only for 64-bit systems. 7.397 typedef LONG64 T; 7.398 typedef volatile T* InterlockTPtr; 7.399 inline static T Exchange_NoSync(volatile T* p, T val) { return InterlockedExchange64((InterlockTPtr)p, val); } 7.400 inline static T ExchangeAdd_NoSync(volatile T* p, T val) { return InterlockedExchangeAdd64((InterlockTPtr)p, val); } 7.401 inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange64((InterlockTPtr)p, val, c) == c; } 7.402 7.403 #elif defined(OVR_CPU_PPC64) 7.404 7.405 typedef UInt64 T; 7.406 7.407 static inline UInt64 Exchange_NoSync(volatile UInt64 *i, UInt64 j) 7.408 { 7.409 UInt64 dummy, ret; 7.410 7.411 asm volatile("1:\n\t" 7.412 "ldarx %[r],0,%[i]\n\t" 7.413 "mr %[o],%[j]\n\t" 7.414 "stdcx. %[o],0,%[i]\n\t" 7.415 "bne- 1b\n" 7.416 : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc"); 7.417 7.418 return ret; 7.419 } 7.420 7.421 static inline UInt64 ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j) 7.422 { 7.423 UInt64 dummy, ret; 7.424 7.425 asm volatile("1:\n\t" 7.426 "ldarx %[r],0,%[i]\n\t" 7.427 "add %[o],%[r],%[j]\n\t" 7.428 "stdcx. %[o],0,%[i]\n\t" 7.429 "bne- 1b\n" 7.430 : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc"); 7.431 7.432 return ret; 7.433 } 7.434 7.435 static inline bool CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value) 7.436 { 7.437 UInt64 ret, dummy; 7.438 7.439 asm volatile("1:\n\t" 7.440 "ldarx %[r],0,%[i]\n\t" 7.441 "cmpw 0,%[r],%[cmp]\n\t" 7.442 "mfcr %[r]\n\t" 7.443 "bne- 2f\n\t" 7.444 "stdcx. %[val],0,%[i]\n\t" 7.445 "bne- 1b\n\t" 7.446 "2:\n" 7.447 : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc"); 7.448 7.449 return (ret & 0x20000000) ? 1 : 0; 7.450 } 7.451 7.452 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) 7.453 7.454 typedef UInt64 T; 7.455 7.456 static inline T Exchange_NoSync(volatile T *i, T j) 7.457 { 7.458 T v; 7.459 do { 7.460 v = *i; 7.461 } while (!__sync_bool_compare_and_swap(i, v, j)); 7.462 return v; 7.463 } 7.464 7.465 static inline T ExchangeAdd_NoSync(volatile T *i, T j) 7.466 { 7.467 return __sync_fetch_and_add(i, j); 7.468 } 7.469 7.470 static inline bool CompareAndSet_NoSync(volatile T *i, T c, T value) 7.471 { 7.472 return __sync_bool_compare_and_swap(i, c, value); 7.473 } 7.474 7.475 #endif // OS 7.476 }; 7.477 7.478 7.479 // Default implementation for AtomicOpsRaw; provides implementation of mem-fenced 7.480 // atomic operations where fencing is done with a sync object wrapped around a NoSync 7.481 // operation implemented in the base class. If such implementation is not possible 7.482 // on a given platform, #ifdefs can be used to disable it and then op functions can be 7.483 // implemented individually in the appropriate AtomicOpsRaw<size> class. 7.484 7.485 template<class O> 7.486 struct AtomicOpsRaw_DefImpl : public O 7.487 { 7.488 typedef typename O::T O_T; 7.489 typedef typename O::FullSync O_FullSync; 7.490 typedef typename O::AcquireSync O_AcquireSync; 7.491 typedef typename O::ReleaseSync O_ReleaseSync; 7.492 7.493 // If there is no thread support, provide the default implementation. In this case, 7.494 // the base class (0) must still provide the T declaration. 7.495 #ifndef OVR_ENABLE_THREADS 7.496 7.497 // Atomic exchange of val with argument. Returns old val. 7.498 inline static O_T Exchange_NoSync(volatile O_T* p, O_T val) { O_T old = *p; *p = val; return old; } 7.499 // Adds a new val to argument; returns its old val. 7.500 inline static O_T ExchangeAdd_NoSync(volatile O_T* p, O_T val) { O_T old = *p; *p += val; return old; } 7.501 // Compares the argument data with 'c' val. 7.502 // If succeeded, stores val int '*p' and returns true; otherwise returns false. 7.503 inline static bool CompareAndSet_NoSync(volatile O_T* p, O_T c, O_T val) { if (*p==c) { *p = val; return 1; } return 0; } 7.504 7.505 #endif 7.506 7.507 // If NoSync wrapped implementation may not be possible, it this block should be 7.508 // replaced with per-function implementation in O. 7.509 // "AtomicOpsRaw_DefImpl<O>::" prefix in calls below. 7.510 inline static O_T Exchange_Sync(volatile O_T* p, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.511 inline static O_T Exchange_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.512 inline static O_T Exchange_Acquire(volatile O_T* p, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.513 inline static O_T ExchangeAdd_Sync(volatile O_T* p, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.514 inline static O_T ExchangeAdd_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.515 inline static O_T ExchangeAdd_Acquire(volatile O_T* p, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.516 inline static bool CompareAndSet_Sync(volatile O_T* p, O_T c, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.517 inline static bool CompareAndSet_Release(volatile O_T* p, O_T c, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.518 inline static bool CompareAndSet_Acquire(volatile O_T* p, O_T c, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.519 7.520 // Loads and stores with memory fence. These have only the relevant versions. 7.521 #ifdef OVR_CPU_X86 7.522 // On X86, Store_Release is implemented as exchange. Note that we can also 7.523 // consider 'sfence' in the future, although it is not as compatible with older CPUs. 7.524 inline static void Store_Release(volatile O_T* p, O_T val) { Exchange_Release(p, val); } 7.525 #else 7.526 inline static void Store_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; } 7.527 #endif 7.528 inline static O_T Load_Acquire(const volatile O_T* p) { O_AcquireSync sync; OVR_UNUSED(sync); return *p; } 7.529 }; 7.530 7.531 7.532 template<int size> 7.533 struct AtomicOpsRaw : public AtomicOpsRawBase { }; 7.534 7.535 template<> 7.536 struct AtomicOpsRaw<4> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl> 7.537 { 7.538 // Ensure that assigned type size is correct. 7.539 AtomicOpsRaw() 7.540 { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>::T) == 4); } 7.541 }; 7.542 template<> 7.543 struct AtomicOpsRaw<8> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl> 7.544 { 7.545 AtomicOpsRaw() 7.546 { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>::T) == 8); } 7.547 }; 7.548 7.549 7.550 // *** AtomicOps - implementation of atomic Ops for specified class 7.551 7.552 // Implements atomic ops on a class, provided that the object is either 7.553 // 4 or 8 bytes in size (depending on the AtomicOpsRaw specializations 7.554 // available). Relies on AtomicOpsRaw for much of implementation. 7.555 7.556 template<class C> 7.557 class AtomicOps 7.558 { 7.559 typedef AtomicOpsRaw<sizeof(C)> Ops; 7.560 typedef typename Ops::T T; 7.561 typedef volatile typename Ops::T* PT; 7.562 // We cast through unions to (1) avoid pointer size compiler warnings 7.563 // and (2) ensure that there are no problems with strict pointer aliasing. 7.564 union C2T_union { C c; T t; }; 7.565 7.566 public: 7.567 // General purpose implementation for standard syncs. 7.568 inline static C Exchange_Sync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Sync((PT)p, u.t); return u.c; } 7.569 inline static C Exchange_Release(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Release((PT)p, u.t); return u.c; } 7.570 inline static C Exchange_Acquire(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Acquire((PT)p, u.t); return u.c; } 7.571 inline static C Exchange_NoSync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_NoSync((PT)p, u.t); return u.c; } 7.572 inline static C ExchangeAdd_Sync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Sync((PT)p, u.t); return u.c; } 7.573 inline static C ExchangeAdd_Release(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Release((PT)p, u.t); return u.c; } 7.574 inline static C ExchangeAdd_Acquire(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Acquire((PT)p, u.t); return u.c; } 7.575 inline static C ExchangeAdd_NoSync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_NoSync((PT)p, u.t); return u.c; } 7.576 inline static bool CompareAndSet_Sync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Sync((PT)p, cu.t, u.t); } 7.577 inline static bool CompareAndSet_Release(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Release((PT)p, cu.t, u.t); } 7.578 inline static bool CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); } 7.579 inline static bool CompareAndSet_NoSync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_NoSync((PT)p, cu.t, u.t); } 7.580 // Loads and stores with memory fence. These have only the relevant versions. 7.581 inline static void Store_Release(volatile C* p, C val) { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); } 7.582 inline static C Load_Acquire(const volatile C* p) { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; } 7.583 }; 7.584 7.585 7.586 7.587 // Atomic value base class - implements operations shared for integers and pointers. 7.588 template<class T> 7.589 class AtomicValueBase 7.590 { 7.591 protected: 7.592 typedef AtomicOps<T> Ops; 7.593 public: 7.594 7.595 volatile T Value; 7.596 7.597 inline AtomicValueBase() { } 7.598 explicit inline AtomicValueBase(T val) { Ops::Store_Release(&Value, val); } 7.599 7.600 // Most libraries (TBB and Joshua Scholar's) library do not do Load_Acquire 7.601 // here, since most algorithms do not require atomic loads. Needs some research. 7.602 inline operator T() const { return Value; } 7.603 7.604 // *** Standard Atomic inlines 7.605 inline T Exchange_Sync(T val) { return Ops::Exchange_Sync(&Value, val); } 7.606 inline T Exchange_Release(T val) { return Ops::Exchange_Release(&Value, val); } 7.607 inline T Exchange_Acquire(T val) { return Ops::Exchange_Acquire(&Value, val); } 7.608 inline T Exchange_NoSync(T val) { return Ops::Exchange_NoSync(&Value, val); } 7.609 inline bool CompareAndSet_Sync(T c, T val) { return Ops::CompareAndSet_Sync(&Value, c, val); } 7.610 inline bool CompareAndSet_Release(T c, T val) { return Ops::CompareAndSet_Release(&Value, c, val); } 7.611 inline bool CompareAndSet_Acquire(T c, T val) { return Ops::CompareAndSet_Relse(&Value, c, val); } 7.612 inline bool CompareAndSet_NoSync(T c, T val) { return Ops::CompareAndSet_NoSync(&Value, c, val); } 7.613 // Load & Store. 7.614 inline void Store_Release(T val) { Ops::Store_Release(&Value, val); } 7.615 inline T Load_Acquire() const { return Ops::Load_Acquire(&Value); } 7.616 }; 7.617 7.618 7.619 // ***** AtomicPtr - Atomic pointer template 7.620 7.621 // This pointer class supports atomic assignments with release, 7.622 // increment / decrement operations, and conditional compare + set. 7.623 7.624 template<class T> 7.625 class AtomicPtr : public AtomicValueBase<T*> 7.626 { 7.627 typedef typename AtomicValueBase<T*>::Ops Ops; 7.628 7.629 public: 7.630 // Initialize pointer value to 0 by default; use Store_Release only with explicit constructor. 7.631 inline AtomicPtr() : AtomicValueBase<T*>() { this->Value = 0; } 7.632 explicit inline AtomicPtr(T* val) : AtomicValueBase<T*>(val) { } 7.633 7.634 // Pointer access. 7.635 inline T* operator -> () const { return this->Load_Acquire(); } 7.636 7.637 // It looks like it is convenient to have Load_Acquire characteristics 7.638 // for this, since that is convenient for algorithms such as linked 7.639 // list traversals that can be added to bu another thread. 7.640 inline operator T* () const { return this->Load_Acquire(); } 7.641 7.642 7.643 // *** Standard Atomic inlines (applicable to pointers) 7.644 7.645 // ExhangeAdd considers pointer size for pointers. 7.646 template<class I> 7.647 inline T* ExchangeAdd_Sync(I incr) { return Ops::ExchangeAdd_Sync(&this->Value, ((T*)0) + incr); } 7.648 template<class I> 7.649 inline T* ExchangeAdd_Release(I incr) { return Ops::ExchangeAdd_Release(&this->Value, ((T*)0) + incr); } 7.650 template<class I> 7.651 inline T* ExchangeAdd_Acquire(I incr) { return Ops::ExchangeAdd_Acquire(&this->Value, ((T*)0) + incr); } 7.652 template<class I> 7.653 inline T* ExchangeAdd_NoSync(I incr) { return Ops::ExchangeAdd_NoSync(&this->Value, ((T*)0) + incr); } 7.654 7.655 // *** Atomic Operators 7.656 7.657 inline T* operator = (T* val) { this->Store_Release(val); return val; } 7.658 7.659 template<class I> 7.660 inline T* operator += (I val) { return ExchangeAdd_Sync(val) + val; } 7.661 template<class I> 7.662 inline T* operator -= (I val) { return operator += (-val); } 7.663 7.664 inline T* operator ++ () { return ExchangeAdd_Sync(1) + 1; } 7.665 inline T* operator -- () { return ExchangeAdd_Sync(-1) - 1; } 7.666 inline T* operator ++ (int) { return ExchangeAdd_Sync(1); } 7.667 inline T* operator -- (int) { return ExchangeAdd_Sync(-1); } 7.668 }; 7.669 7.670 7.671 // ***** AtomicInt - Atomic integer template 7.672 7.673 // Implements an atomic integer type; the exact type to use is provided 7.674 // as an argument. Supports atomic Acquire / Release semantics, atomic 7.675 // arithmetic operations, and atomic conditional compare + set. 7.676 7.677 template<class T> 7.678 class AtomicInt : public AtomicValueBase<T> 7.679 { 7.680 typedef typename AtomicValueBase<T>::Ops Ops; 7.681 7.682 public: 7.683 inline AtomicInt() : AtomicValueBase<T>() { } 7.684 explicit inline AtomicInt(T val) : AtomicValueBase<T>(val) { } 7.685 7.686 7.687 // *** Standard Atomic inlines (applicable to int) 7.688 inline T ExchangeAdd_Sync(T val) { return Ops::ExchangeAdd_Sync(&this->Value, val); } 7.689 inline T ExchangeAdd_Release(T val) { return Ops::ExchangeAdd_Release(&this->Value, val); } 7.690 inline T ExchangeAdd_Acquire(T val) { return Ops::ExchangeAdd_Acquire(&this->Value, val); } 7.691 inline T ExchangeAdd_NoSync(T val) { return Ops::ExchangeAdd_NoSync(&this->Value, val); } 7.692 // These increments could be more efficient because they don't return a value. 7.693 inline void Increment_Sync() { ExchangeAdd_Sync((T)1); } 7.694 inline void Increment_Release() { ExchangeAdd_Release((T)1); } 7.695 inline void Increment_Acquire() { ExchangeAdd_Acquire((T)1); } 7.696 inline void Increment_NoSync() { ExchangeAdd_NoSync((T)1); } 7.697 7.698 // *** Atomic Operators 7.699 7.700 inline T operator = (T val) { this->Store_Release(val); return val; } 7.701 inline T operator += (T val) { return ExchangeAdd_Sync(val) + val; } 7.702 inline T operator -= (T val) { return ExchangeAdd_Sync(0 - val) - val; } 7.703 7.704 inline T operator ++ () { return ExchangeAdd_Sync((T)1) + 1; } 7.705 inline T operator -- () { return ExchangeAdd_Sync(((T)0)-1) - 1; } 7.706 inline T operator ++ (int) { return ExchangeAdd_Sync((T)1); } 7.707 inline T operator -- (int) { return ExchangeAdd_Sync(((T)0)-1); } 7.708 7.709 // More complex atomic operations. Leave it to compiler whether to optimize them or not. 7.710 T operator &= (T arg) 7.711 { 7.712 T comp, newVal; 7.713 do { 7.714 comp = this->Value; 7.715 newVal = comp & arg; 7.716 } while(!this->CompareAndSet_Sync(comp, newVal)); 7.717 return newVal; 7.718 } 7.719 7.720 T operator |= (T arg) 7.721 { 7.722 T comp, newVal; 7.723 do { 7.724 comp = this->Value; 7.725 newVal = comp | arg; 7.726 } while(!this->CompareAndSet_Sync(comp, newVal)); 7.727 return newVal; 7.728 } 7.729 7.730 T operator ^= (T arg) 7.731 { 7.732 T comp, newVal; 7.733 do { 7.734 comp = this->Value; 7.735 newVal = comp ^ arg; 7.736 } while(!this->CompareAndSet_Sync(comp, newVal)); 7.737 return newVal; 7.738 } 7.739 7.740 T operator *= (T arg) 7.741 { 7.742 T comp, newVal; 7.743 do { 7.744 comp = this->Value; 7.745 newVal = comp * arg; 7.746 } while(!this->CompareAndSet_Sync(comp, newVal)); 7.747 return newVal; 7.748 } 7.749 7.750 T operator /= (T arg) 7.751 { 7.752 T comp, newVal; 7.753 do { 7.754 comp = this->Value; 7.755 newVal = comp / arg; 7.756 } while(!CompareAndSet_Sync(comp, newVal)); 7.757 return newVal; 7.758 } 7.759 7.760 T operator >>= (unsigned bits) 7.761 { 7.762 T comp, newVal; 7.763 do { 7.764 comp = this->Value; 7.765 newVal = comp >> bits; 7.766 } while(!CompareAndSet_Sync(comp, newVal)); 7.767 return newVal; 7.768 } 7.769 7.770 T operator <<= (unsigned bits) 7.771 { 7.772 T comp, newVal; 7.773 do { 7.774 comp = this->Value; 7.775 newVal = comp << bits; 7.776 } while(!this->CompareAndSet_Sync(comp, newVal)); 7.777 return newVal; 7.778 } 7.779 }; 7.780 7.781 7.782 7.783 //----------------------------------------------------------------------------------- 7.784 // ***** Lock 7.785 7.786 // Lock is a simplest and most efficient mutual-exclusion lock class. 7.787 // Unlike Mutex, it cannot be waited on. 7.788 7.789 class Lock 7.790 { 7.791 // NOTE: Locks are not allocatable and they themselves should not allocate 7.792 // memory by standard means. This is the case because StandardAllocator 7.793 // relies on this class. 7.794 // Make 'delete' private. Don't do this for 'new' since it can be redefined. 7.795 void operator delete(void*) {} 7.796 7.797 7.798 // *** Lock implementation for various platforms. 7.799 7.800 #if !defined(OVR_ENABLE_THREADS) 7.801 7.802 public: 7.803 // With no thread support, lock does nothing. 7.804 inline Lock() { } 7.805 inline Lock(unsigned) { } 7.806 inline ~Lock() { } 7.807 inline void DoLock() { } 7.808 inline void Unlock() { } 7.809 7.810 // Windows. 7.811 #elif defined(OVR_OS_WIN32) 7.812 7.813 CRITICAL_SECTION cs; 7.814 public: 7.815 Lock(unsigned spinCount = 0); 7.816 ~Lock(); 7.817 // Locking functions. 7.818 inline void DoLock() { ::EnterCriticalSection(&cs); } 7.819 inline void Unlock() { ::LeaveCriticalSection(&cs); } 7.820 7.821 #else 7.822 pthread_mutex_t mutex; 7.823 7.824 public: 7.825 static pthread_mutexattr_t RecursiveAttr; 7.826 static bool RecursiveAttrInit; 7.827 7.828 Lock (unsigned dummy = 0) 7.829 { 7.830 if (!RecursiveAttrInit) 7.831 { 7.832 pthread_mutexattr_init(&RecursiveAttr); 7.833 pthread_mutexattr_settype(&RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 7.834 RecursiveAttrInit = 1; 7.835 } 7.836 pthread_mutex_init(&mutex,&RecursiveAttr); 7.837 } 7.838 ~Lock () { pthread_mutex_destroy(&mutex); } 7.839 inline void DoLock() { pthread_mutex_lock(&mutex); } 7.840 inline void Unlock() { pthread_mutex_unlock(&mutex); } 7.841 7.842 #endif // OVR_ENABLE_THREDS 7.843 7.844 7.845 public: 7.846 // Locker class, used for automatic locking 7.847 class Locker 7.848 { 7.849 public: 7.850 Lock *pLock; 7.851 inline Locker(Lock *plock) 7.852 { pLock = plock; pLock->DoLock(); } 7.853 inline ~Locker() 7.854 { pLock->Unlock(); } 7.855 }; 7.856 }; 7.857 7.858 7.859 7.860 } // OVR 7.861 7.862 #endif 7.863 \ No newline at end of file 7.864 +/************************************************************************************ 7.865 + 7.866 +PublicHeader: OVR.h 7.867 +Filename : OVR_Atomic.h 7.868 +Content : Contains atomic operations and inline fastest locking 7.869 + functionality. Will contain #ifdefs for OS efficiency. 7.870 + Have non-thread-safe implementaion if not available. 7.871 +Created : September 19, 2012 7.872 +Notes : 7.873 + 7.874 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 7.875 + 7.876 +Use of this software is subject to the terms of the Oculus license 7.877 +agreement provided at the time of installation or download, or which 7.878 +otherwise accompanies this software in either electronic or hard copy form. 7.879 + 7.880 +************************************************************************************/ 7.881 +#ifndef OVR_Atomic_h 7.882 +#define OVR_Atomic_h 7.883 + 7.884 +#include "OVR_Types.h" 7.885 + 7.886 +// Include System thread functionality. 7.887 +#if defined(OVR_OS_WIN32) 7.888 +#include <windows.h> 7.889 +#else 7.890 +#include <pthread.h> 7.891 +#endif 7.892 + 7.893 + 7.894 +namespace OVR { 7.895 + 7.896 + 7.897 +// ****** Declared classes 7.898 + 7.899 +// If there is NO thread support we implement AtomicOps and 7.900 +// Lock objects as no-ops. The other classes are not defined. 7.901 +template<class C> class AtomicOps; 7.902 +template<class T> class AtomicInt; 7.903 +template<class T> class AtomicPtr; 7.904 + 7.905 +class Lock; 7.906 + 7.907 + 7.908 +//----------------------------------------------------------------------------------- 7.909 +// ***** AtomicOps 7.910 + 7.911 +// Atomic operations are provided by the AtomicOps templates class, 7.912 +// implemented through system-specific AtomicOpsRaw specializations. 7.913 +// It provides several fundamental operations such as Exchange, ExchangeAdd 7.914 +// CompareAndSet, and Store_Release. Each function includes several memory 7.915 +// synchronization versions, important for multiprocessing CPUs with weak 7.916 +// memory consistency. The following memory fencing strategies are supported: 7.917 +// 7.918 +// - NoSync. No memory synchronization is done for atomic op. 7.919 +// - Release. All other memory writes are completed before atomic op 7.920 +// writes its results. 7.921 +// - Acquire. Further memory reads are forced to wait until atomic op 7.922 +// executes, guaranteeing that the right values will be seen. 7.923 +// - Sync. A combination of Release and Acquire. 7.924 + 7.925 + 7.926 +// *** AtomicOpsRaw 7.927 + 7.928 +// AtomicOpsRaw is a specialized template that provides atomic operations 7.929 +// used by AtomicOps. This class has two fundamental qualities: (1) it 7.930 +// defines a type T of correct size, and (2) provides operations that work 7.931 +// atomically, such as Exchange_Sync and CompareAndSet_Release. 7.932 + 7.933 +// AtomicOpsRawBase class contains shared constants/classes for AtomicOpsRaw. 7.934 +// The primary thing is does is define sync class objects, whose destructor and 7.935 +// constructor provide places to insert appropriate synchronization calls, on 7.936 +// systems where such calls are necessary. So far, the breakdown is as follows: 7.937 +// 7.938 +// - X86 systems don't need custom syncs, since their exchange/atomic 7.939 +// instructions are implicitly synchronized. 7.940 +// - PowerPC requires lwsync/isync instructions that can use this mechanism. 7.941 +// - If some other systems require a mechanism where syncing type is associated 7.942 +// with a particular instruction, the default implementation (which implements 7.943 +// all Sync, Acquire, and Release modes in terms of NoSync and fence) may not 7.944 +// work. Ii that case it will need to be #ifdef-ed conditionally. 7.945 + 7.946 +struct AtomicOpsRawBase 7.947 +{ 7.948 +#if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_OS_WIN32) || defined(OVR_OS_IPHONE) 7.949 + // Need to have empty constructor to avoid class 'unused' variable warning. 7.950 + struct FullSync { inline FullSync() { } }; 7.951 + struct AcquireSync { inline AcquireSync() { } }; 7.952 + struct ReleaseSync { inline ReleaseSync() { } }; 7.953 + 7.954 +#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) 7.955 + struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("isync\n"); } }; 7.956 + struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("isync\n"); } }; 7.957 + struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } }; 7.958 + 7.959 +#elif defined(OVR_CPU_MIPS) 7.960 + struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("sync\n"); } }; 7.961 + struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } }; 7.962 + struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } }; 7.963 + 7.964 +#elif defined(OVR_CPU_ARM) 7.965 + struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } }; 7.966 + struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } }; 7.967 + struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } }; 7.968 + 7.969 + 7.970 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4) 7.971 + // __sync functions are already full sync 7.972 + struct FullSync { inline FullSync() { } }; 7.973 + struct AcquireSync { inline AcquireSync() { } }; 7.974 + struct ReleaseSync { inline ReleaseSync() { } }; 7.975 +#endif 7.976 +}; 7.977 + 7.978 + 7.979 +// 4-Byte raw data atomic op implementation class. 7.980 +struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase 7.981 +{ 7.982 +#if !defined(OVR_ENABLE_THREADS) 7.983 + 7.984 + // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. 7.985 + typedef UInt32 T; 7.986 + 7.987 + // *** Thread - Safe Atomic Versions. 7.988 + 7.989 +#elif defined(OVR_OS_WIN32) 7.990 + 7.991 + // Use special defined for VC6, where volatile is not used and 7.992 + // InterlockedCompareExchange is declared incorrectly. 7.993 + typedef LONG T; 7.994 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC < 1300) 7.995 + typedef T* InterlockTPtr; 7.996 + typedef LPVOID ET; 7.997 + typedef ET* InterlockETPtr; 7.998 +#else 7.999 + typedef volatile T* InterlockTPtr; 7.1000 + typedef T ET; 7.1001 + typedef InterlockTPtr InterlockETPtr; 7.1002 +#endif 7.1003 + inline static T Exchange_NoSync(volatile T* p, T val) { return InterlockedExchange((InterlockTPtr)p, val); } 7.1004 + inline static T ExchangeAdd_NoSync(volatile T* p, T val) { return InterlockedExchangeAdd((InterlockTPtr)p, val); } 7.1005 + inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; } 7.1006 + 7.1007 +#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC) 7.1008 + typedef UInt32 T; 7.1009 + static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.1010 + { 7.1011 + UInt32 ret; 7.1012 + 7.1013 + asm volatile("1:\n\t" 7.1014 + "lwarx %[r],0,%[i]\n\t" 7.1015 + "stwcx. %[j],0,%[i]\n\t" 7.1016 + "bne- 1b\n" 7.1017 + : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [j] "b" (j) : "cc", "memory"); 7.1018 + 7.1019 + return ret; 7.1020 + } 7.1021 + 7.1022 + static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.1023 + { 7.1024 + UInt32 dummy, ret; 7.1025 + 7.1026 + asm volatile("1:\n\t" 7.1027 + "lwarx %[r],0,%[i]\n\t" 7.1028 + "add %[o],%[r],%[j]\n\t" 7.1029 + "stwcx. %[o],0,%[i]\n\t" 7.1030 + "bne- 1b\n" 7.1031 + : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc", "memory"); 7.1032 + 7.1033 + return ret; 7.1034 + } 7.1035 + 7.1036 + static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.1037 + { 7.1038 + UInt32 ret; 7.1039 + 7.1040 + asm volatile("1:\n\t" 7.1041 + "lwarx %[r],0,%[i]\n\t" 7.1042 + "cmpw 0,%[r],%[cmp]\n\t" 7.1043 + "mfcr %[r]\n\t" 7.1044 + "bne- 2f\n\t" 7.1045 + "stwcx. %[val],0,%[i]\n\t" 7.1046 + "bne- 1b\n\t" 7.1047 + "2:\n" 7.1048 + : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc", "memory"); 7.1049 + 7.1050 + return (ret & 0x20000000) ? 1 : 0; 7.1051 + } 7.1052 + 7.1053 +#elif defined(OVR_CPU_MIPS) 7.1054 + typedef UInt32 T; 7.1055 + 7.1056 + static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.1057 + { 7.1058 + UInt32 ret; 7.1059 + 7.1060 + asm volatile("1:\n\t" 7.1061 + "ll %[r],0(%[i])\n\t" 7.1062 + "sc %[j],0(%[i])\n\t" 7.1063 + "beq %[j],$0,1b\n\t" 7.1064 + "nop \n" 7.1065 + : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory"); 7.1066 + 7.1067 + return ret; 7.1068 + } 7.1069 + 7.1070 + static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.1071 + { 7.1072 + UInt32 ret; 7.1073 + 7.1074 + asm volatile("1:\n\t" 7.1075 + "ll %[r],0(%[i])\n\t" 7.1076 + "addu %[j],%[r],%[j]\n\t" 7.1077 + "sc %[j],0(%[i])\n\t" 7.1078 + "beq %[j],$0,1b\n\t" 7.1079 + "nop \n" 7.1080 + : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory"); 7.1081 + 7.1082 + return ret; 7.1083 + } 7.1084 + 7.1085 + static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.1086 + { 7.1087 + UInt32 ret, dummy; 7.1088 + 7.1089 + asm volatile("1:\n\t" 7.1090 + "move %[r],$0\n\t" 7.1091 + "ll %[o],0(%[i])\n\t" 7.1092 + "bne %[o],%[c],2f\n\t" 7.1093 + "move %[r],%[v]\n\t" 7.1094 + "sc %[r],0(%[i])\n\t" 7.1095 + "beq %[r],$0,1b\n\t" 7.1096 + "nop \n\t" 7.1097 + "2:\n" 7.1098 + : "+m" (*i),[r] "=&d" (ret), [o] "=&d" (dummy) : [i] "d" (i), [c] "d" (c), [v] "d" (value) 7.1099 + : "cc", "memory"); 7.1100 + 7.1101 + return ret; 7.1102 + } 7.1103 + 7.1104 +#elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM) 7.1105 + typedef UInt32 T; 7.1106 + 7.1107 + static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.1108 + { 7.1109 + for(;;) 7.1110 + { 7.1111 + T r = __ldrex(i); 7.1112 + if (__strex(j, i) == 0) 7.1113 + return r; 7.1114 + } 7.1115 + } 7.1116 + static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.1117 + { 7.1118 + for(;;) 7.1119 + { 7.1120 + T r = __ldrex(i); 7.1121 + if (__strex(r + j, i) == 0) 7.1122 + return r; 7.1123 + } 7.1124 + } 7.1125 + 7.1126 + static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.1127 + { 7.1128 + for(;;) 7.1129 + { 7.1130 + T r = __ldrex(i); 7.1131 + if (r != c) 7.1132 + return 0; 7.1133 + if (__strex(value, i) == 0) 7.1134 + return 1; 7.1135 + } 7.1136 + } 7.1137 + 7.1138 +#elif defined(OVR_CPU_ARM) 7.1139 + typedef UInt32 T; 7.1140 + 7.1141 + static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.1142 + { 7.1143 + UInt32 ret, dummy; 7.1144 + 7.1145 + asm volatile("1:\n\t" 7.1146 + "ldrex %[r],[%[i]]\n\t" 7.1147 + "strex %[t],%[j],[%[i]]\n\t" 7.1148 + "cmp %[t],#0\n\t" 7.1149 + "bne 1b\n\t" 7.1150 + : "+m" (*i), [r] "=&r" (ret), [t] "=&r" (dummy) : [i] "r" (i), [j] "r" (j) : "cc", "memory"); 7.1151 + 7.1152 + return ret; 7.1153 + } 7.1154 + 7.1155 + static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.1156 + { 7.1157 + UInt32 ret, dummy, test; 7.1158 + 7.1159 + asm volatile("1:\n\t" 7.1160 + "ldrex %[r],[%[i]]\n\t" 7.1161 + "add %[o],%[r],%[j]\n\t" 7.1162 + "strex %[t],%[o],[%[i]]\n\t" 7.1163 + "cmp %[t],#0\n\t" 7.1164 + "bne 1b\n\t" 7.1165 + : "+m" (*i), [r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [j] "r" (j) : "cc", "memory"); 7.1166 + 7.1167 + return ret; 7.1168 + } 7.1169 + 7.1170 + static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.1171 + { 7.1172 + UInt32 ret = 1, dummy, test; 7.1173 + 7.1174 + asm volatile("1:\n\t" 7.1175 + "ldrex %[o],[%[i]]\n\t" 7.1176 + "cmp %[o],%[c]\n\t" 7.1177 + "bne 2f\n\t" 7.1178 + "strex %[r],%[v],[%[i]]\n\t" 7.1179 + "cmp %[r],#0\n\t" 7.1180 + "bne 1b\n\t" 7.1181 + "2:\n" 7.1182 + : "+m" (*i),[r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [c] "r" (c), [v] "r" (value) 7.1183 + : "cc", "memory"); 7.1184 + 7.1185 + return !ret; 7.1186 + } 7.1187 + 7.1188 +#elif defined(OVR_CPU_X86) 7.1189 + typedef UInt32 T; 7.1190 + 7.1191 + static inline UInt32 Exchange_NoSync(volatile UInt32 *i, UInt32 j) 7.1192 + { 7.1193 + asm volatile("xchgl %1,%[i]\n" 7.1194 + : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory"); 7.1195 + 7.1196 + return j; 7.1197 + } 7.1198 + 7.1199 + static inline UInt32 ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j) 7.1200 + { 7.1201 + asm volatile("lock; xaddl %1,%[i]\n" 7.1202 + : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory"); 7.1203 + 7.1204 + return j; 7.1205 + } 7.1206 + 7.1207 + static inline bool CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value) 7.1208 + { 7.1209 + UInt32 ret; 7.1210 + 7.1211 + asm volatile("lock; cmpxchgl %[v],%[i]\n" 7.1212 + : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory"); 7.1213 + 7.1214 + return (ret == c); 7.1215 + } 7.1216 + 7.1217 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) 7.1218 + 7.1219 + typedef UInt32 T; 7.1220 + 7.1221 + static inline T Exchange_NoSync(volatile T *i, T j) 7.1222 + { 7.1223 + T v; 7.1224 + do { 7.1225 + v = *i; 7.1226 + } while (!__sync_bool_compare_and_swap(i, v, j)); 7.1227 + return v; 7.1228 + } 7.1229 + 7.1230 + static inline T ExchangeAdd_NoSync(volatile T *i, T j) 7.1231 + { 7.1232 + return __sync_fetch_and_add(i, j); 7.1233 + } 7.1234 + 7.1235 + static inline bool CompareAndSet_NoSync(volatile T *i, T c, T value) 7.1236 + { 7.1237 + return __sync_bool_compare_and_swap(i, c, value); 7.1238 + } 7.1239 + 7.1240 +#endif // OS 7.1241 +}; 7.1242 + 7.1243 + 7.1244 +// 8-Byte raw data data atomic op implementation class. 7.1245 +// Currently implementation is provided only on systems with 64-bit pointers. 7.1246 +struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase 7.1247 +{ 7.1248 +#if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS) 7.1249 + 7.1250 + // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl. 7.1251 + typedef UInt64 T; 7.1252 + 7.1253 + // *** Thread - Safe OS specific versions. 7.1254 +#elif defined(OVR_OS_WIN32) 7.1255 + 7.1256 + // This is only for 64-bit systems. 7.1257 + typedef LONG64 T; 7.1258 + typedef volatile T* InterlockTPtr; 7.1259 + inline static T Exchange_NoSync(volatile T* p, T val) { return InterlockedExchange64((InterlockTPtr)p, val); } 7.1260 + inline static T ExchangeAdd_NoSync(volatile T* p, T val) { return InterlockedExchangeAdd64((InterlockTPtr)p, val); } 7.1261 + inline static bool CompareAndSet_NoSync(volatile T* p, T c, T val) { return InterlockedCompareExchange64((InterlockTPtr)p, val, c) == c; } 7.1262 + 7.1263 +#elif defined(OVR_CPU_PPC64) 7.1264 + 7.1265 + typedef UInt64 T; 7.1266 + 7.1267 + static inline UInt64 Exchange_NoSync(volatile UInt64 *i, UInt64 j) 7.1268 + { 7.1269 + UInt64 dummy, ret; 7.1270 + 7.1271 + asm volatile("1:\n\t" 7.1272 + "ldarx %[r],0,%[i]\n\t" 7.1273 + "mr %[o],%[j]\n\t" 7.1274 + "stdcx. %[o],0,%[i]\n\t" 7.1275 + "bne- 1b\n" 7.1276 + : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc"); 7.1277 + 7.1278 + return ret; 7.1279 + } 7.1280 + 7.1281 + static inline UInt64 ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j) 7.1282 + { 7.1283 + UInt64 dummy, ret; 7.1284 + 7.1285 + asm volatile("1:\n\t" 7.1286 + "ldarx %[r],0,%[i]\n\t" 7.1287 + "add %[o],%[r],%[j]\n\t" 7.1288 + "stdcx. %[o],0,%[i]\n\t" 7.1289 + "bne- 1b\n" 7.1290 + : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc"); 7.1291 + 7.1292 + return ret; 7.1293 + } 7.1294 + 7.1295 + static inline bool CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value) 7.1296 + { 7.1297 + UInt64 ret, dummy; 7.1298 + 7.1299 + asm volatile("1:\n\t" 7.1300 + "ldarx %[r],0,%[i]\n\t" 7.1301 + "cmpw 0,%[r],%[cmp]\n\t" 7.1302 + "mfcr %[r]\n\t" 7.1303 + "bne- 2f\n\t" 7.1304 + "stdcx. %[val],0,%[i]\n\t" 7.1305 + "bne- 1b\n\t" 7.1306 + "2:\n" 7.1307 + : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc"); 7.1308 + 7.1309 + return (ret & 0x20000000) ? 1 : 0; 7.1310 + } 7.1311 + 7.1312 +#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1) 7.1313 + 7.1314 + typedef UInt64 T; 7.1315 + 7.1316 + static inline T Exchange_NoSync(volatile T *i, T j) 7.1317 + { 7.1318 + T v; 7.1319 + do { 7.1320 + v = *i; 7.1321 + } while (!__sync_bool_compare_and_swap(i, v, j)); 7.1322 + return v; 7.1323 + } 7.1324 + 7.1325 + static inline T ExchangeAdd_NoSync(volatile T *i, T j) 7.1326 + { 7.1327 + return __sync_fetch_and_add(i, j); 7.1328 + } 7.1329 + 7.1330 + static inline bool CompareAndSet_NoSync(volatile T *i, T c, T value) 7.1331 + { 7.1332 + return __sync_bool_compare_and_swap(i, c, value); 7.1333 + } 7.1334 + 7.1335 +#endif // OS 7.1336 +}; 7.1337 + 7.1338 + 7.1339 +// Default implementation for AtomicOpsRaw; provides implementation of mem-fenced 7.1340 +// atomic operations where fencing is done with a sync object wrapped around a NoSync 7.1341 +// operation implemented in the base class. If such implementation is not possible 7.1342 +// on a given platform, #ifdefs can be used to disable it and then op functions can be 7.1343 +// implemented individually in the appropriate AtomicOpsRaw<size> class. 7.1344 + 7.1345 +template<class O> 7.1346 +struct AtomicOpsRaw_DefImpl : public O 7.1347 +{ 7.1348 + typedef typename O::T O_T; 7.1349 + typedef typename O::FullSync O_FullSync; 7.1350 + typedef typename O::AcquireSync O_AcquireSync; 7.1351 + typedef typename O::ReleaseSync O_ReleaseSync; 7.1352 + 7.1353 + // If there is no thread support, provide the default implementation. In this case, 7.1354 + // the base class (0) must still provide the T declaration. 7.1355 +#ifndef OVR_ENABLE_THREADS 7.1356 + 7.1357 + // Atomic exchange of val with argument. Returns old val. 7.1358 + inline static O_T Exchange_NoSync(volatile O_T* p, O_T val) { O_T old = *p; *p = val; return old; } 7.1359 + // Adds a new val to argument; returns its old val. 7.1360 + inline static O_T ExchangeAdd_NoSync(volatile O_T* p, O_T val) { O_T old = *p; *p += val; return old; } 7.1361 + // Compares the argument data with 'c' val. 7.1362 + // If succeeded, stores val int '*p' and returns true; otherwise returns false. 7.1363 + inline static bool CompareAndSet_NoSync(volatile O_T* p, O_T c, O_T val) { if (*p==c) { *p = val; return 1; } return 0; } 7.1364 + 7.1365 +#endif 7.1366 + 7.1367 + // If NoSync wrapped implementation may not be possible, it this block should be 7.1368 + // replaced with per-function implementation in O. 7.1369 + // "AtomicOpsRaw_DefImpl<O>::" prefix in calls below. 7.1370 + inline static O_T Exchange_Sync(volatile O_T* p, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.1371 + inline static O_T Exchange_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.1372 + inline static O_T Exchange_Acquire(volatile O_T* p, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); } 7.1373 + inline static O_T ExchangeAdd_Sync(volatile O_T* p, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.1374 + inline static O_T ExchangeAdd_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.1375 + inline static O_T ExchangeAdd_Acquire(volatile O_T* p, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); } 7.1376 + inline static bool CompareAndSet_Sync(volatile O_T* p, O_T c, O_T val) { O_FullSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.1377 + inline static bool CompareAndSet_Release(volatile O_T* p, O_T c, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.1378 + inline static bool CompareAndSet_Acquire(volatile O_T* p, O_T c, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); } 7.1379 + 7.1380 + // Loads and stores with memory fence. These have only the relevant versions. 7.1381 +#ifdef OVR_CPU_X86 7.1382 + // On X86, Store_Release is implemented as exchange. Note that we can also 7.1383 + // consider 'sfence' in the future, although it is not as compatible with older CPUs. 7.1384 + inline static void Store_Release(volatile O_T* p, O_T val) { Exchange_Release(p, val); } 7.1385 +#else 7.1386 + inline static void Store_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; } 7.1387 +#endif 7.1388 + inline static O_T Load_Acquire(const volatile O_T* p) { O_AcquireSync sync; OVR_UNUSED(sync); return *p; } 7.1389 +}; 7.1390 + 7.1391 + 7.1392 +template<int size> 7.1393 +struct AtomicOpsRaw : public AtomicOpsRawBase { }; 7.1394 + 7.1395 +template<> 7.1396 +struct AtomicOpsRaw<4> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl> 7.1397 +{ 7.1398 + // Ensure that assigned type size is correct. 7.1399 + AtomicOpsRaw() 7.1400 + { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>::T) == 4); } 7.1401 +}; 7.1402 +template<> 7.1403 +struct AtomicOpsRaw<8> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl> 7.1404 +{ 7.1405 + AtomicOpsRaw() 7.1406 + { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>::T) == 8); } 7.1407 +}; 7.1408 + 7.1409 + 7.1410 +// *** AtomicOps - implementation of atomic Ops for specified class 7.1411 + 7.1412 +// Implements atomic ops on a class, provided that the object is either 7.1413 +// 4 or 8 bytes in size (depending on the AtomicOpsRaw specializations 7.1414 +// available). Relies on AtomicOpsRaw for much of implementation. 7.1415 + 7.1416 +template<class C> 7.1417 +class AtomicOps 7.1418 +{ 7.1419 + typedef AtomicOpsRaw<sizeof(C)> Ops; 7.1420 + typedef typename Ops::T T; 7.1421 + typedef volatile typename Ops::T* PT; 7.1422 + // We cast through unions to (1) avoid pointer size compiler warnings 7.1423 + // and (2) ensure that there are no problems with strict pointer aliasing. 7.1424 + union C2T_union { C c; T t; }; 7.1425 + 7.1426 +public: 7.1427 + // General purpose implementation for standard syncs. 7.1428 + inline static C Exchange_Sync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Sync((PT)p, u.t); return u.c; } 7.1429 + inline static C Exchange_Release(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Release((PT)p, u.t); return u.c; } 7.1430 + inline static C Exchange_Acquire(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_Acquire((PT)p, u.t); return u.c; } 7.1431 + inline static C Exchange_NoSync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::Exchange_NoSync((PT)p, u.t); return u.c; } 7.1432 + inline static C ExchangeAdd_Sync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Sync((PT)p, u.t); return u.c; } 7.1433 + inline static C ExchangeAdd_Release(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Release((PT)p, u.t); return u.c; } 7.1434 + inline static C ExchangeAdd_Acquire(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Acquire((PT)p, u.t); return u.c; } 7.1435 + inline static C ExchangeAdd_NoSync(volatile C* p, C val) { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_NoSync((PT)p, u.t); return u.c; } 7.1436 + inline static bool CompareAndSet_Sync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Sync((PT)p, cu.t, u.t); } 7.1437 + inline static bool CompareAndSet_Release(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Release((PT)p, cu.t, u.t); } 7.1438 + inline static bool CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); } 7.1439 + inline static bool CompareAndSet_NoSync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_NoSync((PT)p, cu.t, u.t); } 7.1440 + // Loads and stores with memory fence. These have only the relevant versions. 7.1441 + inline static void Store_Release(volatile C* p, C val) { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); } 7.1442 + inline static C Load_Acquire(const volatile C* p) { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; } 7.1443 +}; 7.1444 + 7.1445 + 7.1446 + 7.1447 +// Atomic value base class - implements operations shared for integers and pointers. 7.1448 +template<class T> 7.1449 +class AtomicValueBase 7.1450 +{ 7.1451 +protected: 7.1452 + typedef AtomicOps<T> Ops; 7.1453 +public: 7.1454 + 7.1455 + volatile T Value; 7.1456 + 7.1457 + inline AtomicValueBase() { } 7.1458 + explicit inline AtomicValueBase(T val) { Ops::Store_Release(&Value, val); } 7.1459 + 7.1460 + // Most libraries (TBB and Joshua Scholar's) library do not do Load_Acquire 7.1461 + // here, since most algorithms do not require atomic loads. Needs some research. 7.1462 + inline operator T() const { return Value; } 7.1463 + 7.1464 + // *** Standard Atomic inlines 7.1465 + inline T Exchange_Sync(T val) { return Ops::Exchange_Sync(&Value, val); } 7.1466 + inline T Exchange_Release(T val) { return Ops::Exchange_Release(&Value, val); } 7.1467 + inline T Exchange_Acquire(T val) { return Ops::Exchange_Acquire(&Value, val); } 7.1468 + inline T Exchange_NoSync(T val) { return Ops::Exchange_NoSync(&Value, val); } 7.1469 + inline bool CompareAndSet_Sync(T c, T val) { return Ops::CompareAndSet_Sync(&Value, c, val); } 7.1470 + inline bool CompareAndSet_Release(T c, T val) { return Ops::CompareAndSet_Release(&Value, c, val); } 7.1471 + inline bool CompareAndSet_Acquire(T c, T val) { return Ops::CompareAndSet_Relse(&Value, c, val); } 7.1472 + inline bool CompareAndSet_NoSync(T c, T val) { return Ops::CompareAndSet_NoSync(&Value, c, val); } 7.1473 + // Load & Store. 7.1474 + inline void Store_Release(T val) { Ops::Store_Release(&Value, val); } 7.1475 + inline T Load_Acquire() const { return Ops::Load_Acquire(&Value); } 7.1476 +}; 7.1477 + 7.1478 + 7.1479 +// ***** AtomicPtr - Atomic pointer template 7.1480 + 7.1481 +// This pointer class supports atomic assignments with release, 7.1482 +// increment / decrement operations, and conditional compare + set. 7.1483 + 7.1484 +template<class T> 7.1485 +class AtomicPtr : public AtomicValueBase<T*> 7.1486 +{ 7.1487 + typedef typename AtomicValueBase<T*>::Ops Ops; 7.1488 + 7.1489 +public: 7.1490 + // Initialize pointer value to 0 by default; use Store_Release only with explicit constructor. 7.1491 + inline AtomicPtr() : AtomicValueBase<T*>() { this->Value = 0; } 7.1492 + explicit inline AtomicPtr(T* val) : AtomicValueBase<T*>(val) { } 7.1493 + 7.1494 + // Pointer access. 7.1495 + inline T* operator -> () const { return this->Load_Acquire(); } 7.1496 + 7.1497 + // It looks like it is convenient to have Load_Acquire characteristics 7.1498 + // for this, since that is convenient for algorithms such as linked 7.1499 + // list traversals that can be added to bu another thread. 7.1500 + inline operator T* () const { return this->Load_Acquire(); } 7.1501 + 7.1502 + 7.1503 + // *** Standard Atomic inlines (applicable to pointers) 7.1504 + 7.1505 + // ExhangeAdd considers pointer size for pointers. 7.1506 + template<class I> 7.1507 + inline T* ExchangeAdd_Sync(I incr) { return Ops::ExchangeAdd_Sync(&this->Value, ((T*)0) + incr); } 7.1508 + template<class I> 7.1509 + inline T* ExchangeAdd_Release(I incr) { return Ops::ExchangeAdd_Release(&this->Value, ((T*)0) + incr); } 7.1510 + template<class I> 7.1511 + inline T* ExchangeAdd_Acquire(I incr) { return Ops::ExchangeAdd_Acquire(&this->Value, ((T*)0) + incr); } 7.1512 + template<class I> 7.1513 + inline T* ExchangeAdd_NoSync(I incr) { return Ops::ExchangeAdd_NoSync(&this->Value, ((T*)0) + incr); } 7.1514 + 7.1515 + // *** Atomic Operators 7.1516 + 7.1517 + inline T* operator = (T* val) { this->Store_Release(val); return val; } 7.1518 + 7.1519 + template<class I> 7.1520 + inline T* operator += (I val) { return ExchangeAdd_Sync(val) + val; } 7.1521 + template<class I> 7.1522 + inline T* operator -= (I val) { return operator += (-val); } 7.1523 + 7.1524 + inline T* operator ++ () { return ExchangeAdd_Sync(1) + 1; } 7.1525 + inline T* operator -- () { return ExchangeAdd_Sync(-1) - 1; } 7.1526 + inline T* operator ++ (int) { return ExchangeAdd_Sync(1); } 7.1527 + inline T* operator -- (int) { return ExchangeAdd_Sync(-1); } 7.1528 +}; 7.1529 + 7.1530 + 7.1531 +// ***** AtomicInt - Atomic integer template 7.1532 + 7.1533 +// Implements an atomic integer type; the exact type to use is provided 7.1534 +// as an argument. Supports atomic Acquire / Release semantics, atomic 7.1535 +// arithmetic operations, and atomic conditional compare + set. 7.1536 + 7.1537 +template<class T> 7.1538 +class AtomicInt : public AtomicValueBase<T> 7.1539 +{ 7.1540 + typedef typename AtomicValueBase<T>::Ops Ops; 7.1541 + 7.1542 +public: 7.1543 + inline AtomicInt() : AtomicValueBase<T>() { } 7.1544 + explicit inline AtomicInt(T val) : AtomicValueBase<T>(val) { } 7.1545 + 7.1546 + 7.1547 + // *** Standard Atomic inlines (applicable to int) 7.1548 + inline T ExchangeAdd_Sync(T val) { return Ops::ExchangeAdd_Sync(&this->Value, val); } 7.1549 + inline T ExchangeAdd_Release(T val) { return Ops::ExchangeAdd_Release(&this->Value, val); } 7.1550 + inline T ExchangeAdd_Acquire(T val) { return Ops::ExchangeAdd_Acquire(&this->Value, val); } 7.1551 + inline T ExchangeAdd_NoSync(T val) { return Ops::ExchangeAdd_NoSync(&this->Value, val); } 7.1552 + // These increments could be more efficient because they don't return a value. 7.1553 + inline void Increment_Sync() { ExchangeAdd_Sync((T)1); } 7.1554 + inline void Increment_Release() { ExchangeAdd_Release((T)1); } 7.1555 + inline void Increment_Acquire() { ExchangeAdd_Acquire((T)1); } 7.1556 + inline void Increment_NoSync() { ExchangeAdd_NoSync((T)1); } 7.1557 + 7.1558 + // *** Atomic Operators 7.1559 + 7.1560 + inline T operator = (T val) { this->Store_Release(val); return val; } 7.1561 + inline T operator += (T val) { return ExchangeAdd_Sync(val) + val; } 7.1562 + inline T operator -= (T val) { return ExchangeAdd_Sync(0 - val) - val; } 7.1563 + 7.1564 + inline T operator ++ () { return ExchangeAdd_Sync((T)1) + 1; } 7.1565 + inline T operator -- () { return ExchangeAdd_Sync(((T)0)-1) - 1; } 7.1566 + inline T operator ++ (int) { return ExchangeAdd_Sync((T)1); } 7.1567 + inline T operator -- (int) { return ExchangeAdd_Sync(((T)0)-1); } 7.1568 + 7.1569 + // More complex atomic operations. Leave it to compiler whether to optimize them or not. 7.1570 + T operator &= (T arg) 7.1571 + { 7.1572 + T comp, newVal; 7.1573 + do { 7.1574 + comp = this->Value; 7.1575 + newVal = comp & arg; 7.1576 + } while(!this->CompareAndSet_Sync(comp, newVal)); 7.1577 + return newVal; 7.1578 + } 7.1579 + 7.1580 + T operator |= (T arg) 7.1581 + { 7.1582 + T comp, newVal; 7.1583 + do { 7.1584 + comp = this->Value; 7.1585 + newVal = comp | arg; 7.1586 + } while(!this->CompareAndSet_Sync(comp, newVal)); 7.1587 + return newVal; 7.1588 + } 7.1589 + 7.1590 + T operator ^= (T arg) 7.1591 + { 7.1592 + T comp, newVal; 7.1593 + do { 7.1594 + comp = this->Value; 7.1595 + newVal = comp ^ arg; 7.1596 + } while(!this->CompareAndSet_Sync(comp, newVal)); 7.1597 + return newVal; 7.1598 + } 7.1599 + 7.1600 + T operator *= (T arg) 7.1601 + { 7.1602 + T comp, newVal; 7.1603 + do { 7.1604 + comp = this->Value; 7.1605 + newVal = comp * arg; 7.1606 + } while(!this->CompareAndSet_Sync(comp, newVal)); 7.1607 + return newVal; 7.1608 + } 7.1609 + 7.1610 + T operator /= (T arg) 7.1611 + { 7.1612 + T comp, newVal; 7.1613 + do { 7.1614 + comp = this->Value; 7.1615 + newVal = comp / arg; 7.1616 + } while(!CompareAndSet_Sync(comp, newVal)); 7.1617 + return newVal; 7.1618 + } 7.1619 + 7.1620 + T operator >>= (unsigned bits) 7.1621 + { 7.1622 + T comp, newVal; 7.1623 + do { 7.1624 + comp = this->Value; 7.1625 + newVal = comp >> bits; 7.1626 + } while(!CompareAndSet_Sync(comp, newVal)); 7.1627 + return newVal; 7.1628 + } 7.1629 + 7.1630 + T operator <<= (unsigned bits) 7.1631 + { 7.1632 + T comp, newVal; 7.1633 + do { 7.1634 + comp = this->Value; 7.1635 + newVal = comp << bits; 7.1636 + } while(!this->CompareAndSet_Sync(comp, newVal)); 7.1637 + return newVal; 7.1638 + } 7.1639 +}; 7.1640 + 7.1641 + 7.1642 + 7.1643 +//----------------------------------------------------------------------------------- 7.1644 +// ***** Lock 7.1645 + 7.1646 +// Lock is a simplest and most efficient mutual-exclusion lock class. 7.1647 +// Unlike Mutex, it cannot be waited on. 7.1648 + 7.1649 +class Lock 7.1650 +{ 7.1651 + // NOTE: Locks are not allocatable and they themselves should not allocate 7.1652 + // memory by standard means. This is the case because StandardAllocator 7.1653 + // relies on this class. 7.1654 + // Make 'delete' private. Don't do this for 'new' since it can be redefined. 7.1655 + void operator delete(void*) {} 7.1656 + 7.1657 + 7.1658 + // *** Lock implementation for various platforms. 7.1659 + 7.1660 +#if !defined(OVR_ENABLE_THREADS) 7.1661 + 7.1662 +public: 7.1663 + // With no thread support, lock does nothing. 7.1664 + inline Lock() { } 7.1665 + inline Lock(unsigned) { } 7.1666 + inline ~Lock() { } 7.1667 + inline void DoLock() { } 7.1668 + inline void Unlock() { } 7.1669 + 7.1670 + // Windows. 7.1671 +#elif defined(OVR_OS_WIN32) 7.1672 + 7.1673 + CRITICAL_SECTION cs; 7.1674 +public: 7.1675 + Lock(unsigned spinCount = 0); 7.1676 + ~Lock(); 7.1677 + // Locking functions. 7.1678 + inline void DoLock() { ::EnterCriticalSection(&cs); } 7.1679 + inline void Unlock() { ::LeaveCriticalSection(&cs); } 7.1680 + 7.1681 +#else 7.1682 + pthread_mutex_t mutex; 7.1683 + 7.1684 +public: 7.1685 + static pthread_mutexattr_t RecursiveAttr; 7.1686 + static bool RecursiveAttrInit; 7.1687 + 7.1688 + Lock (unsigned dummy = 0) 7.1689 + { 7.1690 + if (!RecursiveAttrInit) 7.1691 + { 7.1692 + pthread_mutexattr_init(&RecursiveAttr); 7.1693 + pthread_mutexattr_settype(&RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 7.1694 + RecursiveAttrInit = 1; 7.1695 + } 7.1696 + pthread_mutex_init(&mutex,&RecursiveAttr); 7.1697 + } 7.1698 + ~Lock () { pthread_mutex_destroy(&mutex); } 7.1699 + inline void DoLock() { pthread_mutex_lock(&mutex); } 7.1700 + inline void Unlock() { pthread_mutex_unlock(&mutex); } 7.1701 + 7.1702 +#endif // OVR_ENABLE_THREDS 7.1703 + 7.1704 + 7.1705 +public: 7.1706 + // Locker class, used for automatic locking 7.1707 + class Locker 7.1708 + { 7.1709 + public: 7.1710 + Lock *pLock; 7.1711 + inline Locker(Lock *plock) 7.1712 + { pLock = plock; pLock->DoLock(); } 7.1713 + inline ~Locker() 7.1714 + { pLock->Unlock(); } 7.1715 + }; 7.1716 +}; 7.1717 + 7.1718 + 7.1719 + 7.1720 +} // OVR 7.1721 + 7.1722 +#endif
8.1 --- a/libovr/Src/Kernel/OVR_Color.h Sat Sep 14 17:51:03 2013 +0300 8.2 +++ b/libovr/Src/Kernel/OVR_Color.h Sun Sep 15 04:10:05 2013 +0300 8.3 @@ -1,1 +1,55 @@ 8.4 -/************************************************************************************ 8.5 8.6 PublicHeader: OVR.h 8.7 Filename : OVR_Color.h 8.8 Content : Contains color struct. 8.9 Created : February 7, 2013 8.10 Notes : 8.11 8.12 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 8.13 8.14 Use of this software is subject to the terms of the Oculus license 8.15 agreement provided at the time of installation or download, or which 8.16 otherwise accompanies this software in either electronic or hard copy form. 8.17 8.18 ************************************************************************************/ 8.19 #ifndef OVR_Color_h 8.20 #define OVR_Color_h 8.21 8.22 #include "OVR_Types.h" 8.23 8.24 namespace OVR { 8.25 8.26 struct Color 8.27 { 8.28 UByte R,G,B,A; 8.29 8.30 Color() {} 8.31 8.32 // Constructs color by channel. Alpha is set to 0xFF (fully visible) 8.33 // if not specified. 8.34 Color(unsigned char r,unsigned char g,unsigned char b, unsigned char a = 0xFF) 8.35 : R(r), G(g), B(b), A(a) { } 8.36 8.37 // 0xAARRGGBB - Common HTML color Hex layout 8.38 Color(unsigned c) 8.39 : R((unsigned char)(c>>16)), G((unsigned char)(c>>8)), 8.40 B((unsigned char)c), A((unsigned char)(c>>24)) { } 8.41 8.42 bool operator==(const Color& b) const 8.43 { 8.44 return R == b.R && G == b.G && B == b.B && A == b.A; 8.45 } 8.46 8.47 void GetRGBA(float *r, float *g, float *b, float* a) const 8.48 { 8.49 *r = R / 255.0f; 8.50 *g = G / 255.0f; 8.51 *b = B / 255.0f; 8.52 *a = A / 255.0f; 8.53 } 8.54 }; 8.55 8.56 } 8.57 8.58 #endif 8.59 \ No newline at end of file 8.60 +/************************************************************************************ 8.61 + 8.62 +PublicHeader: OVR.h 8.63 +Filename : OVR_Color.h 8.64 +Content : Contains color struct. 8.65 +Created : February 7, 2013 8.66 +Notes : 8.67 + 8.68 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 8.69 + 8.70 +Use of this software is subject to the terms of the Oculus license 8.71 +agreement provided at the time of installation or download, or which 8.72 +otherwise accompanies this software in either electronic or hard copy form. 8.73 + 8.74 +************************************************************************************/ 8.75 +#ifndef OVR_Color_h 8.76 +#define OVR_Color_h 8.77 + 8.78 +#include "OVR_Types.h" 8.79 + 8.80 +namespace OVR { 8.81 + 8.82 +struct Color 8.83 +{ 8.84 + UByte R,G,B,A; 8.85 + 8.86 + Color() {} 8.87 + 8.88 + // Constructs color by channel. Alpha is set to 0xFF (fully visible) 8.89 + // if not specified. 8.90 + Color(unsigned char r,unsigned char g,unsigned char b, unsigned char a = 0xFF) 8.91 + : R(r), G(g), B(b), A(a) { } 8.92 + 8.93 + // 0xAARRGGBB - Common HTML color Hex layout 8.94 + Color(unsigned c) 8.95 + : R((unsigned char)(c>>16)), G((unsigned char)(c>>8)), 8.96 + B((unsigned char)c), A((unsigned char)(c>>24)) { } 8.97 + 8.98 + bool operator==(const Color& b) const 8.99 + { 8.100 + return R == b.R && G == b.G && B == b.B && A == b.A; 8.101 + } 8.102 + 8.103 + void GetRGBA(float *r, float *g, float *b, float* a) const 8.104 + { 8.105 + *r = R / 255.0f; 8.106 + *g = G / 255.0f; 8.107 + *b = B / 255.0f; 8.108 + *a = A / 255.0f; 8.109 + } 8.110 +}; 8.111 + 8.112 +} 8.113 + 8.114 +#endif
9.1 --- a/libovr/Src/Kernel/OVR_ContainerAllocator.h Sat Sep 14 17:51:03 2013 +0300 9.2 +++ b/libovr/Src/Kernel/OVR_ContainerAllocator.h Sun Sep 15 04:10:05 2013 +0300 9.3 @@ -1,1 +1,256 @@ 9.4 -/************************************************************************************ 9.5 9.6 PublicHeader: OVR.h 9.7 Filename : OVR_ContainerAllocator.h 9.8 Content : Template allocators and constructors for containers. 9.9 Created : September 19, 2012 9.10 Notes : 9.11 9.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 9.13 9.14 Use of this software is subject to the terms of the Oculus license 9.15 agreement provided at the time of installation or download, or which 9.16 otherwise accompanies this software in either electronic or hard copy form. 9.17 9.18 ************************************************************************************/ 9.19 9.20 #ifndef OVR_ContainerAllocator_h 9.21 #define OVR_ContainerAllocator_h 9.22 9.23 #include "OVR_Allocator.h" 9.24 #include <string.h> 9.25 9.26 9.27 namespace OVR { 9.28 9.29 9.30 //----------------------------------------------------------------------------------- 9.31 // ***** Container Allocator 9.32 9.33 // ContainerAllocator serves as a template argument for allocations done by 9.34 // containers, such as Array and Hash; replacing it could allow allocator 9.35 // substitution in containers. 9.36 9.37 class ContainerAllocatorBase 9.38 { 9.39 public: 9.40 static void* Alloc(UPInt size) { return OVR_ALLOC(size); } 9.41 static void* Realloc(void* p, UPInt newSize) { return OVR_REALLOC(p, newSize); } 9.42 static void Free(void *p) { OVR_FREE(p); } 9.43 }; 9.44 9.45 9.46 9.47 //----------------------------------------------------------------------------------- 9.48 // ***** Constructors, Destructors, Copiers 9.49 9.50 // Plain Old Data - movable, no special constructors/destructor. 9.51 template<class T> 9.52 class ConstructorPOD 9.53 { 9.54 public: 9.55 static void Construct(void *) {} 9.56 static void Construct(void *p, const T& source) 9.57 { 9.58 *(T*)p = source; 9.59 } 9.60 9.61 // Same as above, but allows for a different type of constructor. 9.62 template <class S> 9.63 static void ConstructAlt(void *p, const S& source) 9.64 { 9.65 *(T*)p = source; 9.66 } 9.67 9.68 static void ConstructArray(void*, UPInt) {} 9.69 9.70 static void ConstructArray(void* p, UPInt count, const T& source) 9.71 { 9.72 UByte *pdata = (UByte*)p; 9.73 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.74 *(T*)pdata = source; 9.75 } 9.76 9.77 static void ConstructArray(void* p, UPInt count, const T* psource) 9.78 { 9.79 memcpy(p, psource, sizeof(T) * count); 9.80 } 9.81 9.82 static void Destruct(T*) {} 9.83 static void DestructArray(T*, UPInt) {} 9.84 9.85 static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.86 { 9.87 memmove(dst, src, count * sizeof(T)); 9.88 } 9.89 9.90 static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.91 { 9.92 memmove(dst, src, count * sizeof(T)); 9.93 } 9.94 9.95 static bool IsMovable() { return true; } 9.96 }; 9.97 9.98 9.99 //----------------------------------------------------------------------------------- 9.100 // ***** ConstructorMov 9.101 // 9.102 // Correct C++ construction and destruction for movable objects 9.103 template<class T> 9.104 class ConstructorMov 9.105 { 9.106 public: 9.107 static void Construct(void* p) 9.108 { 9.109 OVR::Construct<T>(p); 9.110 } 9.111 9.112 static void Construct(void* p, const T& source) 9.113 { 9.114 OVR::Construct<T>(p, source); 9.115 } 9.116 9.117 // Same as above, but allows for a different type of constructor. 9.118 template <class S> 9.119 static void ConstructAlt(void* p, const S& source) 9.120 { 9.121 OVR::ConstructAlt<T,S>(p, source); 9.122 } 9.123 9.124 static void ConstructArray(void* p, UPInt count) 9.125 { 9.126 UByte* pdata = (UByte*)p; 9.127 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.128 Construct(pdata); 9.129 } 9.130 9.131 static void ConstructArray(void* p, UPInt count, const T& source) 9.132 { 9.133 UByte* pdata = (UByte*)p; 9.134 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.135 Construct(pdata, source); 9.136 } 9.137 9.138 static void ConstructArray(void* p, UPInt count, const T* psource) 9.139 { 9.140 UByte* pdata = (UByte*)p; 9.141 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.142 Construct(pdata, *psource++); 9.143 } 9.144 9.145 static void Destruct(T* p) 9.146 { 9.147 p->~T(); 9.148 OVR_UNUSED(p); // Suppress silly MSVC warning 9.149 } 9.150 9.151 static void DestructArray(T* p, UPInt count) 9.152 { 9.153 p += count - 1; 9.154 for (UPInt i=0; i<count; ++i, --p) 9.155 p->~T(); 9.156 } 9.157 9.158 static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.159 { 9.160 memmove(dst, src, count * sizeof(T)); 9.161 } 9.162 9.163 static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.164 { 9.165 memmove(dst, src, count * sizeof(T)); 9.166 } 9.167 9.168 static bool IsMovable() { return true; } 9.169 }; 9.170 9.171 9.172 //----------------------------------------------------------------------------------- 9.173 // ***** ConstructorCPP 9.174 // 9.175 // Correct C++ construction and destruction for movable objects 9.176 template<class T> 9.177 class ConstructorCPP 9.178 { 9.179 public: 9.180 static void Construct(void* p) 9.181 { 9.182 OVR::Construct<T>(p); 9.183 } 9.184 9.185 static void Construct(void* p, const T& source) 9.186 { 9.187 OVR::Construct<T>(p, source); 9.188 } 9.189 9.190 // Same as above, but allows for a different type of constructor. 9.191 template <class S> 9.192 static void ConstructAlt(void* p, const S& source) 9.193 { 9.194 OVR::ConstructAlt<T,S>(p, source); 9.195 } 9.196 9.197 static void ConstructArray(void* p, UPInt count) 9.198 { 9.199 UByte* pdata = (UByte*)p; 9.200 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.201 Construct(pdata); 9.202 } 9.203 9.204 static void ConstructArray(void* p, UPInt count, const T& source) 9.205 { 9.206 UByte* pdata = (UByte*)p; 9.207 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.208 Construct(pdata, source); 9.209 } 9.210 9.211 static void ConstructArray(void* p, UPInt count, const T* psource) 9.212 { 9.213 UByte* pdata = (UByte*)p; 9.214 for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.215 Construct(pdata, *psource++); 9.216 } 9.217 9.218 static void Destruct(T* p) 9.219 { 9.220 p->~T(); 9.221 OVR_UNUSED(p); // Suppress silly MSVC warning 9.222 } 9.223 9.224 static void DestructArray(T* p, UPInt count) 9.225 { 9.226 p += count - 1; 9.227 for (UPInt i=0; i<count; ++i, --p) 9.228 p->~T(); 9.229 } 9.230 9.231 static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.232 { 9.233 for(UPInt i = 0; i < count; ++i) 9.234 dst[i] = src[i]; 9.235 } 9.236 9.237 static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.238 { 9.239 for(UPInt i = count; i; --i) 9.240 dst[i-1] = src[i-1]; 9.241 } 9.242 9.243 static bool IsMovable() { return false; } 9.244 }; 9.245 9.246 9.247 //----------------------------------------------------------------------------------- 9.248 // ***** Container Allocator with movement policy 9.249 // 9.250 // Simple wraps as specialized allocators 9.251 template<class T> struct ContainerAllocator_POD : ContainerAllocatorBase, ConstructorPOD<T> {}; 9.252 template<class T> struct ContainerAllocator : ContainerAllocatorBase, ConstructorMov<T> {}; 9.253 template<class T> struct ContainerAllocator_CPP : ContainerAllocatorBase, ConstructorCPP<T> {}; 9.254 9.255 9.256 } // OVR 9.257 9.258 9.259 #endif 9.260 \ No newline at end of file 9.261 +/************************************************************************************ 9.262 + 9.263 +PublicHeader: OVR.h 9.264 +Filename : OVR_ContainerAllocator.h 9.265 +Content : Template allocators and constructors for containers. 9.266 +Created : September 19, 2012 9.267 +Notes : 9.268 + 9.269 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 9.270 + 9.271 +Use of this software is subject to the terms of the Oculus license 9.272 +agreement provided at the time of installation or download, or which 9.273 +otherwise accompanies this software in either electronic or hard copy form. 9.274 + 9.275 +************************************************************************************/ 9.276 + 9.277 +#ifndef OVR_ContainerAllocator_h 9.278 +#define OVR_ContainerAllocator_h 9.279 + 9.280 +#include "OVR_Allocator.h" 9.281 +#include <string.h> 9.282 + 9.283 + 9.284 +namespace OVR { 9.285 + 9.286 + 9.287 +//----------------------------------------------------------------------------------- 9.288 +// ***** Container Allocator 9.289 + 9.290 +// ContainerAllocator serves as a template argument for allocations done by 9.291 +// containers, such as Array and Hash; replacing it could allow allocator 9.292 +// substitution in containers. 9.293 + 9.294 +class ContainerAllocatorBase 9.295 +{ 9.296 +public: 9.297 + static void* Alloc(UPInt size) { return OVR_ALLOC(size); } 9.298 + static void* Realloc(void* p, UPInt newSize) { return OVR_REALLOC(p, newSize); } 9.299 + static void Free(void *p) { OVR_FREE(p); } 9.300 +}; 9.301 + 9.302 + 9.303 + 9.304 +//----------------------------------------------------------------------------------- 9.305 +// ***** Constructors, Destructors, Copiers 9.306 + 9.307 +// Plain Old Data - movable, no special constructors/destructor. 9.308 +template<class T> 9.309 +class ConstructorPOD 9.310 +{ 9.311 +public: 9.312 + static void Construct(void *) {} 9.313 + static void Construct(void *p, const T& source) 9.314 + { 9.315 + *(T*)p = source; 9.316 + } 9.317 + 9.318 + // Same as above, but allows for a different type of constructor. 9.319 + template <class S> 9.320 + static void ConstructAlt(void *p, const S& source) 9.321 + { 9.322 + *(T*)p = source; 9.323 + } 9.324 + 9.325 + static void ConstructArray(void*, UPInt) {} 9.326 + 9.327 + static void ConstructArray(void* p, UPInt count, const T& source) 9.328 + { 9.329 + UByte *pdata = (UByte*)p; 9.330 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.331 + *(T*)pdata = source; 9.332 + } 9.333 + 9.334 + static void ConstructArray(void* p, UPInt count, const T* psource) 9.335 + { 9.336 + memcpy(p, psource, sizeof(T) * count); 9.337 + } 9.338 + 9.339 + static void Destruct(T*) {} 9.340 + static void DestructArray(T*, UPInt) {} 9.341 + 9.342 + static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.343 + { 9.344 + memmove(dst, src, count * sizeof(T)); 9.345 + } 9.346 + 9.347 + static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.348 + { 9.349 + memmove(dst, src, count * sizeof(T)); 9.350 + } 9.351 + 9.352 + static bool IsMovable() { return true; } 9.353 +}; 9.354 + 9.355 + 9.356 +//----------------------------------------------------------------------------------- 9.357 +// ***** ConstructorMov 9.358 +// 9.359 +// Correct C++ construction and destruction for movable objects 9.360 +template<class T> 9.361 +class ConstructorMov 9.362 +{ 9.363 +public: 9.364 + static void Construct(void* p) 9.365 + { 9.366 + OVR::Construct<T>(p); 9.367 + } 9.368 + 9.369 + static void Construct(void* p, const T& source) 9.370 + { 9.371 + OVR::Construct<T>(p, source); 9.372 + } 9.373 + 9.374 + // Same as above, but allows for a different type of constructor. 9.375 + template <class S> 9.376 + static void ConstructAlt(void* p, const S& source) 9.377 + { 9.378 + OVR::ConstructAlt<T,S>(p, source); 9.379 + } 9.380 + 9.381 + static void ConstructArray(void* p, UPInt count) 9.382 + { 9.383 + UByte* pdata = (UByte*)p; 9.384 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.385 + Construct(pdata); 9.386 + } 9.387 + 9.388 + static void ConstructArray(void* p, UPInt count, const T& source) 9.389 + { 9.390 + UByte* pdata = (UByte*)p; 9.391 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.392 + Construct(pdata, source); 9.393 + } 9.394 + 9.395 + static void ConstructArray(void* p, UPInt count, const T* psource) 9.396 + { 9.397 + UByte* pdata = (UByte*)p; 9.398 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.399 + Construct(pdata, *psource++); 9.400 + } 9.401 + 9.402 + static void Destruct(T* p) 9.403 + { 9.404 + p->~T(); 9.405 + OVR_UNUSED(p); // Suppress silly MSVC warning 9.406 + } 9.407 + 9.408 + static void DestructArray(T* p, UPInt count) 9.409 + { 9.410 + p += count - 1; 9.411 + for (UPInt i=0; i<count; ++i, --p) 9.412 + p->~T(); 9.413 + } 9.414 + 9.415 + static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.416 + { 9.417 + memmove(dst, src, count * sizeof(T)); 9.418 + } 9.419 + 9.420 + static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.421 + { 9.422 + memmove(dst, src, count * sizeof(T)); 9.423 + } 9.424 + 9.425 + static bool IsMovable() { return true; } 9.426 +}; 9.427 + 9.428 + 9.429 +//----------------------------------------------------------------------------------- 9.430 +// ***** ConstructorCPP 9.431 +// 9.432 +// Correct C++ construction and destruction for movable objects 9.433 +template<class T> 9.434 +class ConstructorCPP 9.435 +{ 9.436 +public: 9.437 + static void Construct(void* p) 9.438 + { 9.439 + OVR::Construct<T>(p); 9.440 + } 9.441 + 9.442 + static void Construct(void* p, const T& source) 9.443 + { 9.444 + OVR::Construct<T>(p, source); 9.445 + } 9.446 + 9.447 + // Same as above, but allows for a different type of constructor. 9.448 + template <class S> 9.449 + static void ConstructAlt(void* p, const S& source) 9.450 + { 9.451 + OVR::ConstructAlt<T,S>(p, source); 9.452 + } 9.453 + 9.454 + static void ConstructArray(void* p, UPInt count) 9.455 + { 9.456 + UByte* pdata = (UByte*)p; 9.457 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.458 + Construct(pdata); 9.459 + } 9.460 + 9.461 + static void ConstructArray(void* p, UPInt count, const T& source) 9.462 + { 9.463 + UByte* pdata = (UByte*)p; 9.464 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.465 + Construct(pdata, source); 9.466 + } 9.467 + 9.468 + static void ConstructArray(void* p, UPInt count, const T* psource) 9.469 + { 9.470 + UByte* pdata = (UByte*)p; 9.471 + for (UPInt i=0; i< count; ++i, pdata += sizeof(T)) 9.472 + Construct(pdata, *psource++); 9.473 + } 9.474 + 9.475 + static void Destruct(T* p) 9.476 + { 9.477 + p->~T(); 9.478 + OVR_UNUSED(p); // Suppress silly MSVC warning 9.479 + } 9.480 + 9.481 + static void DestructArray(T* p, UPInt count) 9.482 + { 9.483 + p += count - 1; 9.484 + for (UPInt i=0; i<count; ++i, --p) 9.485 + p->~T(); 9.486 + } 9.487 + 9.488 + static void CopyArrayForward(T* dst, const T* src, UPInt count) 9.489 + { 9.490 + for(UPInt i = 0; i < count; ++i) 9.491 + dst[i] = src[i]; 9.492 + } 9.493 + 9.494 + static void CopyArrayBackward(T* dst, const T* src, UPInt count) 9.495 + { 9.496 + for(UPInt i = count; i; --i) 9.497 + dst[i-1] = src[i-1]; 9.498 + } 9.499 + 9.500 + static bool IsMovable() { return false; } 9.501 +}; 9.502 + 9.503 + 9.504 +//----------------------------------------------------------------------------------- 9.505 +// ***** Container Allocator with movement policy 9.506 +// 9.507 +// Simple wraps as specialized allocators 9.508 +template<class T> struct ContainerAllocator_POD : ContainerAllocatorBase, ConstructorPOD<T> {}; 9.509 +template<class T> struct ContainerAllocator : ContainerAllocatorBase, ConstructorMov<T> {}; 9.510 +template<class T> struct ContainerAllocator_CPP : ContainerAllocatorBase, ConstructorCPP<T> {}; 9.511 + 9.512 + 9.513 +} // OVR 9.514 + 9.515 + 9.516 +#endif
10.1 --- a/libovr/Src/Kernel/OVR_File.cpp Sat Sep 14 17:51:03 2013 +0300 10.2 +++ b/libovr/Src/Kernel/OVR_File.cpp Sun Sep 15 04:10:05 2013 +0300 10.3 @@ -1,1 +1,571 @@ 10.4 -/************************************************************************** 10.5 10.6 Filename : OVR_File.cpp 10.7 Content : File wrapper class implementation (Win32) 10.8 10.9 Created : April 5, 1999 10.10 Authors : Michael Antonov 10.11 10.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 10.13 10.14 Use of this software is subject to the terms of the Oculus license 10.15 agreement provided at the time of installation or download, or which 10.16 otherwise accompanies this software in either electronic or hard copy form. 10.17 10.18 **************************************************************************/ 10.19 10.20 #define GFILE_CXX 10.21 10.22 // Standard C library (Captain Obvious guarantees!) 10.23 #include <stdio.h> 10.24 10.25 #include "OVR_File.h" 10.26 10.27 namespace OVR { 10.28 10.29 // Buffered file adds buffering to an existing file 10.30 // FILEBUFFER_SIZE defines the size of internal buffer, while 10.31 // FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer 10.32 #define FILEBUFFER_SIZE (8192-8) 10.33 #define FILEBUFFER_TOLERANCE 4096 10.34 10.35 // ** Constructor/Destructor 10.36 10.37 // Hidden constructor 10.38 // Not supposed to be used 10.39 BufferedFile::BufferedFile() : DelegatedFile(0) 10.40 { 10.41 pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 10.42 BufferMode = NoBuffer; 10.43 FilePos = 0; 10.44 Pos = 0; 10.45 DataSize = 0; 10.46 } 10.47 10.48 // Takes another file as source 10.49 BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) 10.50 { 10.51 pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 10.52 BufferMode = NoBuffer; 10.53 FilePos = pfile->LTell(); 10.54 Pos = 0; 10.55 DataSize = 0; 10.56 } 10.57 10.58 10.59 // Destructor 10.60 BufferedFile::~BufferedFile() 10.61 { 10.62 // Flush in case there's data 10.63 if (pFile) 10.64 FlushBuffer(); 10.65 // Get rid of buffer 10.66 if (pBuffer) 10.67 OVR_FREE(pBuffer); 10.68 } 10.69 10.70 /* 10.71 bool BufferedFile::VCopy(const Object &source) 10.72 { 10.73 if (!DelegatedFile::VCopy(source)) 10.74 return 0; 10.75 10.76 // Data members 10.77 BufferedFile *psource = (BufferedFile*)&source; 10.78 10.79 // Buffer & the mode it's in 10.80 pBuffer = psource->pBuffer; 10.81 BufferMode = psource->BufferMode; 10.82 Pos = psource->Pos; 10.83 DataSize = psource->DataSize; 10.84 return 1; 10.85 } 10.86 */ 10.87 10.88 // Initializes buffering to a certain mode 10.89 bool BufferedFile::SetBufferMode(BufferModeType mode) 10.90 { 10.91 if (!pBuffer) 10.92 return false; 10.93 if (mode == BufferMode) 10.94 return true; 10.95 10.96 FlushBuffer(); 10.97 10.98 // Can't set write mode if we can't write 10.99 if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) ) 10.100 return 0; 10.101 10.102 // And SetMode 10.103 BufferMode = mode; 10.104 Pos = 0; 10.105 DataSize = 0; 10.106 return 1; 10.107 } 10.108 10.109 // Flushes buffer 10.110 void BufferedFile::FlushBuffer() 10.111 { 10.112 switch(BufferMode) 10.113 { 10.114 case WriteBuffer: 10.115 // Write data in buffer 10.116 FilePos += pFile->Write(pBuffer,Pos); 10.117 Pos = 0; 10.118 break; 10.119 10.120 case ReadBuffer: 10.121 // Seek back & reset buffer data 10.122 if ((DataSize-Pos)>0) 10.123 FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur); 10.124 DataSize = 0; 10.125 Pos = 0; 10.126 break; 10.127 default: 10.128 // not handled! 10.129 break; 10.130 } 10.131 } 10.132 10.133 // Reloads data for ReadBuffer 10.134 void BufferedFile::LoadBuffer() 10.135 { 10.136 if (BufferMode == ReadBuffer) 10.137 { 10.138 // We should only reload once all of pre-loaded buffer is consumed. 10.139 OVR_ASSERT(Pos == DataSize); 10.140 10.141 // WARNING: Right now LoadBuffer() assumes the buffer's empty 10.142 int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE); 10.143 DataSize = sz<0 ? 0 : (unsigned)sz; 10.144 Pos = 0; 10.145 FilePos += DataSize; 10.146 } 10.147 } 10.148 10.149 10.150 // ** Overridden functions 10.151 10.152 // We override all the functions that can possibly 10.153 // require buffer mode switch, flush, or extra calculations 10.154 10.155 // Tell() requires buffer adjustment 10.156 int BufferedFile::Tell() 10.157 { 10.158 if (BufferMode == ReadBuffer) 10.159 return int (FilePos - DataSize + Pos); 10.160 10.161 int pos = pFile->Tell(); 10.162 // Adjust position based on buffer mode & data 10.163 if (pos!=-1) 10.164 { 10.165 OVR_ASSERT(BufferMode != ReadBuffer); 10.166 if (BufferMode == WriteBuffer) 10.167 pos += Pos; 10.168 } 10.169 return pos; 10.170 } 10.171 10.172 SInt64 BufferedFile::LTell() 10.173 { 10.174 if (BufferMode == ReadBuffer) 10.175 return FilePos - DataSize + Pos; 10.176 10.177 SInt64 pos = pFile->LTell(); 10.178 if (pos!=-1) 10.179 { 10.180 OVR_ASSERT(BufferMode != ReadBuffer); 10.181 if (BufferMode == WriteBuffer) 10.182 pos += Pos; 10.183 } 10.184 return pos; 10.185 } 10.186 10.187 int BufferedFile::GetLength() 10.188 { 10.189 int len = pFile->GetLength(); 10.190 // If writing through buffer, file length may actually be bigger 10.191 if ((len!=-1) && (BufferMode==WriteBuffer)) 10.192 { 10.193 int currPos = pFile->Tell() + Pos; 10.194 if (currPos>len) 10.195 len = currPos; 10.196 } 10.197 return len; 10.198 } 10.199 SInt64 BufferedFile::LGetLength() 10.200 { 10.201 SInt64 len = pFile->LGetLength(); 10.202 // If writing through buffer, file length may actually be bigger 10.203 if ((len!=-1) && (BufferMode==WriteBuffer)) 10.204 { 10.205 SInt64 currPos = pFile->LTell() + Pos; 10.206 if (currPos>len) 10.207 len = currPos; 10.208 } 10.209 return len; 10.210 } 10.211 10.212 /* 10.213 bool BufferedFile::Stat(FileStats *pfs) 10.214 { 10.215 // Have to fix up length is stat 10.216 if (pFile->Stat(pfs)) 10.217 { 10.218 if (BufferMode==WriteBuffer) 10.219 { 10.220 SInt64 currPos = pFile->LTell() + Pos; 10.221 if (currPos > pfs->Size) 10.222 { 10.223 pfs->Size = currPos; 10.224 // ?? 10.225 pfs->Blocks = (pfs->Size+511) >> 9; 10.226 } 10.227 } 10.228 return 1; 10.229 } 10.230 return 0; 10.231 } 10.232 */ 10.233 10.234 int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) 10.235 { 10.236 if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) 10.237 { 10.238 // If not data space in buffer, flush 10.239 if ((FILEBUFFER_SIZE-(int)Pos)<numBytes) 10.240 { 10.241 FlushBuffer(); 10.242 // If bigger then tolerance, just write directly 10.243 if (numBytes>FILEBUFFER_TOLERANCE) 10.244 { 10.245 int sz = pFile->Write(psourceBuffer,numBytes); 10.246 if (sz > 0) 10.247 FilePos += sz; 10.248 return sz; 10.249 } 10.250 } 10.251 10.252 // Enough space in buffer.. so copy to it 10.253 memcpy(pBuffer+Pos, psourceBuffer, numBytes); 10.254 Pos += numBytes; 10.255 return numBytes; 10.256 } 10.257 int sz = pFile->Write(psourceBuffer,numBytes); 10.258 if (sz > 0) 10.259 FilePos += sz; 10.260 return sz; 10.261 } 10.262 10.263 int BufferedFile::Read(UByte *pdestBuffer, int numBytes) 10.264 { 10.265 if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) 10.266 { 10.267 // Data in buffer... copy it 10.268 if ((int)(DataSize-Pos) >= numBytes) 10.269 { 10.270 memcpy(pdestBuffer, pBuffer+Pos, numBytes); 10.271 Pos += numBytes; 10.272 return numBytes; 10.273 } 10.274 10.275 // Not enough data in buffer, copy buffer 10.276 int readBytes = DataSize-Pos; 10.277 memcpy(pdestBuffer, pBuffer+Pos, readBytes); 10.278 numBytes -= readBytes; 10.279 pdestBuffer += readBytes; 10.280 Pos = DataSize; 10.281 10.282 // Don't reload buffer if more then tolerance 10.283 // (No major advantage, and we don't want to write a loop) 10.284 if (numBytes>FILEBUFFER_TOLERANCE) 10.285 { 10.286 numBytes = pFile->Read(pdestBuffer,numBytes); 10.287 if (numBytes > 0) 10.288 { 10.289 FilePos += numBytes; 10.290 Pos = DataSize = 0; 10.291 } 10.292 return readBytes + ((numBytes==-1) ? 0 : numBytes); 10.293 } 10.294 10.295 // Reload the buffer 10.296 // WARNING: Right now LoadBuffer() assumes the buffer's empty 10.297 LoadBuffer(); 10.298 if ((int)(DataSize-Pos) < numBytes) 10.299 numBytes = (int)DataSize-Pos; 10.300 10.301 memcpy(pdestBuffer, pBuffer+Pos, numBytes); 10.302 Pos += numBytes; 10.303 return numBytes + readBytes; 10.304 10.305 /* 10.306 // Alternative Read implementation. The one above is probably better 10.307 // due to FILEBUFFER_TOLERANCE. 10.308 int total = 0; 10.309 10.310 do { 10.311 int bufferBytes = (int)(DataSize-Pos); 10.312 int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes; 10.313 10.314 memcpy(pdestBuffer, pBuffer+Pos, copyBytes); 10.315 numBytes -= copyBytes; 10.316 pdestBuffer += copyBytes; 10.317 Pos += copyBytes; 10.318 total += copyBytes; 10.319 10.320 if (numBytes == 0) 10.321 break; 10.322 LoadBuffer(); 10.323 10.324 } while (DataSize > 0); 10.325 10.326 return total; 10.327 */ 10.328 } 10.329 int sz = pFile->Read(pdestBuffer,numBytes); 10.330 if (sz > 0) 10.331 FilePos += sz; 10.332 return sz; 10.333 } 10.334 10.335 10.336 int BufferedFile::SkipBytes(int numBytes) 10.337 { 10.338 int skippedBytes = 0; 10.339 10.340 // Special case for skipping a little data in read buffer 10.341 if (BufferMode==ReadBuffer) 10.342 { 10.343 skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos); 10.344 Pos += skippedBytes; 10.345 numBytes -= skippedBytes; 10.346 } 10.347 10.348 if (numBytes) 10.349 { 10.350 numBytes = pFile->SkipBytes(numBytes); 10.351 // Make sure we return the actual number skipped, or error 10.352 if (numBytes!=-1) 10.353 { 10.354 skippedBytes += numBytes; 10.355 FilePos += numBytes; 10.356 Pos = DataSize = 0; 10.357 } 10.358 else if (skippedBytes <= 0) 10.359 skippedBytes = -1; 10.360 } 10.361 return skippedBytes; 10.362 } 10.363 10.364 int BufferedFile::BytesAvailable() 10.365 { 10.366 int available = pFile->BytesAvailable(); 10.367 // Adjust available size based on buffers 10.368 switch(BufferMode) 10.369 { 10.370 case ReadBuffer: 10.371 available += DataSize-Pos; 10.372 break; 10.373 case WriteBuffer: 10.374 available -= Pos; 10.375 if (available<0) 10.376 available= 0; 10.377 break; 10.378 default: 10.379 break; 10.380 } 10.381 return available; 10.382 } 10.383 10.384 bool BufferedFile::Flush() 10.385 { 10.386 FlushBuffer(); 10.387 return pFile->Flush(); 10.388 } 10.389 10.390 // Seeking could be optimized better.. 10.391 int BufferedFile::Seek(int offset, int origin) 10.392 { 10.393 if (BufferMode == ReadBuffer) 10.394 { 10.395 if (origin == Seek_Cur) 10.396 { 10.397 // Seek can fall either before or after Pos in the buffer, 10.398 // but it must be within bounds. 10.399 if (((unsigned(offset) + Pos)) <= DataSize) 10.400 { 10.401 Pos += offset; 10.402 return int (FilePos - DataSize + Pos); 10.403 } 10.404 10.405 // Lightweight buffer "Flush". We do this to avoid an extra seek 10.406 // back operation which would take place if we called FlushBuffer directly. 10.407 origin = Seek_Set; 10.408 OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); 10.409 offset = (int)(FilePos - DataSize + Pos) + offset; 10.410 Pos = DataSize = 0; 10.411 } 10.412 else if (origin == Seek_Set) 10.413 { 10.414 if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) 10.415 { 10.416 OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); 10.417 Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); 10.418 return offset; 10.419 } 10.420 Pos = DataSize = 0; 10.421 } 10.422 else 10.423 { 10.424 FlushBuffer(); 10.425 } 10.426 } 10.427 else 10.428 { 10.429 FlushBuffer(); 10.430 } 10.431 10.432 /* 10.433 // Old Seek Logic 10.434 if (origin == Seek_Cur && offset + Pos < DataSize) 10.435 { 10.436 //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset)); 10.437 Pos += offset; 10.438 OVR_ASSERT(int (Pos) >= 0); 10.439 return int (FilePos - DataSize + Pos); 10.440 } 10.441 else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos) 10.442 { 10.443 Pos = unsigned(offset - FilePos + DataSize); 10.444 OVR_ASSERT(int (Pos) >= 0); 10.445 return int (FilePos - DataSize + Pos); 10.446 } 10.447 10.448 FlushBuffer(); 10.449 */ 10.450 10.451 10.452 FilePos = pFile->Seek(offset,origin); 10.453 return int (FilePos); 10.454 } 10.455 10.456 SInt64 BufferedFile::LSeek(SInt64 offset, int origin) 10.457 { 10.458 if (BufferMode == ReadBuffer) 10.459 { 10.460 if (origin == Seek_Cur) 10.461 { 10.462 // Seek can fall either before or after Pos in the buffer, 10.463 // but it must be within bounds. 10.464 if (((unsigned(offset) + Pos)) <= DataSize) 10.465 { 10.466 Pos += (unsigned)offset; 10.467 return SInt64(FilePos - DataSize + Pos); 10.468 } 10.469 10.470 // Lightweight buffer "Flush". We do this to avoid an extra seek 10.471 // back operation which would take place if we called FlushBuffer directly. 10.472 origin = Seek_Set; 10.473 offset = (SInt64)(FilePos - DataSize + Pos) + offset; 10.474 Pos = DataSize = 0; 10.475 } 10.476 else if (origin == Seek_Set) 10.477 { 10.478 if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) 10.479 { 10.480 Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); 10.481 return offset; 10.482 } 10.483 Pos = DataSize = 0; 10.484 } 10.485 else 10.486 { 10.487 FlushBuffer(); 10.488 } 10.489 } 10.490 else 10.491 { 10.492 FlushBuffer(); 10.493 } 10.494 10.495 /* 10.496 OVR_ASSERT(BufferMode != NoBuffer); 10.497 10.498 if (origin == Seek_Cur && offset + Pos < DataSize) 10.499 { 10.500 Pos += int (offset); 10.501 return FilePos - DataSize + Pos; 10.502 } 10.503 else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) 10.504 { 10.505 Pos = unsigned(offset - FilePos + DataSize); 10.506 return FilePos - DataSize + Pos; 10.507 } 10.508 10.509 FlushBuffer(); 10.510 */ 10.511 10.512 FilePos = pFile->LSeek(offset,origin); 10.513 return FilePos; 10.514 } 10.515 10.516 int BufferedFile::CopyFromStream(File *pstream, int byteSize) 10.517 { 10.518 // We can't rely on overridden Write() 10.519 // because delegation doesn't override virtual pointers 10.520 // So, just re-implement 10.521 UByte buff[0x4000]; 10.522 int count = 0; 10.523 int szRequest, szRead, szWritten; 10.524 10.525 while(byteSize) 10.526 { 10.527 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; 10.528 10.529 szRead = pstream->Read(buff,szRequest); 10.530 szWritten = 0; 10.531 if (szRead > 0) 10.532 szWritten = Write(buff,szRead); 10.533 10.534 count +=szWritten; 10.535 byteSize-=szWritten; 10.536 if (szWritten < szRequest) 10.537 break; 10.538 } 10.539 return count; 10.540 } 10.541 10.542 // Closing files 10.543 bool BufferedFile::Close() 10.544 { 10.545 switch(BufferMode) 10.546 { 10.547 case WriteBuffer: 10.548 FlushBuffer(); 10.549 break; 10.550 case ReadBuffer: 10.551 // No need to seek back on close 10.552 BufferMode = NoBuffer; 10.553 break; 10.554 default: 10.555 break; 10.556 } 10.557 return pFile->Close(); 10.558 } 10.559 10.560 10.561 // ***** Global path helpers 10.562 10.563 // Find trailing short filename in a path. 10.564 const char* OVR_CDECL GetShortFilename(const char* purl) 10.565 { 10.566 UPInt len = OVR_strlen(purl); 10.567 for (UPInt i=len; i>0; i--) 10.568 if (purl[i]=='\\' || purl[i]=='/') 10.569 return purl+i+1; 10.570 return purl; 10.571 } 10.572 10.573 } // OVR 10.574 10.575 \ No newline at end of file 10.576 +/************************************************************************** 10.577 + 10.578 +Filename : OVR_File.cpp 10.579 +Content : File wrapper class implementation (Win32) 10.580 + 10.581 +Created : April 5, 1999 10.582 +Authors : Michael Antonov 10.583 + 10.584 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 10.585 + 10.586 +Use of this software is subject to the terms of the Oculus license 10.587 +agreement provided at the time of installation or download, or which 10.588 +otherwise accompanies this software in either electronic or hard copy form. 10.589 + 10.590 +**************************************************************************/ 10.591 + 10.592 +#define GFILE_CXX 10.593 + 10.594 +// Standard C library (Captain Obvious guarantees!) 10.595 +#include <stdio.h> 10.596 + 10.597 +#include "OVR_File.h" 10.598 + 10.599 +namespace OVR { 10.600 + 10.601 +// Buffered file adds buffering to an existing file 10.602 +// FILEBUFFER_SIZE defines the size of internal buffer, while 10.603 +// FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer 10.604 +#define FILEBUFFER_SIZE (8192-8) 10.605 +#define FILEBUFFER_TOLERANCE 4096 10.606 + 10.607 +// ** Constructor/Destructor 10.608 + 10.609 +// Hidden constructor 10.610 +// Not supposed to be used 10.611 +BufferedFile::BufferedFile() : DelegatedFile(0) 10.612 +{ 10.613 + pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 10.614 + BufferMode = NoBuffer; 10.615 + FilePos = 0; 10.616 + Pos = 0; 10.617 + DataSize = 0; 10.618 +} 10.619 + 10.620 +// Takes another file as source 10.621 +BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) 10.622 +{ 10.623 + pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 10.624 + BufferMode = NoBuffer; 10.625 + FilePos = pfile->LTell(); 10.626 + Pos = 0; 10.627 + DataSize = 0; 10.628 +} 10.629 + 10.630 + 10.631 +// Destructor 10.632 +BufferedFile::~BufferedFile() 10.633 +{ 10.634 + // Flush in case there's data 10.635 + if (pFile) 10.636 + FlushBuffer(); 10.637 + // Get rid of buffer 10.638 + if (pBuffer) 10.639 + OVR_FREE(pBuffer); 10.640 +} 10.641 + 10.642 +/* 10.643 +bool BufferedFile::VCopy(const Object &source) 10.644 +{ 10.645 + if (!DelegatedFile::VCopy(source)) 10.646 + return 0; 10.647 + 10.648 + // Data members 10.649 + BufferedFile *psource = (BufferedFile*)&source; 10.650 + 10.651 + // Buffer & the mode it's in 10.652 + pBuffer = psource->pBuffer; 10.653 + BufferMode = psource->BufferMode; 10.654 + Pos = psource->Pos; 10.655 + DataSize = psource->DataSize; 10.656 + return 1; 10.657 +} 10.658 +*/ 10.659 + 10.660 +// Initializes buffering to a certain mode 10.661 +bool BufferedFile::SetBufferMode(BufferModeType mode) 10.662 +{ 10.663 + if (!pBuffer) 10.664 + return false; 10.665 + if (mode == BufferMode) 10.666 + return true; 10.667 + 10.668 + FlushBuffer(); 10.669 + 10.670 + // Can't set write mode if we can't write 10.671 + if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) ) 10.672 + return 0; 10.673 + 10.674 + // And SetMode 10.675 + BufferMode = mode; 10.676 + Pos = 0; 10.677 + DataSize = 0; 10.678 + return 1; 10.679 +} 10.680 + 10.681 +// Flushes buffer 10.682 +void BufferedFile::FlushBuffer() 10.683 +{ 10.684 + switch(BufferMode) 10.685 + { 10.686 + case WriteBuffer: 10.687 + // Write data in buffer 10.688 + FilePos += pFile->Write(pBuffer,Pos); 10.689 + Pos = 0; 10.690 + break; 10.691 + 10.692 + case ReadBuffer: 10.693 + // Seek back & reset buffer data 10.694 + if ((DataSize-Pos)>0) 10.695 + FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur); 10.696 + DataSize = 0; 10.697 + Pos = 0; 10.698 + break; 10.699 + default: 10.700 + // not handled! 10.701 + break; 10.702 + } 10.703 +} 10.704 + 10.705 +// Reloads data for ReadBuffer 10.706 +void BufferedFile::LoadBuffer() 10.707 +{ 10.708 + if (BufferMode == ReadBuffer) 10.709 + { 10.710 + // We should only reload once all of pre-loaded buffer is consumed. 10.711 + OVR_ASSERT(Pos == DataSize); 10.712 + 10.713 + // WARNING: Right now LoadBuffer() assumes the buffer's empty 10.714 + int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE); 10.715 + DataSize = sz<0 ? 0 : (unsigned)sz; 10.716 + Pos = 0; 10.717 + FilePos += DataSize; 10.718 + } 10.719 +} 10.720 + 10.721 + 10.722 +// ** Overridden functions 10.723 + 10.724 +// We override all the functions that can possibly 10.725 +// require buffer mode switch, flush, or extra calculations 10.726 + 10.727 +// Tell() requires buffer adjustment 10.728 +int BufferedFile::Tell() 10.729 +{ 10.730 + if (BufferMode == ReadBuffer) 10.731 + return int (FilePos - DataSize + Pos); 10.732 + 10.733 + int pos = pFile->Tell(); 10.734 + // Adjust position based on buffer mode & data 10.735 + if (pos!=-1) 10.736 + { 10.737 + OVR_ASSERT(BufferMode != ReadBuffer); 10.738 + if (BufferMode == WriteBuffer) 10.739 + pos += Pos; 10.740 + } 10.741 + return pos; 10.742 +} 10.743 + 10.744 +SInt64 BufferedFile::LTell() 10.745 +{ 10.746 + if (BufferMode == ReadBuffer) 10.747 + return FilePos - DataSize + Pos; 10.748 + 10.749 + SInt64 pos = pFile->LTell(); 10.750 + if (pos!=-1) 10.751 + { 10.752 + OVR_ASSERT(BufferMode != ReadBuffer); 10.753 + if (BufferMode == WriteBuffer) 10.754 + pos += Pos; 10.755 + } 10.756 + return pos; 10.757 +} 10.758 + 10.759 +int BufferedFile::GetLength() 10.760 +{ 10.761 + int len = pFile->GetLength(); 10.762 + // If writing through buffer, file length may actually be bigger 10.763 + if ((len!=-1) && (BufferMode==WriteBuffer)) 10.764 + { 10.765 + int currPos = pFile->Tell() + Pos; 10.766 + if (currPos>len) 10.767 + len = currPos; 10.768 + } 10.769 + return len; 10.770 +} 10.771 +SInt64 BufferedFile::LGetLength() 10.772 +{ 10.773 + SInt64 len = pFile->LGetLength(); 10.774 + // If writing through buffer, file length may actually be bigger 10.775 + if ((len!=-1) && (BufferMode==WriteBuffer)) 10.776 + { 10.777 + SInt64 currPos = pFile->LTell() + Pos; 10.778 + if (currPos>len) 10.779 + len = currPos; 10.780 + } 10.781 + return len; 10.782 +} 10.783 + 10.784 +/* 10.785 +bool BufferedFile::Stat(FileStats *pfs) 10.786 +{ 10.787 + // Have to fix up length is stat 10.788 + if (pFile->Stat(pfs)) 10.789 + { 10.790 + if (BufferMode==WriteBuffer) 10.791 + { 10.792 + SInt64 currPos = pFile->LTell() + Pos; 10.793 + if (currPos > pfs->Size) 10.794 + { 10.795 + pfs->Size = currPos; 10.796 + // ?? 10.797 + pfs->Blocks = (pfs->Size+511) >> 9; 10.798 + } 10.799 + } 10.800 + return 1; 10.801 + } 10.802 + return 0; 10.803 +} 10.804 +*/ 10.805 + 10.806 +int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) 10.807 +{ 10.808 + if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) 10.809 + { 10.810 + // If not data space in buffer, flush 10.811 + if ((FILEBUFFER_SIZE-(int)Pos)<numBytes) 10.812 + { 10.813 + FlushBuffer(); 10.814 + // If bigger then tolerance, just write directly 10.815 + if (numBytes>FILEBUFFER_TOLERANCE) 10.816 + { 10.817 + int sz = pFile->Write(psourceBuffer,numBytes); 10.818 + if (sz > 0) 10.819 + FilePos += sz; 10.820 + return sz; 10.821 + } 10.822 + } 10.823 + 10.824 + // Enough space in buffer.. so copy to it 10.825 + memcpy(pBuffer+Pos, psourceBuffer, numBytes); 10.826 + Pos += numBytes; 10.827 + return numBytes; 10.828 + } 10.829 + int sz = pFile->Write(psourceBuffer,numBytes); 10.830 + if (sz > 0) 10.831 + FilePos += sz; 10.832 + return sz; 10.833 +} 10.834 + 10.835 +int BufferedFile::Read(UByte *pdestBuffer, int numBytes) 10.836 +{ 10.837 + if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) 10.838 + { 10.839 + // Data in buffer... copy it 10.840 + if ((int)(DataSize-Pos) >= numBytes) 10.841 + { 10.842 + memcpy(pdestBuffer, pBuffer+Pos, numBytes); 10.843 + Pos += numBytes; 10.844 + return numBytes; 10.845 + } 10.846 + 10.847 + // Not enough data in buffer, copy buffer 10.848 + int readBytes = DataSize-Pos; 10.849 + memcpy(pdestBuffer, pBuffer+Pos, readBytes); 10.850 + numBytes -= readBytes; 10.851 + pdestBuffer += readBytes; 10.852 + Pos = DataSize; 10.853 + 10.854 + // Don't reload buffer if more then tolerance 10.855 + // (No major advantage, and we don't want to write a loop) 10.856 + if (numBytes>FILEBUFFER_TOLERANCE) 10.857 + { 10.858 + numBytes = pFile->Read(pdestBuffer,numBytes); 10.859 + if (numBytes > 0) 10.860 + { 10.861 + FilePos += numBytes; 10.862 + Pos = DataSize = 0; 10.863 + } 10.864 + return readBytes + ((numBytes==-1) ? 0 : numBytes); 10.865 + } 10.866 + 10.867 + // Reload the buffer 10.868 + // WARNING: Right now LoadBuffer() assumes the buffer's empty 10.869 + LoadBuffer(); 10.870 + if ((int)(DataSize-Pos) < numBytes) 10.871 + numBytes = (int)DataSize-Pos; 10.872 + 10.873 + memcpy(pdestBuffer, pBuffer+Pos, numBytes); 10.874 + Pos += numBytes; 10.875 + return numBytes + readBytes; 10.876 + 10.877 + /* 10.878 + // Alternative Read implementation. The one above is probably better 10.879 + // due to FILEBUFFER_TOLERANCE. 10.880 + int total = 0; 10.881 + 10.882 + do { 10.883 + int bufferBytes = (int)(DataSize-Pos); 10.884 + int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes; 10.885 + 10.886 + memcpy(pdestBuffer, pBuffer+Pos, copyBytes); 10.887 + numBytes -= copyBytes; 10.888 + pdestBuffer += copyBytes; 10.889 + Pos += copyBytes; 10.890 + total += copyBytes; 10.891 + 10.892 + if (numBytes == 0) 10.893 + break; 10.894 + LoadBuffer(); 10.895 + 10.896 + } while (DataSize > 0); 10.897 + 10.898 + return total; 10.899 + */ 10.900 + } 10.901 + int sz = pFile->Read(pdestBuffer,numBytes); 10.902 + if (sz > 0) 10.903 + FilePos += sz; 10.904 + return sz; 10.905 +} 10.906 + 10.907 + 10.908 +int BufferedFile::SkipBytes(int numBytes) 10.909 +{ 10.910 + int skippedBytes = 0; 10.911 + 10.912 + // Special case for skipping a little data in read buffer 10.913 + if (BufferMode==ReadBuffer) 10.914 + { 10.915 + skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos); 10.916 + Pos += skippedBytes; 10.917 + numBytes -= skippedBytes; 10.918 + } 10.919 + 10.920 + if (numBytes) 10.921 + { 10.922 + numBytes = pFile->SkipBytes(numBytes); 10.923 + // Make sure we return the actual number skipped, or error 10.924 + if (numBytes!=-1) 10.925 + { 10.926 + skippedBytes += numBytes; 10.927 + FilePos += numBytes; 10.928 + Pos = DataSize = 0; 10.929 + } 10.930 + else if (skippedBytes <= 0) 10.931 + skippedBytes = -1; 10.932 + } 10.933 + return skippedBytes; 10.934 +} 10.935 + 10.936 +int BufferedFile::BytesAvailable() 10.937 +{ 10.938 + int available = pFile->BytesAvailable(); 10.939 + // Adjust available size based on buffers 10.940 + switch(BufferMode) 10.941 + { 10.942 + case ReadBuffer: 10.943 + available += DataSize-Pos; 10.944 + break; 10.945 + case WriteBuffer: 10.946 + available -= Pos; 10.947 + if (available<0) 10.948 + available= 0; 10.949 + break; 10.950 + default: 10.951 + break; 10.952 + } 10.953 + return available; 10.954 +} 10.955 + 10.956 +bool BufferedFile::Flush() 10.957 +{ 10.958 + FlushBuffer(); 10.959 + return pFile->Flush(); 10.960 +} 10.961 + 10.962 +// Seeking could be optimized better.. 10.963 +int BufferedFile::Seek(int offset, int origin) 10.964 +{ 10.965 + if (BufferMode == ReadBuffer) 10.966 + { 10.967 + if (origin == Seek_Cur) 10.968 + { 10.969 + // Seek can fall either before or after Pos in the buffer, 10.970 + // but it must be within bounds. 10.971 + if (((unsigned(offset) + Pos)) <= DataSize) 10.972 + { 10.973 + Pos += offset; 10.974 + return int (FilePos - DataSize + Pos); 10.975 + } 10.976 + 10.977 + // Lightweight buffer "Flush". We do this to avoid an extra seek 10.978 + // back operation which would take place if we called FlushBuffer directly. 10.979 + origin = Seek_Set; 10.980 + OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); 10.981 + offset = (int)(FilePos - DataSize + Pos) + offset; 10.982 + Pos = DataSize = 0; 10.983 + } 10.984 + else if (origin == Seek_Set) 10.985 + { 10.986 + if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) 10.987 + { 10.988 + OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); 10.989 + Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); 10.990 + return offset; 10.991 + } 10.992 + Pos = DataSize = 0; 10.993 + } 10.994 + else 10.995 + { 10.996 + FlushBuffer(); 10.997 + } 10.998 + } 10.999 + else 10.1000 + { 10.1001 + FlushBuffer(); 10.1002 + } 10.1003 + 10.1004 + /* 10.1005 + // Old Seek Logic 10.1006 + if (origin == Seek_Cur && offset + Pos < DataSize) 10.1007 + { 10.1008 + //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset)); 10.1009 + Pos += offset; 10.1010 + OVR_ASSERT(int (Pos) >= 0); 10.1011 + return int (FilePos - DataSize + Pos); 10.1012 + } 10.1013 + else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos) 10.1014 + { 10.1015 + Pos = unsigned(offset - FilePos + DataSize); 10.1016 + OVR_ASSERT(int (Pos) >= 0); 10.1017 + return int (FilePos - DataSize + Pos); 10.1018 + } 10.1019 + 10.1020 + FlushBuffer(); 10.1021 + */ 10.1022 + 10.1023 + 10.1024 + FilePos = pFile->Seek(offset,origin); 10.1025 + return int (FilePos); 10.1026 +} 10.1027 + 10.1028 +SInt64 BufferedFile::LSeek(SInt64 offset, int origin) 10.1029 +{ 10.1030 + if (BufferMode == ReadBuffer) 10.1031 + { 10.1032 + if (origin == Seek_Cur) 10.1033 + { 10.1034 + // Seek can fall either before or after Pos in the buffer, 10.1035 + // but it must be within bounds. 10.1036 + if (((unsigned(offset) + Pos)) <= DataSize) 10.1037 + { 10.1038 + Pos += (unsigned)offset; 10.1039 + return SInt64(FilePos - DataSize + Pos); 10.1040 + } 10.1041 + 10.1042 + // Lightweight buffer "Flush". We do this to avoid an extra seek 10.1043 + // back operation which would take place if we called FlushBuffer directly. 10.1044 + origin = Seek_Set; 10.1045 + offset = (SInt64)(FilePos - DataSize + Pos) + offset; 10.1046 + Pos = DataSize = 0; 10.1047 + } 10.1048 + else if (origin == Seek_Set) 10.1049 + { 10.1050 + if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) 10.1051 + { 10.1052 + Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); 10.1053 + return offset; 10.1054 + } 10.1055 + Pos = DataSize = 0; 10.1056 + } 10.1057 + else 10.1058 + { 10.1059 + FlushBuffer(); 10.1060 + } 10.1061 + } 10.1062 + else 10.1063 + { 10.1064 + FlushBuffer(); 10.1065 + } 10.1066 + 10.1067 +/* 10.1068 + OVR_ASSERT(BufferMode != NoBuffer); 10.1069 + 10.1070 + if (origin == Seek_Cur && offset + Pos < DataSize) 10.1071 + { 10.1072 + Pos += int (offset); 10.1073 + return FilePos - DataSize + Pos; 10.1074 + } 10.1075 + else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) 10.1076 + { 10.1077 + Pos = unsigned(offset - FilePos + DataSize); 10.1078 + return FilePos - DataSize + Pos; 10.1079 + } 10.1080 + 10.1081 + FlushBuffer(); 10.1082 + */ 10.1083 + 10.1084 + FilePos = pFile->LSeek(offset,origin); 10.1085 + return FilePos; 10.1086 +} 10.1087 + 10.1088 +int BufferedFile::CopyFromStream(File *pstream, int byteSize) 10.1089 +{ 10.1090 + // We can't rely on overridden Write() 10.1091 + // because delegation doesn't override virtual pointers 10.1092 + // So, just re-implement 10.1093 + UByte buff[0x4000]; 10.1094 + int count = 0; 10.1095 + int szRequest, szRead, szWritten; 10.1096 + 10.1097 + while(byteSize) 10.1098 + { 10.1099 + szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; 10.1100 + 10.1101 + szRead = pstream->Read(buff,szRequest); 10.1102 + szWritten = 0; 10.1103 + if (szRead > 0) 10.1104 + szWritten = Write(buff,szRead); 10.1105 + 10.1106 + count +=szWritten; 10.1107 + byteSize-=szWritten; 10.1108 + if (szWritten < szRequest) 10.1109 + break; 10.1110 + } 10.1111 + return count; 10.1112 +} 10.1113 + 10.1114 +// Closing files 10.1115 +bool BufferedFile::Close() 10.1116 +{ 10.1117 + switch(BufferMode) 10.1118 + { 10.1119 + case WriteBuffer: 10.1120 + FlushBuffer(); 10.1121 + break; 10.1122 + case ReadBuffer: 10.1123 + // No need to seek back on close 10.1124 + BufferMode = NoBuffer; 10.1125 + break; 10.1126 + default: 10.1127 + break; 10.1128 + } 10.1129 + return pFile->Close(); 10.1130 +} 10.1131 + 10.1132 + 10.1133 +// ***** Global path helpers 10.1134 + 10.1135 +// Find trailing short filename in a path. 10.1136 +const char* OVR_CDECL GetShortFilename(const char* purl) 10.1137 +{ 10.1138 + UPInt len = OVR_strlen(purl); 10.1139 + for (UPInt i=len; i>0; i--) 10.1140 + if (purl[i]=='\\' || purl[i]=='/') 10.1141 + return purl+i+1; 10.1142 + return purl; 10.1143 +} 10.1144 + 10.1145 +} // OVR 10.1146 +
11.1 --- a/libovr/Src/Kernel/OVR_File.h Sat Sep 14 17:51:03 2013 +0300 11.2 +++ b/libovr/Src/Kernel/OVR_File.h Sun Sep 15 04:10:05 2013 +0300 11.3 @@ -1,1 +1,518 @@ 11.4 -/************************************************************************************ 11.5 11.6 PublicHeader: Kernel 11.7 Filename : OVR_File.h 11.8 Content : Header for all internal file management - functions and structures 11.9 to be inherited by OS specific subclasses. 11.10 Created : September 19, 2012 11.11 Notes : 11.12 11.13 Notes : errno may not be preserved across use of BaseFile member functions 11.14 : Directories cannot be deleted while files opened from them are in use 11.15 (For the GetFullName function) 11.16 11.17 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 11.18 11.19 Use of this software is subject to the terms of the Oculus license 11.20 agreement provided at the time of installation or download, or which 11.21 otherwise accompanies this software in either electronic or hard copy form. 11.22 11.23 ************************************************************************************/ 11.24 11.25 #ifndef OVR_File_h 11.26 #define OVR_File_h 11.27 11.28 #include "OVR_RefCount.h" 11.29 #include "OVR_Std.h" 11.30 #include "OVR_Alg.h" 11.31 11.32 #include <stdio.h> 11.33 #include "OVR_String.h" 11.34 11.35 namespace OVR { 11.36 11.37 // ***** Declared classes 11.38 class FileConstants; 11.39 class File; 11.40 class DelegatedFile; 11.41 class BufferedFile; 11.42 11.43 11.44 // ***** Flags for File & Directory accesses 11.45 11.46 class FileConstants 11.47 { 11.48 public: 11.49 11.50 // *** File open flags 11.51 enum OpenFlags 11.52 { 11.53 Open_Read = 1, 11.54 Open_Write = 2, 11.55 Open_ReadWrite = 3, 11.56 11.57 // Opens file and truncates it to zero length 11.58 // - file must have write permission 11.59 // - when used with Create, it opens an existing 11.60 // file and empties it or creates a new file 11.61 Open_Truncate = 4, 11.62 11.63 // Creates and opens new file 11.64 // - does not erase contents if file already 11.65 // exists unless combined with Truncate 11.66 Open_Create = 8, 11.67 11.68 // Returns an error value if the file already exists 11.69 Open_CreateOnly = 24, 11.70 11.71 // Open file with buffering 11.72 Open_Buffered = 32 11.73 }; 11.74 11.75 // *** File Mode flags 11.76 enum Modes 11.77 { 11.78 Mode_Read = 0444, 11.79 Mode_Write = 0222, 11.80 Mode_Execute = 0111, 11.81 11.82 Mode_ReadWrite = 0666 11.83 }; 11.84 11.85 // *** Seek operations 11.86 enum SeekOps 11.87 { 11.88 Seek_Set = 0, 11.89 Seek_Cur = 1, 11.90 Seek_End = 2 11.91 }; 11.92 11.93 // *** Errors 11.94 enum Errors 11.95 { 11.96 Error_FileNotFound = 0x1001, 11.97 Error_Access = 0x1002, 11.98 Error_IOError = 0x1003, 11.99 Error_DiskFull = 0x1004 11.100 }; 11.101 }; 11.102 11.103 11.104 //----------------------------------------------------------------------------------- 11.105 // ***** File Class 11.106 11.107 // The pure virtual base random-access file 11.108 // This is a base class to all files 11.109 11.110 class File : public RefCountBase<File>, public FileConstants 11.111 { 11.112 public: 11.113 File() { } 11.114 // ** Location Information 11.115 11.116 // Returns a file name path relative to the 'reference' directory 11.117 // This is often a path that was used to create a file 11.118 // (this is not a global path, global path can be obtained with help of directory) 11.119 virtual const char* GetFilePath() = 0; 11.120 11.121 11.122 // ** File Information 11.123 11.124 // Return 1 if file's usable (open) 11.125 virtual bool IsValid() = 0; 11.126 // Return 1 if file's writable, otherwise 0 11.127 virtual bool IsWritable() = 0; 11.128 11.129 // Return position 11.130 virtual int Tell() = 0; 11.131 virtual SInt64 LTell() = 0; 11.132 11.133 // File size 11.134 virtual int GetLength() = 0; 11.135 virtual SInt64 LGetLength() = 0; 11.136 11.137 // Returns file stats 11.138 // 0 for failure 11.139 //virtual bool Stat(FileStats *pfs) = 0; 11.140 11.141 // Return errno-based error code 11.142 // Useful if any other function failed 11.143 virtual int GetErrorCode() = 0; 11.144 11.145 11.146 // ** Stream implementation & I/O 11.147 11.148 // Blocking write, will write in the given number of bytes to the stream 11.149 // Returns : -1 for error 11.150 // Otherwise number of bytes read 11.151 virtual int Write(const UByte *pbufer, int numBytes) = 0; 11.152 // Blocking read, will read in the given number of bytes or less from the stream 11.153 // Returns : -1 for error 11.154 // Otherwise number of bytes read, 11.155 // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed 11.156 virtual int Read(UByte *pbufer, int numBytes) = 0; 11.157 11.158 // Skips (ignores) a given # of bytes 11.159 // Same return values as Read 11.160 virtual int SkipBytes(int numBytes) = 0; 11.161 11.162 // Returns the number of bytes available to read from a stream without blocking 11.163 // For a file, this should generally be number of bytes to the end 11.164 virtual int BytesAvailable() = 0; 11.165 11.166 // Causes any implementation's buffered data to be delivered to destination 11.167 // Return 0 for error 11.168 virtual bool Flush() = 0; 11.169 11.170 11.171 // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking 11.172 inline bool IsEOF() { return !BytesAvailable(); } 11.173 11.174 11.175 // Seeking 11.176 // Returns new position, -1 for error 11.177 virtual int Seek(int offset, int origin=Seek_Set) = 0; 11.178 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0; 11.179 // Seek simplification 11.180 int SeekToBegin() {return Seek(0); } 11.181 int SeekToEnd() {return Seek(0,Seek_End); } 11.182 int Skip(int numBytes) {return Seek(numBytes,Seek_Cur); } 11.183 11.184 11.185 // Appends other file data from a stream 11.186 // Return -1 for error, else # of bytes written 11.187 virtual int CopyFromStream(File *pstream, int byteSize) = 0; 11.188 11.189 // Closes the file 11.190 // After close, file cannot be accessed 11.191 virtual bool Close() = 0; 11.192 11.193 11.194 // ***** Inlines for convenient primitive type serialization 11.195 11.196 // Read/Write helpers 11.197 private: 11.198 UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; } 11.199 UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; } 11.200 UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; } 11.201 UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; } 11.202 void PWrite64(UInt64 v) { Write((UByte*)&v, 8); } 11.203 void PWrite32(UInt32 v) { Write((UByte*)&v, 4); } 11.204 void PWrite16(UInt16 v) { Write((UByte*)&v, 2); } 11.205 void PWrite8(UByte v) { Write((UByte*)&v, 1); } 11.206 11.207 public: 11.208 11.209 // Writing primitive types - Little Endian 11.210 inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.211 inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.212 inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.213 inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.214 inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } 11.215 inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } 11.216 inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } 11.217 inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } 11.218 inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } 11.219 inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } 11.220 inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } 11.221 inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); } 11.222 // Writing primitive types - Big Endian 11.223 inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.224 inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.225 inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.226 inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.227 inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } 11.228 inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } 11.229 inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } 11.230 inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } 11.231 inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } 11.232 inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } 11.233 inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); } 11.234 inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); } 11.235 11.236 // Reading primitive types - Little Endian 11.237 inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.238 inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.239 inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.240 inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.241 inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); } 11.242 inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); } 11.243 inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); } 11.244 inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); } 11.245 inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); } 11.246 inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); } 11.247 inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } 11.248 inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } 11.249 // Reading primitive types - Big Endian 11.250 inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.251 inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.252 inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.253 inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.254 inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); } 11.255 inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); } 11.256 inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); } 11.257 inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); } 11.258 inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); } 11.259 inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); } 11.260 inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } 11.261 inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } 11.262 }; 11.263 11.264 11.265 // *** Delegated File 11.266 11.267 class DelegatedFile : public File 11.268 { 11.269 protected: 11.270 // Delegating file pointer 11.271 Ptr<File> pFile; 11.272 11.273 // Hidden default constructor 11.274 DelegatedFile() : pFile(0) { } 11.275 DelegatedFile(const DelegatedFile &source) : File() { OVR_UNUSED(source); } 11.276 public: 11.277 // Constructors 11.278 DelegatedFile(File *pfile) : pFile(pfile) { } 11.279 11.280 // ** Location Information 11.281 virtual const char* GetFilePath() { return pFile->GetFilePath(); } 11.282 11.283 // ** File Information 11.284 virtual bool IsValid() { return pFile && pFile->IsValid(); } 11.285 virtual bool IsWritable() { return pFile->IsWritable(); } 11.286 // virtual bool IsRecoverable() { return pFile->IsRecoverable(); } 11.287 11.288 virtual int Tell() { return pFile->Tell(); } 11.289 virtual SInt64 LTell() { return pFile->LTell(); } 11.290 11.291 virtual int GetLength() { return pFile->GetLength(); } 11.292 virtual SInt64 LGetLength() { return pFile->LGetLength(); } 11.293 11.294 //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); } 11.295 11.296 virtual int GetErrorCode() { return pFile->GetErrorCode(); } 11.297 11.298 // ** Stream implementation & I/O 11.299 virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } 11.300 virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } 11.301 11.302 virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); } 11.303 11.304 virtual int BytesAvailable() { return pFile->BytesAvailable(); } 11.305 11.306 virtual bool Flush() { return pFile->Flush(); } 11.307 11.308 // Seeking 11.309 virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); } 11.310 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } 11.311 11.312 virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); } 11.313 11.314 // Closing the file 11.315 virtual bool Close() { return pFile->Close(); } 11.316 }; 11.317 11.318 11.319 //----------------------------------------------------------------------------------- 11.320 // ***** Buffered File 11.321 11.322 // This file class adds buffering to an existing file 11.323 // Buffered file never fails by itself; if there's not 11.324 // enough memory for buffer, no buffer's used 11.325 11.326 class BufferedFile : public DelegatedFile 11.327 { 11.328 protected: 11.329 enum BufferModeType 11.330 { 11.331 NoBuffer, 11.332 ReadBuffer, 11.333 WriteBuffer 11.334 }; 11.335 11.336 // Buffer & the mode it's in 11.337 UByte* pBuffer; 11.338 BufferModeType BufferMode; 11.339 // Position in buffer 11.340 unsigned Pos; 11.341 // Data in buffer if reading 11.342 unsigned DataSize; 11.343 // Underlying file position 11.344 UInt64 FilePos; 11.345 11.346 // Initializes buffering to a certain mode 11.347 bool SetBufferMode(BufferModeType mode); 11.348 // Flushes buffer 11.349 // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position 11.350 void FlushBuffer(); 11.351 // Loads data into ReadBuffer 11.352 // WARNING: Right now LoadBuffer() assumes the buffer's empty 11.353 void LoadBuffer(); 11.354 11.355 // Hidden constructor 11.356 BufferedFile(); 11.357 inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); } 11.358 public: 11.359 11.360 // Constructor 11.361 // - takes another file as source 11.362 BufferedFile(File *pfile); 11.363 ~BufferedFile(); 11.364 11.365 11.366 // ** Overridden functions 11.367 11.368 // We override all the functions that can possibly 11.369 // require buffer mode switch, flush, or extra calculations 11.370 virtual int Tell(); 11.371 virtual SInt64 LTell(); 11.372 11.373 virtual int GetLength(); 11.374 virtual SInt64 LGetLength(); 11.375 11.376 // virtual bool Stat(GFileStats *pfs); 11.377 11.378 virtual int Write(const UByte *pbufer, int numBytes); 11.379 virtual int Read(UByte *pbufer, int numBytes); 11.380 11.381 virtual int SkipBytes(int numBytes); 11.382 11.383 virtual int BytesAvailable(); 11.384 11.385 virtual bool Flush(); 11.386 11.387 virtual int Seek(int offset, int origin=Seek_Set); 11.388 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set); 11.389 11.390 virtual int CopyFromStream(File *pstream, int byteSize); 11.391 11.392 virtual bool Close(); 11.393 }; 11.394 11.395 11.396 //----------------------------------------------------------------------------------- 11.397 // ***** Memory File 11.398 11.399 class MemoryFile : public File 11.400 { 11.401 public: 11.402 11.403 const char* GetFilePath() { return FilePath.ToCStr(); } 11.404 11.405 bool IsValid() { return Valid; } 11.406 bool IsWritable() { return false; } 11.407 11.408 bool Flush() { return true; } 11.409 int GetErrorCode() { return 0; } 11.410 11.411 int Tell() { return FileIndex; } 11.412 SInt64 LTell() { return (SInt64) FileIndex; } 11.413 11.414 int GetLength() { return FileSize; } 11.415 SInt64 LGetLength() { return (SInt64) FileSize; } 11.416 11.417 bool Close() 11.418 { 11.419 Valid = false; 11.420 return false; 11.421 } 11.422 11.423 int CopyFromStream(File *pstream, int byteSize) 11.424 { OVR_UNUSED2(pstream, byteSize); 11.425 return 0; 11.426 } 11.427 11.428 int Write(const UByte *pbuffer, int numBytes) 11.429 { OVR_UNUSED2(pbuffer, numBytes); 11.430 return 0; 11.431 } 11.432 11.433 int Read(UByte *pbufer, int numBytes) 11.434 { 11.435 if (FileIndex + numBytes > FileSize) 11.436 { 11.437 numBytes = FileSize - FileIndex; 11.438 } 11.439 11.440 if (numBytes > 0) 11.441 { 11.442 ::memcpy (pbufer, &FileData [FileIndex], numBytes); 11.443 11.444 FileIndex += numBytes; 11.445 } 11.446 11.447 return numBytes; 11.448 } 11.449 11.450 int SkipBytes(int numBytes) 11.451 { 11.452 if (FileIndex + numBytes > FileSize) 11.453 { 11.454 numBytes = FileSize - FileIndex; 11.455 } 11.456 11.457 FileIndex += numBytes; 11.458 11.459 return numBytes; 11.460 } 11.461 11.462 int BytesAvailable() 11.463 { 11.464 return (FileSize - FileIndex); 11.465 } 11.466 11.467 int Seek(int offset, int origin = Seek_Set) 11.468 { 11.469 switch (origin) 11.470 { 11.471 case Seek_Set : FileIndex = offset; break; 11.472 case Seek_Cur : FileIndex += offset; break; 11.473 case Seek_End : FileIndex = FileSize - offset; break; 11.474 } 11.475 11.476 return FileIndex; 11.477 } 11.478 11.479 SInt64 LSeek(SInt64 offset, int origin = Seek_Set) 11.480 { 11.481 return (SInt64) Seek((int) offset, origin); 11.482 } 11.483 11.484 public: 11.485 11.486 MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize) 11.487 : FilePath(fileName) 11.488 { 11.489 FileData = pBuffer; 11.490 FileSize = buffSize; 11.491 FileIndex = 0; 11.492 Valid = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false; 11.493 } 11.494 11.495 // pfileName should be encoded as UTF-8 to support international file names. 11.496 MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize) 11.497 : FilePath(pfileName) 11.498 { 11.499 FileData = pBuffer; 11.500 FileSize = buffSize; 11.501 FileIndex = 0; 11.502 Valid = (pfileName && pBuffer && buffSize > 0) ? true : false; 11.503 } 11.504 private: 11.505 11.506 String FilePath; 11.507 const UByte *FileData; 11.508 int FileSize; 11.509 int FileIndex; 11.510 bool Valid; 11.511 }; 11.512 11.513 11.514 // ***** Global path helpers 11.515 11.516 // Find trailing short filename in a path. 11.517 const char* OVR_CDECL GetShortFilename(const char* purl); 11.518 11.519 } // OVR 11.520 11.521 #endif 11.522 \ No newline at end of file 11.523 +/************************************************************************************ 11.524 + 11.525 +PublicHeader: Kernel 11.526 +Filename : OVR_File.h 11.527 +Content : Header for all internal file management - functions and structures 11.528 + to be inherited by OS specific subclasses. 11.529 +Created : September 19, 2012 11.530 +Notes : 11.531 + 11.532 +Notes : errno may not be preserved across use of BaseFile member functions 11.533 + : Directories cannot be deleted while files opened from them are in use 11.534 + (For the GetFullName function) 11.535 + 11.536 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 11.537 + 11.538 +Use of this software is subject to the terms of the Oculus license 11.539 +agreement provided at the time of installation or download, or which 11.540 +otherwise accompanies this software in either electronic or hard copy form. 11.541 + 11.542 +************************************************************************************/ 11.543 + 11.544 +#ifndef OVR_File_h 11.545 +#define OVR_File_h 11.546 + 11.547 +#include "OVR_RefCount.h" 11.548 +#include "OVR_Std.h" 11.549 +#include "OVR_Alg.h" 11.550 + 11.551 +#include <stdio.h> 11.552 +#include "OVR_String.h" 11.553 + 11.554 +namespace OVR { 11.555 + 11.556 +// ***** Declared classes 11.557 +class FileConstants; 11.558 +class File; 11.559 +class DelegatedFile; 11.560 +class BufferedFile; 11.561 + 11.562 + 11.563 +// ***** Flags for File & Directory accesses 11.564 + 11.565 +class FileConstants 11.566 +{ 11.567 +public: 11.568 + 11.569 + // *** File open flags 11.570 + enum OpenFlags 11.571 + { 11.572 + Open_Read = 1, 11.573 + Open_Write = 2, 11.574 + Open_ReadWrite = 3, 11.575 + 11.576 + // Opens file and truncates it to zero length 11.577 + // - file must have write permission 11.578 + // - when used with Create, it opens an existing 11.579 + // file and empties it or creates a new file 11.580 + Open_Truncate = 4, 11.581 + 11.582 + // Creates and opens new file 11.583 + // - does not erase contents if file already 11.584 + // exists unless combined with Truncate 11.585 + Open_Create = 8, 11.586 + 11.587 + // Returns an error value if the file already exists 11.588 + Open_CreateOnly = 24, 11.589 + 11.590 + // Open file with buffering 11.591 + Open_Buffered = 32 11.592 + }; 11.593 + 11.594 + // *** File Mode flags 11.595 + enum Modes 11.596 + { 11.597 + Mode_Read = 0444, 11.598 + Mode_Write = 0222, 11.599 + Mode_Execute = 0111, 11.600 + 11.601 + Mode_ReadWrite = 0666 11.602 + }; 11.603 + 11.604 + // *** Seek operations 11.605 + enum SeekOps 11.606 + { 11.607 + Seek_Set = 0, 11.608 + Seek_Cur = 1, 11.609 + Seek_End = 2 11.610 + }; 11.611 + 11.612 + // *** Errors 11.613 + enum Errors 11.614 + { 11.615 + Error_FileNotFound = 0x1001, 11.616 + Error_Access = 0x1002, 11.617 + Error_IOError = 0x1003, 11.618 + Error_DiskFull = 0x1004 11.619 + }; 11.620 +}; 11.621 + 11.622 + 11.623 +//----------------------------------------------------------------------------------- 11.624 +// ***** File Class 11.625 + 11.626 +// The pure virtual base random-access file 11.627 +// This is a base class to all files 11.628 + 11.629 +class File : public RefCountBase<File>, public FileConstants 11.630 +{ 11.631 +public: 11.632 + File() { } 11.633 + // ** Location Information 11.634 + 11.635 + // Returns a file name path relative to the 'reference' directory 11.636 + // This is often a path that was used to create a file 11.637 + // (this is not a global path, global path can be obtained with help of directory) 11.638 + virtual const char* GetFilePath() = 0; 11.639 + 11.640 + 11.641 + // ** File Information 11.642 + 11.643 + // Return 1 if file's usable (open) 11.644 + virtual bool IsValid() = 0; 11.645 + // Return 1 if file's writable, otherwise 0 11.646 + virtual bool IsWritable() = 0; 11.647 + 11.648 + // Return position 11.649 + virtual int Tell() = 0; 11.650 + virtual SInt64 LTell() = 0; 11.651 + 11.652 + // File size 11.653 + virtual int GetLength() = 0; 11.654 + virtual SInt64 LGetLength() = 0; 11.655 + 11.656 + // Returns file stats 11.657 + // 0 for failure 11.658 + //virtual bool Stat(FileStats *pfs) = 0; 11.659 + 11.660 + // Return errno-based error code 11.661 + // Useful if any other function failed 11.662 + virtual int GetErrorCode() = 0; 11.663 + 11.664 + 11.665 + // ** Stream implementation & I/O 11.666 + 11.667 + // Blocking write, will write in the given number of bytes to the stream 11.668 + // Returns : -1 for error 11.669 + // Otherwise number of bytes read 11.670 + virtual int Write(const UByte *pbufer, int numBytes) = 0; 11.671 + // Blocking read, will read in the given number of bytes or less from the stream 11.672 + // Returns : -1 for error 11.673 + // Otherwise number of bytes read, 11.674 + // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed 11.675 + virtual int Read(UByte *pbufer, int numBytes) = 0; 11.676 + 11.677 + // Skips (ignores) a given # of bytes 11.678 + // Same return values as Read 11.679 + virtual int SkipBytes(int numBytes) = 0; 11.680 + 11.681 + // Returns the number of bytes available to read from a stream without blocking 11.682 + // For a file, this should generally be number of bytes to the end 11.683 + virtual int BytesAvailable() = 0; 11.684 + 11.685 + // Causes any implementation's buffered data to be delivered to destination 11.686 + // Return 0 for error 11.687 + virtual bool Flush() = 0; 11.688 + 11.689 + 11.690 + // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking 11.691 + inline bool IsEOF() { return !BytesAvailable(); } 11.692 + 11.693 + 11.694 + // Seeking 11.695 + // Returns new position, -1 for error 11.696 + virtual int Seek(int offset, int origin=Seek_Set) = 0; 11.697 + virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0; 11.698 + // Seek simplification 11.699 + int SeekToBegin() {return Seek(0); } 11.700 + int SeekToEnd() {return Seek(0,Seek_End); } 11.701 + int Skip(int numBytes) {return Seek(numBytes,Seek_Cur); } 11.702 + 11.703 + 11.704 + // Appends other file data from a stream 11.705 + // Return -1 for error, else # of bytes written 11.706 + virtual int CopyFromStream(File *pstream, int byteSize) = 0; 11.707 + 11.708 + // Closes the file 11.709 + // After close, file cannot be accessed 11.710 + virtual bool Close() = 0; 11.711 + 11.712 + 11.713 + // ***** Inlines for convenient primitive type serialization 11.714 + 11.715 + // Read/Write helpers 11.716 +private: 11.717 + UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; } 11.718 + UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; } 11.719 + UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; } 11.720 + UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; } 11.721 + void PWrite64(UInt64 v) { Write((UByte*)&v, 8); } 11.722 + void PWrite32(UInt32 v) { Write((UByte*)&v, 4); } 11.723 + void PWrite16(UInt16 v) { Write((UByte*)&v, 2); } 11.724 + void PWrite8(UByte v) { Write((UByte*)&v, 1); } 11.725 + 11.726 +public: 11.727 + 11.728 + // Writing primitive types - Little Endian 11.729 + inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.730 + inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.731 + inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.732 + inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } 11.733 + inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } 11.734 + inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } 11.735 + inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } 11.736 + inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } 11.737 + inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } 11.738 + inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } 11.739 + inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } 11.740 + inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); } 11.741 + // Writing primitive types - Big Endian 11.742 + inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.743 + inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.744 + inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.745 + inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } 11.746 + inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } 11.747 + inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } 11.748 + inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } 11.749 + inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } 11.750 + inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } 11.751 + inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } 11.752 + inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); } 11.753 + inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); } 11.754 + 11.755 + // Reading primitive types - Little Endian 11.756 + inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.757 + inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.758 + inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.759 + inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } 11.760 + inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); } 11.761 + inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); } 11.762 + inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); } 11.763 + inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); } 11.764 + inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); } 11.765 + inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); } 11.766 + inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } 11.767 + inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } 11.768 + // Reading primitive types - Big Endian 11.769 + inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.770 + inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.771 + inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.772 + inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } 11.773 + inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); } 11.774 + inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); } 11.775 + inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); } 11.776 + inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); } 11.777 + inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); } 11.778 + inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); } 11.779 + inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } 11.780 + inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } 11.781 +}; 11.782 + 11.783 + 11.784 +// *** Delegated File 11.785 + 11.786 +class DelegatedFile : public File 11.787 +{ 11.788 +protected: 11.789 + // Delegating file pointer 11.790 + Ptr<File> pFile; 11.791 + 11.792 + // Hidden default constructor 11.793 + DelegatedFile() : pFile(0) { } 11.794 + DelegatedFile(const DelegatedFile &source) : File() { OVR_UNUSED(source); } 11.795 +public: 11.796 + // Constructors 11.797 + DelegatedFile(File *pfile) : pFile(pfile) { } 11.798 + 11.799 + // ** Location Information 11.800 + virtual const char* GetFilePath() { return pFile->GetFilePath(); } 11.801 + 11.802 + // ** File Information 11.803 + virtual bool IsValid() { return pFile && pFile->IsValid(); } 11.804 + virtual bool IsWritable() { return pFile->IsWritable(); } 11.805 +// virtual bool IsRecoverable() { return pFile->IsRecoverable(); } 11.806 + 11.807 + virtual int Tell() { return pFile->Tell(); } 11.808 + virtual SInt64 LTell() { return pFile->LTell(); } 11.809 + 11.810 + virtual int GetLength() { return pFile->GetLength(); } 11.811 + virtual SInt64 LGetLength() { return pFile->LGetLength(); } 11.812 + 11.813 + //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); } 11.814 + 11.815 + virtual int GetErrorCode() { return pFile->GetErrorCode(); } 11.816 + 11.817 + // ** Stream implementation & I/O 11.818 + virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } 11.819 + virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } 11.820 + 11.821 + virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); } 11.822 + 11.823 + virtual int BytesAvailable() { return pFile->BytesAvailable(); } 11.824 + 11.825 + virtual bool Flush() { return pFile->Flush(); } 11.826 + 11.827 + // Seeking 11.828 + virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); } 11.829 + virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } 11.830 + 11.831 + virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); } 11.832 + 11.833 + // Closing the file 11.834 + virtual bool Close() { return pFile->Close(); } 11.835 +}; 11.836 + 11.837 + 11.838 +//----------------------------------------------------------------------------------- 11.839 +// ***** Buffered File 11.840 + 11.841 +// This file class adds buffering to an existing file 11.842 +// Buffered file never fails by itself; if there's not 11.843 +// enough memory for buffer, no buffer's used 11.844 + 11.845 +class BufferedFile : public DelegatedFile 11.846 +{ 11.847 +protected: 11.848 + enum BufferModeType 11.849 + { 11.850 + NoBuffer, 11.851 + ReadBuffer, 11.852 + WriteBuffer 11.853 + }; 11.854 + 11.855 + // Buffer & the mode it's in 11.856 + UByte* pBuffer; 11.857 + BufferModeType BufferMode; 11.858 + // Position in buffer 11.859 + unsigned Pos; 11.860 + // Data in buffer if reading 11.861 + unsigned DataSize; 11.862 + // Underlying file position 11.863 + UInt64 FilePos; 11.864 + 11.865 + // Initializes buffering to a certain mode 11.866 + bool SetBufferMode(BufferModeType mode); 11.867 + // Flushes buffer 11.868 + // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position 11.869 + void FlushBuffer(); 11.870 + // Loads data into ReadBuffer 11.871 + // WARNING: Right now LoadBuffer() assumes the buffer's empty 11.872 + void LoadBuffer(); 11.873 + 11.874 + // Hidden constructor 11.875 + BufferedFile(); 11.876 + inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); } 11.877 +public: 11.878 + 11.879 + // Constructor 11.880 + // - takes another file as source 11.881 + BufferedFile(File *pfile); 11.882 + ~BufferedFile(); 11.883 + 11.884 + 11.885 + // ** Overridden functions 11.886 + 11.887 + // We override all the functions that can possibly 11.888 + // require buffer mode switch, flush, or extra calculations 11.889 + virtual int Tell(); 11.890 + virtual SInt64 LTell(); 11.891 + 11.892 + virtual int GetLength(); 11.893 + virtual SInt64 LGetLength(); 11.894 + 11.895 +// virtual bool Stat(GFileStats *pfs); 11.896 + 11.897 + virtual int Write(const UByte *pbufer, int numBytes); 11.898 + virtual int Read(UByte *pbufer, int numBytes); 11.899 + 11.900 + virtual int SkipBytes(int numBytes); 11.901 + 11.902 + virtual int BytesAvailable(); 11.903 + 11.904 + virtual bool Flush(); 11.905 + 11.906 + virtual int Seek(int offset, int origin=Seek_Set); 11.907 + virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set); 11.908 + 11.909 + virtual int CopyFromStream(File *pstream, int byteSize); 11.910 + 11.911 + virtual bool Close(); 11.912 +}; 11.913 + 11.914 + 11.915 +//----------------------------------------------------------------------------------- 11.916 +// ***** Memory File 11.917 + 11.918 +class MemoryFile : public File 11.919 +{ 11.920 +public: 11.921 + 11.922 + const char* GetFilePath() { return FilePath.ToCStr(); } 11.923 + 11.924 + bool IsValid() { return Valid; } 11.925 + bool IsWritable() { return false; } 11.926 + 11.927 + bool Flush() { return true; } 11.928 + int GetErrorCode() { return 0; } 11.929 + 11.930 + int Tell() { return FileIndex; } 11.931 + SInt64 LTell() { return (SInt64) FileIndex; } 11.932 + 11.933 + int GetLength() { return FileSize; } 11.934 + SInt64 LGetLength() { return (SInt64) FileSize; } 11.935 + 11.936 + bool Close() 11.937 + { 11.938 + Valid = false; 11.939 + return false; 11.940 + } 11.941 + 11.942 + int CopyFromStream(File *pstream, int byteSize) 11.943 + { OVR_UNUSED2(pstream, byteSize); 11.944 + return 0; 11.945 + } 11.946 + 11.947 + int Write(const UByte *pbuffer, int numBytes) 11.948 + { OVR_UNUSED2(pbuffer, numBytes); 11.949 + return 0; 11.950 + } 11.951 + 11.952 + int Read(UByte *pbufer, int numBytes) 11.953 + { 11.954 + if (FileIndex + numBytes > FileSize) 11.955 + { 11.956 + numBytes = FileSize - FileIndex; 11.957 + } 11.958 + 11.959 + if (numBytes > 0) 11.960 + { 11.961 + ::memcpy (pbufer, &FileData [FileIndex], numBytes); 11.962 + 11.963 + FileIndex += numBytes; 11.964 + } 11.965 + 11.966 + return numBytes; 11.967 + } 11.968 + 11.969 + int SkipBytes(int numBytes) 11.970 + { 11.971 + if (FileIndex + numBytes > FileSize) 11.972 + { 11.973 + numBytes = FileSize - FileIndex; 11.974 + } 11.975 + 11.976 + FileIndex += numBytes; 11.977 + 11.978 + return numBytes; 11.979 + } 11.980 + 11.981 + int BytesAvailable() 11.982 + { 11.983 + return (FileSize - FileIndex); 11.984 + } 11.985 + 11.986 + int Seek(int offset, int origin = Seek_Set) 11.987 + { 11.988 + switch (origin) 11.989 + { 11.990 + case Seek_Set : FileIndex = offset; break; 11.991 + case Seek_Cur : FileIndex += offset; break; 11.992 + case Seek_End : FileIndex = FileSize - offset; break; 11.993 + } 11.994 + 11.995 + return FileIndex; 11.996 + } 11.997 + 11.998 + SInt64 LSeek(SInt64 offset, int origin = Seek_Set) 11.999 + { 11.1000 + return (SInt64) Seek((int) offset, origin); 11.1001 + } 11.1002 + 11.1003 +public: 11.1004 + 11.1005 + MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize) 11.1006 + : FilePath(fileName) 11.1007 + { 11.1008 + FileData = pBuffer; 11.1009 + FileSize = buffSize; 11.1010 + FileIndex = 0; 11.1011 + Valid = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false; 11.1012 + } 11.1013 + 11.1014 + // pfileName should be encoded as UTF-8 to support international file names. 11.1015 + MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize) 11.1016 + : FilePath(pfileName) 11.1017 + { 11.1018 + FileData = pBuffer; 11.1019 + FileSize = buffSize; 11.1020 + FileIndex = 0; 11.1021 + Valid = (pfileName && pBuffer && buffSize > 0) ? true : false; 11.1022 + } 11.1023 +private: 11.1024 + 11.1025 + String FilePath; 11.1026 + const UByte *FileData; 11.1027 + int FileSize; 11.1028 + int FileIndex; 11.1029 + bool Valid; 11.1030 +}; 11.1031 + 11.1032 + 11.1033 +// ***** Global path helpers 11.1034 + 11.1035 +// Find trailing short filename in a path. 11.1036 +const char* OVR_CDECL GetShortFilename(const char* purl); 11.1037 + 11.1038 +} // OVR 11.1039 + 11.1040 +#endif
12.1 --- a/libovr/Src/Kernel/OVR_FileFILE.cpp Sat Sep 14 17:51:03 2013 +0300 12.2 +++ b/libovr/Src/Kernel/OVR_FileFILE.cpp Sun Sep 15 04:10:05 2013 +0300 12.3 @@ -1,1 +1,583 @@ 12.4 -/************************************************************************** 12.5 12.6 Filename : OVR_FileFILE.cpp 12.7 Content : File wrapper class implementation (Win32) 12.8 12.9 Created : April 5, 1999 12.10 Authors : Michael Antonov 12.11 12.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 12.13 12.14 Use of this software is subject to the terms of the Oculus license 12.15 agreement provided at the time of installation or download, or which 12.16 otherwise accompanies this software in either electronic or hard copy form. 12.17 12.18 **************************************************************************/ 12.19 12.20 #define GFILE_CXX 12.21 12.22 #include "OVR_Types.h" 12.23 #include "OVR_Log.h" 12.24 12.25 // Standard C library (Captain Obvious guarantees!) 12.26 #include <stdio.h> 12.27 #ifndef OVR_OS_WINCE 12.28 #include <sys/stat.h> 12.29 #endif 12.30 12.31 #include "OVR_SysFile.h" 12.32 12.33 #ifndef OVR_OS_WINCE 12.34 #include <errno.h> 12.35 #endif 12.36 12.37 namespace OVR { 12.38 12.39 // ***** File interface 12.40 12.41 // ***** FILEFile - C streams file 12.42 12.43 static int SFerror () 12.44 { 12.45 if (errno == ENOENT) 12.46 return FileConstants::Error_FileNotFound; 12.47 else if (errno == EACCES || errno == EPERM) 12.48 return FileConstants::Error_Access; 12.49 else if (errno == ENOSPC) 12.50 return FileConstants::Error_DiskFull; 12.51 else 12.52 return FileConstants::Error_IOError; 12.53 }; 12.54 12.55 #ifdef OVR_OS_WIN32 12.56 #include "windows.h" 12.57 // A simple helper class to disable/enable system error mode, if necessary 12.58 // Disabling happens conditionally only if a drive name is involved 12.59 class SysErrorModeDisabler 12.60 { 12.61 BOOL Disabled; 12.62 UINT OldMode; 12.63 public: 12.64 SysErrorModeDisabler(const char* pfileName) 12.65 { 12.66 if (pfileName && (pfileName[0]!=0) && pfileName[1]==':') 12.67 { 12.68 Disabled = 1; 12.69 OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS); 12.70 } 12.71 else 12.72 Disabled = 0; 12.73 } 12.74 12.75 ~SysErrorModeDisabler() 12.76 { 12.77 if (Disabled) ::SetErrorMode(OldMode); 12.78 } 12.79 }; 12.80 #else 12.81 class SysErrorModeDisabler 12.82 { 12.83 public: 12.84 SysErrorModeDisabler(const char* pfileName) { } 12.85 }; 12.86 #endif // OVR_OS_WIN32 12.87 12.88 12.89 // This macro enables verification of I/O results after seeks against a pre-loaded 12.90 // full file buffer copy. This is generally not necessary, but can been used to debug 12.91 // memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory 12.92 // under FMOD with XP64 (32-bit) and Realtek HA Audio driver. 12.93 //#define GFILE_VERIFY_SEEK_ERRORS 12.94 12.95 12.96 // This is the simplest possible file implementation, it wraps around the descriptor 12.97 // This file is delegated to by SysFile. 12.98 12.99 class FILEFile : public File 12.100 { 12.101 protected: 12.102 12.103 // Allocated filename 12.104 String FileName; 12.105 12.106 // File handle & open mode 12.107 bool Opened; 12.108 FILE* fs; 12.109 int OpenFlags; 12.110 // Error code for last request 12.111 int ErrorCode; 12.112 12.113 int LastOp; 12.114 12.115 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.116 UByte* pFileTestBuffer; 12.117 unsigned FileTestLength; 12.118 unsigned TestPos; // File pointer position during tests. 12.119 #endif 12.120 12.121 public: 12.122 12.123 FILEFile() 12.124 { 12.125 Opened = 0; FileName = ""; 12.126 12.127 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.128 pFileTestBuffer =0; 12.129 FileTestLength =0; 12.130 TestPos =0; 12.131 #endif 12.132 } 12.133 // Initialize file by opening it 12.134 FILEFile(const String& fileName, int flags, int Mode); 12.135 // The 'pfileName' should be encoded as UTF-8 to support international file names. 12.136 FILEFile(const char* pfileName, int flags, int Mode); 12.137 12.138 ~FILEFile() 12.139 { 12.140 if (Opened) 12.141 Close(); 12.142 } 12.143 12.144 virtual const char* GetFilePath(); 12.145 12.146 // ** File Information 12.147 virtual bool IsValid(); 12.148 virtual bool IsWritable(); 12.149 12.150 // Return position / file size 12.151 virtual int Tell(); 12.152 virtual SInt64 LTell(); 12.153 virtual int GetLength(); 12.154 virtual SInt64 LGetLength(); 12.155 12.156 // virtual bool Stat(FileStats *pfs); 12.157 virtual int GetErrorCode(); 12.158 12.159 // ** Stream implementation & I/O 12.160 virtual int Write(const UByte *pbuffer, int numBytes); 12.161 virtual int Read(UByte *pbuffer, int numBytes); 12.162 virtual int SkipBytes(int numBytes); 12.163 virtual int BytesAvailable(); 12.164 virtual bool Flush(); 12.165 virtual int Seek(int offset, int origin); 12.166 virtual SInt64 LSeek(SInt64 offset, int origin); 12.167 12.168 virtual int CopyFromStream(File *pStream, int byteSize); 12.169 virtual bool Close(); 12.170 private: 12.171 void init(); 12.172 }; 12.173 12.174 12.175 // Initialize file by opening it 12.176 FILEFile::FILEFile(const String& fileName, int flags, int mode) 12.177 : FileName(fileName), OpenFlags(flags) 12.178 { 12.179 OVR_UNUSED(mode); 12.180 init(); 12.181 } 12.182 12.183 // The 'pfileName' should be encoded as UTF-8 to support international file names. 12.184 FILEFile::FILEFile(const char* pfileName, int flags, int mode) 12.185 : FileName(pfileName), OpenFlags(flags) 12.186 { 12.187 OVR_UNUSED(mode); 12.188 init(); 12.189 } 12.190 12.191 void FILEFile::init() 12.192 { 12.193 // Open mode for file's open 12.194 const char *omode = "rb"; 12.195 12.196 if (OpenFlags & Open_Truncate) 12.197 { 12.198 if (OpenFlags & Open_Read) 12.199 omode = "w+b"; 12.200 else 12.201 omode = "wb"; 12.202 } 12.203 else if (OpenFlags & Open_Create) 12.204 { 12.205 if (OpenFlags & Open_Read) 12.206 omode = "a+b"; 12.207 else 12.208 omode = "ab"; 12.209 } 12.210 else if (OpenFlags & Open_Write) 12.211 omode = "r+b"; 12.212 12.213 #ifdef OVR_OS_WIN32 12.214 SysErrorModeDisabler disabler(FileName.ToCStr()); 12.215 #endif 12.216 12.217 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 12.218 wchar_t womode[16]; 12.219 wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t)); 12.220 UTF8Util::DecodeString(pwFileName, FileName.ToCStr()); 12.221 OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0])); 12.222 UTF8Util::DecodeString(womode, omode); 12.223 _wfopen_s(&fs, pwFileName, womode); 12.224 OVR_FREE(pwFileName); 12.225 #else 12.226 fs = fopen(FileName.ToCStr(), omode); 12.227 #endif 12.228 if (fs) 12.229 rewind (fs); 12.230 Opened = (fs != NULL); 12.231 // Set error code 12.232 if (!Opened) 12.233 ErrorCode = SFerror(); 12.234 else 12.235 { 12.236 // If we are testing file seek correctness, pre-load the entire file so 12.237 // that we can do comparison tests later. 12.238 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.239 TestPos = 0; 12.240 fseek(fs, 0, SEEK_END); 12.241 FileTestLength = ftell(fs); 12.242 fseek(fs, 0, SEEK_SET); 12.243 pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength); 12.244 if (pFileTestBuffer) 12.245 { 12.246 OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength)); 12.247 Seek(0, Seek_Set); 12.248 } 12.249 #endif 12.250 12.251 ErrorCode = 0; 12.252 } 12.253 LastOp = 0; 12.254 } 12.255 12.256 12.257 const char* FILEFile::GetFilePath() 12.258 { 12.259 return FileName.ToCStr(); 12.260 } 12.261 12.262 12.263 // ** File Information 12.264 bool FILEFile::IsValid() 12.265 { 12.266 return Opened; 12.267 } 12.268 bool FILEFile::IsWritable() 12.269 { 12.270 return IsValid() && (OpenFlags&Open_Write); 12.271 } 12.272 /* 12.273 bool FILEFile::IsRecoverable() 12.274 { 12.275 return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC); 12.276 } 12.277 */ 12.278 12.279 // Return position / file size 12.280 int FILEFile::Tell() 12.281 { 12.282 int pos = (int)ftell (fs); 12.283 if (pos < 0) 12.284 ErrorCode = SFerror(); 12.285 return pos; 12.286 } 12.287 12.288 SInt64 FILEFile::LTell() 12.289 { 12.290 SInt64 pos = ftell(fs); 12.291 if (pos < 0) 12.292 ErrorCode = SFerror(); 12.293 return pos; 12.294 } 12.295 12.296 int FILEFile::GetLength() 12.297 { 12.298 int pos = Tell(); 12.299 if (pos >= 0) 12.300 { 12.301 Seek (0, Seek_End); 12.302 int size = Tell(); 12.303 Seek (pos, Seek_Set); 12.304 return size; 12.305 } 12.306 return -1; 12.307 } 12.308 SInt64 FILEFile::LGetLength() 12.309 { 12.310 SInt64 pos = LTell(); 12.311 if (pos >= 0) 12.312 { 12.313 LSeek (0, Seek_End); 12.314 SInt64 size = LTell(); 12.315 LSeek (pos, Seek_Set); 12.316 return size; 12.317 } 12.318 return -1; 12.319 } 12.320 12.321 int FILEFile::GetErrorCode() 12.322 { 12.323 return ErrorCode; 12.324 } 12.325 12.326 // ** Stream implementation & I/O 12.327 int FILEFile::Write(const UByte *pbuffer, int numBytes) 12.328 { 12.329 if (LastOp && LastOp != Open_Write) 12.330 fflush(fs); 12.331 LastOp = Open_Write; 12.332 int written = (int) fwrite(pbuffer, 1, numBytes, fs); 12.333 if (written < numBytes) 12.334 ErrorCode = SFerror(); 12.335 12.336 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.337 if (written > 0) 12.338 TestPos += written; 12.339 #endif 12.340 12.341 return written; 12.342 } 12.343 12.344 int FILEFile::Read(UByte *pbuffer, int numBytes) 12.345 { 12.346 if (LastOp && LastOp != Open_Read) 12.347 fflush(fs); 12.348 LastOp = Open_Read; 12.349 int read = (int) fread(pbuffer, 1, numBytes, fs); 12.350 if (read < numBytes) 12.351 ErrorCode = SFerror(); 12.352 12.353 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.354 if (read > 0) 12.355 { 12.356 // Read-in data must match our pre-loaded buffer data! 12.357 UByte* pcompareBuffer = pFileTestBuffer + TestPos; 12.358 for (int i=0; i< read; i++) 12.359 { 12.360 OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]); 12.361 } 12.362 12.363 //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read)); 12.364 TestPos += read; 12.365 OVR_ASSERT(ftell(fs) == (int)TestPos); 12.366 } 12.367 #endif 12.368 12.369 return read; 12.370 } 12.371 12.372 // Seeks ahead to skip bytes 12.373 int FILEFile::SkipBytes(int numBytes) 12.374 { 12.375 SInt64 pos = LTell(); 12.376 SInt64 newPos = LSeek(numBytes, Seek_Cur); 12.377 12.378 // Return -1 for major error 12.379 if ((pos==-1) || (newPos==-1)) 12.380 { 12.381 return -1; 12.382 } 12.383 //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0; 12.384 12.385 return int (newPos-(int)pos); 12.386 } 12.387 12.388 // Return # of bytes till EOF 12.389 int FILEFile::BytesAvailable() 12.390 { 12.391 SInt64 pos = LTell(); 12.392 SInt64 endPos = LGetLength(); 12.393 12.394 // Return -1 for major error 12.395 if ((pos==-1) || (endPos==-1)) 12.396 { 12.397 ErrorCode = SFerror(); 12.398 return 0; 12.399 } 12.400 else 12.401 ErrorCode = 0; 12.402 12.403 return int (endPos-(int)pos); 12.404 } 12.405 12.406 // Flush file contents 12.407 bool FILEFile::Flush() 12.408 { 12.409 return !fflush(fs); 12.410 } 12.411 12.412 int FILEFile::Seek(int offset, int origin) 12.413 { 12.414 int newOrigin = 0; 12.415 switch(origin) 12.416 { 12.417 case Seek_Set: newOrigin = SEEK_SET; break; 12.418 case Seek_Cur: newOrigin = SEEK_CUR; break; 12.419 case Seek_End: newOrigin = SEEK_END; break; 12.420 } 12.421 12.422 if (newOrigin == SEEK_SET && offset == Tell()) 12.423 return Tell(); 12.424 12.425 if (fseek (fs, offset, newOrigin)) 12.426 { 12.427 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.428 OVR_ASSERT(0); 12.429 #endif 12.430 return -1; 12.431 } 12.432 12.433 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.434 // Track file position after seeks for read verification later. 12.435 switch(origin) 12.436 { 12.437 case Seek_Set: TestPos = offset; break; 12.438 case Seek_Cur: TestPos += offset; break; 12.439 case Seek_End: TestPos = FileTestLength + offset; break; 12.440 } 12.441 OVR_ASSERT((int)TestPos == Tell()); 12.442 #endif 12.443 12.444 return (int)Tell(); 12.445 } 12.446 12.447 SInt64 FILEFile::LSeek(SInt64 offset, int origin) 12.448 { 12.449 return Seek((int)offset,origin); 12.450 } 12.451 12.452 int FILEFile::CopyFromStream(File *pstream, int byteSize) 12.453 { 12.454 UByte buff[0x4000]; 12.455 int count = 0; 12.456 int szRequest, szRead, szWritten; 12.457 12.458 while (byteSize) 12.459 { 12.460 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; 12.461 12.462 szRead = pstream->Read(buff, szRequest); 12.463 szWritten = 0; 12.464 if (szRead > 0) 12.465 szWritten = Write(buff, szRead); 12.466 12.467 count += szWritten; 12.468 byteSize -= szWritten; 12.469 if (szWritten < szRequest) 12.470 break; 12.471 } 12.472 return count; 12.473 } 12.474 12.475 12.476 bool FILEFile::Close() 12.477 { 12.478 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.479 if (pFileTestBuffer) 12.480 { 12.481 OVR_FREE(pFileTestBuffer); 12.482 pFileTestBuffer = 0; 12.483 FileTestLength = 0; 12.484 } 12.485 #endif 12.486 12.487 bool closeRet = !fclose(fs); 12.488 12.489 if (!closeRet) 12.490 { 12.491 ErrorCode = SFerror(); 12.492 return 0; 12.493 } 12.494 else 12.495 { 12.496 Opened = 0; 12.497 fs = 0; 12.498 ErrorCode = 0; 12.499 } 12.500 12.501 // Handle safe truncate 12.502 /* 12.503 if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) 12.504 { 12.505 // Delete original file (if it existed) 12.506 DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName); 12.507 if (oldAttributes!=0xFFFFFFFF) 12.508 if (!FileUtilWin32::DeleteFile(FileName)) 12.509 { 12.510 // Try to remove the readonly attribute 12.511 FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) ); 12.512 // And delete the file again 12.513 if (!FileUtilWin32::DeleteFile(FileName)) 12.514 return 0; 12.515 } 12.516 12.517 // Rename temp file to real filename 12.518 if (!FileUtilWin32::MoveFile(TempName, FileName)) 12.519 { 12.520 //ErrorCode = errno; 12.521 return 0; 12.522 } 12.523 } 12.524 */ 12.525 return 1; 12.526 } 12.527 12.528 /* 12.529 bool FILEFile::CloseCancel() 12.530 { 12.531 bool closeRet = (bool)::CloseHandle(fd); 12.532 12.533 if (!closeRet) 12.534 { 12.535 //ErrorCode = errno; 12.536 return 0; 12.537 } 12.538 else 12.539 { 12.540 Opened = 0; 12.541 fd = INVALID_HANDLE_VALUE; 12.542 ErrorCode = 0; 12.543 } 12.544 12.545 // Handle safe truncate (delete tmp file, leave original unchanged) 12.546 if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) 12.547 if (!FileUtilWin32::DeleteFile(TempName)) 12.548 { 12.549 //ErrorCode = errno; 12.550 return 0; 12.551 } 12.552 return 1; 12.553 } 12.554 */ 12.555 12.556 File *FileFILEOpen(const String& path, int flags, int mode) 12.557 { 12.558 return new FILEFile(path, flags, mode); 12.559 } 12.560 12.561 // Helper function: obtain file information time. 12.562 bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) 12.563 { 12.564 #if defined(OVR_OS_WIN32) 12.565 // 64-bit implementation on Windows. 12.566 struct __stat64 fileStat; 12.567 // Stat returns 0 for success. 12.568 wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t)); 12.569 UTF8Util::DecodeString(pwpath, path.ToCStr()); 12.570 12.571 int ret = _wstat64(pwpath, &fileStat); 12.572 OVR_FREE(pwpath); 12.573 if (ret) return false; 12.574 #else 12.575 struct stat fileStat; 12.576 // Stat returns 0 for success. 12.577 if (stat(path, &fileStat) != 0) 12.578 return false; 12.579 #endif 12.580 pfileStat->AccessTime = fileStat.st_atime; 12.581 pfileStat->ModifyTime = fileStat.st_mtime; 12.582 pfileStat->FileSize = fileStat.st_size; 12.583 return true; 12.584 } 12.585 12.586 } // Scaleform 12.587 \ No newline at end of file 12.588 +/************************************************************************** 12.589 + 12.590 +Filename : OVR_FileFILE.cpp 12.591 +Content : File wrapper class implementation (Win32) 12.592 + 12.593 +Created : April 5, 1999 12.594 +Authors : Michael Antonov 12.595 + 12.596 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 12.597 + 12.598 +Use of this software is subject to the terms of the Oculus license 12.599 +agreement provided at the time of installation or download, or which 12.600 +otherwise accompanies this software in either electronic or hard copy form. 12.601 + 12.602 +**************************************************************************/ 12.603 + 12.604 +#define GFILE_CXX 12.605 + 12.606 +#include "OVR_Types.h" 12.607 +#include "OVR_Log.h" 12.608 + 12.609 +// Standard C library (Captain Obvious guarantees!) 12.610 +#include <stdio.h> 12.611 +#ifndef OVR_OS_WINCE 12.612 +#include <sys/stat.h> 12.613 +#endif 12.614 + 12.615 +#include "OVR_SysFile.h" 12.616 + 12.617 +#ifndef OVR_OS_WINCE 12.618 +#include <errno.h> 12.619 +#endif 12.620 + 12.621 +namespace OVR { 12.622 + 12.623 +// ***** File interface 12.624 + 12.625 +// ***** FILEFile - C streams file 12.626 + 12.627 +static int SFerror () 12.628 +{ 12.629 + if (errno == ENOENT) 12.630 + return FileConstants::Error_FileNotFound; 12.631 + else if (errno == EACCES || errno == EPERM) 12.632 + return FileConstants::Error_Access; 12.633 + else if (errno == ENOSPC) 12.634 + return FileConstants::Error_DiskFull; 12.635 + else 12.636 + return FileConstants::Error_IOError; 12.637 +}; 12.638 + 12.639 +#ifdef OVR_OS_WIN32 12.640 +#include "windows.h" 12.641 +// A simple helper class to disable/enable system error mode, if necessary 12.642 +// Disabling happens conditionally only if a drive name is involved 12.643 +class SysErrorModeDisabler 12.644 +{ 12.645 + BOOL Disabled; 12.646 + UINT OldMode; 12.647 +public: 12.648 + SysErrorModeDisabler(const char* pfileName) 12.649 + { 12.650 + if (pfileName && (pfileName[0]!=0) && pfileName[1]==':') 12.651 + { 12.652 + Disabled = 1; 12.653 + OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS); 12.654 + } 12.655 + else 12.656 + Disabled = 0; 12.657 + } 12.658 + 12.659 + ~SysErrorModeDisabler() 12.660 + { 12.661 + if (Disabled) ::SetErrorMode(OldMode); 12.662 + } 12.663 +}; 12.664 +#else 12.665 +class SysErrorModeDisabler 12.666 +{ 12.667 +public: 12.668 + SysErrorModeDisabler(const char* pfileName) { } 12.669 +}; 12.670 +#endif // OVR_OS_WIN32 12.671 + 12.672 + 12.673 +// This macro enables verification of I/O results after seeks against a pre-loaded 12.674 +// full file buffer copy. This is generally not necessary, but can been used to debug 12.675 +// memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory 12.676 +// under FMOD with XP64 (32-bit) and Realtek HA Audio driver. 12.677 +//#define GFILE_VERIFY_SEEK_ERRORS 12.678 + 12.679 + 12.680 +// This is the simplest possible file implementation, it wraps around the descriptor 12.681 +// This file is delegated to by SysFile. 12.682 + 12.683 +class FILEFile : public File 12.684 +{ 12.685 +protected: 12.686 + 12.687 + // Allocated filename 12.688 + String FileName; 12.689 + 12.690 + // File handle & open mode 12.691 + bool Opened; 12.692 + FILE* fs; 12.693 + int OpenFlags; 12.694 + // Error code for last request 12.695 + int ErrorCode; 12.696 + 12.697 + int LastOp; 12.698 + 12.699 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.700 + UByte* pFileTestBuffer; 12.701 + unsigned FileTestLength; 12.702 + unsigned TestPos; // File pointer position during tests. 12.703 +#endif 12.704 + 12.705 +public: 12.706 + 12.707 + FILEFile() 12.708 + { 12.709 + Opened = 0; FileName = ""; 12.710 + 12.711 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.712 + pFileTestBuffer =0; 12.713 + FileTestLength =0; 12.714 + TestPos =0; 12.715 +#endif 12.716 + } 12.717 + // Initialize file by opening it 12.718 + FILEFile(const String& fileName, int flags, int Mode); 12.719 + // The 'pfileName' should be encoded as UTF-8 to support international file names. 12.720 + FILEFile(const char* pfileName, int flags, int Mode); 12.721 + 12.722 + ~FILEFile() 12.723 + { 12.724 + if (Opened) 12.725 + Close(); 12.726 + } 12.727 + 12.728 + virtual const char* GetFilePath(); 12.729 + 12.730 + // ** File Information 12.731 + virtual bool IsValid(); 12.732 + virtual bool IsWritable(); 12.733 + 12.734 + // Return position / file size 12.735 + virtual int Tell(); 12.736 + virtual SInt64 LTell(); 12.737 + virtual int GetLength(); 12.738 + virtual SInt64 LGetLength(); 12.739 + 12.740 +// virtual bool Stat(FileStats *pfs); 12.741 + virtual int GetErrorCode(); 12.742 + 12.743 + // ** Stream implementation & I/O 12.744 + virtual int Write(const UByte *pbuffer, int numBytes); 12.745 + virtual int Read(UByte *pbuffer, int numBytes); 12.746 + virtual int SkipBytes(int numBytes); 12.747 + virtual int BytesAvailable(); 12.748 + virtual bool Flush(); 12.749 + virtual int Seek(int offset, int origin); 12.750 + virtual SInt64 LSeek(SInt64 offset, int origin); 12.751 + 12.752 + virtual int CopyFromStream(File *pStream, int byteSize); 12.753 + virtual bool Close(); 12.754 +private: 12.755 + void init(); 12.756 +}; 12.757 + 12.758 + 12.759 +// Initialize file by opening it 12.760 +FILEFile::FILEFile(const String& fileName, int flags, int mode) 12.761 + : FileName(fileName), OpenFlags(flags) 12.762 +{ 12.763 + OVR_UNUSED(mode); 12.764 + init(); 12.765 +} 12.766 + 12.767 +// The 'pfileName' should be encoded as UTF-8 to support international file names. 12.768 +FILEFile::FILEFile(const char* pfileName, int flags, int mode) 12.769 + : FileName(pfileName), OpenFlags(flags) 12.770 +{ 12.771 + OVR_UNUSED(mode); 12.772 + init(); 12.773 +} 12.774 + 12.775 +void FILEFile::init() 12.776 +{ 12.777 + // Open mode for file's open 12.778 + const char *omode = "rb"; 12.779 + 12.780 + if (OpenFlags & Open_Truncate) 12.781 + { 12.782 + if (OpenFlags & Open_Read) 12.783 + omode = "w+b"; 12.784 + else 12.785 + omode = "wb"; 12.786 + } 12.787 + else if (OpenFlags & Open_Create) 12.788 + { 12.789 + if (OpenFlags & Open_Read) 12.790 + omode = "a+b"; 12.791 + else 12.792 + omode = "ab"; 12.793 + } 12.794 + else if (OpenFlags & Open_Write) 12.795 + omode = "r+b"; 12.796 + 12.797 +#ifdef OVR_OS_WIN32 12.798 + SysErrorModeDisabler disabler(FileName.ToCStr()); 12.799 +#endif 12.800 + 12.801 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 12.802 + wchar_t womode[16]; 12.803 + wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t)); 12.804 + UTF8Util::DecodeString(pwFileName, FileName.ToCStr()); 12.805 + OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0])); 12.806 + UTF8Util::DecodeString(womode, omode); 12.807 + _wfopen_s(&fs, pwFileName, womode); 12.808 + OVR_FREE(pwFileName); 12.809 +#else 12.810 + fs = fopen(FileName.ToCStr(), omode); 12.811 +#endif 12.812 + if (fs) 12.813 + rewind (fs); 12.814 + Opened = (fs != NULL); 12.815 + // Set error code 12.816 + if (!Opened) 12.817 + ErrorCode = SFerror(); 12.818 + else 12.819 + { 12.820 + // If we are testing file seek correctness, pre-load the entire file so 12.821 + // that we can do comparison tests later. 12.822 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.823 + TestPos = 0; 12.824 + fseek(fs, 0, SEEK_END); 12.825 + FileTestLength = ftell(fs); 12.826 + fseek(fs, 0, SEEK_SET); 12.827 + pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength); 12.828 + if (pFileTestBuffer) 12.829 + { 12.830 + OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength)); 12.831 + Seek(0, Seek_Set); 12.832 + } 12.833 +#endif 12.834 + 12.835 + ErrorCode = 0; 12.836 + } 12.837 + LastOp = 0; 12.838 +} 12.839 + 12.840 + 12.841 +const char* FILEFile::GetFilePath() 12.842 +{ 12.843 + return FileName.ToCStr(); 12.844 +} 12.845 + 12.846 + 12.847 +// ** File Information 12.848 +bool FILEFile::IsValid() 12.849 +{ 12.850 + return Opened; 12.851 +} 12.852 +bool FILEFile::IsWritable() 12.853 +{ 12.854 + return IsValid() && (OpenFlags&Open_Write); 12.855 +} 12.856 +/* 12.857 +bool FILEFile::IsRecoverable() 12.858 +{ 12.859 + return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC); 12.860 +} 12.861 +*/ 12.862 + 12.863 +// Return position / file size 12.864 +int FILEFile::Tell() 12.865 +{ 12.866 + int pos = (int)ftell (fs); 12.867 + if (pos < 0) 12.868 + ErrorCode = SFerror(); 12.869 + return pos; 12.870 +} 12.871 + 12.872 +SInt64 FILEFile::LTell() 12.873 +{ 12.874 + SInt64 pos = ftell(fs); 12.875 + if (pos < 0) 12.876 + ErrorCode = SFerror(); 12.877 + return pos; 12.878 +} 12.879 + 12.880 +int FILEFile::GetLength() 12.881 +{ 12.882 + int pos = Tell(); 12.883 + if (pos >= 0) 12.884 + { 12.885 + Seek (0, Seek_End); 12.886 + int size = Tell(); 12.887 + Seek (pos, Seek_Set); 12.888 + return size; 12.889 + } 12.890 + return -1; 12.891 +} 12.892 +SInt64 FILEFile::LGetLength() 12.893 +{ 12.894 + SInt64 pos = LTell(); 12.895 + if (pos >= 0) 12.896 + { 12.897 + LSeek (0, Seek_End); 12.898 + SInt64 size = LTell(); 12.899 + LSeek (pos, Seek_Set); 12.900 + return size; 12.901 + } 12.902 + return -1; 12.903 +} 12.904 + 12.905 +int FILEFile::GetErrorCode() 12.906 +{ 12.907 + return ErrorCode; 12.908 +} 12.909 + 12.910 +// ** Stream implementation & I/O 12.911 +int FILEFile::Write(const UByte *pbuffer, int numBytes) 12.912 +{ 12.913 + if (LastOp && LastOp != Open_Write) 12.914 + fflush(fs); 12.915 + LastOp = Open_Write; 12.916 + int written = (int) fwrite(pbuffer, 1, numBytes, fs); 12.917 + if (written < numBytes) 12.918 + ErrorCode = SFerror(); 12.919 + 12.920 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.921 + if (written > 0) 12.922 + TestPos += written; 12.923 +#endif 12.924 + 12.925 + return written; 12.926 +} 12.927 + 12.928 +int FILEFile::Read(UByte *pbuffer, int numBytes) 12.929 +{ 12.930 + if (LastOp && LastOp != Open_Read) 12.931 + fflush(fs); 12.932 + LastOp = Open_Read; 12.933 + int read = (int) fread(pbuffer, 1, numBytes, fs); 12.934 + if (read < numBytes) 12.935 + ErrorCode = SFerror(); 12.936 + 12.937 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.938 + if (read > 0) 12.939 + { 12.940 + // Read-in data must match our pre-loaded buffer data! 12.941 + UByte* pcompareBuffer = pFileTestBuffer + TestPos; 12.942 + for (int i=0; i< read; i++) 12.943 + { 12.944 + OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]); 12.945 + } 12.946 + 12.947 + //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read)); 12.948 + TestPos += read; 12.949 + OVR_ASSERT(ftell(fs) == (int)TestPos); 12.950 + } 12.951 +#endif 12.952 + 12.953 + return read; 12.954 +} 12.955 + 12.956 +// Seeks ahead to skip bytes 12.957 +int FILEFile::SkipBytes(int numBytes) 12.958 +{ 12.959 + SInt64 pos = LTell(); 12.960 + SInt64 newPos = LSeek(numBytes, Seek_Cur); 12.961 + 12.962 + // Return -1 for major error 12.963 + if ((pos==-1) || (newPos==-1)) 12.964 + { 12.965 + return -1; 12.966 + } 12.967 + //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0; 12.968 + 12.969 + return int (newPos-(int)pos); 12.970 +} 12.971 + 12.972 +// Return # of bytes till EOF 12.973 +int FILEFile::BytesAvailable() 12.974 +{ 12.975 + SInt64 pos = LTell(); 12.976 + SInt64 endPos = LGetLength(); 12.977 + 12.978 + // Return -1 for major error 12.979 + if ((pos==-1) || (endPos==-1)) 12.980 + { 12.981 + ErrorCode = SFerror(); 12.982 + return 0; 12.983 + } 12.984 + else 12.985 + ErrorCode = 0; 12.986 + 12.987 + return int (endPos-(int)pos); 12.988 +} 12.989 + 12.990 +// Flush file contents 12.991 +bool FILEFile::Flush() 12.992 +{ 12.993 + return !fflush(fs); 12.994 +} 12.995 + 12.996 +int FILEFile::Seek(int offset, int origin) 12.997 +{ 12.998 + int newOrigin = 0; 12.999 + switch(origin) 12.1000 + { 12.1001 + case Seek_Set: newOrigin = SEEK_SET; break; 12.1002 + case Seek_Cur: newOrigin = SEEK_CUR; break; 12.1003 + case Seek_End: newOrigin = SEEK_END; break; 12.1004 + } 12.1005 + 12.1006 + if (newOrigin == SEEK_SET && offset == Tell()) 12.1007 + return Tell(); 12.1008 + 12.1009 + if (fseek (fs, offset, newOrigin)) 12.1010 + { 12.1011 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.1012 + OVR_ASSERT(0); 12.1013 +#endif 12.1014 + return -1; 12.1015 + } 12.1016 + 12.1017 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.1018 + // Track file position after seeks for read verification later. 12.1019 + switch(origin) 12.1020 + { 12.1021 + case Seek_Set: TestPos = offset; break; 12.1022 + case Seek_Cur: TestPos += offset; break; 12.1023 + case Seek_End: TestPos = FileTestLength + offset; break; 12.1024 + } 12.1025 + OVR_ASSERT((int)TestPos == Tell()); 12.1026 +#endif 12.1027 + 12.1028 + return (int)Tell(); 12.1029 +} 12.1030 + 12.1031 +SInt64 FILEFile::LSeek(SInt64 offset, int origin) 12.1032 +{ 12.1033 + return Seek((int)offset,origin); 12.1034 +} 12.1035 + 12.1036 +int FILEFile::CopyFromStream(File *pstream, int byteSize) 12.1037 +{ 12.1038 + UByte buff[0x4000]; 12.1039 + int count = 0; 12.1040 + int szRequest, szRead, szWritten; 12.1041 + 12.1042 + while (byteSize) 12.1043 + { 12.1044 + szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; 12.1045 + 12.1046 + szRead = pstream->Read(buff, szRequest); 12.1047 + szWritten = 0; 12.1048 + if (szRead > 0) 12.1049 + szWritten = Write(buff, szRead); 12.1050 + 12.1051 + count += szWritten; 12.1052 + byteSize -= szWritten; 12.1053 + if (szWritten < szRequest) 12.1054 + break; 12.1055 + } 12.1056 + return count; 12.1057 +} 12.1058 + 12.1059 + 12.1060 +bool FILEFile::Close() 12.1061 +{ 12.1062 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS 12.1063 + if (pFileTestBuffer) 12.1064 + { 12.1065 + OVR_FREE(pFileTestBuffer); 12.1066 + pFileTestBuffer = 0; 12.1067 + FileTestLength = 0; 12.1068 + } 12.1069 +#endif 12.1070 + 12.1071 + bool closeRet = !fclose(fs); 12.1072 + 12.1073 + if (!closeRet) 12.1074 + { 12.1075 + ErrorCode = SFerror(); 12.1076 + return 0; 12.1077 + } 12.1078 + else 12.1079 + { 12.1080 + Opened = 0; 12.1081 + fs = 0; 12.1082 + ErrorCode = 0; 12.1083 + } 12.1084 + 12.1085 + // Handle safe truncate 12.1086 + /* 12.1087 + if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) 12.1088 + { 12.1089 + // Delete original file (if it existed) 12.1090 + DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName); 12.1091 + if (oldAttributes!=0xFFFFFFFF) 12.1092 + if (!FileUtilWin32::DeleteFile(FileName)) 12.1093 + { 12.1094 + // Try to remove the readonly attribute 12.1095 + FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) ); 12.1096 + // And delete the file again 12.1097 + if (!FileUtilWin32::DeleteFile(FileName)) 12.1098 + return 0; 12.1099 + } 12.1100 + 12.1101 + // Rename temp file to real filename 12.1102 + if (!FileUtilWin32::MoveFile(TempName, FileName)) 12.1103 + { 12.1104 + //ErrorCode = errno; 12.1105 + return 0; 12.1106 + } 12.1107 + } 12.1108 + */ 12.1109 + return 1; 12.1110 +} 12.1111 + 12.1112 +/* 12.1113 +bool FILEFile::CloseCancel() 12.1114 +{ 12.1115 + bool closeRet = (bool)::CloseHandle(fd); 12.1116 + 12.1117 + if (!closeRet) 12.1118 + { 12.1119 + //ErrorCode = errno; 12.1120 + return 0; 12.1121 + } 12.1122 + else 12.1123 + { 12.1124 + Opened = 0; 12.1125 + fd = INVALID_HANDLE_VALUE; 12.1126 + ErrorCode = 0; 12.1127 + } 12.1128 + 12.1129 + // Handle safe truncate (delete tmp file, leave original unchanged) 12.1130 + if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC) 12.1131 + if (!FileUtilWin32::DeleteFile(TempName)) 12.1132 + { 12.1133 + //ErrorCode = errno; 12.1134 + return 0; 12.1135 + } 12.1136 + return 1; 12.1137 +} 12.1138 +*/ 12.1139 + 12.1140 +File *FileFILEOpen(const String& path, int flags, int mode) 12.1141 +{ 12.1142 + return new FILEFile(path, flags, mode); 12.1143 +} 12.1144 + 12.1145 +// Helper function: obtain file information time. 12.1146 +bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) 12.1147 +{ 12.1148 +#if defined(OVR_OS_WIN32) 12.1149 + // 64-bit implementation on Windows. 12.1150 + struct __stat64 fileStat; 12.1151 + // Stat returns 0 for success. 12.1152 + wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t)); 12.1153 + UTF8Util::DecodeString(pwpath, path.ToCStr()); 12.1154 + 12.1155 + int ret = _wstat64(pwpath, &fileStat); 12.1156 + OVR_FREE(pwpath); 12.1157 + if (ret) return false; 12.1158 +#else 12.1159 + struct stat fileStat; 12.1160 + // Stat returns 0 for success. 12.1161 + if (stat(path, &fileStat) != 0) 12.1162 + return false; 12.1163 +#endif 12.1164 + pfileStat->AccessTime = fileStat.st_atime; 12.1165 + pfileStat->ModifyTime = fileStat.st_mtime; 12.1166 + pfileStat->FileSize = fileStat.st_size; 12.1167 + return true; 12.1168 +} 12.1169 + 12.1170 +} // Scaleform
13.1 --- a/libovr/Src/Kernel/OVR_Hash.h Sat Sep 14 17:51:03 2013 +0300 13.2 +++ b/libovr/Src/Kernel/OVR_Hash.h Sun Sep 15 04:10:05 2013 +0300 13.3 @@ -1,1 +1,1291 @@ 13.4 -/************************************************************************************ 13.5 13.6 PublicHeader: None 13.7 Filename : OVR_Hash.h 13.8 Content : Template hash-table/set implementation 13.9 Created : September 19, 2012 13.10 Notes : 13.11 13.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 13.13 13.14 Use of this software is subject to the terms of the Oculus license 13.15 agreement provided at the time of installation or download, or which 13.16 otherwise accompanies this software in either electronic or hard copy form. 13.17 13.18 ************************************************************************************/ 13.19 13.20 #ifndef OVR_Hash_h 13.21 #define OVR_Hash_h 13.22 13.23 #include "OVR_ContainerAllocator.h" 13.24 #include "OVR_Alg.h" 13.25 13.26 // 'new' operator is redefined/used in this file. 13.27 #undef new 13.28 13.29 namespace OVR { 13.30 13.31 //----------------------------------------------------------------------------------- 13.32 // ***** Hash Table Implementation 13.33 13.34 // HastSet and Hash. 13.35 // 13.36 // Hash table, linear probing, internal chaining. One interesting/nice thing 13.37 // about this implementation is that the table itself is a flat chunk of memory 13.38 // containing no pointers, only relative indices. If the key and value types 13.39 // of the Hash contain no pointers, then the Hash can be serialized using raw IO. 13.40 // 13.41 // Never shrinks, unless you explicitly Clear() it. Expands on 13.42 // demand, though. For best results, if you know roughly how big your 13.43 // table will be, default it to that size when you create it. 13.44 // 13.45 // Key usability feature: 13.46 // 13.47 // 1. Allows node hash values to either be cached or not. 13.48 // 13.49 // 2. Allows for alternative keys with methods such as GetAlt(). Handy 13.50 // if you need to search nodes by their components; no need to create 13.51 // temporary nodes. 13.52 // 13.53 13.54 13.55 // *** Hash functors: 13.56 // 13.57 // IdentityHash - use when the key is already a good hash 13.58 // HFixedSizeHash - general hash based on object's in-memory representation. 13.59 13.60 13.61 // Hash is just the input value; can use this for integer-indexed hash tables. 13.62 template<class C> 13.63 class IdentityHash 13.64 { 13.65 public: 13.66 UPInt operator()(const C& data) const 13.67 { return (UPInt) data; } 13.68 }; 13.69 13.70 // Computes a hash of an object's representation. 13.71 template<class C> 13.72 class FixedSizeHash 13.73 { 13.74 public: 13.75 // Alternative: "sdbm" hash function, suggested at same web page 13.76 // above, http::/www.cs.yorku.ca/~oz/hash.html 13.77 // This is somewhat slower then Bernstein, but it works way better than the above 13.78 // hash function for hashing large numbers of 32-bit ints. 13.79 static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381) 13.80 { 13.81 const UByte* data = (const UByte*) data_in; 13.82 UPInt h = seed; 13.83 while (size > 0) 13.84 { 13.85 size--; 13.86 h = (h << 16) + (h << 6) - h + (UPInt)data[size]; 13.87 } 13.88 return h; 13.89 } 13.90 13.91 UPInt operator()(const C& data) const 13.92 { 13.93 unsigned char* p = (unsigned char*) &data; 13.94 int size = sizeof(C); 13.95 13.96 return SDBM_Hash(p, size); 13.97 } 13.98 }; 13.99 13.100 13.101 13.102 // *** HashsetEntry Entry types. 13.103 13.104 // Compact hash table Entry type that re-computes hash keys during hash traversal. 13.105 // Good to use if the hash function is cheap or the hash value is already cached in C. 13.106 template<class C, class HashF> 13.107 class HashsetEntry 13.108 { 13.109 public: 13.110 // Internal chaining for collisions. 13.111 SPInt NextInChain; 13.112 C Value; 13.113 13.114 HashsetEntry() 13.115 : NextInChain(-2) { } 13.116 HashsetEntry(const HashsetEntry& e) 13.117 : NextInChain(e.NextInChain), Value(e.Value) { } 13.118 HashsetEntry(const C& key, SPInt next) 13.119 : NextInChain(next), Value(key) { } 13.120 13.121 bool IsEmpty() const { return NextInChain == -2; } 13.122 bool IsEndOfChain() const { return NextInChain == -1; } 13.123 13.124 // Cached hash value access - can be optimized bu storing hash locally. 13.125 // Mask value only needs to be used if SetCachedHash is not implemented. 13.126 UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } 13.127 void SetCachedHash(UPInt) {} 13.128 13.129 void Clear() 13.130 { 13.131 Value.~C(); // placement delete 13.132 NextInChain = -2; 13.133 } 13.134 // Free is only used from dtor of hash; Clear is used during regular operations: 13.135 // assignment, hash reallocations, value reassignments, so on. 13.136 void Free() { Clear(); } 13.137 }; 13.138 13.139 // Hash table Entry type that caches the Entry hash value for nodes, so that it 13.140 // does not need to be re-computed during access. 13.141 template<class C, class HashF> 13.142 class HashsetCachedEntry 13.143 { 13.144 public: 13.145 // Internal chaining for collisions. 13.146 SPInt NextInChain; 13.147 UPInt HashValue; 13.148 C Value; 13.149 13.150 HashsetCachedEntry() 13.151 : NextInChain(-2) { } 13.152 HashsetCachedEntry(const HashsetCachedEntry& e) 13.153 : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } 13.154 HashsetCachedEntry(const C& key, SPInt next) 13.155 : NextInChain(next), Value(key) { } 13.156 13.157 bool IsEmpty() const { return NextInChain == -2; } 13.158 bool IsEndOfChain() const { return NextInChain == -1; } 13.159 13.160 // Cached hash value access - can be optimized bu storing hash locally. 13.161 // Mask value only needs to be used if SetCachedHash is not implemented. 13.162 UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } 13.163 void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } 13.164 13.165 void Clear() 13.166 { 13.167 Value.~C(); 13.168 NextInChain = -2; 13.169 } 13.170 // Free is only used from dtor of hash; Clear is used during regular operations: 13.171 // assignment, hash reallocations, value reassignments, so on. 13.172 void Free() { Clear(); } 13.173 }; 13.174 13.175 13.176 //----------------------------------------------------------------------------------- 13.177 // *** HashSet implementation - relies on either cached or regular entries. 13.178 // 13.179 // Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to 13.180 // compute and thus need caching in entries. 13.181 // Entry = HashsetEntry<C, HashF> if hashes are already externally cached. 13.182 // 13.183 template<class C, class HashF = FixedSizeHash<C>, 13.184 class AltHashF = HashF, 13.185 class Allocator = ContainerAllocator<C>, 13.186 class Entry = HashsetCachedEntry<C, HashF> > 13.187 class HashSetBase 13.188 { 13.189 enum { HashMinSize = 8 }; 13.190 13.191 public: 13.192 OVR_MEMORY_REDEFINE_NEW(HashSetBase) 13.193 13.194 typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> SelfType; 13.195 13.196 HashSetBase() : pTable(NULL) { } 13.197 HashSetBase(int sizeHint) : pTable(NULL) { SetCapacity(this, sizeHint); } 13.198 HashSetBase(const SelfType& src) : pTable(NULL) { Assign(this, src); } 13.199 13.200 ~HashSetBase() 13.201 { 13.202 if (pTable) 13.203 { 13.204 // Delete the entries. 13.205 for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) 13.206 { 13.207 Entry* e = &E(i); 13.208 if (!e->IsEmpty()) 13.209 e->Free(); 13.210 } 13.211 13.212 Allocator::Free(pTable); 13.213 pTable = NULL; 13.214 } 13.215 } 13.216 13.217 13.218 void Assign(const SelfType& src) 13.219 { 13.220 Clear(); 13.221 if (src.IsEmpty() == false) 13.222 { 13.223 SetCapacity(src.GetSize()); 13.224 13.225 for (ConstIterator it = src.Begin(); it != src.End(); ++it) 13.226 { 13.227 Add(*it); 13.228 } 13.229 } 13.230 } 13.231 13.232 13.233 // Remove all entries from the HashSet table. 13.234 void Clear() 13.235 { 13.236 if (pTable) 13.237 { 13.238 // Delete the entries. 13.239 for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) 13.240 { 13.241 Entry* e = &E(i); 13.242 if (!e->IsEmpty()) 13.243 e->Clear(); 13.244 } 13.245 13.246 Allocator::Free(pTable); 13.247 pTable = NULL; 13.248 } 13.249 } 13.250 13.251 // Returns true if the HashSet is empty. 13.252 bool IsEmpty() const 13.253 { 13.254 return pTable == NULL || pTable->EntryCount == 0; 13.255 } 13.256 13.257 13.258 // Set a new or existing value under the key, to the value. 13.259 // Pass a different class of 'key' so that assignment reference object 13.260 // can be passed instead of the actual object. 13.261 template<class CRef> 13.262 void Set(const CRef& key) 13.263 { 13.264 UPInt hashValue = HashF()(key); 13.265 SPInt index = (SPInt)-1; 13.266 13.267 if (pTable != NULL) 13.268 index = findIndexCore(key, hashValue & pTable->SizeMask); 13.269 13.270 if (index >= 0) 13.271 { 13.272 E(index).Value = key; 13.273 } 13.274 else 13.275 { 13.276 // Entry under key doesn't exist. 13.277 add(key, hashValue); 13.278 } 13.279 } 13.280 13.281 template<class CRef> 13.282 inline void Add(const CRef& key) 13.283 { 13.284 UPInt hashValue = HashF()(key); 13.285 add(key, hashValue); 13.286 } 13.287 13.288 // Remove by alternative key. 13.289 template<class K> 13.290 void RemoveAlt(const K& key) 13.291 { 13.292 if (pTable == NULL) 13.293 return; 13.294 13.295 UPInt hashValue = AltHashF()(key); 13.296 SPInt index = hashValue & pTable->SizeMask; 13.297 13.298 Entry* e = &E(index); 13.299 13.300 // If empty node or occupied by collider, we have nothing to remove. 13.301 if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index)) 13.302 return; 13.303 13.304 // Save index 13.305 SPInt naturalIndex = index; 13.306 SPInt prevIndex = -1; 13.307 13.308 while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) 13.309 { 13.310 // Keep looking through the chain. 13.311 prevIndex = index; 13.312 index = e->NextInChain; 13.313 if (index == -1) 13.314 return; // End of chain, item not found 13.315 e = &E(index); 13.316 } 13.317 13.318 // Found it - our item is at index 13.319 if (naturalIndex == index) 13.320 { 13.321 // If we have a follower, move it to us 13.322 if (!e->IsEndOfChain()) 13.323 { 13.324 Entry* enext = &E(e->NextInChain); 13.325 e->Clear(); 13.326 new (e) Entry(*enext); 13.327 // Point us to the follower's cell that will be cleared 13.328 e = enext; 13.329 } 13.330 } 13.331 else 13.332 { 13.333 // We are not at natural index, so deal with the prev items next index 13.334 E(prevIndex).NextInChain = e->NextInChain; 13.335 } 13.336 13.337 // Clear us, of the follower cell that was moved. 13.338 e->Clear(); 13.339 pTable->EntryCount --; 13.340 // Should we check the size to condense hash? ... 13.341 } 13.342 13.343 // Remove by main key. 13.344 template<class CRef> 13.345 void Remove(const CRef& key) 13.346 { 13.347 RemoveAlt(key); 13.348 } 13.349 13.350 // Retrieve the pointer to a value under the given key. 13.351 // - If there's no value under the key, then return NULL. 13.352 // - If there is a value, return the pointer. 13.353 template<class K> 13.354 C* Get(const K& key) 13.355 { 13.356 SPInt index = findIndex(key); 13.357 if (index >= 0) 13.358 return &E(index).Value; 13.359 return 0; 13.360 } 13.361 13.362 template<class K> 13.363 const C* Get(const K& key) const 13.364 { 13.365 SPInt index = findIndex(key); 13.366 if (index >= 0) 13.367 return &E(index).Value; 13.368 return 0; 13.369 } 13.370 13.371 // Alternative key versions of Get. Used by Hash. 13.372 template<class K> 13.373 const C* GetAlt(const K& key) const 13.374 { 13.375 SPInt index = findIndexAlt(key); 13.376 if (index >= 0) 13.377 return &E(index).Value; 13.378 return 0; 13.379 } 13.380 13.381 template<class K> 13.382 C* GetAlt(const K& key) 13.383 { 13.384 SPInt index = findIndexAlt(key); 13.385 if (index >= 0) 13.386 return &E(index).Value; 13.387 return 0; 13.388 } 13.389 13.390 template<class K> 13.391 bool GetAlt(const K& key, C* pval) const 13.392 { 13.393 SPInt index = findIndexAlt(key); 13.394 if (index >= 0) 13.395 { 13.396 if (pval) 13.397 *pval = E(index).Value; 13.398 return true; 13.399 } 13.400 return false; 13.401 } 13.402 13.403 13.404 UPInt GetSize() const 13.405 { 13.406 return pTable == NULL ? 0 : (UPInt)pTable->EntryCount; 13.407 } 13.408 13.409 13.410 // Resize the HashSet table to fit one more Entry. Often this 13.411 // doesn't involve any action. 13.412 void CheckExpand() 13.413 { 13.414 if (pTable == NULL) 13.415 { 13.416 // Initial creation of table. Make a minimum-sized table. 13.417 setRawCapacity(HashMinSize); 13.418 } 13.419 else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4) 13.420 { 13.421 // pTable is more than 5/4 ths full. Expand. 13.422 setRawCapacity((pTable->SizeMask + 1) * 2); 13.423 } 13.424 } 13.425 13.426 // Hint the bucket count to >= n. 13.427 void Resize(UPInt n) 13.428 { 13.429 // Not really sure what this means in relation to 13.430 // STLport's hash_map... they say they "increase the 13.431 // bucket count to at least n" -- but does that mean 13.432 // their real capacity after Resize(n) is more like 13.433 // n*2 (since they do linked-list chaining within 13.434 // buckets?). 13.435 SetCapacity(n); 13.436 } 13.437 13.438 // Size the HashSet so that it can comfortably contain the given 13.439 // number of elements. If the HashSet already contains more 13.440 // elements than newSize, then this may be a no-op. 13.441 void SetCapacity(UPInt newSize) 13.442 { 13.443 UPInt newRawSize = (newSize * 5) / 4; 13.444 if (newRawSize <= GetSize()) 13.445 return; 13.446 setRawCapacity(newRawSize); 13.447 } 13.448 13.449 // Disable inappropriate 'operator ->' warning on MSVC6. 13.450 #ifdef OVR_CC_MSVC 13.451 #if (OVR_CC_MSVC < 1300) 13.452 # pragma warning(disable : 4284) 13.453 #endif 13.454 #endif 13.455 13.456 // Iterator API, like STL. 13.457 struct ConstIterator 13.458 { 13.459 const C& operator * () const 13.460 { 13.461 OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); 13.462 return pHash->E(Index).Value; 13.463 } 13.464 13.465 const C* operator -> () const 13.466 { 13.467 OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); 13.468 return &pHash->E(Index).Value; 13.469 } 13.470 13.471 void operator ++ () 13.472 { 13.473 // Find next non-empty Entry. 13.474 if (Index <= (SPInt)pHash->pTable->SizeMask) 13.475 { 13.476 Index++; 13.477 while ((UPInt)Index <= pHash->pTable->SizeMask && 13.478 pHash->E(Index).IsEmpty()) 13.479 { 13.480 Index++; 13.481 } 13.482 } 13.483 } 13.484 13.485 bool operator == (const ConstIterator& it) const 13.486 { 13.487 if (IsEnd() && it.IsEnd()) 13.488 { 13.489 return true; 13.490 } 13.491 else 13.492 { 13.493 return (pHash == it.pHash) && (Index == it.Index); 13.494 } 13.495 } 13.496 13.497 bool operator != (const ConstIterator& it) const 13.498 { 13.499 return ! (*this == it); 13.500 } 13.501 13.502 13.503 bool IsEnd() const 13.504 { 13.505 return (pHash == NULL) || 13.506 (pHash->pTable == NULL) || 13.507 (Index > (SPInt)pHash->pTable->SizeMask); 13.508 } 13.509 13.510 ConstIterator() 13.511 : pHash(NULL), Index(0) 13.512 { } 13.513 13.514 public: 13.515 // Constructor was intentionally made public to allow create 13.516 // iterator with arbitrary index. 13.517 ConstIterator(const SelfType* h, SPInt index) 13.518 : pHash(h), Index(index) 13.519 { } 13.520 13.521 const SelfType* GetContainer() const 13.522 { 13.523 return pHash; 13.524 } 13.525 SPInt GetIndex() const 13.526 { 13.527 return Index; 13.528 } 13.529 13.530 protected: 13.531 friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; 13.532 13.533 const SelfType* pHash; 13.534 SPInt Index; 13.535 }; 13.536 13.537 friend struct ConstIterator; 13.538 13.539 13.540 // Non-const Iterator; Get most of it from ConstIterator. 13.541 struct Iterator : public ConstIterator 13.542 { 13.543 // Allow non-const access to entries. 13.544 C& operator*() const 13.545 { 13.546 OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask); 13.547 return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value; 13.548 } 13.549 13.550 C* operator->() const 13.551 { 13.552 return &(operator*()); 13.553 } 13.554 13.555 Iterator() 13.556 : ConstIterator(NULL, 0) 13.557 { } 13.558 13.559 // Removes current element from Hash 13.560 void Remove() 13.561 { 13.562 RemoveAlt(operator*()); 13.563 } 13.564 13.565 template <class K> 13.566 void RemoveAlt(const K& key) 13.567 { 13.568 SelfType* phash = const_cast<SelfType*>(ConstIterator::pHash); 13.569 //Entry* ee = &phash->E(ConstIterator::Index); 13.570 //const C& key = ee->Value; 13.571 13.572 UPInt hashValue = AltHashF()(key); 13.573 SPInt index = hashValue & phash->pTable->SizeMask; 13.574 13.575 Entry* e = &phash->E(index); 13.576 13.577 // If empty node or occupied by collider, we have nothing to remove. 13.578 if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index)) 13.579 return; 13.580 13.581 // Save index 13.582 SPInt naturalIndex = index; 13.583 SPInt prevIndex = -1; 13.584 13.585 while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) 13.586 { 13.587 // Keep looking through the chain. 13.588 prevIndex = index; 13.589 index = e->NextInChain; 13.590 if (index == -1) 13.591 return; // End of chain, item not found 13.592 e = &phash->E(index); 13.593 } 13.594 13.595 if (index == (SPInt)ConstIterator::Index) 13.596 { 13.597 // Found it - our item is at index 13.598 if (naturalIndex == index) 13.599 { 13.600 // If we have a follower, move it to us 13.601 if (!e->IsEndOfChain()) 13.602 { 13.603 Entry* enext = &phash->E(e->NextInChain); 13.604 e->Clear(); 13.605 new (e) Entry(*enext); 13.606 // Point us to the follower's cell that will be cleared 13.607 e = enext; 13.608 --ConstIterator::Index; 13.609 } 13.610 } 13.611 else 13.612 { 13.613 // We are not at natural index, so deal with the prev items next index 13.614 phash->E(prevIndex).NextInChain = e->NextInChain; 13.615 } 13.616 13.617 // Clear us, of the follower cell that was moved. 13.618 e->Clear(); 13.619 phash->pTable->EntryCount --; 13.620 } 13.621 else 13.622 OVR_ASSERT(0); //? 13.623 } 13.624 13.625 private: 13.626 friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; 13.627 13.628 Iterator(SelfType* h, SPInt i0) 13.629 : ConstIterator(h, i0) 13.630 { } 13.631 }; 13.632 13.633 friend struct Iterator; 13.634 13.635 Iterator Begin() 13.636 { 13.637 if (pTable == 0) 13.638 return Iterator(NULL, 0); 13.639 13.640 // Scan till we hit the First valid Entry. 13.641 UPInt i0 = 0; 13.642 while (i0 <= pTable->SizeMask && E(i0).IsEmpty()) 13.643 { 13.644 i0++; 13.645 } 13.646 return Iterator(this, i0); 13.647 } 13.648 Iterator End() { return Iterator(NULL, 0); } 13.649 13.650 ConstIterator Begin() const { return const_cast<SelfType*>(this)->Begin(); } 13.651 ConstIterator End() const { return const_cast<SelfType*>(this)->End(); } 13.652 13.653 template<class K> 13.654 Iterator Find(const K& key) 13.655 { 13.656 SPInt index = findIndex(key); 13.657 if (index >= 0) 13.658 return Iterator(this, index); 13.659 return Iterator(NULL, 0); 13.660 } 13.661 13.662 template<class K> 13.663 Iterator FindAlt(const K& key) 13.664 { 13.665 SPInt index = findIndexAlt(key); 13.666 if (index >= 0) 13.667 return Iterator(this, index); 13.668 return Iterator(NULL, 0); 13.669 } 13.670 13.671 template<class K> 13.672 ConstIterator Find(const K& key) const { return const_cast<SelfType*>(this)->Find(key); } 13.673 13.674 template<class K> 13.675 ConstIterator FindAlt(const K& key) const { return const_cast<SelfType*>(this)->FindAlt(key); } 13.676 13.677 private: 13.678 // Find the index of the matching Entry. If no match, then return -1. 13.679 template<class K> 13.680 SPInt findIndex(const K& key) const 13.681 { 13.682 if (pTable == NULL) 13.683 return -1; 13.684 UPInt hashValue = HashF()(key) & pTable->SizeMask; 13.685 return findIndexCore(key, hashValue); 13.686 } 13.687 13.688 template<class K> 13.689 SPInt findIndexAlt(const K& key) const 13.690 { 13.691 if (pTable == NULL) 13.692 return -1; 13.693 UPInt hashValue = AltHashF()(key) & pTable->SizeMask; 13.694 return findIndexCore(key, hashValue); 13.695 } 13.696 13.697 // Find the index of the matching Entry. If no match, then return -1. 13.698 template<class K> 13.699 SPInt findIndexCore(const K& key, UPInt hashValue) const 13.700 { 13.701 // Table must exist. 13.702 OVR_ASSERT(pTable != 0); 13.703 // Hash key must be 'and-ed' by the caller. 13.704 OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0); 13.705 13.706 UPInt index = hashValue; 13.707 const Entry* e = &E(index); 13.708 13.709 // If empty or occupied by a collider, not found. 13.710 if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index)) 13.711 return -1; 13.712 13.713 while(1) 13.714 { 13.715 OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue); 13.716 13.717 if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key) 13.718 { 13.719 // Found it. 13.720 return index; 13.721 } 13.722 // Values can not be equal at this point. 13.723 // That would mean that the hash key for the same value differs. 13.724 OVR_ASSERT(!(e->Value == key)); 13.725 13.726 // Keep looking through the chain. 13.727 index = e->NextInChain; 13.728 if (index == (UPInt)-1) 13.729 break; // end of chain 13.730 13.731 e = &E(index); 13.732 OVR_ASSERT(!e->IsEmpty()); 13.733 } 13.734 return -1; 13.735 } 13.736 13.737 13.738 // Add a new value to the HashSet table, under the specified key. 13.739 template<class CRef> 13.740 void add(const CRef& key, UPInt hashValue) 13.741 { 13.742 CheckExpand(); 13.743 hashValue &= pTable->SizeMask; 13.744 13.745 pTable->EntryCount++; 13.746 13.747 SPInt index = hashValue; 13.748 Entry* naturalEntry = &(E(index)); 13.749 13.750 if (naturalEntry->IsEmpty()) 13.751 { 13.752 // Put the new Entry in. 13.753 new (naturalEntry) Entry(key, -1); 13.754 } 13.755 else 13.756 { 13.757 // Find a blank spot. 13.758 SPInt blankIndex = index; 13.759 do { 13.760 blankIndex = (blankIndex + 1) & pTable->SizeMask; 13.761 } while(!E(blankIndex).IsEmpty()); 13.762 13.763 Entry* blankEntry = &E(blankIndex); 13.764 13.765 if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index) 13.766 { 13.767 // Collision. Link into this chain. 13.768 13.769 // Move existing list head. 13.770 new (blankEntry) Entry(*naturalEntry); // placement new, copy ctor 13.771 13.772 // Put the new info in the natural Entry. 13.773 naturalEntry->Value = key; 13.774 naturalEntry->NextInChain = blankIndex; 13.775 } 13.776 else 13.777 { 13.778 // Existing Entry does not naturally 13.779 // belong in this slot. Existing 13.780 // Entry must be moved. 13.781 13.782 // Find natural location of collided element (i.e. root of chain) 13.783 SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); 13.784 OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); 13.785 for (;;) 13.786 { 13.787 Entry* e = &E(collidedIndex); 13.788 if (e->NextInChain == index) 13.789 { 13.790 // Here's where we need to splice. 13.791 new (blankEntry) Entry(*naturalEntry); 13.792 e->NextInChain = blankIndex; 13.793 break; 13.794 } 13.795 collidedIndex = e->NextInChain; 13.796 OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); 13.797 } 13.798 13.799 // Put the new data in the natural Entry. 13.800 naturalEntry->Value = key; 13.801 naturalEntry->NextInChain = -1; 13.802 } 13.803 } 13.804 13.805 // Record hash value: has effect only if cached node is used. 13.806 naturalEntry->SetCachedHash(hashValue); 13.807 } 13.808 13.809 // Index access helpers. 13.810 Entry& E(UPInt index) 13.811 { 13.812 // Must have pTable and access needs to be within bounds. 13.813 OVR_ASSERT(index <= pTable->SizeMask); 13.814 return *(((Entry*) (pTable + 1)) + index); 13.815 } 13.816 const Entry& E(UPInt index) const 13.817 { 13.818 OVR_ASSERT(index <= pTable->SizeMask); 13.819 return *(((Entry*) (pTable + 1)) + index); 13.820 } 13.821 13.822 13.823 // Resize the HashSet table to the given size (Rehash the 13.824 // contents of the current table). The arg is the number of 13.825 // HashSet table entries, not the number of elements we should 13.826 // actually contain (which will be less than this). 13.827 void setRawCapacity(UPInt newSize) 13.828 { 13.829 if (newSize == 0) 13.830 { 13.831 // Special case. 13.832 Clear(); 13.833 return; 13.834 } 13.835 13.836 // Minimum size; don't incur rehashing cost when expanding 13.837 // very small tables. Not that we perform this check before 13.838 // 'log2f' call to avoid fp exception with newSize == 1. 13.839 if (newSize < HashMinSize) 13.840 newSize = HashMinSize; 13.841 else 13.842 { 13.843 // Force newSize to be a power of two. 13.844 int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1); 13.845 OVR_ASSERT((UPInt(1) << bits) >= newSize); 13.846 newSize = UPInt(1) << bits; 13.847 } 13.848 13.849 SelfType newHash; 13.850 newHash.pTable = (TableType*) 13.851 Allocator::Alloc( 13.852 sizeof(TableType) + sizeof(Entry) * newSize); 13.853 // Need to do something on alloc failure! 13.854 OVR_ASSERT(newHash.pTable); 13.855 13.856 newHash.pTable->EntryCount = 0; 13.857 newHash.pTable->SizeMask = newSize - 1; 13.858 UPInt i, n; 13.859 13.860 // Mark all entries as empty. 13.861 for (i = 0; i < newSize; i++) 13.862 newHash.E(i).NextInChain = -2; 13.863 13.864 // Copy stuff to newHash 13.865 if (pTable) 13.866 { 13.867 for (i = 0, n = pTable->SizeMask; i <= n; i++) 13.868 { 13.869 Entry* e = &E(i); 13.870 if (e->IsEmpty() == false) 13.871 { 13.872 // Insert old Entry into new HashSet. 13.873 newHash.Add(e->Value); 13.874 // placement delete of old element 13.875 e->Clear(); 13.876 } 13.877 } 13.878 13.879 // Delete our old data buffer. 13.880 Allocator::Free(pTable); 13.881 } 13.882 13.883 // Steal newHash's data. 13.884 pTable = newHash.pTable; 13.885 newHash.pTable = NULL; 13.886 } 13.887 13.888 struct TableType 13.889 { 13.890 UPInt EntryCount; 13.891 UPInt SizeMask; 13.892 // Entry array follows this structure 13.893 // in memory. 13.894 }; 13.895 TableType* pTable; 13.896 }; 13.897 13.898 13.899 13.900 //----------------------------------------------------------------------------------- 13.901 template<class C, class HashF = FixedSizeHash<C>, 13.902 class AltHashF = HashF, 13.903 class Allocator = ContainerAllocator<C>, 13.904 class Entry = HashsetCachedEntry<C, HashF> > 13.905 class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry> 13.906 { 13.907 public: 13.908 typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType; 13.909 typedef HashSet<C, HashF, AltHashF, Allocator, Entry> SelfType; 13.910 13.911 HashSet() { } 13.912 HashSet(int sizeHint) : BaseType(sizeHint) { } 13.913 HashSet(const SelfType& src) : BaseType(src) { } 13.914 ~HashSet() { } 13.915 13.916 void operator = (const SelfType& src) { BaseType::Assign(src); } 13.917 13.918 // Set a new or existing value under the key, to the value. 13.919 // Pass a different class of 'key' so that assignment reference object 13.920 // can be passed instead of the actual object. 13.921 template<class CRef> 13.922 void Set(const CRef& key) 13.923 { 13.924 BaseType::Set(key); 13.925 } 13.926 13.927 template<class CRef> 13.928 inline void Add(const CRef& key) 13.929 { 13.930 BaseType::Add(key); 13.931 } 13.932 13.933 // Hint the bucket count to >= n. 13.934 void Resize(UPInt n) 13.935 { 13.936 BaseType::SetCapacity(n); 13.937 } 13.938 13.939 // Size the HashSet so that it can comfortably contain the given 13.940 // number of elements. If the HashSet already contains more 13.941 // elements than newSize, then this may be a no-op. 13.942 void SetCapacity(UPInt newSize) 13.943 { 13.944 BaseType::SetCapacity(newSize); 13.945 } 13.946 13.947 }; 13.948 13.949 // HashSet with uncached hash code; declared for convenience. 13.950 template<class C, class HashF = FixedSizeHash<C>, 13.951 class AltHashF = HashF, 13.952 class Allocator = ContainerAllocator<C> > 13.953 class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > 13.954 { 13.955 public: 13.956 13.957 typedef HashSetUncached<C, HashF, AltHashF, Allocator> SelfType; 13.958 typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType; 13.959 13.960 // Delegated constructors. 13.961 HashSetUncached() { } 13.962 HashSetUncached(int sizeHint) : BaseType(sizeHint) { } 13.963 HashSetUncached(const SelfType& src) : BaseType(src) { } 13.964 ~HashSetUncached() { } 13.965 13.966 void operator = (const SelfType& src) 13.967 { 13.968 BaseType::operator = (src); 13.969 } 13.970 }; 13.971 13.972 13.973 //----------------------------------------------------------------------------------- 13.974 // ***** Hash hash table implementation 13.975 13.976 // Node for Hash - necessary so that Hash can delegate its implementation 13.977 // to HashSet. 13.978 template<class C, class U, class HashF> 13.979 struct HashNode 13.980 { 13.981 typedef HashNode<C, U, HashF> SelfType; 13.982 typedef C FirstType; 13.983 typedef U SecondType; 13.984 13.985 C First; 13.986 U Second; 13.987 13.988 // NodeRef is used to allow passing of elements into HashSet 13.989 // without using a temporary object. 13.990 struct NodeRef 13.991 { 13.992 const C* pFirst; 13.993 const U* pSecond; 13.994 13.995 NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { } 13.996 NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { } 13.997 13.998 // Enable computation of ghash_node_hashf. 13.999 inline UPInt GetHash() const { return HashF()(*pFirst); } 13.1000 // Necessary conversion to allow HashNode::operator == to work. 13.1001 operator const C& () const { return *pFirst; } 13.1002 }; 13.1003 13.1004 // Note: No default constructor is necessary. 13.1005 HashNode(const HashNode& src) : First(src.First), Second(src.Second) { } 13.1006 HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond) { } 13.1007 void operator = (const NodeRef& src) { First = *src.pFirst; Second = *src.pSecond; } 13.1008 13.1009 template<class K> 13.1010 bool operator == (const K& src) const { return (First == src); } 13.1011 13.1012 template<class K> 13.1013 static UPInt CalcHash(const K& data) { return HashF()(data); } 13.1014 inline UPInt GetHash() const { return HashF()(First); } 13.1015 13.1016 // Hash functors used with this node. A separate functor is used for alternative 13.1017 // key lookup so that it does not need to access the '.First' element. 13.1018 struct NodeHashF 13.1019 { 13.1020 template<class K> 13.1021 UPInt operator()(const K& data) const { return data.GetHash(); } 13.1022 }; 13.1023 struct NodeAltHashF 13.1024 { 13.1025 template<class K> 13.1026 UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } 13.1027 }; 13.1028 }; 13.1029 13.1030 13.1031 13.1032 // **** Extra hashset_entry types to allow NodeRef construction. 13.1033 13.1034 // The big difference between the below types and the ones used in hash_set is that 13.1035 // these allow initializing the node with 'typename C::NodeRef& keyRef', which 13.1036 // is critical to avoid temporary node allocation on stack when using placement new. 13.1037 13.1038 // Compact hash table Entry type that re-computes hash keys during hash traversal. 13.1039 // Good to use if the hash function is cheap or the hash value is already cached in C. 13.1040 template<class C, class HashF> 13.1041 class HashsetNodeEntry 13.1042 { 13.1043 public: 13.1044 // Internal chaining for collisions. 13.1045 SPInt NextInChain; 13.1046 C Value; 13.1047 13.1048 HashsetNodeEntry() 13.1049 : NextInChain(-2) { } 13.1050 HashsetNodeEntry(const HashsetNodeEntry& e) 13.1051 : NextInChain(e.NextInChain), Value(e.Value) { } 13.1052 HashsetNodeEntry(const C& key, SPInt next) 13.1053 : NextInChain(next), Value(key) { } 13.1054 HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next) 13.1055 : NextInChain(next), Value(keyRef) { } 13.1056 13.1057 bool IsEmpty() const { return NextInChain == -2; } 13.1058 bool IsEndOfChain() const { return NextInChain == -1; } 13.1059 UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } 13.1060 void SetCachedHash(UPInt hashValue) { OVR_UNUSED(hashValue); } 13.1061 13.1062 void Clear() 13.1063 { 13.1064 Value.~C(); // placement delete 13.1065 NextInChain = -2; 13.1066 } 13.1067 // Free is only used from dtor of hash; Clear is used during regular operations: 13.1068 // assignment, hash reallocations, value reassignments, so on. 13.1069 void Free() { Clear(); } 13.1070 }; 13.1071 13.1072 // Hash table Entry type that caches the Entry hash value for nodes, so that it 13.1073 // does not need to be re-computed during access. 13.1074 template<class C, class HashF> 13.1075 class HashsetCachedNodeEntry 13.1076 { 13.1077 public: 13.1078 // Internal chaining for collisions. 13.1079 SPInt NextInChain; 13.1080 UPInt HashValue; 13.1081 C Value; 13.1082 13.1083 HashsetCachedNodeEntry() 13.1084 : NextInChain(-2) { } 13.1085 HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e) 13.1086 : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } 13.1087 HashsetCachedNodeEntry(const C& key, SPInt next) 13.1088 : NextInChain(next), Value(key) { } 13.1089 HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next) 13.1090 : NextInChain(next), Value(keyRef) { } 13.1091 13.1092 bool IsEmpty() const { return NextInChain == -2; } 13.1093 bool IsEndOfChain() const { return NextInChain == -1; } 13.1094 UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } 13.1095 void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } 13.1096 13.1097 void Clear() 13.1098 { 13.1099 Value.~C(); 13.1100 NextInChain = -2; 13.1101 } 13.1102 // Free is only used from dtor of hash; Clear is used during regular operations: 13.1103 // assignment, hash reallocations, value reassignments, so on. 13.1104 void Free() { Clear(); } 13.1105 }; 13.1106 13.1107 13.1108 //----------------------------------------------------------------------------------- 13.1109 template<class C, class U, 13.1110 class HashF = FixedSizeHash<C>, 13.1111 class Allocator = ContainerAllocator<C>, 13.1112 class HashNode = OVR::HashNode<C,U,HashF>, 13.1113 class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>, 13.1114 class Container = HashSet<HashNode, typename HashNode::NodeHashF, 13.1115 typename HashNode::NodeAltHashF, Allocator, 13.1116 Entry> > 13.1117 class Hash 13.1118 { 13.1119 public: 13.1120 OVR_MEMORY_REDEFINE_NEW(Hash) 13.1121 13.1122 // Types used for hash_set. 13.1123 typedef U ValueType; 13.1124 typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container> SelfType; 13.1125 13.1126 // Actual hash table itself, implemented as hash_set. 13.1127 Container mHash; 13.1128 13.1129 public: 13.1130 Hash() { } 13.1131 Hash(int sizeHint) : mHash(sizeHint) { } 13.1132 Hash(const SelfType& src) : mHash(src.mHash) { } 13.1133 ~Hash() { } 13.1134 13.1135 void operator = (const SelfType& src) { mHash = src.mHash; } 13.1136 13.1137 // Remove all entries from the Hash table. 13.1138 inline void Clear() { mHash.Clear(); } 13.1139 // Returns true if the Hash is empty. 13.1140 inline bool IsEmpty() const { return mHash.IsEmpty(); } 13.1141 13.1142 // Access (set). 13.1143 inline void Set(const C& key, const U& value) 13.1144 { 13.1145 typename HashNode::NodeRef e(key, value); 13.1146 mHash.Set(e); 13.1147 } 13.1148 inline void Add(const C& key, const U& value) 13.1149 { 13.1150 typename HashNode::NodeRef e(key, value); 13.1151 mHash.Add(e); 13.1152 } 13.1153 13.1154 // Removes an element by clearing its Entry. 13.1155 inline void Remove(const C& key) 13.1156 { 13.1157 mHash.RemoveAlt(key); 13.1158 } 13.1159 template<class K> 13.1160 inline void RemoveAlt(const K& key) 13.1161 { 13.1162 mHash.RemoveAlt(key); 13.1163 } 13.1164 13.1165 // Retrieve the value under the given key. 13.1166 // - If there's no value under the key, then return false and leave *pvalue alone. 13.1167 // - If there is a value, return true, and Set *Pvalue to the Entry's value. 13.1168 // - If value == NULL, return true or false according to the presence of the key. 13.1169 bool Get(const C& key, U* pvalue) const 13.1170 { 13.1171 const HashNode* p = mHash.GetAlt(key); 13.1172 if (p) 13.1173 { 13.1174 if (pvalue) 13.1175 *pvalue = p->Second; 13.1176 return true; 13.1177 } 13.1178 return false; 13.1179 } 13.1180 13.1181 template<class K> 13.1182 bool GetAlt(const K& key, U* pvalue) const 13.1183 { 13.1184 const HashNode* p = mHash.GetAlt(key); 13.1185 if (p) 13.1186 { 13.1187 if (pvalue) 13.1188 *pvalue = p->Second; 13.1189 return true; 13.1190 } 13.1191 return false; 13.1192 } 13.1193 13.1194 // Retrieve the pointer to a value under the given key. 13.1195 // - If there's no value under the key, then return NULL. 13.1196 // - If there is a value, return the pointer. 13.1197 inline U* Get(const C& key) 13.1198 { 13.1199 HashNode* p = mHash.GetAlt(key); 13.1200 return p ? &p->Second : 0; 13.1201 } 13.1202 inline const U* Get(const C& key) const 13.1203 { 13.1204 const HashNode* p = mHash.GetAlt(key); 13.1205 return p ? &p->Second : 0; 13.1206 } 13.1207 13.1208 template<class K> 13.1209 inline U* GetAlt(const K& key) 13.1210 { 13.1211 HashNode* p = mHash.GetAlt(key); 13.1212 return p ? &p->Second : 0; 13.1213 } 13.1214 template<class K> 13.1215 inline const U* GetAlt(const K& key) const 13.1216 { 13.1217 const HashNode* p = mHash.GetAlt(key); 13.1218 return p ? &p->Second : 0; 13.1219 } 13.1220 13.1221 // Sizing methods - delegate to Hash. 13.1222 inline UPInt GetSize() const { return mHash.GetSize(); } 13.1223 inline void Resize(UPInt n) { mHash.Resize(n); } 13.1224 inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); } 13.1225 13.1226 // Iterator API, like STL. 13.1227 typedef typename Container::ConstIterator ConstIterator; 13.1228 typedef typename Container::Iterator Iterator; 13.1229 13.1230 inline Iterator Begin() { return mHash.Begin(); } 13.1231 inline Iterator End() { return mHash.End(); } 13.1232 inline ConstIterator Begin() const { return mHash.Begin(); } 13.1233 inline ConstIterator End() const { return mHash.End(); } 13.1234 13.1235 Iterator Find(const C& key) { return mHash.FindAlt(key); } 13.1236 ConstIterator Find(const C& key) const { return mHash.FindAlt(key); } 13.1237 13.1238 template<class K> 13.1239 Iterator FindAlt(const K& key) { return mHash.FindAlt(key); } 13.1240 template<class K> 13.1241 ConstIterator FindAlt(const K& key) const { return mHash.FindAlt(key); } 13.1242 }; 13.1243 13.1244 13.1245 13.1246 // Hash with uncached hash code; declared for convenience. 13.1247 template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> > 13.1248 class HashUncached 13.1249 : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>, 13.1250 HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> > 13.1251 { 13.1252 public: 13.1253 typedef HashUncached<C, U, HashF, Allocator> SelfType; 13.1254 typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>, 13.1255 HashsetNodeEntry<HashNode<C,U,HashF>, 13.1256 typename HashNode<C,U,HashF>::NodeHashF> > BaseType; 13.1257 13.1258 // Delegated constructors. 13.1259 HashUncached() { } 13.1260 HashUncached(int sizeHint) : BaseType(sizeHint) { } 13.1261 HashUncached(const SelfType& src) : BaseType(src) { } 13.1262 ~HashUncached() { } 13.1263 void operator = (const SelfType& src) { BaseType::operator = (src); } 13.1264 }; 13.1265 13.1266 13.1267 13.1268 // And identity hash in which keys serve as hash value. Can be uncached, 13.1269 // since hash computation is assumed cheap. 13.1270 template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> > 13.1271 class HashIdentity 13.1272 : public HashUncached<C, U, HashF, Allocator> 13.1273 { 13.1274 public: 13.1275 typedef HashIdentity<C, U, Allocator, HashF> SelfType; 13.1276 typedef HashUncached<C, U, HashF, Allocator> BaseType; 13.1277 13.1278 // Delegated constructors. 13.1279 HashIdentity() { } 13.1280 HashIdentity(int sizeHint) : BaseType(sizeHint) { } 13.1281 HashIdentity(const SelfType& src) : BaseType(src) { } 13.1282 ~HashIdentity() { } 13.1283 void operator = (const SelfType& src) { BaseType::operator = (src); } 13.1284 }; 13.1285 13.1286 13.1287 } // OVR 13.1288 13.1289 13.1290 #ifdef OVR_DEFINE_NEW 13.1291 #define new OVR_DEFINE_NEW 13.1292 #endif 13.1293 13.1294 #endif 13.1295 \ No newline at end of file 13.1296 +/************************************************************************************ 13.1297 + 13.1298 +PublicHeader: None 13.1299 +Filename : OVR_Hash.h 13.1300 +Content : Template hash-table/set implementation 13.1301 +Created : September 19, 2012 13.1302 +Notes : 13.1303 + 13.1304 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 13.1305 + 13.1306 +Use of this software is subject to the terms of the Oculus license 13.1307 +agreement provided at the time of installation or download, or which 13.1308 +otherwise accompanies this software in either electronic or hard copy form. 13.1309 + 13.1310 +************************************************************************************/ 13.1311 + 13.1312 +#ifndef OVR_Hash_h 13.1313 +#define OVR_Hash_h 13.1314 + 13.1315 +#include "OVR_ContainerAllocator.h" 13.1316 +#include "OVR_Alg.h" 13.1317 + 13.1318 +// 'new' operator is redefined/used in this file. 13.1319 +#undef new 13.1320 + 13.1321 +namespace OVR { 13.1322 + 13.1323 +//----------------------------------------------------------------------------------- 13.1324 +// ***** Hash Table Implementation 13.1325 + 13.1326 +// HastSet and Hash. 13.1327 +// 13.1328 +// Hash table, linear probing, internal chaining. One interesting/nice thing 13.1329 +// about this implementation is that the table itself is a flat chunk of memory 13.1330 +// containing no pointers, only relative indices. If the key and value types 13.1331 +// of the Hash contain no pointers, then the Hash can be serialized using raw IO. 13.1332 +// 13.1333 +// Never shrinks, unless you explicitly Clear() it. Expands on 13.1334 +// demand, though. For best results, if you know roughly how big your 13.1335 +// table will be, default it to that size when you create it. 13.1336 +// 13.1337 +// Key usability feature: 13.1338 +// 13.1339 +// 1. Allows node hash values to either be cached or not. 13.1340 +// 13.1341 +// 2. Allows for alternative keys with methods such as GetAlt(). Handy 13.1342 +// if you need to search nodes by their components; no need to create 13.1343 +// temporary nodes. 13.1344 +// 13.1345 + 13.1346 + 13.1347 +// *** Hash functors: 13.1348 +// 13.1349 +// IdentityHash - use when the key is already a good hash 13.1350 +// HFixedSizeHash - general hash based on object's in-memory representation. 13.1351 + 13.1352 + 13.1353 +// Hash is just the input value; can use this for integer-indexed hash tables. 13.1354 +template<class C> 13.1355 +class IdentityHash 13.1356 +{ 13.1357 +public: 13.1358 + UPInt operator()(const C& data) const 13.1359 + { return (UPInt) data; } 13.1360 +}; 13.1361 + 13.1362 +// Computes a hash of an object's representation. 13.1363 +template<class C> 13.1364 +class FixedSizeHash 13.1365 +{ 13.1366 +public: 13.1367 + // Alternative: "sdbm" hash function, suggested at same web page 13.1368 + // above, http::/www.cs.yorku.ca/~oz/hash.html 13.1369 + // This is somewhat slower then Bernstein, but it works way better than the above 13.1370 + // hash function for hashing large numbers of 32-bit ints. 13.1371 + static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381) 13.1372 + { 13.1373 + const UByte* data = (const UByte*) data_in; 13.1374 + UPInt h = seed; 13.1375 + while (size > 0) 13.1376 + { 13.1377 + size--; 13.1378 + h = (h << 16) + (h << 6) - h + (UPInt)data[size]; 13.1379 + } 13.1380 + return h; 13.1381 + } 13.1382 + 13.1383 + UPInt operator()(const C& data) const 13.1384 + { 13.1385 + unsigned char* p = (unsigned char*) &data; 13.1386 + int size = sizeof(C); 13.1387 + 13.1388 + return SDBM_Hash(p, size); 13.1389 + } 13.1390 +}; 13.1391 + 13.1392 + 13.1393 + 13.1394 +// *** HashsetEntry Entry types. 13.1395 + 13.1396 +// Compact hash table Entry type that re-computes hash keys during hash traversal. 13.1397 +// Good to use if the hash function is cheap or the hash value is already cached in C. 13.1398 +template<class C, class HashF> 13.1399 +class HashsetEntry 13.1400 +{ 13.1401 +public: 13.1402 + // Internal chaining for collisions. 13.1403 + SPInt NextInChain; 13.1404 + C Value; 13.1405 + 13.1406 + HashsetEntry() 13.1407 + : NextInChain(-2) { } 13.1408 + HashsetEntry(const HashsetEntry& e) 13.1409 + : NextInChain(e.NextInChain), Value(e.Value) { } 13.1410 + HashsetEntry(const C& key, SPInt next) 13.1411 + : NextInChain(next), Value(key) { } 13.1412 + 13.1413 + bool IsEmpty() const { return NextInChain == -2; } 13.1414 + bool IsEndOfChain() const { return NextInChain == -1; } 13.1415 + 13.1416 + // Cached hash value access - can be optimized bu storing hash locally. 13.1417 + // Mask value only needs to be used if SetCachedHash is not implemented. 13.1418 + UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } 13.1419 + void SetCachedHash(UPInt) {} 13.1420 + 13.1421 + void Clear() 13.1422 + { 13.1423 + Value.~C(); // placement delete 13.1424 + NextInChain = -2; 13.1425 + } 13.1426 + // Free is only used from dtor of hash; Clear is used during regular operations: 13.1427 + // assignment, hash reallocations, value reassignments, so on. 13.1428 + void Free() { Clear(); } 13.1429 +}; 13.1430 + 13.1431 +// Hash table Entry type that caches the Entry hash value for nodes, so that it 13.1432 +// does not need to be re-computed during access. 13.1433 +template<class C, class HashF> 13.1434 +class HashsetCachedEntry 13.1435 +{ 13.1436 +public: 13.1437 + // Internal chaining for collisions. 13.1438 + SPInt NextInChain; 13.1439 + UPInt HashValue; 13.1440 + C Value; 13.1441 + 13.1442 + HashsetCachedEntry() 13.1443 + : NextInChain(-2) { } 13.1444 + HashsetCachedEntry(const HashsetCachedEntry& e) 13.1445 + : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } 13.1446 + HashsetCachedEntry(const C& key, SPInt next) 13.1447 + : NextInChain(next), Value(key) { } 13.1448 + 13.1449 + bool IsEmpty() const { return NextInChain == -2; } 13.1450 + bool IsEndOfChain() const { return NextInChain == -1; } 13.1451 + 13.1452 + // Cached hash value access - can be optimized bu storing hash locally. 13.1453 + // Mask value only needs to be used if SetCachedHash is not implemented. 13.1454 + UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } 13.1455 + void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } 13.1456 + 13.1457 + void Clear() 13.1458 + { 13.1459 + Value.~C(); 13.1460 + NextInChain = -2; 13.1461 + } 13.1462 + // Free is only used from dtor of hash; Clear is used during regular operations: 13.1463 + // assignment, hash reallocations, value reassignments, so on. 13.1464 + void Free() { Clear(); } 13.1465 +}; 13.1466 + 13.1467 + 13.1468 +//----------------------------------------------------------------------------------- 13.1469 +// *** HashSet implementation - relies on either cached or regular entries. 13.1470 +// 13.1471 +// Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to 13.1472 +// compute and thus need caching in entries. 13.1473 +// Entry = HashsetEntry<C, HashF> if hashes are already externally cached. 13.1474 +// 13.1475 +template<class C, class HashF = FixedSizeHash<C>, 13.1476 + class AltHashF = HashF, 13.1477 + class Allocator = ContainerAllocator<C>, 13.1478 + class Entry = HashsetCachedEntry<C, HashF> > 13.1479 +class HashSetBase 13.1480 +{ 13.1481 + enum { HashMinSize = 8 }; 13.1482 + 13.1483 +public: 13.1484 + OVR_MEMORY_REDEFINE_NEW(HashSetBase) 13.1485 + 13.1486 + typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> SelfType; 13.1487 + 13.1488 + HashSetBase() : pTable(NULL) { } 13.1489 + HashSetBase(int sizeHint) : pTable(NULL) { SetCapacity(this, sizeHint); } 13.1490 + HashSetBase(const SelfType& src) : pTable(NULL) { Assign(this, src); } 13.1491 + 13.1492 + ~HashSetBase() 13.1493 + { 13.1494 + if (pTable) 13.1495 + { 13.1496 + // Delete the entries. 13.1497 + for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) 13.1498 + { 13.1499 + Entry* e = &E(i); 13.1500 + if (!e->IsEmpty()) 13.1501 + e->Free(); 13.1502 + } 13.1503 + 13.1504 + Allocator::Free(pTable); 13.1505 + pTable = NULL; 13.1506 + } 13.1507 + } 13.1508 + 13.1509 + 13.1510 + void Assign(const SelfType& src) 13.1511 + { 13.1512 + Clear(); 13.1513 + if (src.IsEmpty() == false) 13.1514 + { 13.1515 + SetCapacity(src.GetSize()); 13.1516 + 13.1517 + for (ConstIterator it = src.Begin(); it != src.End(); ++it) 13.1518 + { 13.1519 + Add(*it); 13.1520 + } 13.1521 + } 13.1522 + } 13.1523 + 13.1524 + 13.1525 + // Remove all entries from the HashSet table. 13.1526 + void Clear() 13.1527 + { 13.1528 + if (pTable) 13.1529 + { 13.1530 + // Delete the entries. 13.1531 + for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++) 13.1532 + { 13.1533 + Entry* e = &E(i); 13.1534 + if (!e->IsEmpty()) 13.1535 + e->Clear(); 13.1536 + } 13.1537 + 13.1538 + Allocator::Free(pTable); 13.1539 + pTable = NULL; 13.1540 + } 13.1541 + } 13.1542 + 13.1543 + // Returns true if the HashSet is empty. 13.1544 + bool IsEmpty() const 13.1545 + { 13.1546 + return pTable == NULL || pTable->EntryCount == 0; 13.1547 + } 13.1548 + 13.1549 + 13.1550 + // Set a new or existing value under the key, to the value. 13.1551 + // Pass a different class of 'key' so that assignment reference object 13.1552 + // can be passed instead of the actual object. 13.1553 + template<class CRef> 13.1554 + void Set(const CRef& key) 13.1555 + { 13.1556 + UPInt hashValue = HashF()(key); 13.1557 + SPInt index = (SPInt)-1; 13.1558 + 13.1559 + if (pTable != NULL) 13.1560 + index = findIndexCore(key, hashValue & pTable->SizeMask); 13.1561 + 13.1562 + if (index >= 0) 13.1563 + { 13.1564 + E(index).Value = key; 13.1565 + } 13.1566 + else 13.1567 + { 13.1568 + // Entry under key doesn't exist. 13.1569 + add(key, hashValue); 13.1570 + } 13.1571 + } 13.1572 + 13.1573 + template<class CRef> 13.1574 + inline void Add(const CRef& key) 13.1575 + { 13.1576 + UPInt hashValue = HashF()(key); 13.1577 + add(key, hashValue); 13.1578 + } 13.1579 + 13.1580 + // Remove by alternative key. 13.1581 + template<class K> 13.1582 + void RemoveAlt(const K& key) 13.1583 + { 13.1584 + if (pTable == NULL) 13.1585 + return; 13.1586 + 13.1587 + UPInt hashValue = AltHashF()(key); 13.1588 + SPInt index = hashValue & pTable->SizeMask; 13.1589 + 13.1590 + Entry* e = &E(index); 13.1591 + 13.1592 + // If empty node or occupied by collider, we have nothing to remove. 13.1593 + if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index)) 13.1594 + return; 13.1595 + 13.1596 + // Save index 13.1597 + SPInt naturalIndex = index; 13.1598 + SPInt prevIndex = -1; 13.1599 + 13.1600 + while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) 13.1601 + { 13.1602 + // Keep looking through the chain. 13.1603 + prevIndex = index; 13.1604 + index = e->NextInChain; 13.1605 + if (index == -1) 13.1606 + return; // End of chain, item not found 13.1607 + e = &E(index); 13.1608 + } 13.1609 + 13.1610 + // Found it - our item is at index 13.1611 + if (naturalIndex == index) 13.1612 + { 13.1613 + // If we have a follower, move it to us 13.1614 + if (!e->IsEndOfChain()) 13.1615 + { 13.1616 + Entry* enext = &E(e->NextInChain); 13.1617 + e->Clear(); 13.1618 + new (e) Entry(*enext); 13.1619 + // Point us to the follower's cell that will be cleared 13.1620 + e = enext; 13.1621 + } 13.1622 + } 13.1623 + else 13.1624 + { 13.1625 + // We are not at natural index, so deal with the prev items next index 13.1626 + E(prevIndex).NextInChain = e->NextInChain; 13.1627 + } 13.1628 + 13.1629 + // Clear us, of the follower cell that was moved. 13.1630 + e->Clear(); 13.1631 + pTable->EntryCount --; 13.1632 + // Should we check the size to condense hash? ... 13.1633 + } 13.1634 + 13.1635 + // Remove by main key. 13.1636 + template<class CRef> 13.1637 + void Remove(const CRef& key) 13.1638 + { 13.1639 + RemoveAlt(key); 13.1640 + } 13.1641 + 13.1642 + // Retrieve the pointer to a value under the given key. 13.1643 + // - If there's no value under the key, then return NULL. 13.1644 + // - If there is a value, return the pointer. 13.1645 + template<class K> 13.1646 + C* Get(const K& key) 13.1647 + { 13.1648 + SPInt index = findIndex(key); 13.1649 + if (index >= 0) 13.1650 + return &E(index).Value; 13.1651 + return 0; 13.1652 + } 13.1653 + 13.1654 + template<class K> 13.1655 + const C* Get(const K& key) const 13.1656 + { 13.1657 + SPInt index = findIndex(key); 13.1658 + if (index >= 0) 13.1659 + return &E(index).Value; 13.1660 + return 0; 13.1661 + } 13.1662 + 13.1663 + // Alternative key versions of Get. Used by Hash. 13.1664 + template<class K> 13.1665 + const C* GetAlt(const K& key) const 13.1666 + { 13.1667 + SPInt index = findIndexAlt(key); 13.1668 + if (index >= 0) 13.1669 + return &E(index).Value; 13.1670 + return 0; 13.1671 + } 13.1672 + 13.1673 + template<class K> 13.1674 + C* GetAlt(const K& key) 13.1675 + { 13.1676 + SPInt index = findIndexAlt(key); 13.1677 + if (index >= 0) 13.1678 + return &E(index).Value; 13.1679 + return 0; 13.1680 + } 13.1681 + 13.1682 + template<class K> 13.1683 + bool GetAlt(const K& key, C* pval) const 13.1684 + { 13.1685 + SPInt index = findIndexAlt(key); 13.1686 + if (index >= 0) 13.1687 + { 13.1688 + if (pval) 13.1689 + *pval = E(index).Value; 13.1690 + return true; 13.1691 + } 13.1692 + return false; 13.1693 + } 13.1694 + 13.1695 + 13.1696 + UPInt GetSize() const 13.1697 + { 13.1698 + return pTable == NULL ? 0 : (UPInt)pTable->EntryCount; 13.1699 + } 13.1700 + 13.1701 + 13.1702 + // Resize the HashSet table to fit one more Entry. Often this 13.1703 + // doesn't involve any action. 13.1704 + void CheckExpand() 13.1705 + { 13.1706 + if (pTable == NULL) 13.1707 + { 13.1708 + // Initial creation of table. Make a minimum-sized table. 13.1709 + setRawCapacity(HashMinSize); 13.1710 + } 13.1711 + else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4) 13.1712 + { 13.1713 + // pTable is more than 5/4 ths full. Expand. 13.1714 + setRawCapacity((pTable->SizeMask + 1) * 2); 13.1715 + } 13.1716 + } 13.1717 + 13.1718 + // Hint the bucket count to >= n. 13.1719 + void Resize(UPInt n) 13.1720 + { 13.1721 + // Not really sure what this means in relation to 13.1722 + // STLport's hash_map... they say they "increase the 13.1723 + // bucket count to at least n" -- but does that mean 13.1724 + // their real capacity after Resize(n) is more like 13.1725 + // n*2 (since they do linked-list chaining within 13.1726 + // buckets?). 13.1727 + SetCapacity(n); 13.1728 + } 13.1729 + 13.1730 + // Size the HashSet so that it can comfortably contain the given 13.1731 + // number of elements. If the HashSet already contains more 13.1732 + // elements than newSize, then this may be a no-op. 13.1733 + void SetCapacity(UPInt newSize) 13.1734 + { 13.1735 + UPInt newRawSize = (newSize * 5) / 4; 13.1736 + if (newRawSize <= GetSize()) 13.1737 + return; 13.1738 + setRawCapacity(newRawSize); 13.1739 + } 13.1740 + 13.1741 + // Disable inappropriate 'operator ->' warning on MSVC6. 13.1742 +#ifdef OVR_CC_MSVC 13.1743 +#if (OVR_CC_MSVC < 1300) 13.1744 +# pragma warning(disable : 4284) 13.1745 +#endif 13.1746 +#endif 13.1747 + 13.1748 + // Iterator API, like STL. 13.1749 + struct ConstIterator 13.1750 + { 13.1751 + const C& operator * () const 13.1752 + { 13.1753 + OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); 13.1754 + return pHash->E(Index).Value; 13.1755 + } 13.1756 + 13.1757 + const C* operator -> () const 13.1758 + { 13.1759 + OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask); 13.1760 + return &pHash->E(Index).Value; 13.1761 + } 13.1762 + 13.1763 + void operator ++ () 13.1764 + { 13.1765 + // Find next non-empty Entry. 13.1766 + if (Index <= (SPInt)pHash->pTable->SizeMask) 13.1767 + { 13.1768 + Index++; 13.1769 + while ((UPInt)Index <= pHash->pTable->SizeMask && 13.1770 + pHash->E(Index).IsEmpty()) 13.1771 + { 13.1772 + Index++; 13.1773 + } 13.1774 + } 13.1775 + } 13.1776 + 13.1777 + bool operator == (const ConstIterator& it) const 13.1778 + { 13.1779 + if (IsEnd() && it.IsEnd()) 13.1780 + { 13.1781 + return true; 13.1782 + } 13.1783 + else 13.1784 + { 13.1785 + return (pHash == it.pHash) && (Index == it.Index); 13.1786 + } 13.1787 + } 13.1788 + 13.1789 + bool operator != (const ConstIterator& it) const 13.1790 + { 13.1791 + return ! (*this == it); 13.1792 + } 13.1793 + 13.1794 + 13.1795 + bool IsEnd() const 13.1796 + { 13.1797 + return (pHash == NULL) || 13.1798 + (pHash->pTable == NULL) || 13.1799 + (Index > (SPInt)pHash->pTable->SizeMask); 13.1800 + } 13.1801 + 13.1802 + ConstIterator() 13.1803 + : pHash(NULL), Index(0) 13.1804 + { } 13.1805 + 13.1806 + public: 13.1807 + // Constructor was intentionally made public to allow create 13.1808 + // iterator with arbitrary index. 13.1809 + ConstIterator(const SelfType* h, SPInt index) 13.1810 + : pHash(h), Index(index) 13.1811 + { } 13.1812 + 13.1813 + const SelfType* GetContainer() const 13.1814 + { 13.1815 + return pHash; 13.1816 + } 13.1817 + SPInt GetIndex() const 13.1818 + { 13.1819 + return Index; 13.1820 + } 13.1821 + 13.1822 + protected: 13.1823 + friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; 13.1824 + 13.1825 + const SelfType* pHash; 13.1826 + SPInt Index; 13.1827 + }; 13.1828 + 13.1829 + friend struct ConstIterator; 13.1830 + 13.1831 + 13.1832 + // Non-const Iterator; Get most of it from ConstIterator. 13.1833 + struct Iterator : public ConstIterator 13.1834 + { 13.1835 + // Allow non-const access to entries. 13.1836 + C& operator*() const 13.1837 + { 13.1838 + OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask); 13.1839 + return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value; 13.1840 + } 13.1841 + 13.1842 + C* operator->() const 13.1843 + { 13.1844 + return &(operator*()); 13.1845 + } 13.1846 + 13.1847 + Iterator() 13.1848 + : ConstIterator(NULL, 0) 13.1849 + { } 13.1850 + 13.1851 + // Removes current element from Hash 13.1852 + void Remove() 13.1853 + { 13.1854 + RemoveAlt(operator*()); 13.1855 + } 13.1856 + 13.1857 + template <class K> 13.1858 + void RemoveAlt(const K& key) 13.1859 + { 13.1860 + SelfType* phash = const_cast<SelfType*>(ConstIterator::pHash); 13.1861 + //Entry* ee = &phash->E(ConstIterator::Index); 13.1862 + //const C& key = ee->Value; 13.1863 + 13.1864 + UPInt hashValue = AltHashF()(key); 13.1865 + SPInt index = hashValue & phash->pTable->SizeMask; 13.1866 + 13.1867 + Entry* e = &phash->E(index); 13.1868 + 13.1869 + // If empty node or occupied by collider, we have nothing to remove. 13.1870 + if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index)) 13.1871 + return; 13.1872 + 13.1873 + // Save index 13.1874 + SPInt naturalIndex = index; 13.1875 + SPInt prevIndex = -1; 13.1876 + 13.1877 + while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key)) 13.1878 + { 13.1879 + // Keep looking through the chain. 13.1880 + prevIndex = index; 13.1881 + index = e->NextInChain; 13.1882 + if (index == -1) 13.1883 + return; // End of chain, item not found 13.1884 + e = &phash->E(index); 13.1885 + } 13.1886 + 13.1887 + if (index == (SPInt)ConstIterator::Index) 13.1888 + { 13.1889 + // Found it - our item is at index 13.1890 + if (naturalIndex == index) 13.1891 + { 13.1892 + // If we have a follower, move it to us 13.1893 + if (!e->IsEndOfChain()) 13.1894 + { 13.1895 + Entry* enext = &phash->E(e->NextInChain); 13.1896 + e->Clear(); 13.1897 + new (e) Entry(*enext); 13.1898 + // Point us to the follower's cell that will be cleared 13.1899 + e = enext; 13.1900 + --ConstIterator::Index; 13.1901 + } 13.1902 + } 13.1903 + else 13.1904 + { 13.1905 + // We are not at natural index, so deal with the prev items next index 13.1906 + phash->E(prevIndex).NextInChain = e->NextInChain; 13.1907 + } 13.1908 + 13.1909 + // Clear us, of the follower cell that was moved. 13.1910 + e->Clear(); 13.1911 + phash->pTable->EntryCount --; 13.1912 + } 13.1913 + else 13.1914 + OVR_ASSERT(0); //? 13.1915 + } 13.1916 + 13.1917 + private: 13.1918 + friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>; 13.1919 + 13.1920 + Iterator(SelfType* h, SPInt i0) 13.1921 + : ConstIterator(h, i0) 13.1922 + { } 13.1923 + }; 13.1924 + 13.1925 + friend struct Iterator; 13.1926 + 13.1927 + Iterator Begin() 13.1928 + { 13.1929 + if (pTable == 0) 13.1930 + return Iterator(NULL, 0); 13.1931 + 13.1932 + // Scan till we hit the First valid Entry. 13.1933 + UPInt i0 = 0; 13.1934 + while (i0 <= pTable->SizeMask && E(i0).IsEmpty()) 13.1935 + { 13.1936 + i0++; 13.1937 + } 13.1938 + return Iterator(this, i0); 13.1939 + } 13.1940 + Iterator End() { return Iterator(NULL, 0); } 13.1941 + 13.1942 + ConstIterator Begin() const { return const_cast<SelfType*>(this)->Begin(); } 13.1943 + ConstIterator End() const { return const_cast<SelfType*>(this)->End(); } 13.1944 + 13.1945 + template<class K> 13.1946 + Iterator Find(const K& key) 13.1947 + { 13.1948 + SPInt index = findIndex(key); 13.1949 + if (index >= 0) 13.1950 + return Iterator(this, index); 13.1951 + return Iterator(NULL, 0); 13.1952 + } 13.1953 + 13.1954 + template<class K> 13.1955 + Iterator FindAlt(const K& key) 13.1956 + { 13.1957 + SPInt index = findIndexAlt(key); 13.1958 + if (index >= 0) 13.1959 + return Iterator(this, index); 13.1960 + return Iterator(NULL, 0); 13.1961 + } 13.1962 + 13.1963 + template<class K> 13.1964 + ConstIterator Find(const K& key) const { return const_cast<SelfType*>(this)->Find(key); } 13.1965 + 13.1966 + template<class K> 13.1967 + ConstIterator FindAlt(const K& key) const { return const_cast<SelfType*>(this)->FindAlt(key); } 13.1968 + 13.1969 +private: 13.1970 + // Find the index of the matching Entry. If no match, then return -1. 13.1971 + template<class K> 13.1972 + SPInt findIndex(const K& key) const 13.1973 + { 13.1974 + if (pTable == NULL) 13.1975 + return -1; 13.1976 + UPInt hashValue = HashF()(key) & pTable->SizeMask; 13.1977 + return findIndexCore(key, hashValue); 13.1978 + } 13.1979 + 13.1980 + template<class K> 13.1981 + SPInt findIndexAlt(const K& key) const 13.1982 + { 13.1983 + if (pTable == NULL) 13.1984 + return -1; 13.1985 + UPInt hashValue = AltHashF()(key) & pTable->SizeMask; 13.1986 + return findIndexCore(key, hashValue); 13.1987 + } 13.1988 + 13.1989 + // Find the index of the matching Entry. If no match, then return -1. 13.1990 + template<class K> 13.1991 + SPInt findIndexCore(const K& key, UPInt hashValue) const 13.1992 + { 13.1993 + // Table must exist. 13.1994 + OVR_ASSERT(pTable != 0); 13.1995 + // Hash key must be 'and-ed' by the caller. 13.1996 + OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0); 13.1997 + 13.1998 + UPInt index = hashValue; 13.1999 + const Entry* e = &E(index); 13.2000 + 13.2001 + // If empty or occupied by a collider, not found. 13.2002 + if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index)) 13.2003 + return -1; 13.2004 + 13.2005 + while(1) 13.2006 + { 13.2007 + OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue); 13.2008 + 13.2009 + if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key) 13.2010 + { 13.2011 + // Found it. 13.2012 + return index; 13.2013 + } 13.2014 + // Values can not be equal at this point. 13.2015 + // That would mean that the hash key for the same value differs. 13.2016 + OVR_ASSERT(!(e->Value == key)); 13.2017 + 13.2018 + // Keep looking through the chain. 13.2019 + index = e->NextInChain; 13.2020 + if (index == (UPInt)-1) 13.2021 + break; // end of chain 13.2022 + 13.2023 + e = &E(index); 13.2024 + OVR_ASSERT(!e->IsEmpty()); 13.2025 + } 13.2026 + return -1; 13.2027 + } 13.2028 + 13.2029 + 13.2030 + // Add a new value to the HashSet table, under the specified key. 13.2031 + template<class CRef> 13.2032 + void add(const CRef& key, UPInt hashValue) 13.2033 + { 13.2034 + CheckExpand(); 13.2035 + hashValue &= pTable->SizeMask; 13.2036 + 13.2037 + pTable->EntryCount++; 13.2038 + 13.2039 + SPInt index = hashValue; 13.2040 + Entry* naturalEntry = &(E(index)); 13.2041 + 13.2042 + if (naturalEntry->IsEmpty()) 13.2043 + { 13.2044 + // Put the new Entry in. 13.2045 + new (naturalEntry) Entry(key, -1); 13.2046 + } 13.2047 + else 13.2048 + { 13.2049 + // Find a blank spot. 13.2050 + SPInt blankIndex = index; 13.2051 + do { 13.2052 + blankIndex = (blankIndex + 1) & pTable->SizeMask; 13.2053 + } while(!E(blankIndex).IsEmpty()); 13.2054 + 13.2055 + Entry* blankEntry = &E(blankIndex); 13.2056 + 13.2057 + if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index) 13.2058 + { 13.2059 + // Collision. Link into this chain. 13.2060 + 13.2061 + // Move existing list head. 13.2062 + new (blankEntry) Entry(*naturalEntry); // placement new, copy ctor 13.2063 + 13.2064 + // Put the new info in the natural Entry. 13.2065 + naturalEntry->Value = key; 13.2066 + naturalEntry->NextInChain = blankIndex; 13.2067 + } 13.2068 + else 13.2069 + { 13.2070 + // Existing Entry does not naturally 13.2071 + // belong in this slot. Existing 13.2072 + // Entry must be moved. 13.2073 + 13.2074 + // Find natural location of collided element (i.e. root of chain) 13.2075 + SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask); 13.2076 + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); 13.2077 + for (;;) 13.2078 + { 13.2079 + Entry* e = &E(collidedIndex); 13.2080 + if (e->NextInChain == index) 13.2081 + { 13.2082 + // Here's where we need to splice. 13.2083 + new (blankEntry) Entry(*naturalEntry); 13.2084 + e->NextInChain = blankIndex; 13.2085 + break; 13.2086 + } 13.2087 + collidedIndex = e->NextInChain; 13.2088 + OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask); 13.2089 + } 13.2090 + 13.2091 + // Put the new data in the natural Entry. 13.2092 + naturalEntry->Value = key; 13.2093 + naturalEntry->NextInChain = -1; 13.2094 + } 13.2095 + } 13.2096 + 13.2097 + // Record hash value: has effect only if cached node is used. 13.2098 + naturalEntry->SetCachedHash(hashValue); 13.2099 + } 13.2100 + 13.2101 + // Index access helpers. 13.2102 + Entry& E(UPInt index) 13.2103 + { 13.2104 + // Must have pTable and access needs to be within bounds. 13.2105 + OVR_ASSERT(index <= pTable->SizeMask); 13.2106 + return *(((Entry*) (pTable + 1)) + index); 13.2107 + } 13.2108 + const Entry& E(UPInt index) const 13.2109 + { 13.2110 + OVR_ASSERT(index <= pTable->SizeMask); 13.2111 + return *(((Entry*) (pTable + 1)) + index); 13.2112 + } 13.2113 + 13.2114 + 13.2115 + // Resize the HashSet table to the given size (Rehash the 13.2116 + // contents of the current table). The arg is the number of 13.2117 + // HashSet table entries, not the number of elements we should 13.2118 + // actually contain (which will be less than this). 13.2119 + void setRawCapacity(UPInt newSize) 13.2120 + { 13.2121 + if (newSize == 0) 13.2122 + { 13.2123 + // Special case. 13.2124 + Clear(); 13.2125 + return; 13.2126 + } 13.2127 + 13.2128 + // Minimum size; don't incur rehashing cost when expanding 13.2129 + // very small tables. Not that we perform this check before 13.2130 + // 'log2f' call to avoid fp exception with newSize == 1. 13.2131 + if (newSize < HashMinSize) 13.2132 + newSize = HashMinSize; 13.2133 + else 13.2134 + { 13.2135 + // Force newSize to be a power of two. 13.2136 + int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1); 13.2137 + OVR_ASSERT((UPInt(1) << bits) >= newSize); 13.2138 + newSize = UPInt(1) << bits; 13.2139 + } 13.2140 + 13.2141 + SelfType newHash; 13.2142 + newHash.pTable = (TableType*) 13.2143 + Allocator::Alloc( 13.2144 + sizeof(TableType) + sizeof(Entry) * newSize); 13.2145 + // Need to do something on alloc failure! 13.2146 + OVR_ASSERT(newHash.pTable); 13.2147 + 13.2148 + newHash.pTable->EntryCount = 0; 13.2149 + newHash.pTable->SizeMask = newSize - 1; 13.2150 + UPInt i, n; 13.2151 + 13.2152 + // Mark all entries as empty. 13.2153 + for (i = 0; i < newSize; i++) 13.2154 + newHash.E(i).NextInChain = -2; 13.2155 + 13.2156 + // Copy stuff to newHash 13.2157 + if (pTable) 13.2158 + { 13.2159 + for (i = 0, n = pTable->SizeMask; i <= n; i++) 13.2160 + { 13.2161 + Entry* e = &E(i); 13.2162 + if (e->IsEmpty() == false) 13.2163 + { 13.2164 + // Insert old Entry into new HashSet. 13.2165 + newHash.Add(e->Value); 13.2166 + // placement delete of old element 13.2167 + e->Clear(); 13.2168 + } 13.2169 + } 13.2170 + 13.2171 + // Delete our old data buffer. 13.2172 + Allocator::Free(pTable); 13.2173 + } 13.2174 + 13.2175 + // Steal newHash's data. 13.2176 + pTable = newHash.pTable; 13.2177 + newHash.pTable = NULL; 13.2178 + } 13.2179 + 13.2180 + struct TableType 13.2181 + { 13.2182 + UPInt EntryCount; 13.2183 + UPInt SizeMask; 13.2184 + // Entry array follows this structure 13.2185 + // in memory. 13.2186 + }; 13.2187 + TableType* pTable; 13.2188 +}; 13.2189 + 13.2190 + 13.2191 + 13.2192 +//----------------------------------------------------------------------------------- 13.2193 +template<class C, class HashF = FixedSizeHash<C>, 13.2194 + class AltHashF = HashF, 13.2195 + class Allocator = ContainerAllocator<C>, 13.2196 + class Entry = HashsetCachedEntry<C, HashF> > 13.2197 +class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry> 13.2198 +{ 13.2199 +public: 13.2200 + typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType; 13.2201 + typedef HashSet<C, HashF, AltHashF, Allocator, Entry> SelfType; 13.2202 + 13.2203 + HashSet() { } 13.2204 + HashSet(int sizeHint) : BaseType(sizeHint) { } 13.2205 + HashSet(const SelfType& src) : BaseType(src) { } 13.2206 + ~HashSet() { } 13.2207 + 13.2208 + void operator = (const SelfType& src) { BaseType::Assign(src); } 13.2209 + 13.2210 + // Set a new or existing value under the key, to the value. 13.2211 + // Pass a different class of 'key' so that assignment reference object 13.2212 + // can be passed instead of the actual object. 13.2213 + template<class CRef> 13.2214 + void Set(const CRef& key) 13.2215 + { 13.2216 + BaseType::Set(key); 13.2217 + } 13.2218 + 13.2219 + template<class CRef> 13.2220 + inline void Add(const CRef& key) 13.2221 + { 13.2222 + BaseType::Add(key); 13.2223 + } 13.2224 + 13.2225 + // Hint the bucket count to >= n. 13.2226 + void Resize(UPInt n) 13.2227 + { 13.2228 + BaseType::SetCapacity(n); 13.2229 + } 13.2230 + 13.2231 + // Size the HashSet so that it can comfortably contain the given 13.2232 + // number of elements. If the HashSet already contains more 13.2233 + // elements than newSize, then this may be a no-op. 13.2234 + void SetCapacity(UPInt newSize) 13.2235 + { 13.2236 + BaseType::SetCapacity(newSize); 13.2237 + } 13.2238 + 13.2239 +}; 13.2240 + 13.2241 +// HashSet with uncached hash code; declared for convenience. 13.2242 +template<class C, class HashF = FixedSizeHash<C>, 13.2243 + class AltHashF = HashF, 13.2244 + class Allocator = ContainerAllocator<C> > 13.2245 +class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > 13.2246 +{ 13.2247 +public: 13.2248 + 13.2249 + typedef HashSetUncached<C, HashF, AltHashF, Allocator> SelfType; 13.2250 + typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType; 13.2251 + 13.2252 + // Delegated constructors. 13.2253 + HashSetUncached() { } 13.2254 + HashSetUncached(int sizeHint) : BaseType(sizeHint) { } 13.2255 + HashSetUncached(const SelfType& src) : BaseType(src) { } 13.2256 + ~HashSetUncached() { } 13.2257 + 13.2258 + void operator = (const SelfType& src) 13.2259 + { 13.2260 + BaseType::operator = (src); 13.2261 + } 13.2262 +}; 13.2263 + 13.2264 + 13.2265 +//----------------------------------------------------------------------------------- 13.2266 +// ***** Hash hash table implementation 13.2267 + 13.2268 +// Node for Hash - necessary so that Hash can delegate its implementation 13.2269 +// to HashSet. 13.2270 +template<class C, class U, class HashF> 13.2271 +struct HashNode 13.2272 +{ 13.2273 + typedef HashNode<C, U, HashF> SelfType; 13.2274 + typedef C FirstType; 13.2275 + typedef U SecondType; 13.2276 + 13.2277 + C First; 13.2278 + U Second; 13.2279 + 13.2280 + // NodeRef is used to allow passing of elements into HashSet 13.2281 + // without using a temporary object. 13.2282 + struct NodeRef 13.2283 + { 13.2284 + const C* pFirst; 13.2285 + const U* pSecond; 13.2286 + 13.2287 + NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { } 13.2288 + NodeRef(const NodeRef& src) : pFirst(src.pFirst), pSecond(src.pSecond) { } 13.2289 + 13.2290 + // Enable computation of ghash_node_hashf. 13.2291 + inline UPInt GetHash() const { return HashF()(*pFirst); } 13.2292 + // Necessary conversion to allow HashNode::operator == to work. 13.2293 + operator const C& () const { return *pFirst; } 13.2294 + }; 13.2295 + 13.2296 + // Note: No default constructor is necessary. 13.2297 + HashNode(const HashNode& src) : First(src.First), Second(src.Second) { } 13.2298 + HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond) { } 13.2299 + void operator = (const NodeRef& src) { First = *src.pFirst; Second = *src.pSecond; } 13.2300 + 13.2301 + template<class K> 13.2302 + bool operator == (const K& src) const { return (First == src); } 13.2303 + 13.2304 + template<class K> 13.2305 + static UPInt CalcHash(const K& data) { return HashF()(data); } 13.2306 + inline UPInt GetHash() const { return HashF()(First); } 13.2307 + 13.2308 + // Hash functors used with this node. A separate functor is used for alternative 13.2309 + // key lookup so that it does not need to access the '.First' element. 13.2310 + struct NodeHashF 13.2311 + { 13.2312 + template<class K> 13.2313 + UPInt operator()(const K& data) const { return data.GetHash(); } 13.2314 + }; 13.2315 + struct NodeAltHashF 13.2316 + { 13.2317 + template<class K> 13.2318 + UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); } 13.2319 + }; 13.2320 +}; 13.2321 + 13.2322 + 13.2323 + 13.2324 +// **** Extra hashset_entry types to allow NodeRef construction. 13.2325 + 13.2326 +// The big difference between the below types and the ones used in hash_set is that 13.2327 +// these allow initializing the node with 'typename C::NodeRef& keyRef', which 13.2328 +// is critical to avoid temporary node allocation on stack when using placement new. 13.2329 + 13.2330 +// Compact hash table Entry type that re-computes hash keys during hash traversal. 13.2331 +// Good to use if the hash function is cheap or the hash value is already cached in C. 13.2332 +template<class C, class HashF> 13.2333 +class HashsetNodeEntry 13.2334 +{ 13.2335 +public: 13.2336 + // Internal chaining for collisions. 13.2337 + SPInt NextInChain; 13.2338 + C Value; 13.2339 + 13.2340 + HashsetNodeEntry() 13.2341 + : NextInChain(-2) { } 13.2342 + HashsetNodeEntry(const HashsetNodeEntry& e) 13.2343 + : NextInChain(e.NextInChain), Value(e.Value) { } 13.2344 + HashsetNodeEntry(const C& key, SPInt next) 13.2345 + : NextInChain(next), Value(key) { } 13.2346 + HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next) 13.2347 + : NextInChain(next), Value(keyRef) { } 13.2348 + 13.2349 + bool IsEmpty() const { return NextInChain == -2; } 13.2350 + bool IsEndOfChain() const { return NextInChain == -1; } 13.2351 + UPInt GetCachedHash(UPInt maskValue) const { return HashF()(Value) & maskValue; } 13.2352 + void SetCachedHash(UPInt hashValue) { OVR_UNUSED(hashValue); } 13.2353 + 13.2354 + void Clear() 13.2355 + { 13.2356 + Value.~C(); // placement delete 13.2357 + NextInChain = -2; 13.2358 + } 13.2359 + // Free is only used from dtor of hash; Clear is used during regular operations: 13.2360 + // assignment, hash reallocations, value reassignments, so on. 13.2361 + void Free() { Clear(); } 13.2362 +}; 13.2363 + 13.2364 +// Hash table Entry type that caches the Entry hash value for nodes, so that it 13.2365 +// does not need to be re-computed during access. 13.2366 +template<class C, class HashF> 13.2367 +class HashsetCachedNodeEntry 13.2368 +{ 13.2369 +public: 13.2370 + // Internal chaining for collisions. 13.2371 + SPInt NextInChain; 13.2372 + UPInt HashValue; 13.2373 + C Value; 13.2374 + 13.2375 + HashsetCachedNodeEntry() 13.2376 + : NextInChain(-2) { } 13.2377 + HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e) 13.2378 + : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { } 13.2379 + HashsetCachedNodeEntry(const C& key, SPInt next) 13.2380 + : NextInChain(next), Value(key) { } 13.2381 + HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next) 13.2382 + : NextInChain(next), Value(keyRef) { } 13.2383 + 13.2384 + bool IsEmpty() const { return NextInChain == -2; } 13.2385 + bool IsEndOfChain() const { return NextInChain == -1; } 13.2386 + UPInt GetCachedHash(UPInt maskValue) const { OVR_UNUSED(maskValue); return HashValue; } 13.2387 + void SetCachedHash(UPInt hashValue) { HashValue = hashValue; } 13.2388 + 13.2389 + void Clear() 13.2390 + { 13.2391 + Value.~C(); 13.2392 + NextInChain = -2; 13.2393 + } 13.2394 + // Free is only used from dtor of hash; Clear is used during regular operations: 13.2395 + // assignment, hash reallocations, value reassignments, so on. 13.2396 + void Free() { Clear(); } 13.2397 +}; 13.2398 + 13.2399 + 13.2400 +//----------------------------------------------------------------------------------- 13.2401 +template<class C, class U, 13.2402 + class HashF = FixedSizeHash<C>, 13.2403 + class Allocator = ContainerAllocator<C>, 13.2404 + class HashNode = OVR::HashNode<C,U,HashF>, 13.2405 + class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>, 13.2406 + class Container = HashSet<HashNode, typename HashNode::NodeHashF, 13.2407 + typename HashNode::NodeAltHashF, Allocator, 13.2408 + Entry> > 13.2409 +class Hash 13.2410 +{ 13.2411 +public: 13.2412 + OVR_MEMORY_REDEFINE_NEW(Hash) 13.2413 + 13.2414 + // Types used for hash_set. 13.2415 + typedef U ValueType; 13.2416 + typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container> SelfType; 13.2417 + 13.2418 + // Actual hash table itself, implemented as hash_set. 13.2419 + Container mHash; 13.2420 + 13.2421 +public: 13.2422 + Hash() { } 13.2423 + Hash(int sizeHint) : mHash(sizeHint) { } 13.2424 + Hash(const SelfType& src) : mHash(src.mHash) { } 13.2425 + ~Hash() { } 13.2426 + 13.2427 + void operator = (const SelfType& src) { mHash = src.mHash; } 13.2428 + 13.2429 + // Remove all entries from the Hash table. 13.2430 + inline void Clear() { mHash.Clear(); } 13.2431 + // Returns true if the Hash is empty. 13.2432 + inline bool IsEmpty() const { return mHash.IsEmpty(); } 13.2433 + 13.2434 + // Access (set). 13.2435 + inline void Set(const C& key, const U& value) 13.2436 + { 13.2437 + typename HashNode::NodeRef e(key, value); 13.2438 + mHash.Set(e); 13.2439 + } 13.2440 + inline void Add(const C& key, const U& value) 13.2441 + { 13.2442 + typename HashNode::NodeRef e(key, value); 13.2443 + mHash.Add(e); 13.2444 + } 13.2445 + 13.2446 + // Removes an element by clearing its Entry. 13.2447 + inline void Remove(const C& key) 13.2448 + { 13.2449 + mHash.RemoveAlt(key); 13.2450 + } 13.2451 + template<class K> 13.2452 + inline void RemoveAlt(const K& key) 13.2453 + { 13.2454 + mHash.RemoveAlt(key); 13.2455 + } 13.2456 + 13.2457 + // Retrieve the value under the given key. 13.2458 + // - If there's no value under the key, then return false and leave *pvalue alone. 13.2459 + // - If there is a value, return true, and Set *Pvalue to the Entry's value. 13.2460 + // - If value == NULL, return true or false according to the presence of the key. 13.2461 + bool Get(const C& key, U* pvalue) const 13.2462 + { 13.2463 + const HashNode* p = mHash.GetAlt(key); 13.2464 + if (p) 13.2465 + { 13.2466 + if (pvalue) 13.2467 + *pvalue = p->Second; 13.2468 + return true; 13.2469 + } 13.2470 + return false; 13.2471 + } 13.2472 + 13.2473 + template<class K> 13.2474 + bool GetAlt(const K& key, U* pvalue) const 13.2475 + { 13.2476 + const HashNode* p = mHash.GetAlt(key); 13.2477 + if (p) 13.2478 + { 13.2479 + if (pvalue) 13.2480 + *pvalue = p->Second; 13.2481 + return true; 13.2482 + } 13.2483 + return false; 13.2484 + } 13.2485 + 13.2486 + // Retrieve the pointer to a value under the given key. 13.2487 + // - If there's no value under the key, then return NULL. 13.2488 + // - If there is a value, return the pointer. 13.2489 + inline U* Get(const C& key) 13.2490 + { 13.2491 + HashNode* p = mHash.GetAlt(key); 13.2492 + return p ? &p->Second : 0; 13.2493 + } 13.2494 + inline const U* Get(const C& key) const 13.2495 + { 13.2496 + const HashNode* p = mHash.GetAlt(key); 13.2497 + return p ? &p->Second : 0; 13.2498 + } 13.2499 + 13.2500 + template<class K> 13.2501 + inline U* GetAlt(const K& key) 13.2502 + { 13.2503 + HashNode* p = mHash.GetAlt(key); 13.2504 + return p ? &p->Second : 0; 13.2505 + } 13.2506 + template<class K> 13.2507 + inline const U* GetAlt(const K& key) const 13.2508 + { 13.2509 + const HashNode* p = mHash.GetAlt(key); 13.2510 + return p ? &p->Second : 0; 13.2511 + } 13.2512 + 13.2513 + // Sizing methods - delegate to Hash. 13.2514 + inline UPInt GetSize() const { return mHash.GetSize(); } 13.2515 + inline void Resize(UPInt n) { mHash.Resize(n); } 13.2516 + inline void SetCapacity(UPInt newSize) { mHash.SetCapacity(newSize); } 13.2517 + 13.2518 + // Iterator API, like STL. 13.2519 + typedef typename Container::ConstIterator ConstIterator; 13.2520 + typedef typename Container::Iterator Iterator; 13.2521 + 13.2522 + inline Iterator Begin() { return mHash.Begin(); } 13.2523 + inline Iterator End() { return mHash.End(); } 13.2524 + inline ConstIterator Begin() const { return mHash.Begin(); } 13.2525 + inline ConstIterator End() const { return mHash.End(); } 13.2526 + 13.2527 + Iterator Find(const C& key) { return mHash.FindAlt(key); } 13.2528 + ConstIterator Find(const C& key) const { return mHash.FindAlt(key); } 13.2529 + 13.2530 + template<class K> 13.2531 + Iterator FindAlt(const K& key) { return mHash.FindAlt(key); } 13.2532 + template<class K> 13.2533 + ConstIterator FindAlt(const K& key) const { return mHash.FindAlt(key); } 13.2534 +}; 13.2535 + 13.2536 + 13.2537 + 13.2538 +// Hash with uncached hash code; declared for convenience. 13.2539 +template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> > 13.2540 +class HashUncached 13.2541 + : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>, 13.2542 + HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> > 13.2543 +{ 13.2544 +public: 13.2545 + typedef HashUncached<C, U, HashF, Allocator> SelfType; 13.2546 + typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>, 13.2547 + HashsetNodeEntry<HashNode<C,U,HashF>, 13.2548 + typename HashNode<C,U,HashF>::NodeHashF> > BaseType; 13.2549 + 13.2550 + // Delegated constructors. 13.2551 + HashUncached() { } 13.2552 + HashUncached(int sizeHint) : BaseType(sizeHint) { } 13.2553 + HashUncached(const SelfType& src) : BaseType(src) { } 13.2554 + ~HashUncached() { } 13.2555 + void operator = (const SelfType& src) { BaseType::operator = (src); } 13.2556 +}; 13.2557 + 13.2558 + 13.2559 + 13.2560 +// And identity hash in which keys serve as hash value. Can be uncached, 13.2561 +// since hash computation is assumed cheap. 13.2562 +template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> > 13.2563 +class HashIdentity 13.2564 + : public HashUncached<C, U, HashF, Allocator> 13.2565 +{ 13.2566 +public: 13.2567 + typedef HashIdentity<C, U, Allocator, HashF> SelfType; 13.2568 + typedef HashUncached<C, U, HashF, Allocator> BaseType; 13.2569 + 13.2570 + // Delegated constructors. 13.2571 + HashIdentity() { } 13.2572 + HashIdentity(int sizeHint) : BaseType(sizeHint) { } 13.2573 + HashIdentity(const SelfType& src) : BaseType(src) { } 13.2574 + ~HashIdentity() { } 13.2575 + void operator = (const SelfType& src) { BaseType::operator = (src); } 13.2576 +}; 13.2577 + 13.2578 + 13.2579 +} // OVR 13.2580 + 13.2581 + 13.2582 +#ifdef OVR_DEFINE_NEW 13.2583 +#define new OVR_DEFINE_NEW 13.2584 +#endif 13.2585 + 13.2586 +#endif
14.1 --- a/libovr/Src/Kernel/OVR_KeyCodes.h Sat Sep 14 17:51:03 2013 +0300 14.2 +++ b/libovr/Src/Kernel/OVR_KeyCodes.h Sun Sep 15 04:10:05 2013 +0300 14.3 @@ -1,1 +1,240 @@ 14.4 -/************************************************************************************ 14.5 14.6 PublicHeader: OVR.h 14.7 Filename : OVR_KeyCodes.h 14.8 Content : Common keyboard constants 14.9 Created : September 19, 2012 14.10 14.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 14.12 14.13 Use of this software is subject to the terms of the Oculus license 14.14 agreement provided at the time of installation or download, or which 14.15 otherwise accompanies this software in either electronic or hard copy form. 14.16 14.17 ************************************************************************************/ 14.18 14.19 #ifndef OVR_KeyCodes_h 14.20 #define OVR_KeyCodes_h 14.21 14.22 namespace OVR { 14.23 14.24 //----------------------------------------------------------------------------------- 14.25 // ***** KeyCode 14.26 14.27 // KeyCode enumeration defines platform-independent keyboard key constants. 14.28 // Note that Key_A through Key_Z are mapped to capital ascii constants. 14.29 14.30 enum KeyCode 14.31 { 14.32 // Key_None indicates that no key was specified. 14.33 Key_None = 0, 14.34 14.35 // A through Z and numbers 0 through 9. 14.36 Key_A = 65, 14.37 Key_B, 14.38 Key_C, 14.39 Key_D, 14.40 Key_E, 14.41 Key_F, 14.42 Key_G, 14.43 Key_H, 14.44 Key_I, 14.45 Key_J, 14.46 Key_K, 14.47 Key_L, 14.48 Key_M, 14.49 Key_N, 14.50 Key_O, 14.51 Key_P, 14.52 Key_Q, 14.53 Key_R, 14.54 Key_S, 14.55 Key_T, 14.56 Key_U, 14.57 Key_V, 14.58 Key_W, 14.59 Key_X, 14.60 Key_Y, 14.61 Key_Z, 14.62 Key_Num0 = 48, 14.63 Key_Num1, 14.64 Key_Num2, 14.65 Key_Num3, 14.66 Key_Num4, 14.67 Key_Num5, 14.68 Key_Num6, 14.69 Key_Num7, 14.70 Key_Num8, 14.71 Key_Num9, 14.72 14.73 // Numeric keypad. 14.74 Key_KP_0 = 0xa0, 14.75 Key_KP_1, 14.76 Key_KP_2, 14.77 Key_KP_3, 14.78 Key_KP_4, 14.79 Key_KP_5, 14.80 Key_KP_6, 14.81 Key_KP_7, 14.82 Key_KP_8, 14.83 Key_KP_9, 14.84 Key_KP_Multiply, 14.85 Key_KP_Add, 14.86 Key_KP_Enter, 14.87 Key_KP_Subtract, 14.88 Key_KP_Decimal, 14.89 Key_KP_Divide, 14.90 14.91 // Function keys. 14.92 Key_F1 = 0xb0, 14.93 Key_F2, 14.94 Key_F3, 14.95 Key_F4, 14.96 Key_F5, 14.97 Key_F6, 14.98 Key_F7, 14.99 Key_F8, 14.100 Key_F9, 14.101 Key_F10, 14.102 Key_F11, 14.103 Key_F12, 14.104 Key_F13, 14.105 Key_F14, 14.106 Key_F15, 14.107 14.108 // Other keys. 14.109 Key_Backspace = 8, 14.110 Key_Tab, 14.111 Key_Clear = 12, 14.112 Key_Return, 14.113 Key_Shift = 16, 14.114 Key_Control, 14.115 Key_Alt, 14.116 Key_Pause, 14.117 Key_CapsLock = 20, // Toggle 14.118 Key_Escape = 27, 14.119 Key_Space = 32, 14.120 Key_Quote = 39, 14.121 Key_PageUp = 0xc0, 14.122 Key_PageDown, 14.123 Key_End, 14.124 Key_Home, 14.125 Key_Left, 14.126 Key_Up, 14.127 Key_Right, 14.128 Key_Down, 14.129 Key_Insert, 14.130 Key_Delete, 14.131 Key_Help, 14.132 14.133 Key_Comma = 44, 14.134 Key_Minus, 14.135 Key_Slash = 47, 14.136 Key_Period, 14.137 Key_NumLock = 144, // Toggle 14.138 Key_ScrollLock = 145, // Toggle 14.139 14.140 Key_Semicolon = 59, 14.141 Key_Equal = 61, 14.142 Key_Bar = 192, 14.143 Key_BracketLeft = 91, 14.144 Key_Backslash, 14.145 Key_BracketRight, 14.146 14.147 Key_OEM_AX = 0xE1, // 'AX' key on Japanese AX keyboard 14.148 Key_OEM_102 = 0xE2, // "<>" or "\|" on RT 102-key keyboard. 14.149 Key_ICO_HELP = 0xE3, // Help key on ICO 14.150 Key_ICO_00 = 0xE4, // 00 key on ICO 14.151 14.152 Key_Meta, 14.153 14.154 // Total number of keys. 14.155 Key_CodeCount 14.156 }; 14.157 14.158 14.159 //----------------------------------------------------------------------------------- 14.160 14.161 class KeyModifiers 14.162 { 14.163 public: 14.164 enum 14.165 { 14.166 Key_ShiftPressed = 0x01, 14.167 Key_CtrlPressed = 0x02, 14.168 Key_AltPressed = 0x04, 14.169 Key_MetaPressed = 0x08, 14.170 Key_CapsToggled = 0x10, 14.171 Key_NumToggled = 0x20, 14.172 Key_ScrollToggled = 0x40, 14.173 14.174 Initialized_Bit = 0x80, 14.175 Initialized_Mask = 0xFF 14.176 }; 14.177 unsigned char States; 14.178 14.179 KeyModifiers() : States(0) { } 14.180 KeyModifiers(unsigned char st) : States((unsigned char)(st | Initialized_Bit)) { } 14.181 14.182 void Reset() { States = 0; } 14.183 14.184 bool IsShiftPressed() const { return (States & Key_ShiftPressed) != 0; } 14.185 bool IsCtrlPressed() const { return (States & Key_CtrlPressed) != 0; } 14.186 bool IsAltPressed() const { return (States & Key_AltPressed) != 0; } 14.187 bool IsMetaPressed() const { return (States & Key_MetaPressed) != 0; } 14.188 bool IsCapsToggled() const { return (States & Key_CapsToggled) != 0; } 14.189 bool IsNumToggled() const { return (States & Key_NumToggled) != 0; } 14.190 bool IsScrollToggled() const{ return (States & Key_ScrollToggled) != 0; } 14.191 14.192 void SetShiftPressed(bool v = true) { (v) ? States |= Key_ShiftPressed : States &= ~Key_ShiftPressed; } 14.193 void SetCtrlPressed(bool v = true) { (v) ? States |= Key_CtrlPressed : States &= ~Key_CtrlPressed; } 14.194 void SetAltPressed(bool v = true) { (v) ? States |= Key_AltPressed : States &= ~Key_AltPressed; } 14.195 void SetMetaPressed(bool v = true) { (v) ? States |= Key_MetaPressed : States &= ~Key_MetaPressed; } 14.196 void SetCapsToggled(bool v = true) { (v) ? States |= Key_CapsToggled : States &= ~Key_CapsToggled; } 14.197 void SetNumToggled(bool v = true) { (v) ? States |= Key_NumToggled : States &= ~Key_NumToggled; } 14.198 void SetScrollToggled(bool v = true) { (v) ? States |= Key_ScrollToggled: States &= ~Key_ScrollToggled; } 14.199 14.200 bool IsInitialized() const { return (States & Initialized_Mask) != 0; } 14.201 }; 14.202 14.203 14.204 //----------------------------------------------------------------------------------- 14.205 14.206 /* 14.207 enum PadKeyCode 14.208 { 14.209 Pad_None, // Indicates absence of key code. 14.210 Pad_Back, 14.211 Pad_Start, 14.212 Pad_A, 14.213 Pad_B, 14.214 Pad_X, 14.215 Pad_Y, 14.216 Pad_R1, // RightShoulder; 14.217 Pad_L1, // LeftShoulder; 14.218 Pad_R2, // RightTrigger; 14.219 Pad_L2, // LeftTrigger; 14.220 Pad_Up, 14.221 Pad_Down, 14.222 Pad_Right, 14.223 Pad_Left, 14.224 Pad_Plus, 14.225 Pad_Minus, 14.226 Pad_1, 14.227 Pad_2, 14.228 Pad_H, 14.229 Pad_C, 14.230 Pad_Z, 14.231 Pad_O, 14.232 Pad_T, 14.233 Pad_S, 14.234 Pad_Select, 14.235 Pad_Home, 14.236 Pad_RT, // RightThumb; 14.237 Pad_LT // LeftThumb; 14.238 }; 14.239 */ 14.240 14.241 } // OVR 14.242 14.243 #endif 14.244 \ No newline at end of file 14.245 +/************************************************************************************ 14.246 + 14.247 +PublicHeader: OVR.h 14.248 +Filename : OVR_KeyCodes.h 14.249 +Content : Common keyboard constants 14.250 +Created : September 19, 2012 14.251 + 14.252 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 14.253 + 14.254 +Use of this software is subject to the terms of the Oculus license 14.255 +agreement provided at the time of installation or download, or which 14.256 +otherwise accompanies this software in either electronic or hard copy form. 14.257 + 14.258 +************************************************************************************/ 14.259 + 14.260 +#ifndef OVR_KeyCodes_h 14.261 +#define OVR_KeyCodes_h 14.262 + 14.263 +namespace OVR { 14.264 + 14.265 +//----------------------------------------------------------------------------------- 14.266 +// ***** KeyCode 14.267 + 14.268 +// KeyCode enumeration defines platform-independent keyboard key constants. 14.269 +// Note that Key_A through Key_Z are mapped to capital ascii constants. 14.270 + 14.271 +enum KeyCode 14.272 +{ 14.273 + // Key_None indicates that no key was specified. 14.274 + Key_None = 0, 14.275 + 14.276 + // A through Z and numbers 0 through 9. 14.277 + Key_A = 65, 14.278 + Key_B, 14.279 + Key_C, 14.280 + Key_D, 14.281 + Key_E, 14.282 + Key_F, 14.283 + Key_G, 14.284 + Key_H, 14.285 + Key_I, 14.286 + Key_J, 14.287 + Key_K, 14.288 + Key_L, 14.289 + Key_M, 14.290 + Key_N, 14.291 + Key_O, 14.292 + Key_P, 14.293 + Key_Q, 14.294 + Key_R, 14.295 + Key_S, 14.296 + Key_T, 14.297 + Key_U, 14.298 + Key_V, 14.299 + Key_W, 14.300 + Key_X, 14.301 + Key_Y, 14.302 + Key_Z, 14.303 + Key_Num0 = 48, 14.304 + Key_Num1, 14.305 + Key_Num2, 14.306 + Key_Num3, 14.307 + Key_Num4, 14.308 + Key_Num5, 14.309 + Key_Num6, 14.310 + Key_Num7, 14.311 + Key_Num8, 14.312 + Key_Num9, 14.313 + 14.314 + // Numeric keypad. 14.315 + Key_KP_0 = 0xa0, 14.316 + Key_KP_1, 14.317 + Key_KP_2, 14.318 + Key_KP_3, 14.319 + Key_KP_4, 14.320 + Key_KP_5, 14.321 + Key_KP_6, 14.322 + Key_KP_7, 14.323 + Key_KP_8, 14.324 + Key_KP_9, 14.325 + Key_KP_Multiply, 14.326 + Key_KP_Add, 14.327 + Key_KP_Enter, 14.328 + Key_KP_Subtract, 14.329 + Key_KP_Decimal, 14.330 + Key_KP_Divide, 14.331 + 14.332 + // Function keys. 14.333 + Key_F1 = 0xb0, 14.334 + Key_F2, 14.335 + Key_F3, 14.336 + Key_F4, 14.337 + Key_F5, 14.338 + Key_F6, 14.339 + Key_F7, 14.340 + Key_F8, 14.341 + Key_F9, 14.342 + Key_F10, 14.343 + Key_F11, 14.344 + Key_F12, 14.345 + Key_F13, 14.346 + Key_F14, 14.347 + Key_F15, 14.348 + 14.349 + // Other keys. 14.350 + Key_Backspace = 8, 14.351 + Key_Tab, 14.352 + Key_Clear = 12, 14.353 + Key_Return, 14.354 + Key_Shift = 16, 14.355 + Key_Control, 14.356 + Key_Alt, 14.357 + Key_Pause, 14.358 + Key_CapsLock = 20, // Toggle 14.359 + Key_Escape = 27, 14.360 + Key_Space = 32, 14.361 + Key_Quote = 39, 14.362 + Key_PageUp = 0xc0, 14.363 + Key_PageDown, 14.364 + Key_End, 14.365 + Key_Home, 14.366 + Key_Left, 14.367 + Key_Up, 14.368 + Key_Right, 14.369 + Key_Down, 14.370 + Key_Insert, 14.371 + Key_Delete, 14.372 + Key_Help, 14.373 + 14.374 + Key_Comma = 44, 14.375 + Key_Minus, 14.376 + Key_Slash = 47, 14.377 + Key_Period, 14.378 + Key_NumLock = 144, // Toggle 14.379 + Key_ScrollLock = 145, // Toggle 14.380 + 14.381 + Key_Semicolon = 59, 14.382 + Key_Equal = 61, 14.383 + Key_Bar = 192, 14.384 + Key_BracketLeft = 91, 14.385 + Key_Backslash, 14.386 + Key_BracketRight, 14.387 + 14.388 + Key_OEM_AX = 0xE1, // 'AX' key on Japanese AX keyboard 14.389 + Key_OEM_102 = 0xE2, // "<>" or "\|" on RT 102-key keyboard. 14.390 + Key_ICO_HELP = 0xE3, // Help key on ICO 14.391 + Key_ICO_00 = 0xE4, // 00 key on ICO 14.392 + 14.393 + Key_Meta, 14.394 + 14.395 + // Total number of keys. 14.396 + Key_CodeCount 14.397 +}; 14.398 + 14.399 + 14.400 +//----------------------------------------------------------------------------------- 14.401 + 14.402 +class KeyModifiers 14.403 +{ 14.404 +public: 14.405 + enum 14.406 + { 14.407 + Key_ShiftPressed = 0x01, 14.408 + Key_CtrlPressed = 0x02, 14.409 + Key_AltPressed = 0x04, 14.410 + Key_MetaPressed = 0x08, 14.411 + Key_CapsToggled = 0x10, 14.412 + Key_NumToggled = 0x20, 14.413 + Key_ScrollToggled = 0x40, 14.414 + 14.415 + Initialized_Bit = 0x80, 14.416 + Initialized_Mask = 0xFF 14.417 + }; 14.418 + unsigned char States; 14.419 + 14.420 + KeyModifiers() : States(0) { } 14.421 + KeyModifiers(unsigned char st) : States((unsigned char)(st | Initialized_Bit)) { } 14.422 + 14.423 + void Reset() { States = 0; } 14.424 + 14.425 + bool IsShiftPressed() const { return (States & Key_ShiftPressed) != 0; } 14.426 + bool IsCtrlPressed() const { return (States & Key_CtrlPressed) != 0; } 14.427 + bool IsAltPressed() const { return (States & Key_AltPressed) != 0; } 14.428 + bool IsMetaPressed() const { return (States & Key_MetaPressed) != 0; } 14.429 + bool IsCapsToggled() const { return (States & Key_CapsToggled) != 0; } 14.430 + bool IsNumToggled() const { return (States & Key_NumToggled) != 0; } 14.431 + bool IsScrollToggled() const{ return (States & Key_ScrollToggled) != 0; } 14.432 + 14.433 + void SetShiftPressed(bool v = true) { (v) ? States |= Key_ShiftPressed : States &= ~Key_ShiftPressed; } 14.434 + void SetCtrlPressed(bool v = true) { (v) ? States |= Key_CtrlPressed : States &= ~Key_CtrlPressed; } 14.435 + void SetAltPressed(bool v = true) { (v) ? States |= Key_AltPressed : States &= ~Key_AltPressed; } 14.436 + void SetMetaPressed(bool v = true) { (v) ? States |= Key_MetaPressed : States &= ~Key_MetaPressed; } 14.437 + void SetCapsToggled(bool v = true) { (v) ? States |= Key_CapsToggled : States &= ~Key_CapsToggled; } 14.438 + void SetNumToggled(bool v = true) { (v) ? States |= Key_NumToggled : States &= ~Key_NumToggled; } 14.439 + void SetScrollToggled(bool v = true) { (v) ? States |= Key_ScrollToggled: States &= ~Key_ScrollToggled; } 14.440 + 14.441 + bool IsInitialized() const { return (States & Initialized_Mask) != 0; } 14.442 +}; 14.443 + 14.444 + 14.445 +//----------------------------------------------------------------------------------- 14.446 + 14.447 +/* 14.448 +enum PadKeyCode 14.449 +{ 14.450 + Pad_None, // Indicates absence of key code. 14.451 + Pad_Back, 14.452 + Pad_Start, 14.453 + Pad_A, 14.454 + Pad_B, 14.455 + Pad_X, 14.456 + Pad_Y, 14.457 + Pad_R1, // RightShoulder; 14.458 + Pad_L1, // LeftShoulder; 14.459 + Pad_R2, // RightTrigger; 14.460 + Pad_L2, // LeftTrigger; 14.461 + Pad_Up, 14.462 + Pad_Down, 14.463 + Pad_Right, 14.464 + Pad_Left, 14.465 + Pad_Plus, 14.466 + Pad_Minus, 14.467 + Pad_1, 14.468 + Pad_2, 14.469 + Pad_H, 14.470 + Pad_C, 14.471 + Pad_Z, 14.472 + Pad_O, 14.473 + Pad_T, 14.474 + Pad_S, 14.475 + Pad_Select, 14.476 + Pad_Home, 14.477 + Pad_RT, // RightThumb; 14.478 + Pad_LT // LeftThumb; 14.479 +}; 14.480 +*/ 14.481 + 14.482 +} // OVR 14.483 + 14.484 +#endif
15.1 --- a/libovr/Src/Kernel/OVR_List.h Sat Sep 14 17:51:03 2013 +0300 15.2 +++ b/libovr/Src/Kernel/OVR_List.h Sun Sep 15 04:10:05 2013 +0300 15.3 @@ -1,1 +1,325 @@ 15.4 -/************************************************************************************ 15.5 15.6 PublicHeader: OVR 15.7 Filename : OVR_List.h 15.8 Content : Template implementation for doubly-connected linked List 15.9 Created : September 19, 2012 15.10 Notes : 15.11 15.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 15.13 15.14 Use of this software is subject to the terms of the Oculus license 15.15 agreement provided at the time of installation or download, or which 15.16 otherwise accompanies this software in either electronic or hard copy form. 15.17 15.18 ************************************************************************************/ 15.19 15.20 #ifndef OVR_List_h 15.21 #define OVR_List_h 15.22 15.23 #include "OVR_Types.h" 15.24 15.25 namespace OVR { 15.26 15.27 //----------------------------------------------------------------------------------- 15.28 // ***** ListNode 15.29 // 15.30 // Base class for the elements of the intrusive linked list. 15.31 // To store elements in the List do: 15.32 // 15.33 // struct MyData : ListNode<MyData> 15.34 // { 15.35 // . . . 15.36 // }; 15.37 15.38 template<class T> 15.39 struct ListNode 15.40 { 15.41 union { 15.42 T* pPrev; 15.43 void* pVoidPrev; 15.44 }; 15.45 union { 15.46 T* pNext; 15.47 void* pVoidNext; 15.48 }; 15.49 15.50 void RemoveNode() 15.51 { 15.52 pPrev->pNext = pNext; 15.53 pNext->pPrev = pPrev; 15.54 } 15.55 15.56 // Removes us from the list and inserts pnew there instead. 15.57 void ReplaceNodeWith(T* pnew) 15.58 { 15.59 pPrev->pNext = pnew; 15.60 pNext->pPrev = pnew; 15.61 pnew->pPrev = pPrev; 15.62 pnew->pNext = pNext; 15.63 } 15.64 15.65 // Inserts the argument linked list node after us in the list. 15.66 void InsertNodeAfter(T* p) 15.67 { 15.68 p->pPrev = pNext->pPrev; // this 15.69 p->pNext = pNext; 15.70 pNext->pPrev = p; 15.71 pNext = p; 15.72 } 15.73 // Inserts the argument linked list node before us in the list. 15.74 void InsertNodeBefore(T* p) 15.75 { 15.76 p->pNext = pNext->pPrev; // this 15.77 p->pPrev = pPrev; 15.78 pPrev->pNext = p; 15.79 pPrev = p; 15.80 } 15.81 15.82 void Alloc_MoveTo(ListNode<T>* pdest) 15.83 { 15.84 pdest->pNext = pNext; 15.85 pdest->pPrev = pPrev; 15.86 pPrev->pNext = (T*)pdest; 15.87 pNext->pPrev = (T*)pdest; 15.88 } 15.89 }; 15.90 15.91 15.92 //------------------------------------------------------------------------ 15.93 // ***** List 15.94 // 15.95 // Doubly linked intrusive list. 15.96 // The data type must be derived from ListNode. 15.97 // 15.98 // Adding: PushFront(), PushBack(). 15.99 // Removing: Remove() - the element must be in the list! 15.100 // Moving: BringToFront(), SendToBack() - the element must be in the list! 15.101 // 15.102 // Iterating: 15.103 // MyData* data = MyList.GetFirst(); 15.104 // while (!MyList.IsNull(data)) 15.105 // { 15.106 // . . . 15.107 // data = MyList.GetNext(data); 15.108 // } 15.109 // 15.110 // Removing: 15.111 // MyData* data = MyList.GetFirst(); 15.112 // while (!MyList.IsNull(data)) 15.113 // { 15.114 // MyData* next = MyList.GetNext(data); 15.115 // if (ToBeRemoved(data)) 15.116 // MyList.Remove(data); 15.117 // data = next; 15.118 // } 15.119 // 15.120 15.121 // List<> represents a doubly-linked list of T, where each T must derive 15.122 // from ListNode<B>. B specifies the base class that was directly 15.123 // derived from ListNode, and is only necessary if there is an intermediate 15.124 // inheritance chain. 15.125 15.126 template<class T, class B = T> class List 15.127 { 15.128 public: 15.129 typedef T ValueType; 15.130 15.131 List() 15.132 { 15.133 Root.pNext = Root.pPrev = (ValueType*)&Root; 15.134 } 15.135 15.136 void Clear() 15.137 { 15.138 Root.pNext = Root.pPrev = (ValueType*)&Root; 15.139 } 15.140 15.141 const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; } 15.142 const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; } 15.143 ValueType* GetFirst() { return (ValueType*)Root.pNext; } 15.144 ValueType* GetLast () { return (ValueType*)Root.pPrev; } 15.145 15.146 // Determine if list is empty (i.e.) points to itself. 15.147 // Go through void* access to avoid issues with strict-aliasing optimizing out the 15.148 // access after RemoveNode(), etc. 15.149 bool IsEmpty() const { return Root.pVoidNext == (const T*)(const B*)&Root; } 15.150 bool IsFirst(const ValueType* p) const { return p == Root.pNext; } 15.151 bool IsLast (const ValueType* p) const { return p == Root.pPrev; } 15.152 bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; } 15.153 15.154 inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; } 15.155 inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; } 15.156 inline static ValueType* GetPrev( ValueType* p) { return (ValueType*)p->pPrev; } 15.157 inline static ValueType* GetNext( ValueType* p) { return (ValueType*)p->pNext; } 15.158 15.159 void PushFront(ValueType* p) 15.160 { 15.161 p->pNext = Root.pNext; 15.162 p->pPrev = (ValueType*)&Root; 15.163 Root.pNext->pPrev = p; 15.164 Root.pNext = p; 15.165 } 15.166 15.167 void PushBack(ValueType* p) 15.168 { 15.169 p->pPrev = Root.pPrev; 15.170 p->pNext = (ValueType*)&Root; 15.171 Root.pPrev->pNext = p; 15.172 Root.pPrev = p; 15.173 } 15.174 15.175 static void Remove(ValueType* p) 15.176 { 15.177 p->pPrev->pNext = p->pNext; 15.178 p->pNext->pPrev = p->pPrev; 15.179 } 15.180 15.181 void BringToFront(ValueType* p) 15.182 { 15.183 Remove(p); 15.184 PushFront(p); 15.185 } 15.186 15.187 void SendToBack(ValueType* p) 15.188 { 15.189 Remove(p); 15.190 PushBack(p); 15.191 } 15.192 15.193 // Appends the contents of the argument list to the front of this list; 15.194 // items are removed from the argument list. 15.195 void PushListToFront(List<T>& src) 15.196 { 15.197 if (!src.IsEmpty()) 15.198 { 15.199 ValueType* pfirst = src.GetFirst(); 15.200 ValueType* plast = src.GetLast(); 15.201 src.Clear(); 15.202 plast->pNext = Root.pNext; 15.203 pfirst->pPrev = (ValueType*)&Root; 15.204 Root.pNext->pPrev = plast; 15.205 Root.pNext = pfirst; 15.206 } 15.207 } 15.208 15.209 void PushListToBack(List<T>& src) 15.210 { 15.211 if (!src.IsEmpty()) 15.212 { 15.213 ValueType* pfirst = src.GetFirst(); 15.214 ValueType* plast = src.GetLast(); 15.215 src.Clear(); 15.216 plast->pNext = (ValueType*)&Root; 15.217 pfirst->pPrev = Root.pPrev; 15.218 Root.pPrev->pNext = pfirst; 15.219 Root.pPrev = plast; 15.220 } 15.221 } 15.222 15.223 // Removes all source list items after (and including) the 'pfirst' node from the 15.224 // source list and adds them to out list. 15.225 void PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst) 15.226 { 15.227 if (pfirst != &src.Root) 15.228 { 15.229 ValueType *plast = src.Root.pPrev; 15.230 15.231 // Remove list remainder from source. 15.232 pfirst->pPrev->pNext = (ValueType*)&src.Root; 15.233 src.Root.pPrev = pfirst->pPrev; 15.234 // Add the rest of the items to list. 15.235 plast->pNext = Root.pNext; 15.236 pfirst->pPrev = (ValueType*)&Root; 15.237 Root.pNext->pPrev = plast; 15.238 Root.pNext = pfirst; 15.239 } 15.240 } 15.241 15.242 // Removes all source list items up to but NOT including the 'pend' node from the 15.243 // source list and adds them to out list. 15.244 void PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail) 15.245 { 15.246 if (src.GetFirst() != ptail) 15.247 { 15.248 ValueType *pfirst = src.Root.pNext; 15.249 ValueType *plast = ptail->pPrev; 15.250 15.251 // Remove list remainder from source. 15.252 ptail->pPrev = (ValueType*)&src.Root; 15.253 src.Root.pNext = ptail; 15.254 15.255 // Add the rest of the items to list. 15.256 plast->pNext = Root.pNext; 15.257 pfirst->pPrev = (ValueType*)&Root; 15.258 Root.pNext->pPrev = plast; 15.259 Root.pNext = pfirst; 15.260 } 15.261 } 15.262 15.263 15.264 // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend', 15.265 // and adds them to out list. Note that source items MUST already be in the list. 15.266 void PushListItemsToFront(ValueType *pfirst, ValueType *pend) 15.267 { 15.268 if (pfirst != pend) 15.269 { 15.270 ValueType *plast = pend->pPrev; 15.271 15.272 // Remove list remainder from source. 15.273 pfirst->pPrev->pNext = pend; 15.274 pend->pPrev = pfirst->pPrev; 15.275 // Add the rest of the items to list. 15.276 plast->pNext = Root.pNext; 15.277 pfirst->pPrev = (ValueType*)&Root; 15.278 Root.pNext->pPrev = plast; 15.279 Root.pNext = pfirst; 15.280 } 15.281 } 15.282 15.283 15.284 void Alloc_MoveTo(List<T>* pdest) 15.285 { 15.286 if (IsEmpty()) 15.287 pdest->Clear(); 15.288 else 15.289 { 15.290 pdest->Root.pNext = Root.pNext; 15.291 pdest->Root.pPrev = Root.pPrev; 15.292 15.293 Root.pNext->pPrev = (ValueType*)&pdest->Root; 15.294 Root.pPrev->pNext = (ValueType*)&pdest->Root; 15.295 } 15.296 } 15.297 15.298 15.299 private: 15.300 // Copying is prohibited 15.301 List(const List<T>&); 15.302 const List<T>& operator = (const List<T>&); 15.303 15.304 ListNode<B> Root; 15.305 }; 15.306 15.307 15.308 //------------------------------------------------------------------------ 15.309 // ***** FreeListElements 15.310 // 15.311 // Remove all elements in the list and free them in the allocator 15.312 15.313 template<class List, class Allocator> 15.314 void FreeListElements(List& list, Allocator& allocator) 15.315 { 15.316 typename List::ValueType* self = list.GetFirst(); 15.317 while(!list.IsNull(self)) 15.318 { 15.319 typename List::ValueType* next = list.GetNext(self); 15.320 allocator.Free(self); 15.321 self = next; 15.322 } 15.323 list.Clear(); 15.324 } 15.325 15.326 } // OVR 15.327 15.328 #endif 15.329 \ No newline at end of file 15.330 +/************************************************************************************ 15.331 + 15.332 +PublicHeader: OVR 15.333 +Filename : OVR_List.h 15.334 +Content : Template implementation for doubly-connected linked List 15.335 +Created : September 19, 2012 15.336 +Notes : 15.337 + 15.338 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 15.339 + 15.340 +Use of this software is subject to the terms of the Oculus license 15.341 +agreement provided at the time of installation or download, or which 15.342 +otherwise accompanies this software in either electronic or hard copy form. 15.343 + 15.344 +************************************************************************************/ 15.345 + 15.346 +#ifndef OVR_List_h 15.347 +#define OVR_List_h 15.348 + 15.349 +#include "OVR_Types.h" 15.350 + 15.351 +namespace OVR { 15.352 + 15.353 +//----------------------------------------------------------------------------------- 15.354 +// ***** ListNode 15.355 +// 15.356 +// Base class for the elements of the intrusive linked list. 15.357 +// To store elements in the List do: 15.358 +// 15.359 +// struct MyData : ListNode<MyData> 15.360 +// { 15.361 +// . . . 15.362 +// }; 15.363 + 15.364 +template<class T> 15.365 +struct ListNode 15.366 +{ 15.367 + union { 15.368 + T* pPrev; 15.369 + void* pVoidPrev; 15.370 + }; 15.371 + union { 15.372 + T* pNext; 15.373 + void* pVoidNext; 15.374 + }; 15.375 + 15.376 + void RemoveNode() 15.377 + { 15.378 + pPrev->pNext = pNext; 15.379 + pNext->pPrev = pPrev; 15.380 + } 15.381 + 15.382 + // Removes us from the list and inserts pnew there instead. 15.383 + void ReplaceNodeWith(T* pnew) 15.384 + { 15.385 + pPrev->pNext = pnew; 15.386 + pNext->pPrev = pnew; 15.387 + pnew->pPrev = pPrev; 15.388 + pnew->pNext = pNext; 15.389 + } 15.390 + 15.391 + // Inserts the argument linked list node after us in the list. 15.392 + void InsertNodeAfter(T* p) 15.393 + { 15.394 + p->pPrev = pNext->pPrev; // this 15.395 + p->pNext = pNext; 15.396 + pNext->pPrev = p; 15.397 + pNext = p; 15.398 + } 15.399 + // Inserts the argument linked list node before us in the list. 15.400 + void InsertNodeBefore(T* p) 15.401 + { 15.402 + p->pNext = pNext->pPrev; // this 15.403 + p->pPrev = pPrev; 15.404 + pPrev->pNext = p; 15.405 + pPrev = p; 15.406 + } 15.407 + 15.408 + void Alloc_MoveTo(ListNode<T>* pdest) 15.409 + { 15.410 + pdest->pNext = pNext; 15.411 + pdest->pPrev = pPrev; 15.412 + pPrev->pNext = (T*)pdest; 15.413 + pNext->pPrev = (T*)pdest; 15.414 + } 15.415 +}; 15.416 + 15.417 + 15.418 +//------------------------------------------------------------------------ 15.419 +// ***** List 15.420 +// 15.421 +// Doubly linked intrusive list. 15.422 +// The data type must be derived from ListNode. 15.423 +// 15.424 +// Adding: PushFront(), PushBack(). 15.425 +// Removing: Remove() - the element must be in the list! 15.426 +// Moving: BringToFront(), SendToBack() - the element must be in the list! 15.427 +// 15.428 +// Iterating: 15.429 +// MyData* data = MyList.GetFirst(); 15.430 +// while (!MyList.IsNull(data)) 15.431 +// { 15.432 +// . . . 15.433 +// data = MyList.GetNext(data); 15.434 +// } 15.435 +// 15.436 +// Removing: 15.437 +// MyData* data = MyList.GetFirst(); 15.438 +// while (!MyList.IsNull(data)) 15.439 +// { 15.440 +// MyData* next = MyList.GetNext(data); 15.441 +// if (ToBeRemoved(data)) 15.442 +// MyList.Remove(data); 15.443 +// data = next; 15.444 +// } 15.445 +// 15.446 + 15.447 +// List<> represents a doubly-linked list of T, where each T must derive 15.448 +// from ListNode<B>. B specifies the base class that was directly 15.449 +// derived from ListNode, and is only necessary if there is an intermediate 15.450 +// inheritance chain. 15.451 + 15.452 +template<class T, class B = T> class List 15.453 +{ 15.454 +public: 15.455 + typedef T ValueType; 15.456 + 15.457 + List() 15.458 + { 15.459 + Root.pNext = Root.pPrev = (ValueType*)&Root; 15.460 + } 15.461 + 15.462 + void Clear() 15.463 + { 15.464 + Root.pNext = Root.pPrev = (ValueType*)&Root; 15.465 + } 15.466 + 15.467 + const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; } 15.468 + const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; } 15.469 + ValueType* GetFirst() { return (ValueType*)Root.pNext; } 15.470 + ValueType* GetLast () { return (ValueType*)Root.pPrev; } 15.471 + 15.472 + // Determine if list is empty (i.e.) points to itself. 15.473 + // Go through void* access to avoid issues with strict-aliasing optimizing out the 15.474 + // access after RemoveNode(), etc. 15.475 + bool IsEmpty() const { return Root.pVoidNext == (const T*)(const B*)&Root; } 15.476 + bool IsFirst(const ValueType* p) const { return p == Root.pNext; } 15.477 + bool IsLast (const ValueType* p) const { return p == Root.pPrev; } 15.478 + bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; } 15.479 + 15.480 + inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; } 15.481 + inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; } 15.482 + inline static ValueType* GetPrev( ValueType* p) { return (ValueType*)p->pPrev; } 15.483 + inline static ValueType* GetNext( ValueType* p) { return (ValueType*)p->pNext; } 15.484 + 15.485 + void PushFront(ValueType* p) 15.486 + { 15.487 + p->pNext = Root.pNext; 15.488 + p->pPrev = (ValueType*)&Root; 15.489 + Root.pNext->pPrev = p; 15.490 + Root.pNext = p; 15.491 + } 15.492 + 15.493 + void PushBack(ValueType* p) 15.494 + { 15.495 + p->pPrev = Root.pPrev; 15.496 + p->pNext = (ValueType*)&Root; 15.497 + Root.pPrev->pNext = p; 15.498 + Root.pPrev = p; 15.499 + } 15.500 + 15.501 + static void Remove(ValueType* p) 15.502 + { 15.503 + p->pPrev->pNext = p->pNext; 15.504 + p->pNext->pPrev = p->pPrev; 15.505 + } 15.506 + 15.507 + void BringToFront(ValueType* p) 15.508 + { 15.509 + Remove(p); 15.510 + PushFront(p); 15.511 + } 15.512 + 15.513 + void SendToBack(ValueType* p) 15.514 + { 15.515 + Remove(p); 15.516 + PushBack(p); 15.517 + } 15.518 + 15.519 + // Appends the contents of the argument list to the front of this list; 15.520 + // items are removed from the argument list. 15.521 + void PushListToFront(List<T>& src) 15.522 + { 15.523 + if (!src.IsEmpty()) 15.524 + { 15.525 + ValueType* pfirst = src.GetFirst(); 15.526 + ValueType* plast = src.GetLast(); 15.527 + src.Clear(); 15.528 + plast->pNext = Root.pNext; 15.529 + pfirst->pPrev = (ValueType*)&Root; 15.530 + Root.pNext->pPrev = plast; 15.531 + Root.pNext = pfirst; 15.532 + } 15.533 + } 15.534 + 15.535 + void PushListToBack(List<T>& src) 15.536 + { 15.537 + if (!src.IsEmpty()) 15.538 + { 15.539 + ValueType* pfirst = src.GetFirst(); 15.540 + ValueType* plast = src.GetLast(); 15.541 + src.Clear(); 15.542 + plast->pNext = (ValueType*)&Root; 15.543 + pfirst->pPrev = Root.pPrev; 15.544 + Root.pPrev->pNext = pfirst; 15.545 + Root.pPrev = plast; 15.546 + } 15.547 + } 15.548 + 15.549 + // Removes all source list items after (and including) the 'pfirst' node from the 15.550 + // source list and adds them to out list. 15.551 + void PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst) 15.552 + { 15.553 + if (pfirst != &src.Root) 15.554 + { 15.555 + ValueType *plast = src.Root.pPrev; 15.556 + 15.557 + // Remove list remainder from source. 15.558 + pfirst->pPrev->pNext = (ValueType*)&src.Root; 15.559 + src.Root.pPrev = pfirst->pPrev; 15.560 + // Add the rest of the items to list. 15.561 + plast->pNext = Root.pNext; 15.562 + pfirst->pPrev = (ValueType*)&Root; 15.563 + Root.pNext->pPrev = plast; 15.564 + Root.pNext = pfirst; 15.565 + } 15.566 + } 15.567 + 15.568 + // Removes all source list items up to but NOT including the 'pend' node from the 15.569 + // source list and adds them to out list. 15.570 + void PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail) 15.571 + { 15.572 + if (src.GetFirst() != ptail) 15.573 + { 15.574 + ValueType *pfirst = src.Root.pNext; 15.575 + ValueType *plast = ptail->pPrev; 15.576 + 15.577 + // Remove list remainder from source. 15.578 + ptail->pPrev = (ValueType*)&src.Root; 15.579 + src.Root.pNext = ptail; 15.580 + 15.581 + // Add the rest of the items to list. 15.582 + plast->pNext = Root.pNext; 15.583 + pfirst->pPrev = (ValueType*)&Root; 15.584 + Root.pNext->pPrev = plast; 15.585 + Root.pNext = pfirst; 15.586 + } 15.587 + } 15.588 + 15.589 + 15.590 + // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend', 15.591 + // and adds them to out list. Note that source items MUST already be in the list. 15.592 + void PushListItemsToFront(ValueType *pfirst, ValueType *pend) 15.593 + { 15.594 + if (pfirst != pend) 15.595 + { 15.596 + ValueType *plast = pend->pPrev; 15.597 + 15.598 + // Remove list remainder from source. 15.599 + pfirst->pPrev->pNext = pend; 15.600 + pend->pPrev = pfirst->pPrev; 15.601 + // Add the rest of the items to list. 15.602 + plast->pNext = Root.pNext; 15.603 + pfirst->pPrev = (ValueType*)&Root; 15.604 + Root.pNext->pPrev = plast; 15.605 + Root.pNext = pfirst; 15.606 + } 15.607 + } 15.608 + 15.609 + 15.610 + void Alloc_MoveTo(List<T>* pdest) 15.611 + { 15.612 + if (IsEmpty()) 15.613 + pdest->Clear(); 15.614 + else 15.615 + { 15.616 + pdest->Root.pNext = Root.pNext; 15.617 + pdest->Root.pPrev = Root.pPrev; 15.618 + 15.619 + Root.pNext->pPrev = (ValueType*)&pdest->Root; 15.620 + Root.pPrev->pNext = (ValueType*)&pdest->Root; 15.621 + } 15.622 + } 15.623 + 15.624 + 15.625 +private: 15.626 + // Copying is prohibited 15.627 + List(const List<T>&); 15.628 + const List<T>& operator = (const List<T>&); 15.629 + 15.630 + ListNode<B> Root; 15.631 +}; 15.632 + 15.633 + 15.634 +//------------------------------------------------------------------------ 15.635 +// ***** FreeListElements 15.636 +// 15.637 +// Remove all elements in the list and free them in the allocator 15.638 + 15.639 +template<class List, class Allocator> 15.640 +void FreeListElements(List& list, Allocator& allocator) 15.641 +{ 15.642 + typename List::ValueType* self = list.GetFirst(); 15.643 + while(!list.IsNull(self)) 15.644 + { 15.645 + typename List::ValueType* next = list.GetNext(self); 15.646 + allocator.Free(self); 15.647 + self = next; 15.648 + } 15.649 + list.Clear(); 15.650 +} 15.651 + 15.652 +} // OVR 15.653 + 15.654 +#endif
16.1 --- a/libovr/Src/Kernel/OVR_Log.cpp Sat Sep 14 17:51:03 2013 +0300 16.2 +++ b/libovr/Src/Kernel/OVR_Log.cpp Sun Sep 15 04:10:05 2013 +0300 16.3 @@ -1,1 +1,173 @@ 16.4 -/************************************************************************************ 16.5 16.6 Filename : OVR_Log.cpp 16.7 Content : Logging support 16.8 Created : September 19, 2012 16.9 Notes : 16.10 16.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 16.12 16.13 Use of this software is subject to the terms of the Oculus license 16.14 agreement provided at the time of installation or download, or which 16.15 otherwise accompanies this software in either electronic or hard copy form. 16.16 16.17 ************************************************************************************/ 16.18 16.19 #include "OVR_Log.h" 16.20 #include "OVR_Std.h" 16.21 #include <stdarg.h> 16.22 #include <stdio.h> 16.23 16.24 #if defined(OVR_OS_WIN32) 16.25 #include <windows.h> 16.26 #elif defined(OVR_OS_ANDROID) 16.27 #include <android/log.h> 16.28 #endif 16.29 16.30 namespace OVR { 16.31 16.32 // Global Log pointer. 16.33 Log* volatile OVR_GlobalLog = 0; 16.34 16.35 //----------------------------------------------------------------------------------- 16.36 // ***** Log Implementation 16.37 16.38 Log::~Log() 16.39 { 16.40 // Clear out global log 16.41 if (this == OVR_GlobalLog) 16.42 { 16.43 // TBD: perhaps we should ASSERT if this happens before system shutdown? 16.44 OVR_GlobalLog = 0; 16.45 } 16.46 } 16.47 16.48 void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList) 16.49 { 16.50 if ((messageType & LoggingMask) == 0) 16.51 return; 16.52 #ifndef OVR_BUILD_DEBUG 16.53 if (IsDebugMessage(messageType)) 16.54 return; 16.55 #endif 16.56 16.57 char buffer[MaxLogBufferMessageSize]; 16.58 FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList); 16.59 DefaultLogOutput(buffer, IsDebugMessage(messageType)); 16.60 } 16.61 16.62 void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...) 16.63 { 16.64 va_list argList; 16.65 va_start(argList, pfmt); 16.66 LogMessageVarg(messageType, pfmt, argList); 16.67 va_end(argList); 16.68 } 16.69 16.70 16.71 void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, 16.72 const char* fmt, va_list argList) 16.73 { 16.74 bool addNewline = true; 16.75 16.76 switch(messageType) 16.77 { 16.78 case Log_Error: OVR_strcpy(buffer, bufferSize, "Error: "); break; 16.79 case Log_Debug: OVR_strcpy(buffer, bufferSize, "Debug: "); break; 16.80 case Log_Assert: OVR_strcpy(buffer, bufferSize, "Assert: "); break; 16.81 case Log_Text: buffer[0] = 0; addNewline = false; break; 16.82 case Log_DebugText: buffer[0] = 0; addNewline = false; break; 16.83 default: 16.84 buffer[0] = 0; 16.85 addNewline = false; 16.86 break; 16.87 } 16.88 16.89 UPInt prefixLength = OVR_strlen(buffer); 16.90 char *buffer2 = buffer + prefixLength; 16.91 OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList); 16.92 16.93 if (addNewline) 16.94 OVR_strcat(buffer, bufferSize, "\n"); 16.95 } 16.96 16.97 16.98 void Log::DefaultLogOutput(const char* formattedText, bool debug) 16.99 { 16.100 16.101 #if defined(OVR_OS_WIN32) 16.102 // Under Win32, output regular messages to console if it exists; debug window otherwise. 16.103 static DWORD dummyMode; 16.104 static bool hasConsole = (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) && 16.105 (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummyMode)); 16.106 16.107 if (!hasConsole || debug) 16.108 { 16.109 ::OutputDebugStringA(formattedText); 16.110 } 16.111 else 16.112 { 16.113 fputs(formattedText, stdout); 16.114 } 16.115 16.116 #elif defined(OVR_OS_ANDROID) 16.117 __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText); 16.118 16.119 #else 16.120 fputs(formattedText, stdout); 16.121 16.122 #endif 16.123 16.124 // Just in case. 16.125 OVR_UNUSED2(formattedText, debug); 16.126 } 16.127 16.128 16.129 //static 16.130 void Log::SetGlobalLog(Log *log) 16.131 { 16.132 OVR_GlobalLog = log; 16.133 } 16.134 //static 16.135 Log* Log::GetGlobalLog() 16.136 { 16.137 // No global log by default? 16.138 // if (!OVR_GlobalLog) 16.139 // OVR_GlobalLog = GetDefaultLog(); 16.140 return OVR_GlobalLog; 16.141 } 16.142 16.143 //static 16.144 Log* Log::GetDefaultLog() 16.145 { 16.146 // Create default log pointer statically so that it can be used 16.147 // even during startup. 16.148 static Log defaultLog; 16.149 return &defaultLog; 16.150 } 16.151 16.152 16.153 //----------------------------------------------------------------------------------- 16.154 // ***** Global Logging functions 16.155 16.156 #define OVR_LOG_FUNCTION_IMPL(Name) \ 16.157 void Log##Name(const char* fmt, ...) \ 16.158 { \ 16.159 if (OVR_GlobalLog) \ 16.160 { \ 16.161 va_list argList; va_start(argList, fmt); \ 16.162 OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList); \ 16.163 va_end(argList); \ 16.164 } \ 16.165 } 16.166 16.167 OVR_LOG_FUNCTION_IMPL(Text) 16.168 OVR_LOG_FUNCTION_IMPL(Error) 16.169 16.170 #ifdef OVR_BUILD_DEBUG 16.171 OVR_LOG_FUNCTION_IMPL(DebugText) 16.172 OVR_LOG_FUNCTION_IMPL(Debug) 16.173 OVR_LOG_FUNCTION_IMPL(Assert) 16.174 #endif 16.175 16.176 } // OVR 16.177 \ No newline at end of file 16.178 +/************************************************************************************ 16.179 + 16.180 +Filename : OVR_Log.cpp 16.181 +Content : Logging support 16.182 +Created : September 19, 2012 16.183 +Notes : 16.184 + 16.185 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 16.186 + 16.187 +Use of this software is subject to the terms of the Oculus license 16.188 +agreement provided at the time of installation or download, or which 16.189 +otherwise accompanies this software in either electronic or hard copy form. 16.190 + 16.191 +************************************************************************************/ 16.192 + 16.193 +#include "OVR_Log.h" 16.194 +#include "OVR_Std.h" 16.195 +#include <stdarg.h> 16.196 +#include <stdio.h> 16.197 + 16.198 +#if defined(OVR_OS_WIN32) 16.199 +#include <windows.h> 16.200 +#elif defined(OVR_OS_ANDROID) 16.201 +#include <android/log.h> 16.202 +#endif 16.203 + 16.204 +namespace OVR { 16.205 + 16.206 +// Global Log pointer. 16.207 +Log* volatile OVR_GlobalLog = 0; 16.208 + 16.209 +//----------------------------------------------------------------------------------- 16.210 +// ***** Log Implementation 16.211 + 16.212 +Log::~Log() 16.213 +{ 16.214 + // Clear out global log 16.215 + if (this == OVR_GlobalLog) 16.216 + { 16.217 + // TBD: perhaps we should ASSERT if this happens before system shutdown? 16.218 + OVR_GlobalLog = 0; 16.219 + } 16.220 +} 16.221 + 16.222 +void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList) 16.223 +{ 16.224 + if ((messageType & LoggingMask) == 0) 16.225 + return; 16.226 +#ifndef OVR_BUILD_DEBUG 16.227 + if (IsDebugMessage(messageType)) 16.228 + return; 16.229 +#endif 16.230 + 16.231 + char buffer[MaxLogBufferMessageSize]; 16.232 + FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList); 16.233 + DefaultLogOutput(buffer, IsDebugMessage(messageType)); 16.234 +} 16.235 + 16.236 +void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...) 16.237 +{ 16.238 + va_list argList; 16.239 + va_start(argList, pfmt); 16.240 + LogMessageVarg(messageType, pfmt, argList); 16.241 + va_end(argList); 16.242 +} 16.243 + 16.244 + 16.245 +void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, 16.246 + const char* fmt, va_list argList) 16.247 +{ 16.248 + bool addNewline = true; 16.249 + 16.250 + switch(messageType) 16.251 + { 16.252 + case Log_Error: OVR_strcpy(buffer, bufferSize, "Error: "); break; 16.253 + case Log_Debug: OVR_strcpy(buffer, bufferSize, "Debug: "); break; 16.254 + case Log_Assert: OVR_strcpy(buffer, bufferSize, "Assert: "); break; 16.255 + case Log_Text: buffer[0] = 0; addNewline = false; break; 16.256 + case Log_DebugText: buffer[0] = 0; addNewline = false; break; 16.257 + default: 16.258 + buffer[0] = 0; 16.259 + addNewline = false; 16.260 + break; 16.261 + } 16.262 + 16.263 + UPInt prefixLength = OVR_strlen(buffer); 16.264 + char *buffer2 = buffer + prefixLength; 16.265 + OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList); 16.266 + 16.267 + if (addNewline) 16.268 + OVR_strcat(buffer, bufferSize, "\n"); 16.269 +} 16.270 + 16.271 + 16.272 +void Log::DefaultLogOutput(const char* formattedText, bool debug) 16.273 +{ 16.274 + 16.275 +#if defined(OVR_OS_WIN32) 16.276 + // Under Win32, output regular messages to console if it exists; debug window otherwise. 16.277 + static DWORD dummyMode; 16.278 + static bool hasConsole = (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) && 16.279 + (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummyMode)); 16.280 + 16.281 + if (!hasConsole || debug) 16.282 + { 16.283 + ::OutputDebugStringA(formattedText); 16.284 + } 16.285 + else 16.286 + { 16.287 + fputs(formattedText, stdout); 16.288 + } 16.289 + 16.290 +#elif defined(OVR_OS_ANDROID) 16.291 + __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText); 16.292 + 16.293 +#else 16.294 + fputs(formattedText, stdout); 16.295 + 16.296 +#endif 16.297 + 16.298 + // Just in case. 16.299 + OVR_UNUSED2(formattedText, debug); 16.300 +} 16.301 + 16.302 + 16.303 +//static 16.304 +void Log::SetGlobalLog(Log *log) 16.305 +{ 16.306 + OVR_GlobalLog = log; 16.307 +} 16.308 +//static 16.309 +Log* Log::GetGlobalLog() 16.310 +{ 16.311 +// No global log by default? 16.312 +// if (!OVR_GlobalLog) 16.313 +// OVR_GlobalLog = GetDefaultLog(); 16.314 + return OVR_GlobalLog; 16.315 +} 16.316 + 16.317 +//static 16.318 +Log* Log::GetDefaultLog() 16.319 +{ 16.320 + // Create default log pointer statically so that it can be used 16.321 + // even during startup. 16.322 + static Log defaultLog; 16.323 + return &defaultLog; 16.324 +} 16.325 + 16.326 + 16.327 +//----------------------------------------------------------------------------------- 16.328 +// ***** Global Logging functions 16.329 + 16.330 +#define OVR_LOG_FUNCTION_IMPL(Name) \ 16.331 + void Log##Name(const char* fmt, ...) \ 16.332 + { \ 16.333 + if (OVR_GlobalLog) \ 16.334 + { \ 16.335 + va_list argList; va_start(argList, fmt); \ 16.336 + OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList); \ 16.337 + va_end(argList); \ 16.338 + } \ 16.339 + } 16.340 + 16.341 +OVR_LOG_FUNCTION_IMPL(Text) 16.342 +OVR_LOG_FUNCTION_IMPL(Error) 16.343 + 16.344 +#ifdef OVR_BUILD_DEBUG 16.345 +OVR_LOG_FUNCTION_IMPL(DebugText) 16.346 +OVR_LOG_FUNCTION_IMPL(Debug) 16.347 +OVR_LOG_FUNCTION_IMPL(Assert) 16.348 +#endif 16.349 + 16.350 +} // OVR
17.1 --- a/libovr/Src/Kernel/OVR_Log.h Sat Sep 14 17:51:03 2013 +0300 17.2 +++ b/libovr/Src/Kernel/OVR_Log.h Sun Sep 15 04:10:05 2013 +0300 17.3 @@ -1,1 +1,193 @@ 17.4 -/************************************************************************************ 17.5 17.6 PublicHeader: OVR 17.7 Filename : OVR_Log.h 17.8 Content : Logging support 17.9 Created : September 19, 2012 17.10 Notes : 17.11 17.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 17.13 17.14 Use of this software is subject to the terms of the Oculus license 17.15 agreement provided at the time of installation or download, or which 17.16 otherwise accompanies this software in either electronic or hard copy form. 17.17 17.18 ************************************************************************************/ 17.19 17.20 #ifndef OVR_Log_h 17.21 #define OVR_Log_h 17.22 17.23 #include "OVR_Types.h" 17.24 #include <stdarg.h> 17.25 17.26 namespace OVR { 17.27 17.28 //----------------------------------------------------------------------------------- 17.29 // ***** Logging Constants 17.30 17.31 // LogMaskConstants defined bit mask constants that describe what log messages 17.32 // should be displayed. 17.33 enum LogMaskConstants 17.34 { 17.35 LogMask_Regular = 0x100, 17.36 LogMask_Debug = 0x200, 17.37 LogMask_None = 0, 17.38 LogMask_All = LogMask_Regular|LogMask_Debug 17.39 }; 17.40 17.41 17.42 // LogMessageType describes the type of the log message, controls when it is 17.43 // displayed and what prefix/suffix is given to it. Messages are subdivided into 17.44 // regular and debug logging types. Debug logging is only generated in debug builds. 17.45 // 17.46 // Log_Text - General output text displayed without prefix or new-line. 17.47 // Used in OVR libraries for general log flow messages 17.48 // such as "Device Initialized". 17.49 // 17.50 // Log_Error - Error message output with "Error: %s\n", intended for 17.51 // application/sample-level use only, in cases where an expected 17.52 // operation failed. OVR libraries should not use this internally, 17.53 // reporting status codes instead. 17.54 // 17.55 // Log_DebugText - Message without prefix or new lines; output in Debug build only. 17.56 // 17.57 // Log_Debug - Debug-build only message, formatted with "Debug: %s\n". 17.58 // Intended to comment on incorrect API usage that doesn't lead 17.59 // to crashes but can be avoided with proper use. 17.60 // There is no Debug Error on purpose, since real errors should 17.61 // be handled by API user. 17.62 // 17.63 // Log_Assert - Debug-build only message, formatted with "Assert: %s\n". 17.64 // Intended for severe unrecoverable conditions in library 17.65 // source code. Generated though OVR_ASSERT_MSG(c, "Text"). 17.66 17.67 enum LogMessageType 17.68 { 17.69 // General Logging 17.70 Log_Text = LogMask_Regular | 0, 17.71 Log_Error = LogMask_Regular | 1, // "Error: %s\n". 17.72 17.73 // Debug-only messages (not generated in release build) 17.74 Log_DebugText = LogMask_Debug | 0, 17.75 Log_Debug = LogMask_Debug | 1, // "Debug: %s\n". 17.76 Log_Assert = LogMask_Debug | 2, // "Assert: %s\n". 17.77 }; 17.78 17.79 17.80 // LOG_VAARG_ATTRIBUTE macro, enforces printf-style fromatting for message types 17.81 #ifdef __GNUC__ 17.82 # define OVR_LOG_VAARG_ATTRIBUTE(a,b) __attribute__((format (printf, a, b))) 17.83 #else 17.84 # define OVR_LOG_VAARG_ATTRIBUTE(a,b) 17.85 #endif 17.86 17.87 17.88 //----------------------------------------------------------------------------------- 17.89 // ***** Log 17.90 17.91 // Log defines a base class interface that can be implemented to catch both 17.92 // debug and runtime messages. 17.93 // Debug logging can be overridden by calling Log::SetGlobalLog. 17.94 17.95 class Log 17.96 { 17.97 friend class System; 17.98 public: 17.99 Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { } 17.100 virtual ~Log(); 17.101 17.102 // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated. 17.103 enum { MaxLogBufferMessageSize = 2048 }; 17.104 17.105 unsigned GetLoggingMask() const { return LoggingMask; } 17.106 void SetLoggingMask(unsigned logMask) { LoggingMask = logMask; } 17.107 17.108 // This virtual function receives all the messages, 17.109 // developers should override this function in order to do custom logging 17.110 virtual void LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList); 17.111 17.112 // Call the logging function with specific message type, with no type filtering. 17.113 void LogMessage(LogMessageType messageType, 17.114 const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4); 17.115 17.116 17.117 // Helper used by LogMessageVarg to format the log message, writing the resulting 17.118 // string into buffer. It formats text based on fmt and appends prefix/new line 17.119 // based on LogMessageType. 17.120 static void FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, 17.121 const char* fmt, va_list argList); 17.122 17.123 // Default log output implementation used by by LogMessageVarg. 17.124 // Debug flag may be used to re-direct output on some platforms, but doesn't 17.125 // necessarily disable it in release builds; that is the job of the called. 17.126 static void DefaultLogOutput(const char* textBuffer, bool debug); 17.127 17.128 // Determines if the specified message type is for debugging only. 17.129 static bool IsDebugMessage(LogMessageType messageType) 17.130 { 17.131 return (messageType & LogMask_Debug) != 0; 17.132 } 17.133 17.134 // *** Global APIs 17.135 17.136 // Global Log registration APIs. 17.137 // - Global log is used for OVR_DEBUG messages. Set global log to null (0) 17.138 // to disable all logging. 17.139 static void SetGlobalLog(Log *log); 17.140 static Log* GetGlobalLog(); 17.141 17.142 // Returns default log singleton instance. 17.143 static Log* GetDefaultLog(); 17.144 17.145 // Applies logMask to the default log and returns a pointer to it. 17.146 // By default, only Debug logging is enabled, so to avoid SDK generating console 17.147 // messages in user app (those are always disabled in release build, 17.148 // even if the flag is set). This function is useful in System constructor. 17.149 static Log* ConfigureDefaultLog(unsigned logMask = LogMask_Debug) 17.150 { 17.151 Log* log = GetDefaultLog(); 17.152 log->SetLoggingMask(logMask); 17.153 return log; 17.154 } 17.155 17.156 private: 17.157 // Logging mask described by LogMaskConstants. 17.158 unsigned LoggingMask; 17.159 }; 17.160 17.161 17.162 //----------------------------------------------------------------------------------- 17.163 // ***** Global Logging Functions and Debug Macros 17.164 17.165 // These functions will output text to global log with semantics described by 17.166 // their LogMessageType. 17.167 void LogText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.168 void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.169 17.170 #ifdef OVR_BUILD_DEBUG 17.171 17.172 // Debug build only logging. 17.173 void LogDebugText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.174 void LogDebug(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.175 void LogAssert(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.176 17.177 // Macro to do debug logging, printf-style. 17.178 // An extra set of set of parenthesis must be used around arguments, 17.179 // as in: OVR_LOG_DEBUG(("Value %d", 2)). 17.180 #define OVR_DEBUG_LOG(args) do { OVR::LogDebug args; } while(0) 17.181 #define OVR_DEBUG_LOG_TEXT(args) do { OVR::LogDebugText args; } while(0) 17.182 17.183 #define OVR_ASSERT_LOG(c, args) do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0) 17.184 17.185 #else 17.186 17.187 // If not in debug build, macros do nothing. 17.188 #define OVR_DEBUG_LOG(args) ((void)0) 17.189 #define OVR_DEBUG_LOG_TEXT(args) ((void)0) 17.190 #define OVR_ASSERT_LOG(c, args) ((void)0) 17.191 17.192 #endif 17.193 17.194 } // OVR 17.195 17.196 #endif 17.197 \ No newline at end of file 17.198 +/************************************************************************************ 17.199 + 17.200 +PublicHeader: OVR 17.201 +Filename : OVR_Log.h 17.202 +Content : Logging support 17.203 +Created : September 19, 2012 17.204 +Notes : 17.205 + 17.206 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 17.207 + 17.208 +Use of this software is subject to the terms of the Oculus license 17.209 +agreement provided at the time of installation or download, or which 17.210 +otherwise accompanies this software in either electronic or hard copy form. 17.211 + 17.212 +************************************************************************************/ 17.213 + 17.214 +#ifndef OVR_Log_h 17.215 +#define OVR_Log_h 17.216 + 17.217 +#include "OVR_Types.h" 17.218 +#include <stdarg.h> 17.219 + 17.220 +namespace OVR { 17.221 + 17.222 +//----------------------------------------------------------------------------------- 17.223 +// ***** Logging Constants 17.224 + 17.225 +// LogMaskConstants defined bit mask constants that describe what log messages 17.226 +// should be displayed. 17.227 +enum LogMaskConstants 17.228 +{ 17.229 + LogMask_Regular = 0x100, 17.230 + LogMask_Debug = 0x200, 17.231 + LogMask_None = 0, 17.232 + LogMask_All = LogMask_Regular|LogMask_Debug 17.233 +}; 17.234 + 17.235 + 17.236 +// LogMessageType describes the type of the log message, controls when it is 17.237 +// displayed and what prefix/suffix is given to it. Messages are subdivided into 17.238 +// regular and debug logging types. Debug logging is only generated in debug builds. 17.239 +// 17.240 +// Log_Text - General output text displayed without prefix or new-line. 17.241 +// Used in OVR libraries for general log flow messages 17.242 +// such as "Device Initialized". 17.243 +// 17.244 +// Log_Error - Error message output with "Error: %s\n", intended for 17.245 +// application/sample-level use only, in cases where an expected 17.246 +// operation failed. OVR libraries should not use this internally, 17.247 +// reporting status codes instead. 17.248 +// 17.249 +// Log_DebugText - Message without prefix or new lines; output in Debug build only. 17.250 +// 17.251 +// Log_Debug - Debug-build only message, formatted with "Debug: %s\n". 17.252 +// Intended to comment on incorrect API usage that doesn't lead 17.253 +// to crashes but can be avoided with proper use. 17.254 +// There is no Debug Error on purpose, since real errors should 17.255 +// be handled by API user. 17.256 +// 17.257 +// Log_Assert - Debug-build only message, formatted with "Assert: %s\n". 17.258 +// Intended for severe unrecoverable conditions in library 17.259 +// source code. Generated though OVR_ASSERT_MSG(c, "Text"). 17.260 + 17.261 +enum LogMessageType 17.262 +{ 17.263 + // General Logging 17.264 + Log_Text = LogMask_Regular | 0, 17.265 + Log_Error = LogMask_Regular | 1, // "Error: %s\n". 17.266 + 17.267 + // Debug-only messages (not generated in release build) 17.268 + Log_DebugText = LogMask_Debug | 0, 17.269 + Log_Debug = LogMask_Debug | 1, // "Debug: %s\n". 17.270 + Log_Assert = LogMask_Debug | 2, // "Assert: %s\n". 17.271 +}; 17.272 + 17.273 + 17.274 +// LOG_VAARG_ATTRIBUTE macro, enforces printf-style fromatting for message types 17.275 +#ifdef __GNUC__ 17.276 +# define OVR_LOG_VAARG_ATTRIBUTE(a,b) __attribute__((format (printf, a, b))) 17.277 +#else 17.278 +# define OVR_LOG_VAARG_ATTRIBUTE(a,b) 17.279 +#endif 17.280 + 17.281 + 17.282 +//----------------------------------------------------------------------------------- 17.283 +// ***** Log 17.284 + 17.285 +// Log defines a base class interface that can be implemented to catch both 17.286 +// debug and runtime messages. 17.287 +// Debug logging can be overridden by calling Log::SetGlobalLog. 17.288 + 17.289 +class Log 17.290 +{ 17.291 + friend class System; 17.292 +public: 17.293 + Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { } 17.294 + virtual ~Log(); 17.295 + 17.296 + // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated. 17.297 + enum { MaxLogBufferMessageSize = 2048 }; 17.298 + 17.299 + unsigned GetLoggingMask() const { return LoggingMask; } 17.300 + void SetLoggingMask(unsigned logMask) { LoggingMask = logMask; } 17.301 + 17.302 + // This virtual function receives all the messages, 17.303 + // developers should override this function in order to do custom logging 17.304 + virtual void LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList); 17.305 + 17.306 + // Call the logging function with specific message type, with no type filtering. 17.307 + void LogMessage(LogMessageType messageType, 17.308 + const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4); 17.309 + 17.310 + 17.311 + // Helper used by LogMessageVarg to format the log message, writing the resulting 17.312 + // string into buffer. It formats text based on fmt and appends prefix/new line 17.313 + // based on LogMessageType. 17.314 + static void FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType, 17.315 + const char* fmt, va_list argList); 17.316 + 17.317 + // Default log output implementation used by by LogMessageVarg. 17.318 + // Debug flag may be used to re-direct output on some platforms, but doesn't 17.319 + // necessarily disable it in release builds; that is the job of the called. 17.320 + static void DefaultLogOutput(const char* textBuffer, bool debug); 17.321 + 17.322 + // Determines if the specified message type is for debugging only. 17.323 + static bool IsDebugMessage(LogMessageType messageType) 17.324 + { 17.325 + return (messageType & LogMask_Debug) != 0; 17.326 + } 17.327 + 17.328 + // *** Global APIs 17.329 + 17.330 + // Global Log registration APIs. 17.331 + // - Global log is used for OVR_DEBUG messages. Set global log to null (0) 17.332 + // to disable all logging. 17.333 + static void SetGlobalLog(Log *log); 17.334 + static Log* GetGlobalLog(); 17.335 + 17.336 + // Returns default log singleton instance. 17.337 + static Log* GetDefaultLog(); 17.338 + 17.339 + // Applies logMask to the default log and returns a pointer to it. 17.340 + // By default, only Debug logging is enabled, so to avoid SDK generating console 17.341 + // messages in user app (those are always disabled in release build, 17.342 + // even if the flag is set). This function is useful in System constructor. 17.343 + static Log* ConfigureDefaultLog(unsigned logMask = LogMask_Debug) 17.344 + { 17.345 + Log* log = GetDefaultLog(); 17.346 + log->SetLoggingMask(logMask); 17.347 + return log; 17.348 + } 17.349 + 17.350 +private: 17.351 + // Logging mask described by LogMaskConstants. 17.352 + unsigned LoggingMask; 17.353 +}; 17.354 + 17.355 + 17.356 +//----------------------------------------------------------------------------------- 17.357 +// ***** Global Logging Functions and Debug Macros 17.358 + 17.359 +// These functions will output text to global log with semantics described by 17.360 +// their LogMessageType. 17.361 +void LogText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.362 +void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.363 + 17.364 +#ifdef OVR_BUILD_DEBUG 17.365 + 17.366 + // Debug build only logging. 17.367 + void LogDebugText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.368 + void LogDebug(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.369 + void LogAssert(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2); 17.370 + 17.371 + // Macro to do debug logging, printf-style. 17.372 + // An extra set of set of parenthesis must be used around arguments, 17.373 + // as in: OVR_LOG_DEBUG(("Value %d", 2)). 17.374 + #define OVR_DEBUG_LOG(args) do { OVR::LogDebug args; } while(0) 17.375 + #define OVR_DEBUG_LOG_TEXT(args) do { OVR::LogDebugText args; } while(0) 17.376 + 17.377 + #define OVR_ASSERT_LOG(c, args) do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0) 17.378 + 17.379 +#else 17.380 + 17.381 + // If not in debug build, macros do nothing. 17.382 + #define OVR_DEBUG_LOG(args) ((void)0) 17.383 + #define OVR_DEBUG_LOG_TEXT(args) ((void)0) 17.384 + #define OVR_ASSERT_LOG(c, args) ((void)0) 17.385 + 17.386 +#endif 17.387 + 17.388 +} // OVR 17.389 + 17.390 +#endif
18.1 --- a/libovr/Src/Kernel/OVR_Math.cpp Sat Sep 14 17:51:03 2013 +0300 18.2 +++ b/libovr/Src/Kernel/OVR_Math.cpp Sun Sep 15 04:10:05 2013 +0300 18.3 @@ -1,1 +1,153 @@ 18.4 -/************************************************************************************ 18.5 18.6 Filename : OVR_Math.h 18.7 Content : Implementation of 3D primitives such as vectors, matrices. 18.8 Created : September 4, 2012 18.9 Authors : Andrew Reisse, Michael Antonov 18.10 18.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 18.12 18.13 Use of this software is subject to the terms of the Oculus license 18.14 agreement provided at the time of installation or download, or which 18.15 otherwise accompanies this software in either electronic or hard copy form. 18.16 18.17 *************************************************************************************/ 18.18 18.19 #include "OVR_Math.h" 18.20 18.21 #include <float.h> 18.22 18.23 namespace OVR { 18.24 18.25 18.26 //------------------------------------------------------------------------------------- 18.27 // ***** Math 18.28 18.29 18.30 // Single-precision Math constants class. 18.31 const float Math<float>::Pi = 3.1415926f; 18.32 const float Math<float>::TwoPi = 3.1415926f * 2; 18.33 const float Math<float>::PiOver2 = 3.1415926f / 2.0f; 18.34 const float Math<float>::PiOver4 = 3.1415926f / 4.0f; 18.35 const float Math<float>::E = 2.7182818f; 18.36 18.37 const float Math<float>::MaxValue = FLT_MAX; 18.38 const float Math<float>::MinPositiveValue = FLT_MIN; 18.39 18.40 const float Math<float>::RadToDegreeFactor = 360.0f / Math<float>::TwoPi; 18.41 const float Math<float>::DegreeToRadFactor = Math<float>::TwoPi / 360.0f; 18.42 18.43 const float Math<float>::Tolerance = 0.00001f; 18.44 const float Math<float>::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems 18.45 18.46 18.47 // Double-precision Math constants class. 18.48 const double Math<double>::Pi = 3.14159265358979; 18.49 const double Math<double>::TwoPi = 3.14159265358979 * 2; 18.50 const double Math<double>::PiOver2 = 3.14159265358979 / 2.0; 18.51 const double Math<double>::PiOver4 = 3.14159265358979 / 4.0; 18.52 const double Math<double>::E = 2.71828182845905; 18.53 18.54 const double Math<double>::MaxValue = DBL_MAX; 18.55 const double Math<double>::MinPositiveValue = DBL_MIN; 18.56 18.57 const double Math<double>::RadToDegreeFactor = 360.0 / Math<double>::TwoPi; 18.58 const double Math<double>::DegreeToRadFactor = Math<double>::TwoPi / 360.0; 18.59 18.60 const double Math<double>::Tolerance = 0.00001; 18.61 const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems 18.62 18.63 18.64 18.65 //------------------------------------------------------------------------------------- 18.66 // ***** Matrix4f 18.67 18.68 18.69 Matrix4f Matrix4f::LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) 18.70 { 18.71 Vector3f z = (eye - at).Normalized(); // Forward 18.72 Vector3f x = up.Cross(z).Normalized(); // Right 18.73 Vector3f y = z.Cross(x); 18.74 18.75 Matrix4f m(x.x, x.y, x.z, -(x * eye), 18.76 y.x, y.y, y.z, -(y * eye), 18.77 z.x, z.y, z.z, -(z * eye), 18.78 0, 0, 0, 1 ); 18.79 return m; 18.80 } 18.81 18.82 Matrix4f Matrix4f::LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) 18.83 { 18.84 Vector3f z = (at - eye).Normalized(); // Forward 18.85 Vector3f x = up.Cross(z).Normalized(); // Right 18.86 Vector3f y = z.Cross(x); 18.87 18.88 Matrix4f m(x.x, x.y, x.z, -(x * eye), 18.89 y.x, y.y, y.z, -(y * eye), 18.90 z.x, z.y, z.z, -(z * eye), 18.91 0, 0, 0, 1 ); 18.92 return m; 18.93 } 18.94 18.95 18.96 Matrix4f Matrix4f::PerspectiveLH(float yfov, float aspect, float znear, float zfar) 18.97 { 18.98 Matrix4f m; 18.99 float tanHalfFov = tan(yfov * 0.5f); 18.100 18.101 m.M[0][0] = 1.0f / (aspect * tanHalfFov); 18.102 m.M[1][1] = 1.0f / tanHalfFov; 18.103 m.M[2][2] = zfar / (zfar - znear); 18.104 m.M[3][2] = 1.0f; 18.105 m.M[2][3] = (zfar * znear) / (znear - zfar); 18.106 m.M[3][3] = 0.0f; 18.107 18.108 // Note: Post-projection matrix result assumes Left-Handed coordinate system, 18.109 // with Y up, X right and Z forward. This supports positive z-buffer values. 18.110 return m; 18.111 } 18.112 18.113 18.114 Matrix4f Matrix4f::PerspectiveRH(float yfov, float aspect, float znear, float zfar) 18.115 { 18.116 Matrix4f m; 18.117 float tanHalfFov = tan(yfov * 0.5f); 18.118 18.119 m.M[0][0] = 1.0f / (aspect * tanHalfFov); 18.120 m.M[1][1] = 1.0f / tanHalfFov; 18.121 m.M[2][2] = zfar / (znear - zfar); 18.122 // m.M[2][2] = zfar / (zfar - znear); 18.123 m.M[3][2] = -1.0f; 18.124 m.M[2][3] = (zfar * znear) / (znear - zfar); 18.125 m.M[3][3] = 0.0f; 18.126 18.127 // Note: Post-projection matrix result assumes Left-Handed coordinate system, 18.128 // with Y up, X right and Z forward. This supports positive z-buffer values. 18.129 // This is the case even for RHS cooridnate input. 18.130 return m; 18.131 } 18.132 18.133 18.134 /* 18.135 OffCenterLH 18.136 18.137 2*zn/(r-l) 0 0 0 18.138 0 2*zn/(t-b) 0 0 18.139 (l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 18.140 0 0 zn*zf/(zn-zf) 0 18.141 18.142 */ 18.143 18.144 18.145 Matrix4f Matrix4f::Ortho2D(float w, float h) 18.146 { 18.147 Matrix4f m; 18.148 m.M[0][0] = 2.0f/w; 18.149 m.M[1][1] = -2.0f/h; 18.150 m.M[0][3] = -1.0; 18.151 m.M[1][3] = 1.0; 18.152 m.M[2][2] = 0; 18.153 return m; 18.154 } 18.155 18.156 } 18.157 \ No newline at end of file 18.158 +/************************************************************************************ 18.159 + 18.160 +Filename : OVR_Math.h 18.161 +Content : Implementation of 3D primitives such as vectors, matrices. 18.162 +Created : September 4, 2012 18.163 +Authors : Andrew Reisse, Michael Antonov 18.164 + 18.165 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 18.166 + 18.167 +Use of this software is subject to the terms of the Oculus license 18.168 +agreement provided at the time of installation or download, or which 18.169 +otherwise accompanies this software in either electronic or hard copy form. 18.170 + 18.171 +*************************************************************************************/ 18.172 + 18.173 +#include "OVR_Math.h" 18.174 + 18.175 +#include <float.h> 18.176 + 18.177 +namespace OVR { 18.178 + 18.179 + 18.180 +//------------------------------------------------------------------------------------- 18.181 +// ***** Math 18.182 + 18.183 + 18.184 +// Single-precision Math constants class. 18.185 +const float Math<float>::Pi = 3.1415926f; 18.186 +const float Math<float>::TwoPi = 3.1415926f * 2; 18.187 +const float Math<float>::PiOver2 = 3.1415926f / 2.0f; 18.188 +const float Math<float>::PiOver4 = 3.1415926f / 4.0f; 18.189 +const float Math<float>::E = 2.7182818f; 18.190 + 18.191 +const float Math<float>::MaxValue = FLT_MAX; 18.192 +const float Math<float>::MinPositiveValue = FLT_MIN; 18.193 + 18.194 +const float Math<float>::RadToDegreeFactor = 360.0f / Math<float>::TwoPi; 18.195 +const float Math<float>::DegreeToRadFactor = Math<float>::TwoPi / 360.0f; 18.196 + 18.197 +const float Math<float>::Tolerance = 0.00001f; 18.198 +const float Math<float>::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems 18.199 + 18.200 + 18.201 +// Double-precision Math constants class. 18.202 +const double Math<double>::Pi = 3.14159265358979; 18.203 +const double Math<double>::TwoPi = 3.14159265358979 * 2; 18.204 +const double Math<double>::PiOver2 = 3.14159265358979 / 2.0; 18.205 +const double Math<double>::PiOver4 = 3.14159265358979 / 4.0; 18.206 +const double Math<double>::E = 2.71828182845905; 18.207 + 18.208 +const double Math<double>::MaxValue = DBL_MAX; 18.209 +const double Math<double>::MinPositiveValue = DBL_MIN; 18.210 + 18.211 +const double Math<double>::RadToDegreeFactor = 360.0 / Math<double>::TwoPi; 18.212 +const double Math<double>::DegreeToRadFactor = Math<double>::TwoPi / 360.0; 18.213 + 18.214 +const double Math<double>::Tolerance = 0.00001; 18.215 +const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems 18.216 + 18.217 + 18.218 + 18.219 +//------------------------------------------------------------------------------------- 18.220 +// ***** Matrix4f 18.221 + 18.222 + 18.223 +Matrix4f Matrix4f::LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) 18.224 +{ 18.225 + Vector3f z = (eye - at).Normalized(); // Forward 18.226 + Vector3f x = up.Cross(z).Normalized(); // Right 18.227 + Vector3f y = z.Cross(x); 18.228 + 18.229 + Matrix4f m(x.x, x.y, x.z, -(x * eye), 18.230 + y.x, y.y, y.z, -(y * eye), 18.231 + z.x, z.y, z.z, -(z * eye), 18.232 + 0, 0, 0, 1 ); 18.233 + return m; 18.234 +} 18.235 + 18.236 +Matrix4f Matrix4f::LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up) 18.237 +{ 18.238 + Vector3f z = (at - eye).Normalized(); // Forward 18.239 + Vector3f x = up.Cross(z).Normalized(); // Right 18.240 + Vector3f y = z.Cross(x); 18.241 + 18.242 + Matrix4f m(x.x, x.y, x.z, -(x * eye), 18.243 + y.x, y.y, y.z, -(y * eye), 18.244 + z.x, z.y, z.z, -(z * eye), 18.245 + 0, 0, 0, 1 ); 18.246 + return m; 18.247 +} 18.248 + 18.249 + 18.250 +Matrix4f Matrix4f::PerspectiveLH(float yfov, float aspect, float znear, float zfar) 18.251 +{ 18.252 + Matrix4f m; 18.253 + float tanHalfFov = tan(yfov * 0.5f); 18.254 + 18.255 + m.M[0][0] = 1.0f / (aspect * tanHalfFov); 18.256 + m.M[1][1] = 1.0f / tanHalfFov; 18.257 + m.M[2][2] = zfar / (zfar - znear); 18.258 + m.M[3][2] = 1.0f; 18.259 + m.M[2][3] = (zfar * znear) / (znear - zfar); 18.260 + m.M[3][3] = 0.0f; 18.261 + 18.262 + // Note: Post-projection matrix result assumes Left-Handed coordinate system, 18.263 + // with Y up, X right and Z forward. This supports positive z-buffer values. 18.264 + return m; 18.265 +} 18.266 + 18.267 + 18.268 +Matrix4f Matrix4f::PerspectiveRH(float yfov, float aspect, float znear, float zfar) 18.269 +{ 18.270 + Matrix4f m; 18.271 + float tanHalfFov = tan(yfov * 0.5f); 18.272 + 18.273 + m.M[0][0] = 1.0f / (aspect * tanHalfFov); 18.274 + m.M[1][1] = 1.0f / tanHalfFov; 18.275 + m.M[2][2] = zfar / (znear - zfar); 18.276 + // m.M[2][2] = zfar / (zfar - znear); 18.277 + m.M[3][2] = -1.0f; 18.278 + m.M[2][3] = (zfar * znear) / (znear - zfar); 18.279 + m.M[3][3] = 0.0f; 18.280 + 18.281 + // Note: Post-projection matrix result assumes Left-Handed coordinate system, 18.282 + // with Y up, X right and Z forward. This supports positive z-buffer values. 18.283 + // This is the case even for RHS cooridnate input. 18.284 + return m; 18.285 +} 18.286 + 18.287 + 18.288 +/* 18.289 +OffCenterLH 18.290 + 18.291 +2*zn/(r-l) 0 0 0 18.292 +0 2*zn/(t-b) 0 0 18.293 +(l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 18.294 +0 0 zn*zf/(zn-zf) 0 18.295 + 18.296 +*/ 18.297 + 18.298 + 18.299 +Matrix4f Matrix4f::Ortho2D(float w, float h) 18.300 +{ 18.301 + Matrix4f m; 18.302 + m.M[0][0] = 2.0f/w; 18.303 + m.M[1][1] = -2.0f/h; 18.304 + m.M[0][3] = -1.0; 18.305 + m.M[1][3] = 1.0; 18.306 + m.M[2][2] = 0; 18.307 + return m; 18.308 +} 18.309 + 18.310 +}
19.1 --- a/libovr/Src/Kernel/OVR_Math.h Sat Sep 14 17:51:03 2013 +0300 19.2 +++ b/libovr/Src/Kernel/OVR_Math.h Sun Sep 15 04:10:05 2013 +0300 19.3 @@ -1,1 +1,1149 @@ 19.4 -/************************************************************************************ 19.5 19.6 PublicHeader: OVR.h 19.7 Filename : OVR_Math.h 19.8 Content : Implementation of 3D primitives such as vectors, matrices. 19.9 Created : September 4, 2012 19.10 Authors : Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova 19.11 19.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 19.13 19.14 Use of this software is subject to the terms of the Oculus license 19.15 agreement provided at the time of installation or download, or which 19.16 otherwise accompanies this software in either electronic or hard copy form. 19.17 19.18 *************************************************************************************/ 19.19 19.20 #ifndef OVR_Math_h 19.21 #define OVR_Math_h 19.22 19.23 #include <assert.h> 19.24 #include <stdlib.h> 19.25 #include <math.h> 19.26 19.27 #include "OVR_Types.h" 19.28 #include "OVR_RefCount.h" 19.29 19.30 namespace OVR { 19.31 19.32 //------------------------------------------------------------------------------------- 19.33 // Constants for 3D world/axis definitions. 19.34 19.35 // Definitions of axes for coordinate and rotation conversions. 19.36 enum Axis 19.37 { 19.38 Axis_X = 0, Axis_Y = 1, Axis_Z = 2 19.39 }; 19.40 19.41 // RotateDirection describes the rotation direction around an axis, interpreted as follows: 19.42 // CW - Clockwise while looking "down" from positive axis towards the origin. 19.43 // CCW - Counter-clockwise while looking from the positive axis towards the origin, 19.44 // which is in the negative axis direction. 19.45 // CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate 19.46 // system defines Y up, X right, and Z back (pointing out from the screen). In this 19.47 // system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane. 19.48 enum RotateDirection 19.49 { 19.50 Rotate_CCW = 1, 19.51 Rotate_CW = -1 19.52 }; 19.53 19.54 enum HandedSystem 19.55 { 19.56 Handed_R = 1, Handed_L = -1 19.57 }; 19.58 19.59 // AxisDirection describes which way the axis points. Used by WorldAxes. 19.60 enum AxisDirection 19.61 { 19.62 Axis_Up = 2, 19.63 Axis_Down = -2, 19.64 Axis_Right = 1, 19.65 Axis_Left = -1, 19.66 Axis_In = 3, 19.67 Axis_Out = -3 19.68 }; 19.69 19.70 struct WorldAxes 19.71 { 19.72 AxisDirection XAxis, YAxis, ZAxis; 19.73 19.74 WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z) 19.75 : XAxis(x), YAxis(y), ZAxis(z) 19.76 { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));} 19.77 }; 19.78 19.79 19.80 //------------------------------------------------------------------------------------- 19.81 // ***** Math 19.82 19.83 // Math class contains constants and functions. This class is a template specialized 19.84 // per type, with Math<float> and Math<double> being distinct. 19.85 template<class Type> 19.86 class Math 19.87 { 19.88 }; 19.89 19.90 // Single-precision Math constants class. 19.91 template<> 19.92 class Math<float> 19.93 { 19.94 public: 19.95 static const float Pi; 19.96 static const float TwoPi; 19.97 static const float PiOver2; 19.98 static const float PiOver4; 19.99 static const float E; 19.100 19.101 static const float MaxValue; // Largest positive float Value 19.102 static const float MinPositiveValue; // Smallest possible positive value 19.103 19.104 static const float RadToDegreeFactor; 19.105 static const float DegreeToRadFactor; 19.106 19.107 static const float Tolerance; // 0.00001f; 19.108 static const float SingularityRadius; //0.00000000001f for Gimbal lock numerical problems 19.109 }; 19.110 19.111 // Double-precision Math constants class. 19.112 template<> 19.113 class Math<double> 19.114 { 19.115 public: 19.116 static const double Pi; 19.117 static const double TwoPi; 19.118 static const double PiOver2; 19.119 static const double PiOver4; 19.120 static const double E; 19.121 19.122 static const double MaxValue; // Largest positive double Value 19.123 static const double MinPositiveValue; // Smallest possible positive value 19.124 19.125 static const double RadToDegreeFactor; 19.126 static const double DegreeToRadFactor; 19.127 19.128 static const double Tolerance; // 0.00001f; 19.129 static const double SingularityRadius; //0.00000000001 for Gimbal lock numerical problems 19.130 }; 19.131 19.132 typedef Math<float> Mathf; 19.133 typedef Math<double> Mathd; 19.134 19.135 // Conversion functions between degrees and radians 19.136 template<class FT> 19.137 FT RadToDegree(FT rads) { return rads * Math<FT>::RadToDegreeFactor; } 19.138 template<class FT> 19.139 FT DegreeToRad(FT rads) { return rads * Math<FT>::DegreeToRadFactor; } 19.140 19.141 template<class T> 19.142 class Quat; 19.143 19.144 //------------------------------------------------------------------------------------- 19.145 // ***** Vector2f - 2D Vector2f 19.146 19.147 // Vector2f represents a 2-dimensional vector or point in space, 19.148 // consisting of coordinates x and y, 19.149 19.150 template<class T> 19.151 class Vector2 19.152 { 19.153 public: 19.154 T x, y; 19.155 19.156 Vector2() : x(0), y(0) { } 19.157 Vector2(T x_, T y_) : x(x_), y(y_) { } 19.158 explicit Vector2(T s) : x(s), y(s) { } 19.159 19.160 bool operator== (const Vector2& b) const { return x == b.x && y == b.y; } 19.161 bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; } 19.162 19.163 Vector2 operator+ (const Vector2& b) const { return Vector2(x + b.x, y + b.y); } 19.164 Vector2& operator+= (const Vector2& b) { x += b.x; y += b.y; return *this; } 19.165 Vector2 operator- (const Vector2& b) const { return Vector2(x - b.x, y - b.y); } 19.166 Vector2& operator-= (const Vector2& b) { x -= b.x; y -= b.y; return *this; } 19.167 Vector2 operator- () const { return Vector2(-x, -y); } 19.168 19.169 // Scalar multiplication/division scales vector. 19.170 Vector2 operator* (T s) const { return Vector2(x*s, y*s); } 19.171 Vector2& operator*= (T s) { x *= s; y *= s; return *this; } 19.172 19.173 Vector2 operator/ (T s) const { T rcp = T(1)/s; 19.174 return Vector2(x*rcp, y*rcp); } 19.175 Vector2& operator/= (T s) { T rcp = T(1)/s; 19.176 x *= rcp; y *= rcp; 19.177 return *this; } 19.178 19.179 // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. 19.180 bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) 19.181 { 19.182 return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); 19.183 } 19.184 19.185 // Dot product overload. 19.186 // Used to calculate angle q between two vectors among other things, 19.187 // as (A dot B) = |a||b|cos(q). 19.188 T operator* (const Vector2& b) const { return x*b.x + y*b.y; } 19.189 19.190 // Returns the angle from this vector to b, in radians. 19.191 T Angle(const Vector2& b) const { return acos((*this * b)/(Length()*b.Length())); } 19.192 19.193 // Return Length of the vector squared. 19.194 T LengthSq() const { return (x * x + y * y); } 19.195 // Return vector length. 19.196 T Length() const { return sqrt(LengthSq()); } 19.197 19.198 // Returns distance between two points represented by vectors. 19.199 T Distance(Vector2& b) const { return (*this - b).Length(); } 19.200 19.201 // Determine if this a unit vector. 19.202 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } 19.203 // Normalize, convention vector length to 1. 19.204 void Normalize() { *this /= Length(); } 19.205 // Returns normalized (unit) version of the vector without modifying itself. 19.206 Vector2 Normalized() const { return *this / Length(); } 19.207 19.208 // Linearly interpolates from this vector to another. 19.209 // Factor should be between 0.0 and 1.0, with 0 giving full value to this. 19.210 Vector2 Lerp(const Vector2& b, T f) const { return *this*(T(1) - f) + b*f; } 19.211 19.212 // Projects this vector onto the argument; in other words, 19.213 // A.Project(B) returns projection of vector A onto B. 19.214 Vector2 ProjectTo(const Vector2& b) const { return b * ((*this * b) / b.LengthSq()); } 19.215 }; 19.216 19.217 19.218 typedef Vector2<float> Vector2f; 19.219 typedef Vector2<double> Vector2d; 19.220 19.221 //------------------------------------------------------------------------------------- 19.222 // ***** Vector3f - 3D Vector3f 19.223 19.224 // Vector3f represents a 3-dimensional vector or point in space, 19.225 // consisting of coordinates x, y and z. 19.226 19.227 template<class T> 19.228 class Vector3 19.229 { 19.230 public: 19.231 T x, y, z; 19.232 19.233 Vector3() : x(0), y(0), z(0) { } 19.234 Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { } 19.235 explicit Vector3(T s) : x(s), y(s), z(s) { } 19.236 19.237 bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; } 19.238 bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; } 19.239 19.240 Vector3 operator+ (const Vector3& b) const { return Vector3(x + b.x, y + b.y, z + b.z); } 19.241 Vector3& operator+= (const Vector3& b) { x += b.x; y += b.y; z += b.z; return *this; } 19.242 Vector3 operator- (const Vector3& b) const { return Vector3(x - b.x, y - b.y, z - b.z); } 19.243 Vector3& operator-= (const Vector3& b) { x -= b.x; y -= b.y; z -= b.z; return *this; } 19.244 Vector3 operator- () const { return Vector3(-x, -y, -z); } 19.245 19.246 // Scalar multiplication/division scales vector. 19.247 Vector3 operator* (T s) const { return Vector3(x*s, y*s, z*s); } 19.248 Vector3& operator*= (T s) { x *= s; y *= s; z *= s; return *this; } 19.249 19.250 Vector3 operator/ (T s) const { T rcp = T(1)/s; 19.251 return Vector3(x*rcp, y*rcp, z*rcp); } 19.252 Vector3& operator/= (T s) { T rcp = T(1)/s; 19.253 x *= rcp; y *= rcp; z *= rcp; 19.254 return *this; } 19.255 19.256 // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. 19.257 bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) 19.258 { 19.259 return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance); 19.260 } 19.261 19.262 // Dot product overload. 19.263 // Used to calculate angle q between two vectors among other things, 19.264 // as (A dot B) = |a||b|cos(q). 19.265 T operator* (const Vector3& b) const { return x*b.x + y*b.y + z*b.z; } 19.266 19.267 // Compute cross product, which generates a normal vector. 19.268 // Direction vector can be determined by right-hand rule: Pointing index finder in 19.269 // direction a and middle finger in direction b, thumb will point in a.Cross(b). 19.270 Vector3 Cross(const Vector3& b) const { return Vector3(y*b.z - z*b.y, 19.271 z*b.x - x*b.z, 19.272 x*b.y - y*b.x); } 19.273 19.274 // Returns the angle from this vector to b, in radians. 19.275 T Angle(const Vector3& b) const { return acos((*this * b)/(Length()*b.Length())); } 19.276 19.277 // Return Length of the vector squared. 19.278 T LengthSq() const { return (x * x + y * y + z * z); } 19.279 // Return vector length. 19.280 T Length() const { return sqrt(LengthSq()); } 19.281 19.282 // Returns distance between two points represented by vectors. 19.283 T Distance(Vector3& b) const { return (*this - b).Length(); } 19.284 19.285 // Determine if this a unit vector. 19.286 bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } 19.287 // Normalize, convention vector length to 1. 19.288 void Normalize() { *this /= Length(); } 19.289 // Returns normalized (unit) version of the vector without modifying itself. 19.290 Vector3 Normalized() const { return *this / Length(); } 19.291 19.292 // Linearly interpolates from this vector to another. 19.293 // Factor should be between 0.0 and 1.0, with 0 giving full value to this. 19.294 Vector3 Lerp(const Vector3& b, T f) const { return *this*(T(1) - f) + b*f; } 19.295 19.296 // Projects this vector onto the argument; in other words, 19.297 // A.Project(B) returns projection of vector A onto B. 19.298 Vector3 ProjectTo(const Vector3& b) const { return b * ((*this * b) / b.LengthSq()); } 19.299 }; 19.300 19.301 19.302 typedef Vector3<float> Vector3f; 19.303 typedef Vector3<double> Vector3d; 19.304 19.305 19.306 //------------------------------------------------------------------------------------- 19.307 // ***** Matrix4f 19.308 19.309 // Matrix4f is a 4x4 matrix used for 3d transformations and projections. 19.310 // Translation stored in the last column. 19.311 // The matrix is stored in row-major order in memory, meaning that values 19.312 // of the first row are stored before the next one. 19.313 // 19.314 // The arrangement of the matrix is chosen to be in Right-Handed 19.315 // coordinate system and counterclockwise rotations when looking down 19.316 // the axis 19.317 // 19.318 // Transformation Order: 19.319 // - Transformations are applied from right to left, so the expression 19.320 // M1 * M2 * M3 * V means that the vector V is transformed by M3 first, 19.321 // followed by M2 and M1. 19.322 // 19.323 // Coordinate system: Right Handed 19.324 // 19.325 // Rotations: Counterclockwise when looking down the axis. All angles are in radians. 19.326 // 19.327 // | sx 01 02 tx | // First column (sx, 10, 20): Axis X basis vector. 19.328 // | 10 sy 12 ty | // Second column (01, sy, 21): Axis Y basis vector. 19.329 // | 20 21 sz tz | // Third columnt (02, 12, sz): Axis Z basis vector. 19.330 // | 30 31 32 33 | 19.331 // 19.332 // The basis vectors are first three columns. 19.333 19.334 class Matrix4f 19.335 { 19.336 static Matrix4f IdentityValue; 19.337 19.338 public: 19.339 float M[4][4]; 19.340 19.341 enum NoInitType { NoInit }; 19.342 19.343 // Construct with no memory initialization. 19.344 Matrix4f(NoInitType) { } 19.345 19.346 // By default, we construct identity matrix. 19.347 Matrix4f() 19.348 { 19.349 SetIdentity(); 19.350 } 19.351 19.352 Matrix4f(float m11, float m12, float m13, float m14, 19.353 float m21, float m22, float m23, float m24, 19.354 float m31, float m32, float m33, float m34, 19.355 float m41, float m42, float m43, float m44) 19.356 { 19.357 M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14; 19.358 M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24; 19.359 M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34; 19.360 M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44; 19.361 } 19.362 19.363 Matrix4f(float m11, float m12, float m13, 19.364 float m21, float m22, float m23, 19.365 float m31, float m32, float m33) 19.366 { 19.367 M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0; 19.368 M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0; 19.369 M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0; 19.370 M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1; 19.371 } 19.372 19.373 static const Matrix4f& Identity() { return IdentityValue; } 19.374 19.375 void SetIdentity() 19.376 { 19.377 M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1; 19.378 M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0; 19.379 M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0; 19.380 M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0; 19.381 } 19.382 19.383 // Multiplies two matrices into destination with minimum copying. 19.384 static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b) 19.385 { 19.386 OVR_ASSERT((d != &a) && (d != &b)); 19.387 int i = 0; 19.388 do { 19.389 d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0]; 19.390 d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1]; 19.391 d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2]; 19.392 d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3]; 19.393 } while((++i) < 4); 19.394 19.395 return *d; 19.396 } 19.397 19.398 Matrix4f operator* (const Matrix4f& b) const 19.399 { 19.400 Matrix4f result(Matrix4f::NoInit); 19.401 Multiply(&result, *this, b); 19.402 return result; 19.403 } 19.404 19.405 Matrix4f& operator*= (const Matrix4f& b) 19.406 { 19.407 return Multiply(this, Matrix4f(*this), b); 19.408 } 19.409 19.410 Matrix4f operator* (float s) const 19.411 { 19.412 return Matrix4f(M[0][0] * s, M[0][1] * s, M[0][2] * s, M[0][3] * s, 19.413 M[1][0] * s, M[1][1] * s, M[1][2] * s, M[1][3] * s, 19.414 M[2][0] * s, M[2][1] * s, M[2][2] * s, M[2][3] * s, 19.415 M[3][0] * s, M[3][1] * s, M[3][2] * s, M[3][3] * s); 19.416 } 19.417 19.418 Matrix4f& operator*= (float s) 19.419 { 19.420 M[0][0] *= s; M[0][1] *= s; M[0][2] *= s; M[0][3] *= s; 19.421 M[1][0] *= s; M[1][1] *= s; M[1][2] *= s; M[1][3] *= s; 19.422 M[2][0] *= s; M[2][1] *= s; M[2][2] *= s; M[2][3] *= s; 19.423 M[3][0] *= s; M[3][1] *= s; M[3][2] *= s; M[3][3] *= s; 19.424 return *this; 19.425 } 19.426 19.427 Vector3f Transform(const Vector3f& v) const 19.428 { 19.429 return Vector3f(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3], 19.430 M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3], 19.431 M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]); 19.432 } 19.433 19.434 Matrix4f Transposed() const 19.435 { 19.436 return Matrix4f(M[0][0], M[1][0], M[2][0], M[3][0], 19.437 M[0][1], M[1][1], M[2][1], M[3][1], 19.438 M[0][2], M[1][2], M[2][2], M[3][2], 19.439 M[0][3], M[1][3], M[2][3], M[3][3]); 19.440 } 19.441 19.442 void Transpose() 19.443 { 19.444 *this = Transposed(); 19.445 } 19.446 19.447 19.448 float SubDet (const int* rows, const int* cols) const 19.449 { 19.450 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]]) 19.451 - 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]]) 19.452 + 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]]); 19.453 } 19.454 19.455 float Cofactor(int I, int J) const 19.456 { 19.457 const int indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; 19.458 return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); 19.459 } 19.460 19.461 float Determinant() const 19.462 { 19.463 return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3); 19.464 } 19.465 19.466 Matrix4f Adjugated() const 19.467 { 19.468 return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 19.469 Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 19.470 Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2), 19.471 Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3)); 19.472 } 19.473 19.474 Matrix4f Inverted() const 19.475 { 19.476 float det = Determinant(); 19.477 assert(det != 0); 19.478 return Adjugated() * (1.0f/det); 19.479 } 19.480 19.481 void Invert() 19.482 { 19.483 *this = Inverted(); 19.484 } 19.485 19.486 //AnnaSteve: 19.487 // a,b,c, are the YawPitchRoll angles to be returned 19.488 // rotation a around axis A1 19.489 // is followed by rotation b around axis A2 19.490 // is followed by rotation c around axis A3 19.491 // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.492 template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> 19.493 void ToEulerAngles(float *a, float *b, float *c) 19.494 { 19.495 OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); 19.496 19.497 float psign = -1.0f; 19.498 if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation 19.499 psign = 1.0f; 19.500 19.501 float pm = psign*M[A1][A3]; 19.502 if (pm < -1.0f + Math<float>::SingularityRadius) 19.503 { // South pole singularity 19.504 *a = 0.0f; 19.505 *b = -S*D*Math<float>::PiOver2; 19.506 *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); 19.507 } 19.508 else if (pm > 1.0 - Math<float>::SingularityRadius) 19.509 { // North pole singularity 19.510 *a = 0.0f; 19.511 *b = S*D*Math<float>::PiOver2; 19.512 *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); 19.513 } 19.514 else 19.515 { // Normal case (nonsingular) 19.516 *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] ); 19.517 *b = S*D*asin(pm); 19.518 *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] ); 19.519 } 19.520 19.521 return; 19.522 } 19.523 19.524 //AnnaSteve: 19.525 // a,b,c, are the YawPitchRoll angles to be returned 19.526 // rotation a around axis A1 19.527 // is followed by rotation b around axis A2 19.528 // is followed by rotation c around axis A1 19.529 // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.530 template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> 19.531 void ToEulerAnglesABA(float *a, float *b, float *c) 19.532 { 19.533 OVR_COMPILER_ASSERT(A1 != A2); 19.534 19.535 // Determine the axis that was not supplied 19.536 int m = 3 - A1 - A2; 19.537 19.538 float psign = -1.0f; 19.539 if ((A1 + 1) % 3 == A2) // Determine whether even permutation 19.540 psign = 1.0f; 19.541 19.542 float c2 = M[A1][A1]; 19.543 if (c2 < -1.0 + Math<float>::SingularityRadius) 19.544 { // South pole singularity 19.545 *a = 0.0f; 19.546 *b = S*D*Math<float>::Pi; 19.547 *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); 19.548 } 19.549 else if (c2 > 1.0 - Math<float>::SingularityRadius) 19.550 { // North pole singularity 19.551 *a = 0.0f; 19.552 *b = 0.0f; 19.553 *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); 19.554 } 19.555 else 19.556 { // Normal case (nonsingular) 19.557 *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]); 19.558 *b = S*D*acos(c2); 19.559 *c = S*D*atan2( M[A1][A2],psign*M[A1][m]); 19.560 } 19.561 return; 19.562 } 19.563 19.564 // Creates a matrix that converts the vertices from one coordinate system 19.565 // to another. 19.566 // 19.567 static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from) 19.568 { 19.569 // Holds axis values from the 'to' structure 19.570 int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis }; 19.571 19.572 // The inverse of the toArray 19.573 int inv[4]; 19.574 inv[0] = inv[abs(to.XAxis)] = 0; 19.575 inv[abs(to.YAxis)] = 1; 19.576 inv[abs(to.ZAxis)] = 2; 19.577 19.578 Matrix4f m(0, 0, 0, 19.579 0, 0, 0, 19.580 0, 0, 0); 19.581 19.582 // Only three values in the matrix need to be changed to 1 or -1. 19.583 m.M[inv[abs(from.XAxis)]][0] = float(from.XAxis/toArray[inv[abs(from.XAxis)]]); 19.584 m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]); 19.585 m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]); 19.586 return m; 19.587 } 19.588 19.589 19.590 19.591 static Matrix4f Translation(const Vector3f& v) 19.592 { 19.593 Matrix4f t; 19.594 t.M[0][3] = v.x; 19.595 t.M[1][3] = v.y; 19.596 t.M[2][3] = v.z; 19.597 return t; 19.598 } 19.599 19.600 static Matrix4f Translation(float x, float y, float z = 0.0f) 19.601 { 19.602 Matrix4f t; 19.603 t.M[0][3] = x; 19.604 t.M[1][3] = y; 19.605 t.M[2][3] = z; 19.606 return t; 19.607 } 19.608 19.609 static Matrix4f Scaling(const Vector3f& v) 19.610 { 19.611 Matrix4f t; 19.612 t.M[0][0] = v.x; 19.613 t.M[1][1] = v.y; 19.614 t.M[2][2] = v.z; 19.615 return t; 19.616 } 19.617 19.618 static Matrix4f Scaling(float x, float y, float z) 19.619 { 19.620 Matrix4f t; 19.621 t.M[0][0] = x; 19.622 t.M[1][1] = y; 19.623 t.M[2][2] = z; 19.624 return t; 19.625 } 19.626 19.627 static Matrix4f Scaling(float s) 19.628 { 19.629 Matrix4f t; 19.630 t.M[0][0] = s; 19.631 t.M[1][1] = s; 19.632 t.M[2][2] = s; 19.633 return t; 19.634 } 19.635 19.636 19.637 19.638 //AnnaSteve : Just for quick testing. Not for final API. Need to remove case. 19.639 static Matrix4f RotationAxis(Axis A, float angle, RotateDirection d, HandedSystem s) 19.640 { 19.641 float sina = s * d *sin(angle); 19.642 float cosa = cos(angle); 19.643 19.644 switch(A) 19.645 { 19.646 case Axis_X: 19.647 return Matrix4f(1, 0, 0, 19.648 0, cosa, -sina, 19.649 0, sina, cosa); 19.650 case Axis_Y: 19.651 return Matrix4f(cosa, 0, sina, 19.652 0, 1, 0, 19.653 -sina, 0, cosa); 19.654 case Axis_Z: 19.655 return Matrix4f(cosa, -sina, 0, 19.656 sina, cosa, 0, 19.657 0, 0, 1); 19.658 } 19.659 } 19.660 19.661 19.662 // Creates a rotation matrix rotating around the X axis by 'angle' radians. 19.663 // Rotation direction is depends on the coordinate system: 19.664 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.665 // while looking in the negative axis direction. This is the 19.666 // same as looking down from positive axis values towards origin. 19.667 // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.668 // negative axis direction. 19.669 static Matrix4f RotationX(float angle) 19.670 { 19.671 float sina = sin(angle); 19.672 float cosa = cos(angle); 19.673 return Matrix4f(1, 0, 0, 19.674 0, cosa, -sina, 19.675 0, sina, cosa); 19.676 } 19.677 19.678 // Creates a rotation matrix rotating around the Y axis by 'angle' radians. 19.679 // Rotation direction is depends on the coordinate system: 19.680 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.681 // while looking in the negative axis direction. This is the 19.682 // same as looking down from positive axis values towards origin. 19.683 // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.684 // negative axis direction. 19.685 static Matrix4f RotationY(float angle) 19.686 { 19.687 float sina = sin(angle); 19.688 float cosa = cos(angle); 19.689 return Matrix4f(cosa, 0, sina, 19.690 0, 1, 0, 19.691 -sina, 0, cosa); 19.692 } 19.693 19.694 // Creates a rotation matrix rotating around the Z axis by 'angle' radians. 19.695 // Rotation direction is depends on the coordinate system: 19.696 // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.697 // while looking in the negative axis direction. This is the 19.698 // same as looking down from positive axis values towards origin. 19.699 // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.700 // negative axis direction. 19.701 static Matrix4f RotationZ(float angle) 19.702 { 19.703 float sina = sin(angle); 19.704 float cosa = cos(angle); 19.705 return Matrix4f(cosa, -sina, 0, 19.706 sina, cosa, 0, 19.707 0, 0, 1); 19.708 } 19.709 19.710 19.711 // LookAtRH creates a View transformation matrix for right-handed coordinate system. 19.712 // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' 19.713 // specifying the up vector. The resulting matrix should be used with PerspectiveRH 19.714 // projection. 19.715 static Matrix4f LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up); 19.716 19.717 // LookAtLH creates a View transformation matrix for left-handed coordinate system. 19.718 // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' 19.719 // specifying the up vector. 19.720 static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up); 19.721 19.722 19.723 // PerspectiveRH creates a right-handed perspective projection matrix that can be 19.724 // used with the Oculus sample renderer. 19.725 // yfov - Specifies vertical field of view in radians. 19.726 // aspect - Screen aspect ration, which is usually width/height for square pixels. 19.727 // Note that xfov = yfov * aspect. 19.728 // znear - Absolute value of near Z clipping clipping range. 19.729 // zfar - Absolute value of far Z clipping clipping range (larger then near). 19.730 // Even though RHS usually looks in the direction of negative Z, positive values 19.731 // are expected for znear and zfar. 19.732 static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar); 19.733 19.734 19.735 // PerspectiveRH creates a left-handed perspective projection matrix that can be 19.736 // used with the Oculus sample renderer. 19.737 // yfov - Specifies vertical field of view in radians. 19.738 // aspect - Screen aspect ration, which is usually width/height for square pixels. 19.739 // Note that xfov = yfov * aspect. 19.740 // znear - Absolute value of near Z clipping clipping range. 19.741 // zfar - Absolute value of far Z clipping clipping range (larger then near). 19.742 static Matrix4f PerspectiveLH(float yfov, float aspect, float znear, float zfar); 19.743 19.744 19.745 static Matrix4f Ortho2D(float w, float h); 19.746 }; 19.747 19.748 19.749 //------------------------------------------------------------------------------------- 19.750 // ***** Quat 19.751 19.752 // Quatf represents a quaternion class used for rotations. 19.753 // 19.754 // Quaternion multiplications are done in right-to-left order, to match the 19.755 // behavior of matrices. 19.756 19.757 19.758 template<class T> 19.759 class Quat 19.760 { 19.761 public: 19.762 // w + Xi + Yj + Zk 19.763 T x, y, z, w; 19.764 19.765 Quat() : x(0), y(0), z(0), w(1) {} 19.766 Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {} 19.767 19.768 19.769 // Constructs rotation quaternion around the axis. 19.770 Quat(const Vector3<T>& axis, T angle) 19.771 { 19.772 Vector3<T> unitAxis = axis.Normalized(); 19.773 T sinHalfAngle = sin(angle * T(0.5)); 19.774 19.775 w = cos(angle * T(0.5)); 19.776 x = unitAxis.x * sinHalfAngle; 19.777 y = unitAxis.y * sinHalfAngle; 19.778 z = unitAxis.z * sinHalfAngle; 19.779 } 19.780 19.781 //AnnaSteve: 19.782 void AxisAngle(Axis A, T angle, RotateDirection d, HandedSystem s) 19.783 { 19.784 T sinHalfAngle = s * d *sin(angle * (T)0.5); 19.785 T v[3]; 19.786 v[0] = v[1] = v[2] = (T)0; 19.787 v[A] = sinHalfAngle; 19.788 //return Quat(v[0], v[1], v[2], cos(angle * (T)0.5)); 19.789 w = cos(angle * (T)0.5); 19.790 x = v[0]; 19.791 y = v[1]; 19.792 z = v[2]; 19.793 } 19.794 19.795 19.796 void GetAxisAngle(Vector3<T>* axis, T* angle) const 19.797 { 19.798 if (LengthSq() > Math<T>::Tolerance * Math<T>::Tolerance) 19.799 { 19.800 *axis = Vector3<T>(x, y, z).Normalized(); 19.801 *angle = 2 * acos(w); 19.802 } 19.803 else 19.804 { 19.805 *axis = Vector3<T>(1, 0, 0); 19.806 *angle= 0; 19.807 } 19.808 } 19.809 19.810 bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } 19.811 bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } 19.812 19.813 Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); } 19.814 Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; } 19.815 Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); } 19.816 Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; } 19.817 19.818 Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); } 19.819 Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; } 19.820 Quat operator/ (T s) const { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); } 19.821 Quat& operator/= (T s) { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; } 19.822 19.823 // Get Imaginary part vector 19.824 Vector3<T> Imag() const { return Vector3<T>(x,y,z); } 19.825 19.826 // Get quaternion length. 19.827 T Length() const { return sqrt(x * x + y * y + z * z + w * w); } 19.828 // Get quaternion length squared. 19.829 T LengthSq() const { return (x * x + y * y + z * z + w * w); } 19.830 // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure) 19.831 T Distance(const Quat& q) const 19.832 { 19.833 T d1 = (*this - q).Length(); 19.834 T d2 = (*this + q).Length(); // Antipoldal point check 19.835 return (d1 < d2) ? d1 : d2; 19.836 } 19.837 T DistanceSq(const Quat& q) const 19.838 { 19.839 T d1 = (*this - q).LengthSq(); 19.840 T d2 = (*this + q).LengthSq(); // Antipoldal point check 19.841 return (d1 < d2) ? d1 : d2; 19.842 } 19.843 19.844 // Normalize 19.845 bool IsNormalized() const { return fabs(LengthSq() - 1) < Math<T>::Tolerance; } 19.846 void Normalize() { *this /= Length(); } 19.847 Quat Normalized() const { return *this / Length(); } 19.848 19.849 // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized. 19.850 Quat Conj() const { return Quat(-x, -y, -z, w); } 19.851 19.852 // AnnaSteve fixed: order of quaternion multiplication 19.853 // Quaternion multiplication. Combines quaternion rotations, performing the one on the 19.854 // right hand side first. 19.855 Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y, 19.856 w * b.y - x * b.z + y * b.w + z * b.x, 19.857 w * b.z + x * b.y - y * b.x + z * b.w, 19.858 w * b.w - x * b.x - y * b.y - z * b.z); } 19.859 19.860 // 19.861 // this^p normalized; same as rotating by this p times. 19.862 Quat PowNormalized(T p) const 19.863 { 19.864 Vector3<T> v; 19.865 T a; 19.866 GetAxisAngle(&v, &a); 19.867 return Quat(v, a * p); 19.868 } 19.869 19.870 // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise, 19.871 // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 19.872 Vector3<T> Rotate(const Vector3<T>& v) const 19.873 { 19.874 return ((*this * Quat<T>(v.x, v.y, v.z, 0)) * Inverted()).Imag(); 19.875 } 19.876 19.877 19.878 // Inversed quaternion rotates in the opposite direction. 19.879 Quat Inverted() const 19.880 { 19.881 return Quat(-x, -y, -z, w); 19.882 } 19.883 19.884 // Sets this quaternion to the one rotates in the opposite direction. 19.885 void Invert() 19.886 { 19.887 *this = Quat(-x, -y, -z, w); 19.888 } 19.889 19.890 // Converting quaternion to matrix. 19.891 operator Matrix4f() const 19.892 { 19.893 T ww = w*w; 19.894 T xx = x*x; 19.895 T yy = y*y; 19.896 T zz = z*z; 19.897 19.898 return Matrix4f(float(ww + xx - yy - zz), float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)), 19.899 float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz), float(T(2) * (y*z - w*x)), 19.900 float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) ); 19.901 } 19.902 19.903 19.904 // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of 19.905 // axis rotations and the specified coordinate system. Right-handed coordinate system 19.906 // is the default, with CCW rotations while looking in the negative axis direction. 19.907 // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. 19.908 // rotation a around axis A1 19.909 // is followed by rotation b around axis A2 19.910 // is followed by rotation c around axis A3 19.911 // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.912 template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> 19.913 void GetEulerAngles(T *a, T *b, T *c) 19.914 { 19.915 OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); 19.916 19.917 T Q[3] = { x, y, z }; //Quaternion components x,y,z 19.918 19.919 T ww = w*w; 19.920 T Q11 = Q[A1]*Q[A1]; 19.921 T Q22 = Q[A2]*Q[A2]; 19.922 T Q33 = Q[A3]*Q[A3]; 19.923 19.924 T psign = T(-1.0); 19.925 // Determine whether even permutation 19.926 if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) 19.927 psign = T(1.0); 19.928 19.929 T s2 = psign * T(2.0) * (psign*w*Q[A2] + Q[A1]*Q[A3]); 19.930 19.931 if (s2 < (T)-1.0 + Math<T>::SingularityRadius) 19.932 { // South pole singularity 19.933 *a = T(0.0); 19.934 *b = -S*D*Math<T>::PiOver2; 19.935 *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), 19.936 ww + Q22 - Q11 - Q33 ); 19.937 } 19.938 else if (s2 > (T)1.0 - Math<T>::SingularityRadius) 19.939 { // North pole singularity 19.940 *a = (T)0.0; 19.941 *b = S*D*Math<T>::PiOver2; 19.942 *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), 19.943 ww + Q22 - Q11 - Q33); 19.944 } 19.945 else 19.946 { 19.947 *a = -S*D*atan2((T)-2.0*(w*Q[A1] - psign*Q[A2]*Q[A3]), 19.948 ww + Q33 - Q11 - Q22); 19.949 *b = S*D*asin(s2); 19.950 *c = S*D*atan2((T)2.0*(w*Q[A3] - psign*Q[A1]*Q[A2]), 19.951 ww + Q11 - Q22 - Q33); 19.952 } 19.953 return; 19.954 } 19.955 19.956 template <Axis A1, Axis A2, Axis A3, RotateDirection D> 19.957 void GetEulerAngles(T *a, T *b, T *c) 19.958 { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); } 19.959 19.960 template <Axis A1, Axis A2, Axis A3> 19.961 void GetEulerAngles(T *a, T *b, T *c) 19.962 { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); } 19.963 19.964 19.965 // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of 19.966 // axis rotations and the specified coordinate system. Right-handed coordinate system 19.967 // is the default, with CCW rotations while looking in the negative axis direction. 19.968 // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. 19.969 // rotation a around axis A1 19.970 // is followed by rotation b around axis A2 19.971 // is followed by rotation c around axis A1 19.972 // Rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.973 template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> 19.974 void GetEulerAnglesABA(T *a, T *b, T *c) 19.975 { 19.976 OVR_COMPILER_ASSERT(A1 != A2); 19.977 19.978 T Q[3] = {x, y, z}; // Quaternion components 19.979 19.980 // Determine the missing axis that was not supplied 19.981 int m = 3 - A1 - A2; 19.982 19.983 T ww = w*w; 19.984 T Q11 = Q[A1]*Q[A1]; 19.985 T Q22 = Q[A2]*Q[A2]; 19.986 T Qmm = Q[m]*Q[m]; 19.987 19.988 T psign = T(-1.0); 19.989 if ((A1 + 1) % 3 == A2) // Determine whether even permutation 19.990 { 19.991 psign = (T)1.0; 19.992 } 19.993 19.994 T c2 = ww + Q11 - Q22 - Qmm; 19.995 if (c2 < (T)-1.0 + Math<T>::SingularityRadius) 19.996 { // South pole singularity 19.997 *a = (T)0.0; 19.998 *b = S*D*Math<T>::Pi; 19.999 *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), 19.1000 ww + Q22 - Q11 - Qmm); 19.1001 } 19.1002 else if (c2 > (T)1.0 - Math<T>::SingularityRadius) 19.1003 { // North pole singularity 19.1004 *a = (T)0.0; 19.1005 *b = (T)0.0; 19.1006 *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), 19.1007 ww + Q22 - Q11 - Qmm); 19.1008 } 19.1009 else 19.1010 { 19.1011 *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2], 19.1012 w*Q[A2] -psign*Q[A1]*Q[m]); 19.1013 *b = S*D*acos(c2); 19.1014 *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2], 19.1015 w*Q[A2] + psign*Q[A1]*Q[m]); 19.1016 } 19.1017 return; 19.1018 } 19.1019 }; 19.1020 19.1021 19.1022 typedef Quat<float> Quatf; 19.1023 typedef Quat<double> Quatd; 19.1024 19.1025 19.1026 19.1027 //------------------------------------------------------------------------------------- 19.1028 // ***** Angle 19.1029 19.1030 // Cleanly representing the algebra of 2D rotations. 19.1031 // The operations maintain the angle between -Pi and Pi, the same range as atan2. 19.1032 // 19.1033 19.1034 template<class T> 19.1035 class Angle 19.1036 { 19.1037 public: 19.1038 enum AngularUnits 19.1039 { 19.1040 Radians = 0, 19.1041 Degrees = 1 19.1042 }; 19.1043 19.1044 Angle() : a(0) {} 19.1045 19.1046 // Fix the range to be between -Pi and Pi 19.1047 Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); } 19.1048 19.1049 T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; } 19.1050 void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); } 19.1051 int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } 19.1052 T Abs() const { return (a > 0) ? a : -a; } 19.1053 19.1054 bool operator== (const Angle& b) const { return a == b.a; } 19.1055 bool operator!= (const Angle& b) const { return a != b.a; } 19.1056 // bool operator< (const Angle& b) const { return a < a.b; } 19.1057 // bool operator> (const Angle& b) const { return a > a.b; } 19.1058 // bool operator<= (const Angle& b) const { return a <= a.b; } 19.1059 // bool operator>= (const Angle& b) const { return a >= a.b; } 19.1060 // bool operator= (const T& x) { a = x; FixRange(); } 19.1061 19.1062 // These operations assume a is already between -Pi and Pi. 19.1063 Angle operator+ (const Angle& b) const { return Angle(a + b.a); } 19.1064 Angle operator+ (const T& x) const { return Angle(a + x); } 19.1065 Angle& operator+= (const Angle& b) { a = a + b.a; FastFixRange(); return *this; } 19.1066 Angle& operator+= (const T& x) { a = a + x; FixRange(); return *this; } 19.1067 Angle operator- (const Angle& b) const { return Angle(a - b.a); } 19.1068 Angle operator- (const T& x) const { return Angle(a - x); } 19.1069 Angle& operator-= (const Angle& b) { a = a - b.a; FastFixRange(); return *this; } 19.1070 Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; } 19.1071 19.1072 T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; } 19.1073 19.1074 private: 19.1075 19.1076 // The stored angle, which should be maintained between -Pi and Pi 19.1077 T a; 19.1078 19.1079 // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 19.1080 inline void FastFixRange() 19.1081 { 19.1082 if (a < -Math<T>::Pi) 19.1083 a += Math<T>::TwoPi; 19.1084 else if (a > Math<T>::Pi) 19.1085 a -= Math<T>::TwoPi; 19.1086 } 19.1087 19.1088 // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method 19.1089 inline void FixRange() 19.1090 { 19.1091 a = fmod(a,Math<T>::TwoPi); 19.1092 if (a < -Math<T>::Pi) 19.1093 a += Math<T>::TwoPi; 19.1094 else if (a > Math<T>::Pi) 19.1095 a -= Math<T>::TwoPi; 19.1096 } 19.1097 }; 19.1098 19.1099 19.1100 typedef Angle<float> Anglef; 19.1101 typedef Angle<double> Angled; 19.1102 19.1103 19.1104 //------------------------------------------------------------------------------------- 19.1105 // ***** Plane 19.1106 19.1107 // Consists of a normal vector and distance from the origin where the plane is located. 19.1108 19.1109 template<class T> 19.1110 class Plane : public RefCountBase<Plane<T> > 19.1111 { 19.1112 public: 19.1113 Vector3<T> N; 19.1114 T D; 19.1115 19.1116 Plane() : D(0) {} 19.1117 19.1118 // Normals must already be normalized 19.1119 Plane(const Vector3<T>& n, T d) : N(n), D(d) {} 19.1120 Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {} 19.1121 19.1122 // construct from a point on the plane and the normal 19.1123 Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {} 19.1124 19.1125 // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane). 19.1126 T TestSide(const Vector3<T>& p) const 19.1127 { 19.1128 return (N * p) + D; 19.1129 } 19.1130 19.1131 Plane<T> Flipped() const 19.1132 { 19.1133 return Plane(-N, -D); 19.1134 } 19.1135 19.1136 void Flip() 19.1137 { 19.1138 N = -N; 19.1139 D = -D; 19.1140 } 19.1141 19.1142 bool operator==(const Plane<T>& rhs) const 19.1143 { 19.1144 return (this->D == rhs.D && this->N == rhs.N); 19.1145 } 19.1146 }; 19.1147 19.1148 typedef Plane<float> Planef; 19.1149 19.1150 } 19.1151 19.1152 #endif 19.1153 \ No newline at end of file 19.1154 +/************************************************************************************ 19.1155 + 19.1156 +PublicHeader: OVR.h 19.1157 +Filename : OVR_Math.h 19.1158 +Content : Implementation of 3D primitives such as vectors, matrices. 19.1159 +Created : September 4, 2012 19.1160 +Authors : Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova 19.1161 + 19.1162 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 19.1163 + 19.1164 +Use of this software is subject to the terms of the Oculus license 19.1165 +agreement provided at the time of installation or download, or which 19.1166 +otherwise accompanies this software in either electronic or hard copy form. 19.1167 + 19.1168 +*************************************************************************************/ 19.1169 + 19.1170 +#ifndef OVR_Math_h 19.1171 +#define OVR_Math_h 19.1172 + 19.1173 +#include <assert.h> 19.1174 +#include <stdlib.h> 19.1175 +#include <math.h> 19.1176 + 19.1177 +#include "OVR_Types.h" 19.1178 +#include "OVR_RefCount.h" 19.1179 + 19.1180 +namespace OVR { 19.1181 + 19.1182 +//------------------------------------------------------------------------------------- 19.1183 +// Constants for 3D world/axis definitions. 19.1184 + 19.1185 +// Definitions of axes for coordinate and rotation conversions. 19.1186 +enum Axis 19.1187 +{ 19.1188 + Axis_X = 0, Axis_Y = 1, Axis_Z = 2 19.1189 +}; 19.1190 + 19.1191 +// RotateDirection describes the rotation direction around an axis, interpreted as follows: 19.1192 +// CW - Clockwise while looking "down" from positive axis towards the origin. 19.1193 +// CCW - Counter-clockwise while looking from the positive axis towards the origin, 19.1194 +// which is in the negative axis direction. 19.1195 +// CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate 19.1196 +// system defines Y up, X right, and Z back (pointing out from the screen). In this 19.1197 +// system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane. 19.1198 +enum RotateDirection 19.1199 +{ 19.1200 + Rotate_CCW = 1, 19.1201 + Rotate_CW = -1 19.1202 +}; 19.1203 + 19.1204 +enum HandedSystem 19.1205 +{ 19.1206 + Handed_R = 1, Handed_L = -1 19.1207 +}; 19.1208 + 19.1209 +// AxisDirection describes which way the axis points. Used by WorldAxes. 19.1210 +enum AxisDirection 19.1211 +{ 19.1212 + Axis_Up = 2, 19.1213 + Axis_Down = -2, 19.1214 + Axis_Right = 1, 19.1215 + Axis_Left = -1, 19.1216 + Axis_In = 3, 19.1217 + Axis_Out = -3 19.1218 +}; 19.1219 + 19.1220 +struct WorldAxes 19.1221 +{ 19.1222 + AxisDirection XAxis, YAxis, ZAxis; 19.1223 + 19.1224 + WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z) 19.1225 + : XAxis(x), YAxis(y), ZAxis(z) 19.1226 + { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));} 19.1227 +}; 19.1228 + 19.1229 + 19.1230 +//------------------------------------------------------------------------------------- 19.1231 +// ***** Math 19.1232 + 19.1233 +// Math class contains constants and functions. This class is a template specialized 19.1234 +// per type, with Math<float> and Math<double> being distinct. 19.1235 +template<class Type> 19.1236 +class Math 19.1237 +{ 19.1238 +}; 19.1239 + 19.1240 +// Single-precision Math constants class. 19.1241 +template<> 19.1242 +class Math<float> 19.1243 +{ 19.1244 +public: 19.1245 + static const float Pi; 19.1246 + static const float TwoPi; 19.1247 + static const float PiOver2; 19.1248 + static const float PiOver4; 19.1249 + static const float E; 19.1250 + 19.1251 + static const float MaxValue; // Largest positive float Value 19.1252 + static const float MinPositiveValue; // Smallest possible positive value 19.1253 + 19.1254 + static const float RadToDegreeFactor; 19.1255 + static const float DegreeToRadFactor; 19.1256 + 19.1257 + static const float Tolerance; // 0.00001f; 19.1258 + static const float SingularityRadius; //0.00000000001f for Gimbal lock numerical problems 19.1259 +}; 19.1260 + 19.1261 +// Double-precision Math constants class. 19.1262 +template<> 19.1263 +class Math<double> 19.1264 +{ 19.1265 +public: 19.1266 + static const double Pi; 19.1267 + static const double TwoPi; 19.1268 + static const double PiOver2; 19.1269 + static const double PiOver4; 19.1270 + static const double E; 19.1271 + 19.1272 + static const double MaxValue; // Largest positive double Value 19.1273 + static const double MinPositiveValue; // Smallest possible positive value 19.1274 + 19.1275 + static const double RadToDegreeFactor; 19.1276 + static const double DegreeToRadFactor; 19.1277 + 19.1278 + static const double Tolerance; // 0.00001f; 19.1279 + static const double SingularityRadius; //0.00000000001 for Gimbal lock numerical problems 19.1280 +}; 19.1281 + 19.1282 +typedef Math<float> Mathf; 19.1283 +typedef Math<double> Mathd; 19.1284 + 19.1285 +// Conversion functions between degrees and radians 19.1286 +template<class FT> 19.1287 +FT RadToDegree(FT rads) { return rads * Math<FT>::RadToDegreeFactor; } 19.1288 +template<class FT> 19.1289 +FT DegreeToRad(FT rads) { return rads * Math<FT>::DegreeToRadFactor; } 19.1290 + 19.1291 +template<class T> 19.1292 +class Quat; 19.1293 + 19.1294 +//------------------------------------------------------------------------------------- 19.1295 +// ***** Vector2f - 2D Vector2f 19.1296 + 19.1297 +// Vector2f represents a 2-dimensional vector or point in space, 19.1298 +// consisting of coordinates x and y, 19.1299 + 19.1300 +template<class T> 19.1301 +class Vector2 19.1302 +{ 19.1303 +public: 19.1304 + T x, y; 19.1305 + 19.1306 + Vector2() : x(0), y(0) { } 19.1307 + Vector2(T x_, T y_) : x(x_), y(y_) { } 19.1308 + explicit Vector2(T s) : x(s), y(s) { } 19.1309 + 19.1310 + bool operator== (const Vector2& b) const { return x == b.x && y == b.y; } 19.1311 + bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; } 19.1312 + 19.1313 + Vector2 operator+ (const Vector2& b) const { return Vector2(x + b.x, y + b.y); } 19.1314 + Vector2& operator+= (const Vector2& b) { x += b.x; y += b.y; return *this; } 19.1315 + Vector2 operator- (const Vector2& b) const { return Vector2(x - b.x, y - b.y); } 19.1316 + Vector2& operator-= (const Vector2& b) { x -= b.x; y -= b.y; return *this; } 19.1317 + Vector2 operator- () const { return Vector2(-x, -y); } 19.1318 + 19.1319 + // Scalar multiplication/division scales vector. 19.1320 + Vector2 operator* (T s) const { return Vector2(x*s, y*s); } 19.1321 + Vector2& operator*= (T s) { x *= s; y *= s; return *this; } 19.1322 + 19.1323 + Vector2 operator/ (T s) const { T rcp = T(1)/s; 19.1324 + return Vector2(x*rcp, y*rcp); } 19.1325 + Vector2& operator/= (T s) { T rcp = T(1)/s; 19.1326 + x *= rcp; y *= rcp; 19.1327 + return *this; } 19.1328 + 19.1329 + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. 19.1330 + bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) 19.1331 + { 19.1332 + return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); 19.1333 + } 19.1334 + 19.1335 + // Dot product overload. 19.1336 + // Used to calculate angle q between two vectors among other things, 19.1337 + // as (A dot B) = |a||b|cos(q). 19.1338 + T operator* (const Vector2& b) const { return x*b.x + y*b.y; } 19.1339 + 19.1340 + // Returns the angle from this vector to b, in radians. 19.1341 + T Angle(const Vector2& b) const { return acos((*this * b)/(Length()*b.Length())); } 19.1342 + 19.1343 + // Return Length of the vector squared. 19.1344 + T LengthSq() const { return (x * x + y * y); } 19.1345 + // Return vector length. 19.1346 + T Length() const { return sqrt(LengthSq()); } 19.1347 + 19.1348 + // Returns distance between two points represented by vectors. 19.1349 + T Distance(Vector2& b) const { return (*this - b).Length(); } 19.1350 + 19.1351 + // Determine if this a unit vector. 19.1352 + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } 19.1353 + // Normalize, convention vector length to 1. 19.1354 + void Normalize() { *this /= Length(); } 19.1355 + // Returns normalized (unit) version of the vector without modifying itself. 19.1356 + Vector2 Normalized() const { return *this / Length(); } 19.1357 + 19.1358 + // Linearly interpolates from this vector to another. 19.1359 + // Factor should be between 0.0 and 1.0, with 0 giving full value to this. 19.1360 + Vector2 Lerp(const Vector2& b, T f) const { return *this*(T(1) - f) + b*f; } 19.1361 + 19.1362 + // Projects this vector onto the argument; in other words, 19.1363 + // A.Project(B) returns projection of vector A onto B. 19.1364 + Vector2 ProjectTo(const Vector2& b) const { return b * ((*this * b) / b.LengthSq()); } 19.1365 +}; 19.1366 + 19.1367 + 19.1368 +typedef Vector2<float> Vector2f; 19.1369 +typedef Vector2<double> Vector2d; 19.1370 + 19.1371 +//------------------------------------------------------------------------------------- 19.1372 +// ***** Vector3f - 3D Vector3f 19.1373 + 19.1374 +// Vector3f represents a 3-dimensional vector or point in space, 19.1375 +// consisting of coordinates x, y and z. 19.1376 + 19.1377 +template<class T> 19.1378 +class Vector3 19.1379 +{ 19.1380 +public: 19.1381 + T x, y, z; 19.1382 + 19.1383 + Vector3() : x(0), y(0), z(0) { } 19.1384 + Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { } 19.1385 + explicit Vector3(T s) : x(s), y(s), z(s) { } 19.1386 + 19.1387 + bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; } 19.1388 + bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; } 19.1389 + 19.1390 + Vector3 operator+ (const Vector3& b) const { return Vector3(x + b.x, y + b.y, z + b.z); } 19.1391 + Vector3& operator+= (const Vector3& b) { x += b.x; y += b.y; z += b.z; return *this; } 19.1392 + Vector3 operator- (const Vector3& b) const { return Vector3(x - b.x, y - b.y, z - b.z); } 19.1393 + Vector3& operator-= (const Vector3& b) { x -= b.x; y -= b.y; z -= b.z; return *this; } 19.1394 + Vector3 operator- () const { return Vector3(-x, -y, -z); } 19.1395 + 19.1396 + // Scalar multiplication/division scales vector. 19.1397 + Vector3 operator* (T s) const { return Vector3(x*s, y*s, z*s); } 19.1398 + Vector3& operator*= (T s) { x *= s; y *= s; z *= s; return *this; } 19.1399 + 19.1400 + Vector3 operator/ (T s) const { T rcp = T(1)/s; 19.1401 + return Vector3(x*rcp, y*rcp, z*rcp); } 19.1402 + Vector3& operator/= (T s) { T rcp = T(1)/s; 19.1403 + x *= rcp; y *= rcp; z *= rcp; 19.1404 + return *this; } 19.1405 + 19.1406 + // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. 19.1407 + bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) 19.1408 + { 19.1409 + return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance); 19.1410 + } 19.1411 + 19.1412 + // Dot product overload. 19.1413 + // Used to calculate angle q between two vectors among other things, 19.1414 + // as (A dot B) = |a||b|cos(q). 19.1415 + T operator* (const Vector3& b) const { return x*b.x + y*b.y + z*b.z; } 19.1416 + 19.1417 + // Compute cross product, which generates a normal vector. 19.1418 + // Direction vector can be determined by right-hand rule: Pointing index finder in 19.1419 + // direction a and middle finger in direction b, thumb will point in a.Cross(b). 19.1420 + Vector3 Cross(const Vector3& b) const { return Vector3(y*b.z - z*b.y, 19.1421 + z*b.x - x*b.z, 19.1422 + x*b.y - y*b.x); } 19.1423 + 19.1424 + // Returns the angle from this vector to b, in radians. 19.1425 + T Angle(const Vector3& b) const { return acos((*this * b)/(Length()*b.Length())); } 19.1426 + 19.1427 + // Return Length of the vector squared. 19.1428 + T LengthSq() const { return (x * x + y * y + z * z); } 19.1429 + // Return vector length. 19.1430 + T Length() const { return sqrt(LengthSq()); } 19.1431 + 19.1432 + // Returns distance between two points represented by vectors. 19.1433 + T Distance(Vector3& b) const { return (*this - b).Length(); } 19.1434 + 19.1435 + // Determine if this a unit vector. 19.1436 + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } 19.1437 + // Normalize, convention vector length to 1. 19.1438 + void Normalize() { *this /= Length(); } 19.1439 + // Returns normalized (unit) version of the vector without modifying itself. 19.1440 + Vector3 Normalized() const { return *this / Length(); } 19.1441 + 19.1442 + // Linearly interpolates from this vector to another. 19.1443 + // Factor should be between 0.0 and 1.0, with 0 giving full value to this. 19.1444 + Vector3 Lerp(const Vector3& b, T f) const { return *this*(T(1) - f) + b*f; } 19.1445 + 19.1446 + // Projects this vector onto the argument; in other words, 19.1447 + // A.Project(B) returns projection of vector A onto B. 19.1448 + Vector3 ProjectTo(const Vector3& b) const { return b * ((*this * b) / b.LengthSq()); } 19.1449 +}; 19.1450 + 19.1451 + 19.1452 +typedef Vector3<float> Vector3f; 19.1453 +typedef Vector3<double> Vector3d; 19.1454 + 19.1455 + 19.1456 +//------------------------------------------------------------------------------------- 19.1457 +// ***** Matrix4f 19.1458 + 19.1459 +// Matrix4f is a 4x4 matrix used for 3d transformations and projections. 19.1460 +// Translation stored in the last column. 19.1461 +// The matrix is stored in row-major order in memory, meaning that values 19.1462 +// of the first row are stored before the next one. 19.1463 +// 19.1464 +// The arrangement of the matrix is chosen to be in Right-Handed 19.1465 +// coordinate system and counterclockwise rotations when looking down 19.1466 +// the axis 19.1467 +// 19.1468 +// Transformation Order: 19.1469 +// - Transformations are applied from right to left, so the expression 19.1470 +// M1 * M2 * M3 * V means that the vector V is transformed by M3 first, 19.1471 +// followed by M2 and M1. 19.1472 +// 19.1473 +// Coordinate system: Right Handed 19.1474 +// 19.1475 +// Rotations: Counterclockwise when looking down the axis. All angles are in radians. 19.1476 +// 19.1477 +// | sx 01 02 tx | // First column (sx, 10, 20): Axis X basis vector. 19.1478 +// | 10 sy 12 ty | // Second column (01, sy, 21): Axis Y basis vector. 19.1479 +// | 20 21 sz tz | // Third columnt (02, 12, sz): Axis Z basis vector. 19.1480 +// | 30 31 32 33 | 19.1481 +// 19.1482 +// The basis vectors are first three columns. 19.1483 + 19.1484 +class Matrix4f 19.1485 +{ 19.1486 + static Matrix4f IdentityValue; 19.1487 + 19.1488 +public: 19.1489 + float M[4][4]; 19.1490 + 19.1491 + enum NoInitType { NoInit }; 19.1492 + 19.1493 + // Construct with no memory initialization. 19.1494 + Matrix4f(NoInitType) { } 19.1495 + 19.1496 + // By default, we construct identity matrix. 19.1497 + Matrix4f() 19.1498 + { 19.1499 + SetIdentity(); 19.1500 + } 19.1501 + 19.1502 + Matrix4f(float m11, float m12, float m13, float m14, 19.1503 + float m21, float m22, float m23, float m24, 19.1504 + float m31, float m32, float m33, float m34, 19.1505 + float m41, float m42, float m43, float m44) 19.1506 + { 19.1507 + M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14; 19.1508 + M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24; 19.1509 + M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34; 19.1510 + M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44; 19.1511 + } 19.1512 + 19.1513 + Matrix4f(float m11, float m12, float m13, 19.1514 + float m21, float m22, float m23, 19.1515 + float m31, float m32, float m33) 19.1516 + { 19.1517 + M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0; 19.1518 + M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0; 19.1519 + M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0; 19.1520 + M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1; 19.1521 + } 19.1522 + 19.1523 + static const Matrix4f& Identity() { return IdentityValue; } 19.1524 + 19.1525 + void SetIdentity() 19.1526 + { 19.1527 + M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1; 19.1528 + M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0; 19.1529 + M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0; 19.1530 + M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0; 19.1531 + } 19.1532 + 19.1533 + // Multiplies two matrices into destination with minimum copying. 19.1534 + static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b) 19.1535 + { 19.1536 + OVR_ASSERT((d != &a) && (d != &b)); 19.1537 + int i = 0; 19.1538 + do { 19.1539 + d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0]; 19.1540 + d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1]; 19.1541 + d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2]; 19.1542 + d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3]; 19.1543 + } while((++i) < 4); 19.1544 + 19.1545 + return *d; 19.1546 + } 19.1547 + 19.1548 + Matrix4f operator* (const Matrix4f& b) const 19.1549 + { 19.1550 + Matrix4f result(Matrix4f::NoInit); 19.1551 + Multiply(&result, *this, b); 19.1552 + return result; 19.1553 + } 19.1554 + 19.1555 + Matrix4f& operator*= (const Matrix4f& b) 19.1556 + { 19.1557 + return Multiply(this, Matrix4f(*this), b); 19.1558 + } 19.1559 + 19.1560 + Matrix4f operator* (float s) const 19.1561 + { 19.1562 + return Matrix4f(M[0][0] * s, M[0][1] * s, M[0][2] * s, M[0][3] * s, 19.1563 + M[1][0] * s, M[1][1] * s, M[1][2] * s, M[1][3] * s, 19.1564 + M[2][0] * s, M[2][1] * s, M[2][2] * s, M[2][3] * s, 19.1565 + M[3][0] * s, M[3][1] * s, M[3][2] * s, M[3][3] * s); 19.1566 + } 19.1567 + 19.1568 + Matrix4f& operator*= (float s) 19.1569 + { 19.1570 + M[0][0] *= s; M[0][1] *= s; M[0][2] *= s; M[0][3] *= s; 19.1571 + M[1][0] *= s; M[1][1] *= s; M[1][2] *= s; M[1][3] *= s; 19.1572 + M[2][0] *= s; M[2][1] *= s; M[2][2] *= s; M[2][3] *= s; 19.1573 + M[3][0] *= s; M[3][1] *= s; M[3][2] *= s; M[3][3] *= s; 19.1574 + return *this; 19.1575 + } 19.1576 + 19.1577 + Vector3f Transform(const Vector3f& v) const 19.1578 + { 19.1579 + return Vector3f(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3], 19.1580 + M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3], 19.1581 + M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]); 19.1582 + } 19.1583 + 19.1584 + Matrix4f Transposed() const 19.1585 + { 19.1586 + return Matrix4f(M[0][0], M[1][0], M[2][0], M[3][0], 19.1587 + M[0][1], M[1][1], M[2][1], M[3][1], 19.1588 + M[0][2], M[1][2], M[2][2], M[3][2], 19.1589 + M[0][3], M[1][3], M[2][3], M[3][3]); 19.1590 + } 19.1591 + 19.1592 + void Transpose() 19.1593 + { 19.1594 + *this = Transposed(); 19.1595 + } 19.1596 + 19.1597 + 19.1598 + float SubDet (const int* rows, const int* cols) const 19.1599 + { 19.1600 + 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]]) 19.1601 + - 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]]) 19.1602 + + 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]]); 19.1603 + } 19.1604 + 19.1605 + float Cofactor(int I, int J) const 19.1606 + { 19.1607 + const int indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; 19.1608 + return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); 19.1609 + } 19.1610 + 19.1611 + float Determinant() const 19.1612 + { 19.1613 + return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3); 19.1614 + } 19.1615 + 19.1616 + Matrix4f Adjugated() const 19.1617 + { 19.1618 + return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 19.1619 + Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 19.1620 + Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2), 19.1621 + Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3)); 19.1622 + } 19.1623 + 19.1624 + Matrix4f Inverted() const 19.1625 + { 19.1626 + float det = Determinant(); 19.1627 + assert(det != 0); 19.1628 + return Adjugated() * (1.0f/det); 19.1629 + } 19.1630 + 19.1631 + void Invert() 19.1632 + { 19.1633 + *this = Inverted(); 19.1634 + } 19.1635 + 19.1636 + //AnnaSteve: 19.1637 + // a,b,c, are the YawPitchRoll angles to be returned 19.1638 + // rotation a around axis A1 19.1639 + // is followed by rotation b around axis A2 19.1640 + // is followed by rotation c around axis A3 19.1641 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.1642 + template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> 19.1643 + void ToEulerAngles(float *a, float *b, float *c) 19.1644 + { 19.1645 + OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); 19.1646 + 19.1647 + float psign = -1.0f; 19.1648 + if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation 19.1649 + psign = 1.0f; 19.1650 + 19.1651 + float pm = psign*M[A1][A3]; 19.1652 + if (pm < -1.0f + Math<float>::SingularityRadius) 19.1653 + { // South pole singularity 19.1654 + *a = 0.0f; 19.1655 + *b = -S*D*Math<float>::PiOver2; 19.1656 + *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); 19.1657 + } 19.1658 + else if (pm > 1.0 - Math<float>::SingularityRadius) 19.1659 + { // North pole singularity 19.1660 + *a = 0.0f; 19.1661 + *b = S*D*Math<float>::PiOver2; 19.1662 + *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); 19.1663 + } 19.1664 + else 19.1665 + { // Normal case (nonsingular) 19.1666 + *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] ); 19.1667 + *b = S*D*asin(pm); 19.1668 + *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] ); 19.1669 + } 19.1670 + 19.1671 + return; 19.1672 + } 19.1673 + 19.1674 + //AnnaSteve: 19.1675 + // a,b,c, are the YawPitchRoll angles to be returned 19.1676 + // rotation a around axis A1 19.1677 + // is followed by rotation b around axis A2 19.1678 + // is followed by rotation c around axis A1 19.1679 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.1680 + template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> 19.1681 + void ToEulerAnglesABA(float *a, float *b, float *c) 19.1682 + { 19.1683 + OVR_COMPILER_ASSERT(A1 != A2); 19.1684 + 19.1685 + // Determine the axis that was not supplied 19.1686 + int m = 3 - A1 - A2; 19.1687 + 19.1688 + float psign = -1.0f; 19.1689 + if ((A1 + 1) % 3 == A2) // Determine whether even permutation 19.1690 + psign = 1.0f; 19.1691 + 19.1692 + float c2 = M[A1][A1]; 19.1693 + if (c2 < -1.0 + Math<float>::SingularityRadius) 19.1694 + { // South pole singularity 19.1695 + *a = 0.0f; 19.1696 + *b = S*D*Math<float>::Pi; 19.1697 + *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); 19.1698 + } 19.1699 + else if (c2 > 1.0 - Math<float>::SingularityRadius) 19.1700 + { // North pole singularity 19.1701 + *a = 0.0f; 19.1702 + *b = 0.0f; 19.1703 + *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); 19.1704 + } 19.1705 + else 19.1706 + { // Normal case (nonsingular) 19.1707 + *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]); 19.1708 + *b = S*D*acos(c2); 19.1709 + *c = S*D*atan2( M[A1][A2],psign*M[A1][m]); 19.1710 + } 19.1711 + return; 19.1712 + } 19.1713 + 19.1714 + // Creates a matrix that converts the vertices from one coordinate system 19.1715 + // to another. 19.1716 + // 19.1717 + static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from) 19.1718 + { 19.1719 + // Holds axis values from the 'to' structure 19.1720 + int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis }; 19.1721 + 19.1722 + // The inverse of the toArray 19.1723 + int inv[4]; 19.1724 + inv[0] = inv[abs(to.XAxis)] = 0; 19.1725 + inv[abs(to.YAxis)] = 1; 19.1726 + inv[abs(to.ZAxis)] = 2; 19.1727 + 19.1728 + Matrix4f m(0, 0, 0, 19.1729 + 0, 0, 0, 19.1730 + 0, 0, 0); 19.1731 + 19.1732 + // Only three values in the matrix need to be changed to 1 or -1. 19.1733 + m.M[inv[abs(from.XAxis)]][0] = float(from.XAxis/toArray[inv[abs(from.XAxis)]]); 19.1734 + m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]); 19.1735 + m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]); 19.1736 + return m; 19.1737 + } 19.1738 + 19.1739 + 19.1740 + 19.1741 + static Matrix4f Translation(const Vector3f& v) 19.1742 + { 19.1743 + Matrix4f t; 19.1744 + t.M[0][3] = v.x; 19.1745 + t.M[1][3] = v.y; 19.1746 + t.M[2][3] = v.z; 19.1747 + return t; 19.1748 + } 19.1749 + 19.1750 + static Matrix4f Translation(float x, float y, float z = 0.0f) 19.1751 + { 19.1752 + Matrix4f t; 19.1753 + t.M[0][3] = x; 19.1754 + t.M[1][3] = y; 19.1755 + t.M[2][3] = z; 19.1756 + return t; 19.1757 + } 19.1758 + 19.1759 + static Matrix4f Scaling(const Vector3f& v) 19.1760 + { 19.1761 + Matrix4f t; 19.1762 + t.M[0][0] = v.x; 19.1763 + t.M[1][1] = v.y; 19.1764 + t.M[2][2] = v.z; 19.1765 + return t; 19.1766 + } 19.1767 + 19.1768 + static Matrix4f Scaling(float x, float y, float z) 19.1769 + { 19.1770 + Matrix4f t; 19.1771 + t.M[0][0] = x; 19.1772 + t.M[1][1] = y; 19.1773 + t.M[2][2] = z; 19.1774 + return t; 19.1775 + } 19.1776 + 19.1777 + static Matrix4f Scaling(float s) 19.1778 + { 19.1779 + Matrix4f t; 19.1780 + t.M[0][0] = s; 19.1781 + t.M[1][1] = s; 19.1782 + t.M[2][2] = s; 19.1783 + return t; 19.1784 + } 19.1785 + 19.1786 + 19.1787 + 19.1788 + //AnnaSteve : Just for quick testing. Not for final API. Need to remove case. 19.1789 + static Matrix4f RotationAxis(Axis A, float angle, RotateDirection d, HandedSystem s) 19.1790 + { 19.1791 + float sina = s * d *sin(angle); 19.1792 + float cosa = cos(angle); 19.1793 + 19.1794 + switch(A) 19.1795 + { 19.1796 + case Axis_X: 19.1797 + return Matrix4f(1, 0, 0, 19.1798 + 0, cosa, -sina, 19.1799 + 0, sina, cosa); 19.1800 + case Axis_Y: 19.1801 + return Matrix4f(cosa, 0, sina, 19.1802 + 0, 1, 0, 19.1803 + -sina, 0, cosa); 19.1804 + case Axis_Z: 19.1805 + return Matrix4f(cosa, -sina, 0, 19.1806 + sina, cosa, 0, 19.1807 + 0, 0, 1); 19.1808 + } 19.1809 + } 19.1810 + 19.1811 + 19.1812 + // Creates a rotation matrix rotating around the X axis by 'angle' radians. 19.1813 + // Rotation direction is depends on the coordinate system: 19.1814 + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.1815 + // while looking in the negative axis direction. This is the 19.1816 + // same as looking down from positive axis values towards origin. 19.1817 + // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.1818 + // negative axis direction. 19.1819 + static Matrix4f RotationX(float angle) 19.1820 + { 19.1821 + float sina = sin(angle); 19.1822 + float cosa = cos(angle); 19.1823 + return Matrix4f(1, 0, 0, 19.1824 + 0, cosa, -sina, 19.1825 + 0, sina, cosa); 19.1826 + } 19.1827 + 19.1828 + // Creates a rotation matrix rotating around the Y axis by 'angle' radians. 19.1829 + // Rotation direction is depends on the coordinate system: 19.1830 + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.1831 + // while looking in the negative axis direction. This is the 19.1832 + // same as looking down from positive axis values towards origin. 19.1833 + // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.1834 + // negative axis direction. 19.1835 + static Matrix4f RotationY(float angle) 19.1836 + { 19.1837 + float sina = sin(angle); 19.1838 + float cosa = cos(angle); 19.1839 + return Matrix4f(cosa, 0, sina, 19.1840 + 0, 1, 0, 19.1841 + -sina, 0, cosa); 19.1842 + } 19.1843 + 19.1844 + // Creates a rotation matrix rotating around the Z axis by 'angle' radians. 19.1845 + // Rotation direction is depends on the coordinate system: 19.1846 + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), 19.1847 + // while looking in the negative axis direction. This is the 19.1848 + // same as looking down from positive axis values towards origin. 19.1849 + // LHS: Positive angle values rotate clock-wise (CW), while looking in the 19.1850 + // negative axis direction. 19.1851 + static Matrix4f RotationZ(float angle) 19.1852 + { 19.1853 + float sina = sin(angle); 19.1854 + float cosa = cos(angle); 19.1855 + return Matrix4f(cosa, -sina, 0, 19.1856 + sina, cosa, 0, 19.1857 + 0, 0, 1); 19.1858 + } 19.1859 + 19.1860 + 19.1861 + // LookAtRH creates a View transformation matrix for right-handed coordinate system. 19.1862 + // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' 19.1863 + // specifying the up vector. The resulting matrix should be used with PerspectiveRH 19.1864 + // projection. 19.1865 + static Matrix4f LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up); 19.1866 + 19.1867 + // LookAtLH creates a View transformation matrix for left-handed coordinate system. 19.1868 + // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' 19.1869 + // specifying the up vector. 19.1870 + static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up); 19.1871 + 19.1872 + 19.1873 + // PerspectiveRH creates a right-handed perspective projection matrix that can be 19.1874 + // used with the Oculus sample renderer. 19.1875 + // yfov - Specifies vertical field of view in radians. 19.1876 + // aspect - Screen aspect ration, which is usually width/height for square pixels. 19.1877 + // Note that xfov = yfov * aspect. 19.1878 + // znear - Absolute value of near Z clipping clipping range. 19.1879 + // zfar - Absolute value of far Z clipping clipping range (larger then near). 19.1880 + // Even though RHS usually looks in the direction of negative Z, positive values 19.1881 + // are expected for znear and zfar. 19.1882 + static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar); 19.1883 + 19.1884 + 19.1885 + // PerspectiveRH creates a left-handed perspective projection matrix that can be 19.1886 + // used with the Oculus sample renderer. 19.1887 + // yfov - Specifies vertical field of view in radians. 19.1888 + // aspect - Screen aspect ration, which is usually width/height for square pixels. 19.1889 + // Note that xfov = yfov * aspect. 19.1890 + // znear - Absolute value of near Z clipping clipping range. 19.1891 + // zfar - Absolute value of far Z clipping clipping range (larger then near). 19.1892 + static Matrix4f PerspectiveLH(float yfov, float aspect, float znear, float zfar); 19.1893 + 19.1894 + 19.1895 + static Matrix4f Ortho2D(float w, float h); 19.1896 +}; 19.1897 + 19.1898 + 19.1899 +//------------------------------------------------------------------------------------- 19.1900 +// ***** Quat 19.1901 + 19.1902 +// Quatf represents a quaternion class used for rotations. 19.1903 +// 19.1904 +// Quaternion multiplications are done in right-to-left order, to match the 19.1905 +// behavior of matrices. 19.1906 + 19.1907 + 19.1908 +template<class T> 19.1909 +class Quat 19.1910 +{ 19.1911 +public: 19.1912 + // w + Xi + Yj + Zk 19.1913 + T x, y, z, w; 19.1914 + 19.1915 + Quat() : x(0), y(0), z(0), w(1) {} 19.1916 + Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {} 19.1917 + 19.1918 + 19.1919 + // Constructs rotation quaternion around the axis. 19.1920 + Quat(const Vector3<T>& axis, T angle) 19.1921 + { 19.1922 + Vector3<T> unitAxis = axis.Normalized(); 19.1923 + T sinHalfAngle = sin(angle * T(0.5)); 19.1924 + 19.1925 + w = cos(angle * T(0.5)); 19.1926 + x = unitAxis.x * sinHalfAngle; 19.1927 + y = unitAxis.y * sinHalfAngle; 19.1928 + z = unitAxis.z * sinHalfAngle; 19.1929 + } 19.1930 + 19.1931 + //AnnaSteve: 19.1932 + void AxisAngle(Axis A, T angle, RotateDirection d, HandedSystem s) 19.1933 + { 19.1934 + T sinHalfAngle = s * d *sin(angle * (T)0.5); 19.1935 + T v[3]; 19.1936 + v[0] = v[1] = v[2] = (T)0; 19.1937 + v[A] = sinHalfAngle; 19.1938 + //return Quat(v[0], v[1], v[2], cos(angle * (T)0.5)); 19.1939 + w = cos(angle * (T)0.5); 19.1940 + x = v[0]; 19.1941 + y = v[1]; 19.1942 + z = v[2]; 19.1943 + } 19.1944 + 19.1945 + 19.1946 + void GetAxisAngle(Vector3<T>* axis, T* angle) const 19.1947 + { 19.1948 + if (LengthSq() > Math<T>::Tolerance * Math<T>::Tolerance) 19.1949 + { 19.1950 + *axis = Vector3<T>(x, y, z).Normalized(); 19.1951 + *angle = 2 * acos(w); 19.1952 + } 19.1953 + else 19.1954 + { 19.1955 + *axis = Vector3<T>(1, 0, 0); 19.1956 + *angle= 0; 19.1957 + } 19.1958 + } 19.1959 + 19.1960 + bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } 19.1961 + bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; } 19.1962 + 19.1963 + Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); } 19.1964 + Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; } 19.1965 + Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); } 19.1966 + Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; } 19.1967 + 19.1968 + Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); } 19.1969 + Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; } 19.1970 + Quat operator/ (T s) const { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); } 19.1971 + Quat& operator/= (T s) { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; } 19.1972 + 19.1973 + // Get Imaginary part vector 19.1974 + Vector3<T> Imag() const { return Vector3<T>(x,y,z); } 19.1975 + 19.1976 + // Get quaternion length. 19.1977 + T Length() const { return sqrt(x * x + y * y + z * z + w * w); } 19.1978 + // Get quaternion length squared. 19.1979 + T LengthSq() const { return (x * x + y * y + z * z + w * w); } 19.1980 + // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure) 19.1981 + T Distance(const Quat& q) const 19.1982 + { 19.1983 + T d1 = (*this - q).Length(); 19.1984 + T d2 = (*this + q).Length(); // Antipoldal point check 19.1985 + return (d1 < d2) ? d1 : d2; 19.1986 + } 19.1987 + T DistanceSq(const Quat& q) const 19.1988 + { 19.1989 + T d1 = (*this - q).LengthSq(); 19.1990 + T d2 = (*this + q).LengthSq(); // Antipoldal point check 19.1991 + return (d1 < d2) ? d1 : d2; 19.1992 + } 19.1993 + 19.1994 + // Normalize 19.1995 + bool IsNormalized() const { return fabs(LengthSq() - 1) < Math<T>::Tolerance; } 19.1996 + void Normalize() { *this /= Length(); } 19.1997 + Quat Normalized() const { return *this / Length(); } 19.1998 + 19.1999 + // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized. 19.2000 + Quat Conj() const { return Quat(-x, -y, -z, w); } 19.2001 + 19.2002 + // AnnaSteve fixed: order of quaternion multiplication 19.2003 + // Quaternion multiplication. Combines quaternion rotations, performing the one on the 19.2004 + // right hand side first. 19.2005 + Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y, 19.2006 + w * b.y - x * b.z + y * b.w + z * b.x, 19.2007 + w * b.z + x * b.y - y * b.x + z * b.w, 19.2008 + w * b.w - x * b.x - y * b.y - z * b.z); } 19.2009 + 19.2010 + // 19.2011 + // this^p normalized; same as rotating by this p times. 19.2012 + Quat PowNormalized(T p) const 19.2013 + { 19.2014 + Vector3<T> v; 19.2015 + T a; 19.2016 + GetAxisAngle(&v, &a); 19.2017 + return Quat(v, a * p); 19.2018 + } 19.2019 + 19.2020 + // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise, 19.2021 + // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 19.2022 + Vector3<T> Rotate(const Vector3<T>& v) const 19.2023 + { 19.2024 + return ((*this * Quat<T>(v.x, v.y, v.z, 0)) * Inverted()).Imag(); 19.2025 + } 19.2026 + 19.2027 + 19.2028 + // Inversed quaternion rotates in the opposite direction. 19.2029 + Quat Inverted() const 19.2030 + { 19.2031 + return Quat(-x, -y, -z, w); 19.2032 + } 19.2033 + 19.2034 + // Sets this quaternion to the one rotates in the opposite direction. 19.2035 + void Invert() 19.2036 + { 19.2037 + *this = Quat(-x, -y, -z, w); 19.2038 + } 19.2039 + 19.2040 + // Converting quaternion to matrix. 19.2041 + operator Matrix4f() const 19.2042 + { 19.2043 + T ww = w*w; 19.2044 + T xx = x*x; 19.2045 + T yy = y*y; 19.2046 + T zz = z*z; 19.2047 + 19.2048 + return Matrix4f(float(ww + xx - yy - zz), float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)), 19.2049 + float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz), float(T(2) * (y*z - w*x)), 19.2050 + float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) ); 19.2051 + } 19.2052 + 19.2053 + 19.2054 + // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of 19.2055 + // axis rotations and the specified coordinate system. Right-handed coordinate system 19.2056 + // is the default, with CCW rotations while looking in the negative axis direction. 19.2057 + // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. 19.2058 + // rotation a around axis A1 19.2059 + // is followed by rotation b around axis A2 19.2060 + // is followed by rotation c around axis A3 19.2061 + // rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.2062 + template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> 19.2063 + void GetEulerAngles(T *a, T *b, T *c) 19.2064 + { 19.2065 + OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); 19.2066 + 19.2067 + T Q[3] = { x, y, z }; //Quaternion components x,y,z 19.2068 + 19.2069 + T ww = w*w; 19.2070 + T Q11 = Q[A1]*Q[A1]; 19.2071 + T Q22 = Q[A2]*Q[A2]; 19.2072 + T Q33 = Q[A3]*Q[A3]; 19.2073 + 19.2074 + T psign = T(-1.0); 19.2075 + // Determine whether even permutation 19.2076 + if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) 19.2077 + psign = T(1.0); 19.2078 + 19.2079 + T s2 = psign * T(2.0) * (psign*w*Q[A2] + Q[A1]*Q[A3]); 19.2080 + 19.2081 + if (s2 < (T)-1.0 + Math<T>::SingularityRadius) 19.2082 + { // South pole singularity 19.2083 + *a = T(0.0); 19.2084 + *b = -S*D*Math<T>::PiOver2; 19.2085 + *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), 19.2086 + ww + Q22 - Q11 - Q33 ); 19.2087 + } 19.2088 + else if (s2 > (T)1.0 - Math<T>::SingularityRadius) 19.2089 + { // North pole singularity 19.2090 + *a = (T)0.0; 19.2091 + *b = S*D*Math<T>::PiOver2; 19.2092 + *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), 19.2093 + ww + Q22 - Q11 - Q33); 19.2094 + } 19.2095 + else 19.2096 + { 19.2097 + *a = -S*D*atan2((T)-2.0*(w*Q[A1] - psign*Q[A2]*Q[A3]), 19.2098 + ww + Q33 - Q11 - Q22); 19.2099 + *b = S*D*asin(s2); 19.2100 + *c = S*D*atan2((T)2.0*(w*Q[A3] - psign*Q[A1]*Q[A2]), 19.2101 + ww + Q11 - Q22 - Q33); 19.2102 + } 19.2103 + return; 19.2104 + } 19.2105 + 19.2106 + template <Axis A1, Axis A2, Axis A3, RotateDirection D> 19.2107 + void GetEulerAngles(T *a, T *b, T *c) 19.2108 + { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); } 19.2109 + 19.2110 + template <Axis A1, Axis A2, Axis A3> 19.2111 + void GetEulerAngles(T *a, T *b, T *c) 19.2112 + { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); } 19.2113 + 19.2114 + 19.2115 + // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of 19.2116 + // axis rotations and the specified coordinate system. Right-handed coordinate system 19.2117 + // is the default, with CCW rotations while looking in the negative axis direction. 19.2118 + // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned. 19.2119 + // rotation a around axis A1 19.2120 + // is followed by rotation b around axis A2 19.2121 + // is followed by rotation c around axis A1 19.2122 + // Rotations are CCW or CW (D) in LH or RH coordinate system (S) 19.2123 + template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> 19.2124 + void GetEulerAnglesABA(T *a, T *b, T *c) 19.2125 + { 19.2126 + OVR_COMPILER_ASSERT(A1 != A2); 19.2127 + 19.2128 + T Q[3] = {x, y, z}; // Quaternion components 19.2129 + 19.2130 + // Determine the missing axis that was not supplied 19.2131 + int m = 3 - A1 - A2; 19.2132 + 19.2133 + T ww = w*w; 19.2134 + T Q11 = Q[A1]*Q[A1]; 19.2135 + T Q22 = Q[A2]*Q[A2]; 19.2136 + T Qmm = Q[m]*Q[m]; 19.2137 + 19.2138 + T psign = T(-1.0); 19.2139 + if ((A1 + 1) % 3 == A2) // Determine whether even permutation 19.2140 + { 19.2141 + psign = (T)1.0; 19.2142 + } 19.2143 + 19.2144 + T c2 = ww + Q11 - Q22 - Qmm; 19.2145 + if (c2 < (T)-1.0 + Math<T>::SingularityRadius) 19.2146 + { // South pole singularity 19.2147 + *a = (T)0.0; 19.2148 + *b = S*D*Math<T>::Pi; 19.2149 + *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), 19.2150 + ww + Q22 - Q11 - Qmm); 19.2151 + } 19.2152 + else if (c2 > (T)1.0 - Math<T>::SingularityRadius) 19.2153 + { // North pole singularity 19.2154 + *a = (T)0.0; 19.2155 + *b = (T)0.0; 19.2156 + *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), 19.2157 + ww + Q22 - Q11 - Qmm); 19.2158 + } 19.2159 + else 19.2160 + { 19.2161 + *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2], 19.2162 + w*Q[A2] -psign*Q[A1]*Q[m]); 19.2163 + *b = S*D*acos(c2); 19.2164 + *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2], 19.2165 + w*Q[A2] + psign*Q[A1]*Q[m]); 19.2166 + } 19.2167 + return; 19.2168 + } 19.2169 +}; 19.2170 + 19.2171 + 19.2172 +typedef Quat<float> Quatf; 19.2173 +typedef Quat<double> Quatd; 19.2174 + 19.2175 + 19.2176 + 19.2177 +//------------------------------------------------------------------------------------- 19.2178 +// ***** Angle 19.2179 + 19.2180 +// Cleanly representing the algebra of 2D rotations. 19.2181 +// The operations maintain the angle between -Pi and Pi, the same range as atan2. 19.2182 +// 19.2183 + 19.2184 +template<class T> 19.2185 +class Angle 19.2186 +{ 19.2187 +public: 19.2188 + enum AngularUnits 19.2189 + { 19.2190 + Radians = 0, 19.2191 + Degrees = 1 19.2192 + }; 19.2193 + 19.2194 + Angle() : a(0) {} 19.2195 + 19.2196 + // Fix the range to be between -Pi and Pi 19.2197 + Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); } 19.2198 + 19.2199 + T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; } 19.2200 + void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); } 19.2201 + int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } 19.2202 + T Abs() const { return (a > 0) ? a : -a; } 19.2203 + 19.2204 + bool operator== (const Angle& b) const { return a == b.a; } 19.2205 + bool operator!= (const Angle& b) const { return a != b.a; } 19.2206 +// bool operator< (const Angle& b) const { return a < a.b; } 19.2207 +// bool operator> (const Angle& b) const { return a > a.b; } 19.2208 +// bool operator<= (const Angle& b) const { return a <= a.b; } 19.2209 +// bool operator>= (const Angle& b) const { return a >= a.b; } 19.2210 +// bool operator= (const T& x) { a = x; FixRange(); } 19.2211 + 19.2212 + // These operations assume a is already between -Pi and Pi. 19.2213 + Angle operator+ (const Angle& b) const { return Angle(a + b.a); } 19.2214 + Angle operator+ (const T& x) const { return Angle(a + x); } 19.2215 + Angle& operator+= (const Angle& b) { a = a + b.a; FastFixRange(); return *this; } 19.2216 + Angle& operator+= (const T& x) { a = a + x; FixRange(); return *this; } 19.2217 + Angle operator- (const Angle& b) const { return Angle(a - b.a); } 19.2218 + Angle operator- (const T& x) const { return Angle(a - x); } 19.2219 + Angle& operator-= (const Angle& b) { a = a - b.a; FastFixRange(); return *this; } 19.2220 + Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; } 19.2221 + 19.2222 + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; } 19.2223 + 19.2224 +private: 19.2225 + 19.2226 + // The stored angle, which should be maintained between -Pi and Pi 19.2227 + T a; 19.2228 + 19.2229 + // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 19.2230 + inline void FastFixRange() 19.2231 + { 19.2232 + if (a < -Math<T>::Pi) 19.2233 + a += Math<T>::TwoPi; 19.2234 + else if (a > Math<T>::Pi) 19.2235 + a -= Math<T>::TwoPi; 19.2236 + } 19.2237 + 19.2238 + // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method 19.2239 + inline void FixRange() 19.2240 + { 19.2241 + a = fmod(a,Math<T>::TwoPi); 19.2242 + if (a < -Math<T>::Pi) 19.2243 + a += Math<T>::TwoPi; 19.2244 + else if (a > Math<T>::Pi) 19.2245 + a -= Math<T>::TwoPi; 19.2246 + } 19.2247 +}; 19.2248 + 19.2249 + 19.2250 +typedef Angle<float> Anglef; 19.2251 +typedef Angle<double> Angled; 19.2252 + 19.2253 + 19.2254 +//------------------------------------------------------------------------------------- 19.2255 +// ***** Plane 19.2256 + 19.2257 +// Consists of a normal vector and distance from the origin where the plane is located. 19.2258 + 19.2259 +template<class T> 19.2260 +class Plane : public RefCountBase<Plane<T> > 19.2261 +{ 19.2262 +public: 19.2263 + Vector3<T> N; 19.2264 + T D; 19.2265 + 19.2266 + Plane() : D(0) {} 19.2267 + 19.2268 + // Normals must already be normalized 19.2269 + Plane(const Vector3<T>& n, T d) : N(n), D(d) {} 19.2270 + Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {} 19.2271 + 19.2272 + // construct from a point on the plane and the normal 19.2273 + Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {} 19.2274 + 19.2275 + // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane). 19.2276 + T TestSide(const Vector3<T>& p) const 19.2277 + { 19.2278 + return (N * p) + D; 19.2279 + } 19.2280 + 19.2281 + Plane<T> Flipped() const 19.2282 + { 19.2283 + return Plane(-N, -D); 19.2284 + } 19.2285 + 19.2286 + void Flip() 19.2287 + { 19.2288 + N = -N; 19.2289 + D = -D; 19.2290 + } 19.2291 + 19.2292 + bool operator==(const Plane<T>& rhs) const 19.2293 + { 19.2294 + return (this->D == rhs.D && this->N == rhs.N); 19.2295 + } 19.2296 +}; 19.2297 + 19.2298 +typedef Plane<float> Planef; 19.2299 + 19.2300 +} 19.2301 + 19.2302 +#endif
20.1 --- a/libovr/Src/Kernel/OVR_RefCount.cpp Sat Sep 14 17:51:03 2013 +0300 20.2 +++ b/libovr/Src/Kernel/OVR_RefCount.cpp Sun Sep 15 04:10:05 2013 +0300 20.3 @@ -1,1 +1,100 @@ 20.4 -/************************************************************************************ 20.5 20.6 Filename : OVR_RefCount.cpp 20.7 Content : Reference counting implementation 20.8 Created : September 19, 2012 20.9 Notes : 20.10 20.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 20.12 20.13 Use of this software is subject to the terms of the Oculus license 20.14 agreement provided at the time of installation or download, or which 20.15 otherwise accompanies this software in either electronic or hard copy form. 20.16 20.17 ************************************************************************************/ 20.18 20.19 #include "OVR_RefCount.h" 20.20 #include "OVR_Atomic.h" 20.21 #include "OVR_Log.h" 20.22 20.23 namespace OVR { 20.24 20.25 #ifdef OVR_CC_ARM 20.26 void* ReturnArg0(void* p) 20.27 { 20.28 return p; 20.29 } 20.30 #endif 20.31 20.32 // ***** Reference Count Base implementation 20.33 20.34 RefCountImplCore::~RefCountImplCore() 20.35 { 20.36 // RefCount can be either 1 or 0 here. 20.37 // 0 if Release() was properly called. 20.38 // 1 if the object was declared on stack or as an aggregate. 20.39 OVR_ASSERT(RefCount <= 1); 20.40 } 20.41 20.42 #ifdef OVR_BUILD_DEBUG 20.43 void RefCountImplCore::reportInvalidDelete(void *pmem) 20.44 { 20.45 OVR_DEBUG_LOG( 20.46 ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem)); 20.47 OVR_ASSERT(0); 20.48 } 20.49 #endif 20.50 20.51 RefCountNTSImplCore::~RefCountNTSImplCore() 20.52 { 20.53 // RefCount can be either 1 or 0 here. 20.54 // 0 if Release() was properly called. 20.55 // 1 if the object was declared on stack or as an aggregate. 20.56 OVR_ASSERT(RefCount <= 1); 20.57 } 20.58 20.59 #ifdef OVR_BUILD_DEBUG 20.60 void RefCountNTSImplCore::reportInvalidDelete(void *pmem) 20.61 { 20.62 OVR_DEBUG_LOG( 20.63 ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem)); 20.64 OVR_ASSERT(0); 20.65 } 20.66 #endif 20.67 20.68 20.69 // *** Thread-Safe RefCountImpl 20.70 20.71 void RefCountImpl::AddRef() 20.72 { 20.73 AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1); 20.74 } 20.75 void RefCountImpl::Release() 20.76 { 20.77 if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 20.78 delete this; 20.79 } 20.80 20.81 // *** Thread-Safe RefCountVImpl w/virtual AddRef/Release 20.82 20.83 void RefCountVImpl::AddRef() 20.84 { 20.85 AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1); 20.86 } 20.87 void RefCountVImpl::Release() 20.88 { 20.89 if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 20.90 delete this; 20.91 } 20.92 20.93 // *** NON-Thread-Safe RefCountImpl 20.94 20.95 void RefCountNTSImpl::Release() const 20.96 { 20.97 RefCount--; 20.98 if (RefCount == 0) 20.99 delete this; 20.100 } 20.101 20.102 20.103 } // OVR 20.104 \ No newline at end of file 20.105 +/************************************************************************************ 20.106 + 20.107 +Filename : OVR_RefCount.cpp 20.108 +Content : Reference counting implementation 20.109 +Created : September 19, 2012 20.110 +Notes : 20.111 + 20.112 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 20.113 + 20.114 +Use of this software is subject to the terms of the Oculus license 20.115 +agreement provided at the time of installation or download, or which 20.116 +otherwise accompanies this software in either electronic or hard copy form. 20.117 + 20.118 +************************************************************************************/ 20.119 + 20.120 +#include "OVR_RefCount.h" 20.121 +#include "OVR_Atomic.h" 20.122 +#include "OVR_Log.h" 20.123 + 20.124 +namespace OVR { 20.125 + 20.126 +#ifdef OVR_CC_ARM 20.127 +void* ReturnArg0(void* p) 20.128 +{ 20.129 + return p; 20.130 +} 20.131 +#endif 20.132 + 20.133 +// ***** Reference Count Base implementation 20.134 + 20.135 +RefCountImplCore::~RefCountImplCore() 20.136 +{ 20.137 + // RefCount can be either 1 or 0 here. 20.138 + // 0 if Release() was properly called. 20.139 + // 1 if the object was declared on stack or as an aggregate. 20.140 + OVR_ASSERT(RefCount <= 1); 20.141 +} 20.142 + 20.143 +#ifdef OVR_BUILD_DEBUG 20.144 +void RefCountImplCore::reportInvalidDelete(void *pmem) 20.145 +{ 20.146 + OVR_DEBUG_LOG( 20.147 + ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem)); 20.148 + OVR_ASSERT(0); 20.149 +} 20.150 +#endif 20.151 + 20.152 +RefCountNTSImplCore::~RefCountNTSImplCore() 20.153 +{ 20.154 + // RefCount can be either 1 or 0 here. 20.155 + // 0 if Release() was properly called. 20.156 + // 1 if the object was declared on stack or as an aggregate. 20.157 + OVR_ASSERT(RefCount <= 1); 20.158 +} 20.159 + 20.160 +#ifdef OVR_BUILD_DEBUG 20.161 +void RefCountNTSImplCore::reportInvalidDelete(void *pmem) 20.162 +{ 20.163 + OVR_DEBUG_LOG( 20.164 + ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem)); 20.165 + OVR_ASSERT(0); 20.166 +} 20.167 +#endif 20.168 + 20.169 + 20.170 +// *** Thread-Safe RefCountImpl 20.171 + 20.172 +void RefCountImpl::AddRef() 20.173 +{ 20.174 + AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1); 20.175 +} 20.176 +void RefCountImpl::Release() 20.177 +{ 20.178 + if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 20.179 + delete this; 20.180 +} 20.181 + 20.182 +// *** Thread-Safe RefCountVImpl w/virtual AddRef/Release 20.183 + 20.184 +void RefCountVImpl::AddRef() 20.185 +{ 20.186 + AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1); 20.187 +} 20.188 +void RefCountVImpl::Release() 20.189 +{ 20.190 + if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 20.191 + delete this; 20.192 +} 20.193 + 20.194 +// *** NON-Thread-Safe RefCountImpl 20.195 + 20.196 +void RefCountNTSImpl::Release() const 20.197 +{ 20.198 + RefCount--; 20.199 + if (RefCount == 0) 20.200 + delete this; 20.201 +} 20.202 + 20.203 + 20.204 +} // OVR
21.1 --- a/libovr/Src/Kernel/OVR_RefCount.h Sat Sep 14 17:51:03 2013 +0300 21.2 +++ b/libovr/Src/Kernel/OVR_RefCount.h Sun Sep 15 04:10:05 2013 +0300 21.3 @@ -1,1 +1,522 @@ 21.4 -/************************************************************************************ 21.5 21.6 PublicHeader: Kernel 21.7 Filename : OVR_RefCount.h 21.8 Content : Reference counting implementation headers 21.9 Created : September 19, 2012 21.10 Notes : 21.11 21.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 21.13 21.14 Use of this software is subject to the terms of the Oculus license 21.15 agreement provided at the time of installation or download, or which 21.16 otherwise accompanies this software in either electronic or hard copy form. 21.17 21.18 ************************************************************************************/ 21.19 21.20 #ifndef OVR_RefCount_h 21.21 #define OVR_RefCount_h 21.22 21.23 #include "OVR_Types.h" 21.24 #include "OVR_Allocator.h" 21.25 21.26 namespace OVR { 21.27 21.28 //----------------------------------------------------------------------------------- 21.29 // ***** Reference Counting 21.30 21.31 // There are three types of reference counting base classes: 21.32 // 21.33 // RefCountBase - Provides thread-safe reference counting (Default). 21.34 // RefCountBaseNTS - Non Thread Safe version of reference counting. 21.35 21.36 21.37 // ***** Declared classes 21.38 21.39 template<class C> 21.40 class RefCountBase; 21.41 template<class C> 21.42 class RefCountBaseNTS; 21.43 21.44 class RefCountImpl; 21.45 class RefCountNTSImpl; 21.46 21.47 21.48 //----------------------------------------------------------------------------------- 21.49 // ***** Implementation For Reference Counting 21.50 21.51 // RefCountImplCore holds RefCount value and defines a few utility 21.52 // functions shared by all implementations. 21.53 21.54 class RefCountImplCore 21.55 { 21.56 protected: 21.57 volatile int RefCount; 21.58 21.59 public: 21.60 // RefCountImpl constructor always initializes RefCount to 1 by default. 21.61 OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { } 21.62 21.63 // Need virtual destructor 21.64 // This: 1. Makes sure the right destructor's called. 21.65 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 21.66 virtual ~RefCountImplCore(); 21.67 21.68 // Debug method only. 21.69 int GetRefCount() const { return RefCount; } 21.70 21.71 // This logic is used to detect invalid 'delete' calls of reference counted 21.72 // objects. Direct delete calls are not allowed on them unless they come in 21.73 // internally from Release. 21.74 #ifdef OVR_BUILD_DEBUG 21.75 static void OVR_CDECL reportInvalidDelete(void *pmem); 21.76 inline static void checkInvalidDelete(RefCountImplCore *pmem) 21.77 { 21.78 if (pmem->RefCount != 0) 21.79 reportInvalidDelete(pmem); 21.80 } 21.81 #else 21.82 inline static void checkInvalidDelete(RefCountImplCore *) { } 21.83 #endif 21.84 21.85 // Base class ref-count content should not be copied. 21.86 void operator = (const RefCountImplCore &) { } 21.87 }; 21.88 21.89 class RefCountNTSImplCore 21.90 { 21.91 protected: 21.92 mutable int RefCount; 21.93 21.94 public: 21.95 // RefCountImpl constructor always initializes RefCount to 1 by default. 21.96 OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { } 21.97 21.98 // Need virtual destructor 21.99 // This: 1. Makes sure the right destructor's called. 21.100 // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 21.101 virtual ~RefCountNTSImplCore(); 21.102 21.103 // Debug method only. 21.104 int GetRefCount() const { return RefCount; } 21.105 21.106 // This logic is used to detect invalid 'delete' calls of reference counted 21.107 // objects. Direct delete calls are not allowed on them unless they come in 21.108 // internally from Release. 21.109 #ifdef OVR_BUILD_DEBUG 21.110 static void OVR_CDECL reportInvalidDelete(void *pmem); 21.111 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem) 21.112 { 21.113 if (pmem->RefCount != 0) 21.114 reportInvalidDelete(pmem); 21.115 } 21.116 #else 21.117 OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { } 21.118 #endif 21.119 21.120 // Base class ref-count content should not be copied. 21.121 void operator = (const RefCountNTSImplCore &) { } 21.122 }; 21.123 21.124 21.125 21.126 // RefCountImpl provides Thread-Safe implementation of reference counting, so 21.127 // it should be used by default in most places. 21.128 21.129 class RefCountImpl : public RefCountImplCore 21.130 { 21.131 public: 21.132 // Thread-Safe Ref-Count Implementation. 21.133 void AddRef(); 21.134 void Release(); 21.135 }; 21.136 21.137 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus, 21.138 // virtual AddRef and Release. 21.139 21.140 class RefCountVImpl : public RefCountImplCore 21.141 { 21.142 public: 21.143 // Thread-Safe Ref-Count Implementation. 21.144 virtual void AddRef(); 21.145 virtual void Release(); 21.146 }; 21.147 21.148 21.149 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting, 21.150 // which is slightly more efficient since it doesn't use atomics. 21.151 21.152 class RefCountNTSImpl : public RefCountNTSImplCore 21.153 { 21.154 public: 21.155 OVR_FORCE_INLINE void AddRef() const { RefCount++; } 21.156 void Release() const; 21.157 }; 21.158 21.159 21.160 21.161 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking 21.162 // to the reference counting implementation. Base must be one of the RefCountImpl classes. 21.163 21.164 template<class Base> 21.165 class RefCountBaseStatImpl : public Base 21.166 { 21.167 public: 21.168 RefCountBaseStatImpl() { } 21.169 21.170 // *** Override New and Delete 21.171 21.172 // DOM-IGNORE-BEGIN 21.173 // Undef new temporarily if it is being redefined 21.174 #ifdef OVR_DEFINE_NEW 21.175 #undef new 21.176 #endif 21.177 21.178 #ifdef OVR_BUILD_DEBUG 21.179 // Custom check used to detect incorrect calls of 'delete' on ref-counted objects. 21.180 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \ 21.181 do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0) 21.182 #else 21.183 #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) 21.184 #endif 21.185 21.186 // Redefine all new & delete operators. 21.187 OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE) 21.188 21.189 #ifdef OVR_DEFINE_NEW 21.190 #define new OVR_DEFINE_NEW 21.191 #endif 21.192 // OVR_BUILD_DEFINE_NEW 21.193 // DOM-IGNORE-END 21.194 }; 21.195 21.196 21.197 21.198 //----------------------------------------------------------------------------------- 21.199 // *** End user RefCountBase<> classes 21.200 21.201 21.202 // RefCountBase is a base class for classes that require thread-safe reference 21.203 // counting; it also overrides the new and delete operators to use MemoryHeap. 21.204 // 21.205 // Reference counted objects start out with RefCount value of 1. Further lifetime 21.206 // management is done through the AddRef() and Release() methods, typically 21.207 // hidden by Ptr<>. 21.208 21.209 template<class C> 21.210 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl> 21.211 { 21.212 public: 21.213 // Constructor. 21.214 OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { } 21.215 }; 21.216 21.217 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release 21.218 21.219 template<class C> 21.220 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl> 21.221 { 21.222 public: 21.223 // Constructor. 21.224 OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { } 21.225 }; 21.226 21.227 21.228 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference 21.229 // counting; it also overrides the new and delete operators to use MemoryHeap. 21.230 // This class should only be used if all pointers to it are known to be assigned, 21.231 // destroyed and manipulated within one thread. 21.232 // 21.233 // Reference counted objects start out with RefCount value of 1. Further lifetime 21.234 // management is done through the AddRef() and Release() methods, typically 21.235 // hidden by Ptr<>. 21.236 21.237 template<class C> 21.238 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl> 21.239 { 21.240 public: 21.241 // Constructor. 21.242 OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { } 21.243 }; 21.244 21.245 //----------------------------------------------------------------------------------- 21.246 // ***** Pickable template pointer 21.247 enum PickType { PickValue }; 21.248 21.249 template <typename T> 21.250 class Pickable 21.251 { 21.252 public: 21.253 Pickable() : pV(NULL) {} 21.254 explicit Pickable(T* p) : pV(p) {} 21.255 Pickable(T* p, PickType) : pV(p) 21.256 { 21.257 OVR_ASSERT(pV); 21.258 if (pV) 21.259 pV->AddRef(); 21.260 } 21.261 template <typename OT> 21.262 Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {} 21.263 21.264 public: 21.265 Pickable& operator =(const Pickable& other) 21.266 { 21.267 OVR_ASSERT(pV == NULL); 21.268 pV = other.pV; 21.269 // Extra check. 21.270 //other.pV = NULL; 21.271 return *this; 21.272 } 21.273 21.274 public: 21.275 T* GetPtr() const { return pV; } 21.276 T* operator->() const 21.277 { 21.278 return pV; 21.279 } 21.280 T& operator*() const 21.281 { 21.282 OVR_ASSERT(pV); 21.283 return *pV; 21.284 } 21.285 21.286 private: 21.287 T* pV; 21.288 }; 21.289 21.290 template <typename T> 21.291 OVR_FORCE_INLINE 21.292 Pickable<T> MakePickable(T* p) 21.293 { 21.294 return Pickable<T>(p); 21.295 } 21.296 21.297 //----------------------------------------------------------------------------------- 21.298 // ***** Ref-Counted template pointer 21.299 21.300 // Automatically AddRefs and Releases interfaces 21.301 21.302 void* ReturnArg0(void* p); 21.303 21.304 template<class C> 21.305 class Ptr 21.306 { 21.307 #ifdef OVR_CC_ARM 21.308 static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); } 21.309 #endif 21.310 21.311 protected: 21.312 C *pObject; 21.313 21.314 public: 21.315 21.316 // Constructors 21.317 OVR_FORCE_INLINE Ptr() : pObject(0) 21.318 { } 21.319 #ifdef OVR_CC_ARM 21.320 OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj)) 21.321 #else 21.322 OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj) 21.323 #endif 21.324 { } 21.325 OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr()) 21.326 { 21.327 // No AddRef() on purpose. 21.328 } 21.329 OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject) 21.330 { 21.331 other.pObject = NULL; 21.332 // No AddRef() on purpose. 21.333 } 21.334 OVR_FORCE_INLINE Ptr(C *pobj) 21.335 { 21.336 if (pobj) pobj->AddRef(); 21.337 pObject = pobj; 21.338 } 21.339 OVR_FORCE_INLINE Ptr(const Ptr<C> &src) 21.340 { 21.341 if (src.pObject) src.pObject->AddRef(); 21.342 pObject = src.pObject; 21.343 } 21.344 21.345 template<class R> 21.346 OVR_FORCE_INLINE Ptr(Ptr<R> &src) 21.347 { 21.348 if (src) src->AddRef(); 21.349 pObject = src; 21.350 } 21.351 template<class R> 21.352 OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr()) 21.353 { 21.354 // No AddRef() on purpose. 21.355 } 21.356 21.357 // Destructor 21.358 OVR_FORCE_INLINE ~Ptr() 21.359 { 21.360 if (pObject) pObject->Release(); 21.361 } 21.362 21.363 // Compares 21.364 OVR_FORCE_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; } 21.365 OVR_FORCE_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; } 21.366 21.367 OVR_FORCE_INLINE bool operator == (C *pother) const { return pObject == pother; } 21.368 OVR_FORCE_INLINE bool operator != (C *pother) const { return pObject != pother; } 21.369 21.370 21.371 OVR_FORCE_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; } 21.372 21.373 // Assignment 21.374 template<class R> 21.375 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src) 21.376 { 21.377 if (src) src->AddRef(); 21.378 if (pObject) pObject->Release(); 21.379 pObject = src; 21.380 return *this; 21.381 } 21.382 // Specialization 21.383 OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src) 21.384 { 21.385 if (src) src->AddRef(); 21.386 if (pObject) pObject->Release(); 21.387 pObject = src; 21.388 return *this; 21.389 } 21.390 21.391 OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc) 21.392 { 21.393 if (psrc) psrc->AddRef(); 21.394 if (pObject) pObject->Release(); 21.395 pObject = psrc; 21.396 return *this; 21.397 } 21.398 OVR_FORCE_INLINE const Ptr<C>& operator = (C &src) 21.399 { 21.400 if (pObject) pObject->Release(); 21.401 pObject = &src; 21.402 return *this; 21.403 } 21.404 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src) 21.405 { 21.406 return Pick(src); 21.407 } 21.408 template<class R> 21.409 OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src) 21.410 { 21.411 return Pick(src); 21.412 } 21.413 21.414 // Set Assignment 21.415 template<class R> 21.416 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src) 21.417 { 21.418 if (src) src->AddRef(); 21.419 if (pObject) pObject->Release(); 21.420 pObject = src; 21.421 return *this; 21.422 } 21.423 // Specialization 21.424 OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src) 21.425 { 21.426 if (src) src->AddRef(); 21.427 if (pObject) pObject->Release(); 21.428 pObject = src; 21.429 return *this; 21.430 } 21.431 21.432 OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc) 21.433 { 21.434 if (psrc) psrc->AddRef(); 21.435 if (pObject) pObject->Release(); 21.436 pObject = psrc; 21.437 return *this; 21.438 } 21.439 OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src) 21.440 { 21.441 if (pObject) pObject->Release(); 21.442 pObject = &src; 21.443 return *this; 21.444 } 21.445 OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src) 21.446 { 21.447 return Pick(src); 21.448 } 21.449 21.450 // Nulls ref-counted pointer without decrement 21.451 OVR_FORCE_INLINE void NullWithoutRelease() 21.452 { 21.453 pObject = 0; 21.454 } 21.455 21.456 // Clears the pointer to the object 21.457 OVR_FORCE_INLINE void Clear() 21.458 { 21.459 if (pObject) pObject->Release(); 21.460 pObject = 0; 21.461 } 21.462 21.463 // Obtain pointer reference directly, for D3D interfaces 21.464 OVR_FORCE_INLINE C*& GetRawRef() { return pObject; } 21.465 21.466 // Access Operators 21.467 OVR_FORCE_INLINE C* GetPtr() const { return pObject; } 21.468 OVR_FORCE_INLINE C& operator * () const { return *pObject; } 21.469 OVR_FORCE_INLINE C* operator -> () const { return pObject; } 21.470 // Conversion 21.471 OVR_FORCE_INLINE operator C* () const { return pObject; } 21.472 21.473 // Pickers. 21.474 21.475 // Pick a value. 21.476 OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other) 21.477 { 21.478 if (&other != this) 21.479 { 21.480 if (pObject) pObject->Release(); 21.481 pObject = other.pObject; 21.482 other.pObject = 0; 21.483 } 21.484 21.485 return *this; 21.486 } 21.487 21.488 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v) 21.489 { 21.490 if (v.GetPtr() != pObject) 21.491 { 21.492 if (pObject) pObject->Release(); 21.493 pObject = v.GetPtr(); 21.494 } 21.495 21.496 return *this; 21.497 } 21.498 21.499 template<class R> 21.500 OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v) 21.501 { 21.502 if (v.GetPtr() != pObject) 21.503 { 21.504 if (pObject) pObject->Release(); 21.505 pObject = v.GetPtr(); 21.506 } 21.507 21.508 return *this; 21.509 } 21.510 21.511 OVR_FORCE_INLINE Ptr<C>& Pick(C* p) 21.512 { 21.513 if (p != pObject) 21.514 { 21.515 if (pObject) pObject->Release(); 21.516 pObject = p; 21.517 } 21.518 21.519 return *this; 21.520 } 21.521 }; 21.522 21.523 } // OVR 21.524 21.525 #endif 21.526 \ No newline at end of file 21.527 +/************************************************************************************ 21.528 + 21.529 +PublicHeader: Kernel 21.530 +Filename : OVR_RefCount.h 21.531 +Content : Reference counting implementation headers 21.532 +Created : September 19, 2012 21.533 +Notes : 21.534 + 21.535 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 21.536 + 21.537 +Use of this software is subject to the terms of the Oculus license 21.538 +agreement provided at the time of installation or download, or which 21.539 +otherwise accompanies this software in either electronic or hard copy form. 21.540 + 21.541 +************************************************************************************/ 21.542 + 21.543 +#ifndef OVR_RefCount_h 21.544 +#define OVR_RefCount_h 21.545 + 21.546 +#include "OVR_Types.h" 21.547 +#include "OVR_Allocator.h" 21.548 + 21.549 +namespace OVR { 21.550 + 21.551 +//----------------------------------------------------------------------------------- 21.552 +// ***** Reference Counting 21.553 + 21.554 +// There are three types of reference counting base classes: 21.555 +// 21.556 +// RefCountBase - Provides thread-safe reference counting (Default). 21.557 +// RefCountBaseNTS - Non Thread Safe version of reference counting. 21.558 + 21.559 + 21.560 +// ***** Declared classes 21.561 + 21.562 +template<class C> 21.563 +class RefCountBase; 21.564 +template<class C> 21.565 +class RefCountBaseNTS; 21.566 + 21.567 +class RefCountImpl; 21.568 +class RefCountNTSImpl; 21.569 + 21.570 + 21.571 +//----------------------------------------------------------------------------------- 21.572 +// ***** Implementation For Reference Counting 21.573 + 21.574 +// RefCountImplCore holds RefCount value and defines a few utility 21.575 +// functions shared by all implementations. 21.576 + 21.577 +class RefCountImplCore 21.578 +{ 21.579 +protected: 21.580 + volatile int RefCount; 21.581 + 21.582 +public: 21.583 + // RefCountImpl constructor always initializes RefCount to 1 by default. 21.584 + OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { } 21.585 + 21.586 + // Need virtual destructor 21.587 + // This: 1. Makes sure the right destructor's called. 21.588 + // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 21.589 + virtual ~RefCountImplCore(); 21.590 + 21.591 + // Debug method only. 21.592 + int GetRefCount() const { return RefCount; } 21.593 + 21.594 + // This logic is used to detect invalid 'delete' calls of reference counted 21.595 + // objects. Direct delete calls are not allowed on them unless they come in 21.596 + // internally from Release. 21.597 +#ifdef OVR_BUILD_DEBUG 21.598 + static void OVR_CDECL reportInvalidDelete(void *pmem); 21.599 + inline static void checkInvalidDelete(RefCountImplCore *pmem) 21.600 + { 21.601 + if (pmem->RefCount != 0) 21.602 + reportInvalidDelete(pmem); 21.603 + } 21.604 +#else 21.605 + inline static void checkInvalidDelete(RefCountImplCore *) { } 21.606 +#endif 21.607 + 21.608 + // Base class ref-count content should not be copied. 21.609 + void operator = (const RefCountImplCore &) { } 21.610 +}; 21.611 + 21.612 +class RefCountNTSImplCore 21.613 +{ 21.614 +protected: 21.615 + mutable int RefCount; 21.616 + 21.617 +public: 21.618 + // RefCountImpl constructor always initializes RefCount to 1 by default. 21.619 + OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { } 21.620 + 21.621 + // Need virtual destructor 21.622 + // This: 1. Makes sure the right destructor's called. 21.623 + // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem() 21.624 + virtual ~RefCountNTSImplCore(); 21.625 + 21.626 + // Debug method only. 21.627 + int GetRefCount() const { return RefCount; } 21.628 + 21.629 + // This logic is used to detect invalid 'delete' calls of reference counted 21.630 + // objects. Direct delete calls are not allowed on them unless they come in 21.631 + // internally from Release. 21.632 +#ifdef OVR_BUILD_DEBUG 21.633 + static void OVR_CDECL reportInvalidDelete(void *pmem); 21.634 + OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem) 21.635 + { 21.636 + if (pmem->RefCount != 0) 21.637 + reportInvalidDelete(pmem); 21.638 + } 21.639 +#else 21.640 + OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { } 21.641 +#endif 21.642 + 21.643 + // Base class ref-count content should not be copied. 21.644 + void operator = (const RefCountNTSImplCore &) { } 21.645 +}; 21.646 + 21.647 + 21.648 + 21.649 +// RefCountImpl provides Thread-Safe implementation of reference counting, so 21.650 +// it should be used by default in most places. 21.651 + 21.652 +class RefCountImpl : public RefCountImplCore 21.653 +{ 21.654 +public: 21.655 + // Thread-Safe Ref-Count Implementation. 21.656 + void AddRef(); 21.657 + void Release(); 21.658 +}; 21.659 + 21.660 +// RefCountVImpl provides Thread-Safe implementation of reference counting, plus, 21.661 +// virtual AddRef and Release. 21.662 + 21.663 +class RefCountVImpl : public RefCountImplCore 21.664 +{ 21.665 +public: 21.666 + // Thread-Safe Ref-Count Implementation. 21.667 + virtual void AddRef(); 21.668 + virtual void Release(); 21.669 +}; 21.670 + 21.671 + 21.672 +// RefCountImplNTS provides Non-Thread-Safe implementation of reference counting, 21.673 +// which is slightly more efficient since it doesn't use atomics. 21.674 + 21.675 +class RefCountNTSImpl : public RefCountNTSImplCore 21.676 +{ 21.677 +public: 21.678 + OVR_FORCE_INLINE void AddRef() const { RefCount++; } 21.679 + void Release() const; 21.680 +}; 21.681 + 21.682 + 21.683 + 21.684 +// RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking 21.685 +// to the reference counting implementation. Base must be one of the RefCountImpl classes. 21.686 + 21.687 +template<class Base> 21.688 +class RefCountBaseStatImpl : public Base 21.689 +{ 21.690 +public: 21.691 + RefCountBaseStatImpl() { } 21.692 + 21.693 + // *** Override New and Delete 21.694 + 21.695 + // DOM-IGNORE-BEGIN 21.696 + // Undef new temporarily if it is being redefined 21.697 +#ifdef OVR_DEFINE_NEW 21.698 +#undef new 21.699 +#endif 21.700 + 21.701 +#ifdef OVR_BUILD_DEBUG 21.702 + // Custom check used to detect incorrect calls of 'delete' on ref-counted objects. 21.703 + #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \ 21.704 + do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0) 21.705 +#else 21.706 + #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p) 21.707 +#endif 21.708 + 21.709 + // Redefine all new & delete operators. 21.710 + OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE) 21.711 + 21.712 +#ifdef OVR_DEFINE_NEW 21.713 +#define new OVR_DEFINE_NEW 21.714 +#endif 21.715 + // OVR_BUILD_DEFINE_NEW 21.716 + // DOM-IGNORE-END 21.717 +}; 21.718 + 21.719 + 21.720 + 21.721 +//----------------------------------------------------------------------------------- 21.722 +// *** End user RefCountBase<> classes 21.723 + 21.724 + 21.725 +// RefCountBase is a base class for classes that require thread-safe reference 21.726 +// counting; it also overrides the new and delete operators to use MemoryHeap. 21.727 +// 21.728 +// Reference counted objects start out with RefCount value of 1. Further lifetime 21.729 +// management is done through the AddRef() and Release() methods, typically 21.730 +// hidden by Ptr<>. 21.731 + 21.732 +template<class C> 21.733 +class RefCountBase : public RefCountBaseStatImpl<RefCountImpl> 21.734 +{ 21.735 +public: 21.736 + // Constructor. 21.737 + OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { } 21.738 +}; 21.739 + 21.740 +// RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release 21.741 + 21.742 +template<class C> 21.743 +class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl> 21.744 +{ 21.745 +public: 21.746 + // Constructor. 21.747 + OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { } 21.748 +}; 21.749 + 21.750 + 21.751 +// RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference 21.752 +// counting; it also overrides the new and delete operators to use MemoryHeap. 21.753 +// This class should only be used if all pointers to it are known to be assigned, 21.754 +// destroyed and manipulated within one thread. 21.755 +// 21.756 +// Reference counted objects start out with RefCount value of 1. Further lifetime 21.757 +// management is done through the AddRef() and Release() methods, typically 21.758 +// hidden by Ptr<>. 21.759 + 21.760 +template<class C> 21.761 +class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl> 21.762 +{ 21.763 +public: 21.764 + // Constructor. 21.765 + OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { } 21.766 +}; 21.767 + 21.768 +//----------------------------------------------------------------------------------- 21.769 +// ***** Pickable template pointer 21.770 +enum PickType { PickValue }; 21.771 + 21.772 +template <typename T> 21.773 +class Pickable 21.774 +{ 21.775 +public: 21.776 + Pickable() : pV(NULL) {} 21.777 + explicit Pickable(T* p) : pV(p) {} 21.778 + Pickable(T* p, PickType) : pV(p) 21.779 + { 21.780 + OVR_ASSERT(pV); 21.781 + if (pV) 21.782 + pV->AddRef(); 21.783 + } 21.784 + template <typename OT> 21.785 + Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {} 21.786 + 21.787 +public: 21.788 + Pickable& operator =(const Pickable& other) 21.789 + { 21.790 + OVR_ASSERT(pV == NULL); 21.791 + pV = other.pV; 21.792 + // Extra check. 21.793 + //other.pV = NULL; 21.794 + return *this; 21.795 + } 21.796 + 21.797 +public: 21.798 + T* GetPtr() const { return pV; } 21.799 + T* operator->() const 21.800 + { 21.801 + return pV; 21.802 + } 21.803 + T& operator*() const 21.804 + { 21.805 + OVR_ASSERT(pV); 21.806 + return *pV; 21.807 + } 21.808 + 21.809 +private: 21.810 + T* pV; 21.811 +}; 21.812 + 21.813 +template <typename T> 21.814 +OVR_FORCE_INLINE 21.815 +Pickable<T> MakePickable(T* p) 21.816 +{ 21.817 + return Pickable<T>(p); 21.818 +} 21.819 + 21.820 +//----------------------------------------------------------------------------------- 21.821 +// ***** Ref-Counted template pointer 21.822 + 21.823 +// Automatically AddRefs and Releases interfaces 21.824 + 21.825 +void* ReturnArg0(void* p); 21.826 + 21.827 +template<class C> 21.828 +class Ptr 21.829 +{ 21.830 +#ifdef OVR_CC_ARM 21.831 + static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); } 21.832 +#endif 21.833 + 21.834 +protected: 21.835 + C *pObject; 21.836 + 21.837 +public: 21.838 + 21.839 + // Constructors 21.840 + OVR_FORCE_INLINE Ptr() : pObject(0) 21.841 + { } 21.842 +#ifdef OVR_CC_ARM 21.843 + OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj)) 21.844 +#else 21.845 + OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj) 21.846 +#endif 21.847 + { } 21.848 + OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr()) 21.849 + { 21.850 + // No AddRef() on purpose. 21.851 + } 21.852 + OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject) 21.853 + { 21.854 + other.pObject = NULL; 21.855 + // No AddRef() on purpose. 21.856 + } 21.857 + OVR_FORCE_INLINE Ptr(C *pobj) 21.858 + { 21.859 + if (pobj) pobj->AddRef(); 21.860 + pObject = pobj; 21.861 + } 21.862 + OVR_FORCE_INLINE Ptr(const Ptr<C> &src) 21.863 + { 21.864 + if (src.pObject) src.pObject->AddRef(); 21.865 + pObject = src.pObject; 21.866 + } 21.867 + 21.868 + template<class R> 21.869 + OVR_FORCE_INLINE Ptr(Ptr<R> &src) 21.870 + { 21.871 + if (src) src->AddRef(); 21.872 + pObject = src; 21.873 + } 21.874 + template<class R> 21.875 + OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr()) 21.876 + { 21.877 + // No AddRef() on purpose. 21.878 + } 21.879 + 21.880 + // Destructor 21.881 + OVR_FORCE_INLINE ~Ptr() 21.882 + { 21.883 + if (pObject) pObject->Release(); 21.884 + } 21.885 + 21.886 + // Compares 21.887 + OVR_FORCE_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; } 21.888 + OVR_FORCE_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; } 21.889 + 21.890 + OVR_FORCE_INLINE bool operator == (C *pother) const { return pObject == pother; } 21.891 + OVR_FORCE_INLINE bool operator != (C *pother) const { return pObject != pother; } 21.892 + 21.893 + 21.894 + OVR_FORCE_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; } 21.895 + 21.896 + // Assignment 21.897 + template<class R> 21.898 + OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src) 21.899 + { 21.900 + if (src) src->AddRef(); 21.901 + if (pObject) pObject->Release(); 21.902 + pObject = src; 21.903 + return *this; 21.904 + } 21.905 + // Specialization 21.906 + OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src) 21.907 + { 21.908 + if (src) src->AddRef(); 21.909 + if (pObject) pObject->Release(); 21.910 + pObject = src; 21.911 + return *this; 21.912 + } 21.913 + 21.914 + OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc) 21.915 + { 21.916 + if (psrc) psrc->AddRef(); 21.917 + if (pObject) pObject->Release(); 21.918 + pObject = psrc; 21.919 + return *this; 21.920 + } 21.921 + OVR_FORCE_INLINE const Ptr<C>& operator = (C &src) 21.922 + { 21.923 + if (pObject) pObject->Release(); 21.924 + pObject = &src; 21.925 + return *this; 21.926 + } 21.927 + OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src) 21.928 + { 21.929 + return Pick(src); 21.930 + } 21.931 + template<class R> 21.932 + OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src) 21.933 + { 21.934 + return Pick(src); 21.935 + } 21.936 + 21.937 + // Set Assignment 21.938 + template<class R> 21.939 + OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src) 21.940 + { 21.941 + if (src) src->AddRef(); 21.942 + if (pObject) pObject->Release(); 21.943 + pObject = src; 21.944 + return *this; 21.945 + } 21.946 + // Specialization 21.947 + OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src) 21.948 + { 21.949 + if (src) src->AddRef(); 21.950 + if (pObject) pObject->Release(); 21.951 + pObject = src; 21.952 + return *this; 21.953 + } 21.954 + 21.955 + OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc) 21.956 + { 21.957 + if (psrc) psrc->AddRef(); 21.958 + if (pObject) pObject->Release(); 21.959 + pObject = psrc; 21.960 + return *this; 21.961 + } 21.962 + OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src) 21.963 + { 21.964 + if (pObject) pObject->Release(); 21.965 + pObject = &src; 21.966 + return *this; 21.967 + } 21.968 + OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src) 21.969 + { 21.970 + return Pick(src); 21.971 + } 21.972 + 21.973 + // Nulls ref-counted pointer without decrement 21.974 + OVR_FORCE_INLINE void NullWithoutRelease() 21.975 + { 21.976 + pObject = 0; 21.977 + } 21.978 + 21.979 + // Clears the pointer to the object 21.980 + OVR_FORCE_INLINE void Clear() 21.981 + { 21.982 + if (pObject) pObject->Release(); 21.983 + pObject = 0; 21.984 + } 21.985 + 21.986 + // Obtain pointer reference directly, for D3D interfaces 21.987 + OVR_FORCE_INLINE C*& GetRawRef() { return pObject; } 21.988 + 21.989 + // Access Operators 21.990 + OVR_FORCE_INLINE C* GetPtr() const { return pObject; } 21.991 + OVR_FORCE_INLINE C& operator * () const { return *pObject; } 21.992 + OVR_FORCE_INLINE C* operator -> () const { return pObject; } 21.993 + // Conversion 21.994 + OVR_FORCE_INLINE operator C* () const { return pObject; } 21.995 + 21.996 + // Pickers. 21.997 + 21.998 + // Pick a value. 21.999 + OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other) 21.1000 + { 21.1001 + if (&other != this) 21.1002 + { 21.1003 + if (pObject) pObject->Release(); 21.1004 + pObject = other.pObject; 21.1005 + other.pObject = 0; 21.1006 + } 21.1007 + 21.1008 + return *this; 21.1009 + } 21.1010 + 21.1011 + OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v) 21.1012 + { 21.1013 + if (v.GetPtr() != pObject) 21.1014 + { 21.1015 + if (pObject) pObject->Release(); 21.1016 + pObject = v.GetPtr(); 21.1017 + } 21.1018 + 21.1019 + return *this; 21.1020 + } 21.1021 + 21.1022 + template<class R> 21.1023 + OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v) 21.1024 + { 21.1025 + if (v.GetPtr() != pObject) 21.1026 + { 21.1027 + if (pObject) pObject->Release(); 21.1028 + pObject = v.GetPtr(); 21.1029 + } 21.1030 + 21.1031 + return *this; 21.1032 + } 21.1033 + 21.1034 + OVR_FORCE_INLINE Ptr<C>& Pick(C* p) 21.1035 + { 21.1036 + if (p != pObject) 21.1037 + { 21.1038 + if (pObject) pObject->Release(); 21.1039 + pObject = p; 21.1040 + } 21.1041 + 21.1042 + return *this; 21.1043 + } 21.1044 +}; 21.1045 + 21.1046 +} // OVR 21.1047 + 21.1048 +#endif
22.1 --- a/libovr/Src/Kernel/OVR_Std.cpp Sat Sep 14 17:51:03 2013 +0300 22.2 +++ b/libovr/Src/Kernel/OVR_Std.cpp Sun Sep 15 04:10:05 2013 +0300 22.3 @@ -1,1 +1,1025 @@ 22.4 -/************************************************************************************ 22.5 22.6 Filename : OVR_Std.cpp 22.7 Content : Standard C function implementation 22.8 Created : September 19, 2012 22.9 Notes : 22.10 22.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 22.12 22.13 Use of this software is subject to the terms of the Oculus license 22.14 agreement provided at the time of installation or download, or which 22.15 otherwise accompanies this software in either electronic or hard copy form. 22.16 22.17 ************************************************************************************/ 22.18 22.19 #include "OVR_Std.h" 22.20 #include "OVR_Alg.h" 22.21 22.22 // localeconv() call in OVR_strtod() 22.23 #include <locale.h> 22.24 22.25 namespace OVR { 22.26 22.27 // Source for functions not available on all platforms is included here. 22.28 22.29 // Case insensitive compare implemented in platform-specific way. 22.30 int OVR_CDECL OVR_stricmp(const char* a, const char* b) 22.31 { 22.32 #if defined(OVR_OS_WIN32) 22.33 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.34 return ::_stricmp(a, b); 22.35 #else 22.36 return ::stricmp(a, b); 22.37 #endif 22.38 22.39 #else 22.40 return strcasecmp(a, b); 22.41 #endif 22.42 } 22.43 22.44 int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count) 22.45 { 22.46 #if defined(OVR_OS_WIN32) 22.47 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.48 return ::_strnicmp(a, b, count); 22.49 #else 22.50 return ::strnicmp(a, b, count); 22.51 #endif 22.52 22.53 #else 22.54 return strncasecmp(a, b, count); 22.55 #endif 22.56 } 22.57 22.58 wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src) 22.59 { 22.60 #if defined(OVR_MSVC_SAFESTRING) 22.61 wcscpy_s(dest, destsize, src); 22.62 return dest; 22.63 #elif defined(OVR_OS_WIN32) 22.64 OVR_UNUSED(destsize); 22.65 wcscpy(dest, src); 22.66 return dest; 22.67 #else 22.68 UPInt l = OVR_wcslen(src) + 1; // incl term null 22.69 l = (l < destsize) ? l : destsize; 22.70 memcpy(dest, src, l * sizeof(wchar_t)); 22.71 return dest; 22.72 #endif 22.73 } 22.74 22.75 wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count) 22.76 { 22.77 #if defined(OVR_MSVC_SAFESTRING) 22.78 wcsncpy_s(dest, destsize, src, count); 22.79 return dest; 22.80 #else 22.81 UPInt srclen = OVR_wcslen(src); 22.82 UPInt l = Alg::Min(srclen, count); 22.83 l = (l < destsize) ? l : destsize; 22.84 memcpy(dest, src, l * sizeof(wchar_t)); 22.85 if (count > srclen) 22.86 { 22.87 UPInt remLen = Alg::Min(destsize - l, (count - srclen)); 22.88 memset(&dest[l], 0, sizeof(wchar_t)*remLen); 22.89 } 22.90 else if (l < destsize) 22.91 dest[l] = 0; 22.92 return dest; 22.93 #endif 22.94 } 22.95 22.96 22.97 wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src) 22.98 { 22.99 #if defined(OVR_MSVC_SAFESTRING) 22.100 wcscat_s(dest, destsize, src); 22.101 return dest; 22.102 #elif defined(OVR_OS_WIN32) 22.103 OVR_UNUSED(destsize); 22.104 wcscat(dest, src); 22.105 return dest; 22.106 #else 22.107 UPInt dstlen = OVR_wcslen(dest); // do not incl term null 22.108 UPInt srclen = OVR_wcslen(src) + 1; // incl term null 22.109 UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; 22.110 memcpy(dest + dstlen, src, copylen * sizeof(wchar_t)); 22.111 return dest; 22.112 #endif 22.113 } 22.114 22.115 UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) 22.116 { 22.117 #if defined(OVR_OS_WIN32) 22.118 return wcslen(str); 22.119 #else 22.120 UPInt i = 0; 22.121 while(str[i] != '\0') 22.122 ++i; 22.123 return i; 22.124 #endif 22.125 } 22.126 22.127 int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) 22.128 { 22.129 #if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) 22.130 return wcscmp(a, b); 22.131 #else 22.132 // not supported, use custom implementation 22.133 const wchar_t *pa = a, *pb = b; 22.134 while (*pa && *pb) 22.135 { 22.136 wchar_t ca = *pa; 22.137 wchar_t cb = *pb; 22.138 if (ca < cb) 22.139 return -1; 22.140 else if (ca > cb) 22.141 return 1; 22.142 pa++; 22.143 pb++; 22.144 } 22.145 if (*pa) 22.146 return 1; 22.147 else if (*pb) 22.148 return -1; 22.149 else 22.150 return 0; 22.151 #endif 22.152 } 22.153 22.154 int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) 22.155 { 22.156 #if defined(OVR_OS_WIN32) 22.157 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.158 return ::_wcsicmp(a, b); 22.159 #else 22.160 return ::wcsicmp(a, b); 22.161 #endif 22.162 #elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE) 22.163 // not supported, use custom implementation 22.164 const wchar_t *pa = a, *pb = b; 22.165 while (*pa && *pb) 22.166 { 22.167 wchar_t ca = OVR_towlower(*pa); 22.168 wchar_t cb = OVR_towlower(*pb); 22.169 if (ca < cb) 22.170 return -1; 22.171 else if (ca > cb) 22.172 return 1; 22.173 pa++; 22.174 pb++; 22.175 } 22.176 if (*pa) 22.177 return 1; 22.178 else if (*pb) 22.179 return -1; 22.180 else 22.181 return 0; 22.182 #else 22.183 return wcscasecmp(a, b); 22.184 #endif 22.185 } 22.186 22.187 // This function is not inline because of dependency on <locale.h> 22.188 double OVR_CDECL OVR_strtod(const char* string, char** tailptr) 22.189 { 22.190 #if !defined(OVR_OS_ANDROID) 22.191 const char s = *localeconv()->decimal_point; 22.192 22.193 if (s != '.') 22.194 { 22.195 char buffer[347 + 1]; 22.196 22.197 OVR_strcpy(buffer, sizeof(buffer), string); 22.198 22.199 for (char* c = buffer; *c != '\0'; ++c) 22.200 { 22.201 if (*c == '.') 22.202 { 22.203 *c = s; 22.204 break; 22.205 } 22.206 } 22.207 22.208 return strtod(buffer, tailptr); 22.209 } 22.210 #endif 22.211 22.212 return strtod(string, tailptr); 22.213 } 22.214 22.215 22.216 #ifndef OVR_NO_WCTYPE 22.217 22.218 //// Use this class to generate Unicode bitsets. For example: 22.219 //// 22.220 //// UnicodeBitSet bitSet; 22.221 //// for(unsigned i = 0; i < 65536; ++i) 22.222 //// { 22.223 //// if (iswalpha(i)) 22.224 //// bitSet.Set(i); 22.225 //// } 22.226 //// bitSet.Dump(); 22.227 //// 22.228 ////--------------------------------------------------------------- 22.229 //class UnicodeBitSet 22.230 //{ 22.231 //public: 22.232 // UnicodeBitSet() 22.233 // { 22.234 // memset(Offsets, 0, sizeof(Offsets)); 22.235 // memset(Bits, 0, sizeof(Bits)); 22.236 // } 22.237 // 22.238 // void Set(unsigned bit) { Bits[bit >> 8][(bit >> 4) & 15] |= 1 << (bit & 15); } 22.239 // 22.240 // void Dump() 22.241 // { 22.242 // unsigned i, j; 22.243 // unsigned offsetCount = 0; 22.244 // for(i = 0; i < 256; ++i) 22.245 // { 22.246 // if (isNull(i)) Offsets[i] = 0; 22.247 // else 22.248 // if (isFull(i)) Offsets[i] = 1; 22.249 // else Offsets[i] = UInt16(offsetCount++ * 16 + 256); 22.250 // } 22.251 // for(i = 0; i < 16; ++i) 22.252 // { 22.253 // for(j = 0; j < 16; ++j) 22.254 // { 22.255 // printf("%5u,", Offsets[i*16+j]); 22.256 // } 22.257 // printf("\n"); 22.258 // } 22.259 // for(i = 0; i < 256; ++i) 22.260 // { 22.261 // if (Offsets[i] > 255) 22.262 // { 22.263 // for(j = 0; j < 16; j++) 22.264 // { 22.265 // printf("%5u,", Bits[i][j]); 22.266 // } 22.267 // printf("\n"); 22.268 // } 22.269 // } 22.270 // } 22.271 // 22.272 //private: 22.273 // bool isNull(unsigned n) const 22.274 // { 22.275 // const UInt16* p = Bits[n]; 22.276 // for(unsigned i = 0; i < 16; ++i) 22.277 // if (p[i] != 0) return false; 22.278 // return true; 22.279 // } 22.280 // 22.281 // bool isFull(unsigned n) const 22.282 // { 22.283 // const UInt16* p = Bits[n]; 22.284 // for(unsigned i = 0; i < 16; ++i) 22.285 // if (p[i] != 0xFFFF) return false; 22.286 // return true; 22.287 // } 22.288 // 22.289 // UInt16 Offsets[256]; 22.290 // UInt16 Bits[256][16]; 22.291 //}; 22.292 22.293 22.294 const UInt16 UnicodeAlnumBits[] = { 22.295 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.296 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.297 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.298 672, 688, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 704, 1, 1, 22.300 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 22.305 1, 1, 1, 1, 736, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.306 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.307 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.308 1, 1, 1, 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 0, 22.309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.310 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 768, 784, 1, 800, 816, 832, 22.311 0, 0, 0, 1023,65534, 2047,65534, 2047, 0, 0, 0, 524,65535,65407,65535,65407, 22.312 65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.313 0, 0, 0, 0, 32, 0, 0, 1024,55104,65535,65531,65535,32767,64767,65535, 15, 22.314 65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.315 0, 0, 0,65534,65535, 639,65534,65535, 255, 0, 0, 0, 0,65535, 2047, 7, 22.316 0, 0,65534, 2047,65534, 63, 1023,65535,65535,65535,65535,65535,65535, 8175, 8702, 8191, 22.317 0,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.318 65518,65535,65535,58367, 8191,65281,65487, 0,40942,65529,65023,50117, 6559,45184,65487, 3, 22.319 34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.320 40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.321 57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.322 57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 12, 22.323 65534,65535,65535, 2047,32767, 1023, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.324 1, 0, 1023, 0,65279,65535, 2047,65534, 3843,65279,65535, 8191, 0, 0, 0, 0, 22.325 65535,65535,63227, 327, 1023, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 127, 22.326 65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.327 65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.328 32767,32573,65535,65535,65407, 2047,65024, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.329 65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.330 65535,65535,65535,65535,65535,65535,40959, 127,65534, 2047,65535,65535,65535,65535, 2047, 0, 22.331 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 0, 1023, 0, 22.332 0, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.333 65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.334 65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.335 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.336 64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.337 192, 0, 1022, 1792,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 2047, 22.338 65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.339 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.340 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.341 65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.342 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.343 65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.344 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.345 65535,65535,65535,16383, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.346 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.347 0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.348 22.349 const UInt16 UnicodeAlphaBits[] = { 22.350 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.351 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.352 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.353 672, 688, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.354 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 704, 1, 1, 22.355 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.356 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.357 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.358 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.359 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 22.360 1, 1, 1, 1, 736, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.361 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.362 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.363 1, 1, 1, 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 0, 22.364 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.365 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 768, 784, 1, 800, 816, 832, 22.366 0, 0, 0, 0,65534, 2047,65534, 2047, 0, 0, 0, 0,65535,65407,65535,65407, 22.367 65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.368 0, 0, 0, 0, 32, 0, 0, 1024,55104,65535,65531,65535,32767,64767,65535, 15, 22.369 65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.370 0, 0, 0,65534,65535, 639,65534,65535, 255, 0, 0, 0, 0,65535, 2047, 7, 22.371 0, 0,65534, 2047,65534, 63, 0,65535,65535,65535,65535,65535,65535, 8175, 8702, 7168, 22.372 0,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.373 65518,65535,65535,58367, 8191,65281, 15, 0,40942,65529,65023,50117, 6559,45184, 15, 3, 22.374 34788,65529,65023,50029, 6535,24064, 0, 31,45038,65531,65023,58349, 7103, 1, 1, 0, 22.375 40942,65529,65023,58317, 6543,45248, 3, 0,51180,54845,50968,50111, 7623, 128, 0, 0, 22.376 57326,65533,65023,50159, 7647, 96, 3, 0,57324,65533,65023,50159, 7647,16480, 3, 0, 22.377 57324,65533,65023,50175, 7631, 128, 3, 0,65516,64639,65535,12283,32895,65375, 0, 12, 22.378 65534,65535,65535, 2047,32767, 0, 0, 0, 9622,65264,60590,15359, 8223,12288, 0, 0, 22.379 1, 0, 0, 0,65279,65535, 2047,65534, 3843,65279,65535, 8191, 0, 0, 0, 0, 22.380 65535,65535,63227, 327, 0, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 127, 22.381 65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.382 65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.383 32767,32573,65535,65535,65407, 2047, 0, 0, 0, 0,65535,65535,65535,65535,65535, 31, 22.384 65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.385 65535,65535,65535,65535,65535,65535,40959, 127,65534, 2047,65535,65535,65535,65535, 2047, 0, 22.386 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 0, 0, 0, 22.387 0, 0,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.388 65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.389 65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.390 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.391 64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.392 192, 0, 1022, 1792,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 2047, 22.393 65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.394 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.395 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.396 65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.397 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.398 65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.399 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.400 65535,65535,65535,16383, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.401 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.402 0, 0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.403 22.404 const UInt16 UnicodeDigitBits[] = { 22.405 256, 0, 0, 0, 0, 0, 272, 0, 0, 288, 304, 320, 336, 352, 368, 384, 22.406 400, 0, 0, 416, 0, 0, 0, 432, 448, 0, 0, 0, 0, 0, 0, 0, 22.407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.416 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.417 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.420 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 464, 22.421 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 22.422 0, 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 22.423 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.424 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.425 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65408, 0, 22.426 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.427 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.428 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 0, 22.429 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.430 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.431 0, 0, 0, 0, 0, 0,65024, 3, 0, 0, 0, 0, 0, 0, 0, 0, 22.432 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 22.433 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.434 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.435 22.436 const UInt16 UnicodeSpaceBits[] = { 22.437 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.438 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.439 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.440 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.441 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.442 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.443 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.444 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.445 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.446 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.447 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.448 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.449 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.450 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.451 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.453 15872, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 22.454 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 22.455 4095, 0,33536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.456 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.457 22.458 const UInt16 UnicodeXDigitBits[] = { 22.459 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.460 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.461 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.462 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.463 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.464 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.465 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.468 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.469 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.470 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.471 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.472 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.474 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 22.475 0, 0, 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.476 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.477 22.478 // Uncomment if necessary 22.479 //const UInt16 UnicodeCntrlBits[] = { 22.480 // 256, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 22.481 // 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 22.482 // 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.483 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.484 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.485 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.486 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.487 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.488 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.489 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.490 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.491 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.492 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.493 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.494 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.495 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 320, 336, 22.496 //65535,65535, 0, 0, 0, 0, 0,32768,65535,65535, 0, 0, 0, 0, 0, 0, 22.497 //32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.498 //30720, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.499 //61440, 0,31744, 0, 0, 0,64512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.500 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32768, 22.501 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3584}; 22.502 // 22.503 //const UInt16 UnicodeGraphBits[] = { 22.504 // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.505 // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.506 // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.507 // 688, 704, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.508 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 1, 1, 22.509 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.510 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.511 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.512 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.513 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 736, 22.514 // 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.515 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.516 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.517 // 1, 1, 1, 1, 1, 1, 1, 768, 0, 0, 0, 0, 0, 0, 0, 0, 22.518 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.519 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 784, 800, 1, 816, 832, 848, 22.520 // 0, 0,65534,65535,65535,65535,65535,32767, 0, 0,65534,65535,65535,65535,65535,65535, 22.521 //65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.522 // 0, 0, 0, 0, 32, 0, 0,17408,55232,65535,65531,65535,32767,64767,65535, 15, 22.523 //65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.524 // 0, 0, 0,65534,65535,65151,65534,65535, 1791, 0, 0,16384, 9,65535, 2047, 31, 22.525 // 4096,34816,65534, 2047,65534, 63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191, 22.526 //16383,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.527 //65518,65535,65535,58367, 8191,65281,65535, 1,40942,65529,65023,50117, 6559,45184,65487, 3, 22.528 //34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.529 //40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.530 //57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.531 //57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 28, 22.532 //65534,65535,65535, 2047,65535, 4095, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.533 //65521, 7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191, 0, 0, 0, 0, 22.534 //65535,65535,63227, 327,65535, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 2175, 22.535 //65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.536 //65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.537 //32767,32573,65535,65535,65407, 2047,65534, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.538 //65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.539 //65535,65535,65535,65535,65535,65535,65535, 127,65534, 8191,65535,65535,65535,65535,16383, 0, 22.540 // 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 6128, 1023, 0, 22.541 // 2047, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.542 //65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.543 //65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.544 // 0,65535, 255,65535,16239, 0, 0,57344,24576, 0, 0, 0, 0, 0, 0, 0, 22.545 //64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.546 // 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.547 //65486,65523, 1022, 1793,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 4095, 22.548 //65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.549 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.550 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.551 //65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.552 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.553 //65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.554 // 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.555 //65535,65535,65535,65535, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.556 // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.557 //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.558 // 22.559 //const UInt16 UnicodePrintBits[] = { 22.560 // 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.561 // 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.562 // 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.563 // 688, 704, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.564 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 1, 1, 22.565 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.566 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.567 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.568 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.569 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 736, 22.570 // 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.571 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.572 // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.573 // 1, 1, 1, 1, 1, 1, 1, 768, 0, 0, 0, 0, 0, 0, 0, 0, 22.574 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.575 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 784, 800, 1, 816, 832, 848, 22.576 // 512, 0,65535,65535,65535,65535,65535,32767, 0, 0,65535,65535,65535,65535,65535,65535, 22.577 //65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.578 // 0, 0, 0, 0, 32, 0, 0,17408,55232,65535,65531,65535,32767,64767,65535, 15, 22.579 //65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.580 // 0, 0, 0,65534,65535,65151,65534,65535, 1791, 0, 0,16384, 9,65535, 2047, 31, 22.581 // 4096,34816,65534, 2047,65534, 63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191, 22.582 //16383,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.583 //65518,65535,65535,58367, 8191,65281,65535, 1,40942,65529,65023,50117, 6559,45184,65487, 3, 22.584 //34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.585 //40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.586 //57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.587 //57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 28, 22.588 //65534,65535,65535, 2047,65535, 4095, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.589 //65521, 7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191, 0, 0, 0, 0, 22.590 //65535,65535,63227, 327,65535, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 2175, 22.591 //65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.592 //65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.593 //32767,32573,65535,65535,65407, 2047,65534, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.594 //65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.595 //65535,65535,65535,65535,65535,65535,65535, 127,65534, 8191,65535,65535,65535,65535,16383, 0, 22.596 // 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 6128, 1023, 0, 22.597 // 2047, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.598 //65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.599 //65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.600 // 0,65535, 255,65535,16239, 0, 0,57344,24576, 0, 0, 0, 0, 0, 0, 0, 22.601 //64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.602 // 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.603 //65487,65523, 1022, 1793,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 4095, 22.604 //65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.605 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.606 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.607 //65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.608 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.609 //65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.610 // 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.611 //65535,65535,65535,65535, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.612 // 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959, 22.613 //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.614 // 22.615 //const UInt16 UnicodePunctBits[] = { 22.616 // 256, 0, 0, 272, 0, 288, 304, 320, 0, 336, 0, 0, 0, 352, 368, 384, 22.617 // 400, 0, 0, 416, 0, 0, 432, 448, 464, 0, 0, 0, 0, 0, 0, 0, 22.618 // 480, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.619 // 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.620 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.621 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.622 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.623 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.624 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.625 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.626 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.627 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.628 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.629 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.630 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.631 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 528, 544, 560, 22.632 // 0, 0,65534,64512, 1,63488, 1,30720, 0, 0,65534,65535, 0, 128, 0, 128, 22.633 // 0, 0, 0, 0, 0, 0, 0,16384, 128, 0, 0, 0, 0, 0, 0, 0, 22.634 // 0, 0, 0, 0, 0,64512, 0, 0, 1536, 0, 0,16384, 9, 0, 0, 24, 22.635 // 4096,34816, 0, 0, 0, 0,15360, 0, 0, 0, 0, 0, 0, 16, 0, 0, 22.636 //16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.637 // 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, 22.638 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 22.639 // 0, 0, 0, 0,32768, 3072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.640 //65520, 7, 0,15360, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 22.641 // 0, 0, 0, 0,64512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2048, 22.642 // 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.643 // 0, 0, 0, 0, 0, 0,24576, 0, 0, 6144, 0, 0, 0, 0,14336, 0, 22.644 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6128, 0, 0, 22.645 // 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.646 // 0,65535, 255,65535,16239, 0, 0,24576,24576, 0, 0, 0, 0, 0, 0, 0, 22.647 // 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.648 //65294,65523, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2048, 22.649 // 0, 0, 0,49152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.650 // 0, 0, 0,65535,65055,65527, 3339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.651 //63470,35840, 1,47104, 0,10240, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.652 // 22.653 //const UInt16 UnicodeLowerBits[] = { 22.654 // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.655 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 22.656 // 384, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.657 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.658 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.659 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.660 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.661 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.662 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.663 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.664 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.665 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.666 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.667 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.668 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.669 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 432, 22.670 // 0, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0,32768,65535,65407, 22.671 //43690,43690,43690,21930,43861,43690,43690,54442,12585,20004,11562,58961,23392,46421,43690,43565, 22.672 //43690,43690,43688, 10, 0,65535,65535,65535,65535,65535,16383, 0, 0, 0, 0, 0, 22.673 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,61440,65535,32767,43235,43690, 15, 22.674 // 0, 0, 0,65535,65535,65535,43690,43690,40962,43690,43690,43690, 4372,43690,43690, 554, 22.675 // 0, 0, 0, 0, 0, 0,65534,65535, 255, 0, 0, 0, 0, 0, 0, 0, 22.676 //43690,43690,43690,43690,43690,43690,43690,43690,43690, 4074,43690,43690,43690,43690,43690, 682, 22.677 // 255, 63, 255, 255, 63, 255, 255,16383,65535,65535,65535,20703, 4316, 207, 255, 4316, 22.678 // 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.679 //50176, 8,32768, 528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.680 // 127, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.681 // 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.682 // 22.683 //const UInt16 UnicodeUpperBits[] = { 22.684 // 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.685 // 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 22.686 // 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.687 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.688 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.689 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.690 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.691 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.692 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.693 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.694 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.695 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.696 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.697 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.698 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.699 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 22.700 // 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,32639, 0, 0, 22.701 //21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53973, 4526,44464,19114,21845,21974, 22.702 //21845,21845,21844, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.703 // 0, 0, 0, 0, 0, 0, 0, 0,55104,65534, 4091, 0, 0,21532,21845, 0, 22.704 //65535,65535,65535, 0, 0, 0,21845,21845,20481,21845,21845,21845, 2187,21845,21845, 277, 22.705 // 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.706 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535,65535, 63, 0, 0, 0, 22.707 //21845,21845,21845,21845,21845,21845,21845,21845,21845, 21,21845,21845,21845,21845,21845, 341, 22.708 //65280,16128,65280,65280,16128,43520,65280, 0,65280,65280,65280, 7936, 7936, 3840, 7936, 7936, 22.709 //14468,15911,15696, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.710 // 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.711 22.712 22.713 // MA: March 19, 2010 22.714 // Modified ToUpper and ToLower tables to match values expected by AS3 tests. 22.715 // ToLower modifications: 22.716 // 304 -> 105 22.717 // 1024 -> 1104 * 22.718 // 1037 -> 1117 * 22.719 // UoUpper modifications: 22.720 // 255 -> 376 22.721 // 305 -> 73 22.722 // 383 -> 83 22.723 // 1104 -> 1024 * 22.724 // 1117 -> 1037 * 22.725 // Entries marked with a '*' don't make complete sense based on Unicode manual, although 22.726 // they match AS3. 22.727 22.728 22.729 static const UInt16 UnicodeToUpperBits[] = { 22.730 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.731 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 22.732 0, 384, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.733 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.734 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.735 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.736 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.739 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.741 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.742 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.745 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 22.746 0, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,65407, 22.747 43690,43690,43690,21674,43349,43690,43690,54442, 4392, 516, 8490, 8785,21056,46421,43690,43048, // MA: Modified for AS3. 22.748 43690, 170, 0, 0, 0, 2776,33545, 36, 3336, 4, 0, 0, 0, 0, 0, 0, 22.749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,61440,65534,32767, 0,43688, 0, 22.750 0, 0, 0,65535,65535,65535,43690,43690, 2,43690,43690,43690, 4372,43690,35498, 554, // MA: Modified for AS3. 22.751 0, 0, 0, 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 22.752 43690,43690,43690,43690,43690,43690,43690,43690,43690, 42,43690,43690,43690,43690,43690, 682, 22.753 255, 63, 255, 255, 63, 170, 255,16383, 0, 0, 0, 3, 0, 3, 35, 0, 22.754 0, 0, 0, 0, 0, 0, 0,65535, 0, 0, 0, 0, 0, 0, 0, 0, 22.755 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535, 1023, 0, 22.756 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.757 22.758 static const UInt16 UnicodeToLowerBits[] = { 22.759 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.760 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 22.761 0, 400, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.763 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 432, 22.775 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,32639, 0, 0, 22.776 21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53909, 4526,42128,19114,21845,21522,// MA: Modidied for AS3. 22.777 21845, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.778 0, 0, 0, 0, 0, 0, 0, 0,55104,65534, 4091, 0, 0, 0,21844, 0, 22.779 65535,65535,65535, 0, 0, 0,21845,21845, 1,21845,21845,21845, 2186,21845,17749, 277, 22.780 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535,65535, 63, 0, 0, 0, 22.782 21845,21845,21845,21845,21845,21845,21845,21845,21845, 21,21845,21845,21845,21845,21845, 341, 22.783 65280,16128,65280,65280,16128,43520,65280, 0, 0, 0, 0, 3840, 3840, 3840, 7936, 3840, 22.784 0, 0, 0, 0, 0, 0,65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.785 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65472,65535, 0, 0, 0, 22.786 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.787 22.788 struct GUnicodePairType 22.789 { 22.790 UInt16 Key, Value; 22.791 }; 22.792 22.793 static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key) 22.794 { 22.795 return a.Key < key; 22.796 } 22.797 22.798 static const GUnicodePairType UnicodeToUpperTable[] = { 22.799 { 97, 65}, { 98, 66}, { 99, 67}, { 100, 68}, { 101, 69}, { 102, 70}, { 103, 71}, 22.800 { 104, 72}, { 105, 73}, { 106, 74}, { 107, 75}, { 108, 76}, { 109, 77}, { 110, 78}, 22.801 { 111, 79}, { 112, 80}, { 113, 81}, { 114, 82}, { 115, 83}, { 116, 84}, { 117, 85}, 22.802 { 118, 86}, { 119, 87}, { 120, 88}, { 121, 89}, { 122, 90}, { 224, 192}, { 225, 193}, 22.803 { 226, 194}, { 227, 195}, { 228, 196}, { 229, 197}, { 230, 198}, { 231, 199}, { 232, 200}, 22.804 { 233, 201}, { 234, 202}, { 235, 203}, { 236, 204}, { 237, 205}, { 238, 206}, { 239, 207}, 22.805 { 240, 208}, { 241, 209}, { 242, 210}, { 243, 211}, { 244, 212}, { 245, 213}, { 246, 214}, 22.806 { 248, 216}, { 249, 217}, { 250, 218}, { 251, 219}, { 252, 220}, { 253, 221}, { 254, 222}, 22.807 { 255, 376}, { 257, 256}, { 259, 258}, { 261, 260}, { 263, 262}, { 265, 264}, { 267, 266}, 22.808 { 269, 268}, { 271, 270}, { 273, 272}, { 275, 274}, { 277, 276}, { 279, 278}, { 281, 280}, 22.809 { 283, 282}, { 285, 284}, { 287, 286}, { 289, 288}, { 291, 290}, { 293, 292}, { 295, 294}, 22.810 { 297, 296}, { 299, 298}, { 301, 300}, { 303, 302}, { 305, 73}, { 307, 306}, { 309, 308}, { 311, 310}, 22.811 { 314, 313}, { 316, 315}, { 318, 317}, { 320, 319}, { 322, 321}, { 324, 323}, { 326, 325}, 22.812 { 328, 327}, { 331, 330}, { 333, 332}, { 335, 334}, { 337, 336}, { 339, 338}, { 341, 340}, 22.813 { 343, 342}, { 345, 344}, { 347, 346}, { 349, 348}, { 351, 350}, { 353, 352}, { 355, 354}, 22.814 { 357, 356}, { 359, 358}, { 361, 360}, { 363, 362}, { 365, 364}, { 367, 366}, { 369, 368}, 22.815 { 371, 370}, { 373, 372}, { 375, 374}, { 378, 377}, { 380, 379}, { 382, 381}, { 383, 83}, { 387, 386}, 22.816 { 389, 388}, { 392, 391}, { 396, 395}, { 402, 401}, { 409, 408}, { 417, 416}, { 419, 418}, 22.817 { 421, 420}, { 424, 423}, { 429, 428}, { 432, 431}, { 436, 435}, { 438, 437}, { 441, 440}, 22.818 { 445, 444}, { 454, 452}, { 457, 455}, { 460, 458}, { 462, 461}, { 464, 463}, { 466, 465}, 22.819 { 468, 467}, { 470, 469}, { 472, 471}, { 474, 473}, { 476, 475}, { 477, 398}, { 479, 478}, 22.820 { 481, 480}, { 483, 482}, { 485, 484}, { 487, 486}, { 489, 488}, { 491, 490}, { 493, 492}, 22.821 { 495, 494}, { 499, 497}, { 501, 500}, { 507, 506}, { 509, 508}, { 511, 510}, { 513, 512}, 22.822 { 515, 514}, { 517, 516}, { 519, 518}, { 521, 520}, { 523, 522}, { 525, 524}, { 527, 526}, 22.823 { 529, 528}, { 531, 530}, { 533, 532}, { 535, 534}, { 595, 385}, { 596, 390}, { 598, 393}, 22.824 { 599, 394}, { 601, 399}, { 603, 400}, { 608, 403}, { 611, 404}, { 616, 407}, { 617, 406}, 22.825 { 623, 412}, { 626, 413}, { 629, 415}, { 643, 425}, { 648, 430}, { 650, 433}, { 651, 434}, 22.826 { 658, 439}, { 940, 902}, { 941, 904}, { 942, 905}, { 943, 906}, { 945, 913}, { 946, 914}, 22.827 { 947, 915}, { 948, 916}, { 949, 917}, { 950, 918}, { 951, 919}, { 952, 920}, { 953, 921}, 22.828 { 954, 922}, { 955, 923}, { 956, 924}, { 957, 925}, { 958, 926}, { 959, 927}, { 960, 928}, 22.829 { 961, 929}, { 962, 931}, { 963, 931}, { 964, 932}, { 965, 933}, { 966, 934}, { 967, 935}, 22.830 { 968, 936}, { 969, 937}, { 970, 938}, { 971, 939}, { 972, 908}, { 973, 910}, { 974, 911}, 22.831 { 995, 994}, { 997, 996}, { 999, 998}, { 1001, 1000}, { 1003, 1002}, { 1005, 1004}, { 1007, 1006}, 22.832 { 1072, 1040}, { 1073, 1041}, { 1074, 1042}, { 1075, 1043}, { 1076, 1044}, { 1077, 1045}, { 1078, 1046}, 22.833 { 1079, 1047}, { 1080, 1048}, { 1081, 1049}, { 1082, 1050}, { 1083, 1051}, { 1084, 1052}, { 1085, 1053}, 22.834 { 1086, 1054}, { 1087, 1055}, { 1088, 1056}, { 1089, 1057}, { 1090, 1058}, { 1091, 1059}, { 1092, 1060}, 22.835 { 1093, 1061}, { 1094, 1062}, { 1095, 1063}, { 1096, 1064}, { 1097, 1065}, { 1098, 1066}, { 1099, 1067}, 22.836 { 1100, 1068}, { 1101, 1069}, { 1102, 1070}, { 1103, 1071}, { 1104, 1024}, { 1105, 1025}, { 1106, 1026}, { 1107, 1027}, 22.837 { 1108, 1028}, { 1109, 1029}, { 1110, 1030}, { 1111, 1031}, { 1112, 1032}, { 1113, 1033}, { 1114, 1034}, 22.838 { 1115, 1035}, { 1116, 1036}, { 1117, 1037}, { 1118, 1038}, { 1119, 1039}, { 1121, 1120}, { 1123, 1122}, { 1125, 1124}, 22.839 { 1127, 1126}, { 1129, 1128}, { 1131, 1130}, { 1133, 1132}, { 1135, 1134}, { 1137, 1136}, { 1139, 1138}, 22.840 { 1141, 1140}, { 1143, 1142}, { 1145, 1144}, { 1147, 1146}, { 1149, 1148}, { 1151, 1150}, { 1153, 1152}, 22.841 { 1169, 1168}, { 1171, 1170}, { 1173, 1172}, { 1175, 1174}, { 1177, 1176}, { 1179, 1178}, { 1181, 1180}, 22.842 { 1183, 1182}, { 1185, 1184}, { 1187, 1186}, { 1189, 1188}, { 1191, 1190}, { 1193, 1192}, { 1195, 1194}, 22.843 { 1197, 1196}, { 1199, 1198}, { 1201, 1200}, { 1203, 1202}, { 1205, 1204}, { 1207, 1206}, { 1209, 1208}, 22.844 { 1211, 1210}, { 1213, 1212}, { 1215, 1214}, { 1218, 1217}, { 1220, 1219}, { 1224, 1223}, { 1228, 1227}, 22.845 { 1233, 1232}, { 1235, 1234}, { 1237, 1236}, { 1239, 1238}, { 1241, 1240}, { 1243, 1242}, { 1245, 1244}, 22.846 { 1247, 1246}, { 1249, 1248}, { 1251, 1250}, { 1253, 1252}, { 1255, 1254}, { 1257, 1256}, { 1259, 1258}, 22.847 { 1263, 1262}, { 1265, 1264}, { 1267, 1266}, { 1269, 1268}, { 1273, 1272}, { 1377, 1329}, { 1378, 1330}, 22.848 { 1379, 1331}, { 1380, 1332}, { 1381, 1333}, { 1382, 1334}, { 1383, 1335}, { 1384, 1336}, { 1385, 1337}, 22.849 { 1386, 1338}, { 1387, 1339}, { 1388, 1340}, { 1389, 1341}, { 1390, 1342}, { 1391, 1343}, { 1392, 1344}, 22.850 { 1393, 1345}, { 1394, 1346}, { 1395, 1347}, { 1396, 1348}, { 1397, 1349}, { 1398, 1350}, { 1399, 1351}, 22.851 { 1400, 1352}, { 1401, 1353}, { 1402, 1354}, { 1403, 1355}, { 1404, 1356}, { 1405, 1357}, { 1406, 1358}, 22.852 { 1407, 1359}, { 1408, 1360}, { 1409, 1361}, { 1410, 1362}, { 1411, 1363}, { 1412, 1364}, { 1413, 1365}, 22.853 { 1414, 1366}, { 7681, 7680}, { 7683, 7682}, { 7685, 7684}, { 7687, 7686}, { 7689, 7688}, { 7691, 7690}, 22.854 { 7693, 7692}, { 7695, 7694}, { 7697, 7696}, { 7699, 7698}, { 7701, 7700}, { 7703, 7702}, { 7705, 7704}, 22.855 { 7707, 7706}, { 7709, 7708}, { 7711, 7710}, { 7713, 7712}, { 7715, 7714}, { 7717, 7716}, { 7719, 7718}, 22.856 { 7721, 7720}, { 7723, 7722}, { 7725, 7724}, { 7727, 7726}, { 7729, 7728}, { 7731, 7730}, { 7733, 7732}, 22.857 { 7735, 7734}, { 7737, 7736}, { 7739, 7738}, { 7741, 7740}, { 7743, 7742}, { 7745, 7744}, { 7747, 7746}, 22.858 { 7749, 7748}, { 7751, 7750}, { 7753, 7752}, { 7755, 7754}, { 7757, 7756}, { 7759, 7758}, { 7761, 7760}, 22.859 { 7763, 7762}, { 7765, 7764}, { 7767, 7766}, { 7769, 7768}, { 7771, 7770}, { 7773, 7772}, { 7775, 7774}, 22.860 { 7777, 7776}, { 7779, 7778}, { 7781, 7780}, { 7783, 7782}, { 7785, 7784}, { 7787, 7786}, { 7789, 7788}, 22.861 { 7791, 7790}, { 7793, 7792}, { 7795, 7794}, { 7797, 7796}, { 7799, 7798}, { 7801, 7800}, { 7803, 7802}, 22.862 { 7805, 7804}, { 7807, 7806}, { 7809, 7808}, { 7811, 7810}, { 7813, 7812}, { 7815, 7814}, { 7817, 7816}, 22.863 { 7819, 7818}, { 7821, 7820}, { 7823, 7822}, { 7825, 7824}, { 7827, 7826}, { 7829, 7828}, { 7841, 7840}, 22.864 { 7843, 7842}, { 7845, 7844}, { 7847, 7846}, { 7849, 7848}, { 7851, 7850}, { 7853, 7852}, { 7855, 7854}, 22.865 { 7857, 7856}, { 7859, 7858}, { 7861, 7860}, { 7863, 7862}, { 7865, 7864}, { 7867, 7866}, { 7869, 7868}, 22.866 { 7871, 7870}, { 7873, 7872}, { 7875, 7874}, { 7877, 7876}, { 7879, 7878}, { 7881, 7880}, { 7883, 7882}, 22.867 { 7885, 7884}, { 7887, 7886}, { 7889, 7888}, { 7891, 7890}, { 7893, 7892}, { 7895, 7894}, { 7897, 7896}, 22.868 { 7899, 7898}, { 7901, 7900}, { 7903, 7902}, { 7905, 7904}, { 7907, 7906}, { 7909, 7908}, { 7911, 7910}, 22.869 { 7913, 7912}, { 7915, 7914}, { 7917, 7916}, { 7919, 7918}, { 7921, 7920}, { 7923, 7922}, { 7925, 7924}, 22.870 { 7927, 7926}, { 7929, 7928}, { 7936, 7944}, { 7937, 7945}, { 7938, 7946}, { 7939, 7947}, { 7940, 7948}, 22.871 { 7941, 7949}, { 7942, 7950}, { 7943, 7951}, { 7952, 7960}, { 7953, 7961}, { 7954, 7962}, { 7955, 7963}, 22.872 { 7956, 7964}, { 7957, 7965}, { 7968, 7976}, { 7969, 7977}, { 7970, 7978}, { 7971, 7979}, { 7972, 7980}, 22.873 { 7973, 7981}, { 7974, 7982}, { 7975, 7983}, { 7984, 7992}, { 7985, 7993}, { 7986, 7994}, { 7987, 7995}, 22.874 { 7988, 7996}, { 7989, 7997}, { 7990, 7998}, { 7991, 7999}, { 8000, 8008}, { 8001, 8009}, { 8002, 8010}, 22.875 { 8003, 8011}, { 8004, 8012}, { 8005, 8013}, { 8017, 8025}, { 8019, 8027}, { 8021, 8029}, { 8023, 8031}, 22.876 { 8032, 8040}, { 8033, 8041}, { 8034, 8042}, { 8035, 8043}, { 8036, 8044}, { 8037, 8045}, { 8038, 8046}, 22.877 { 8039, 8047}, { 8048, 8122}, { 8049, 8123}, { 8050, 8136}, { 8051, 8137}, { 8052, 8138}, { 8053, 8139}, 22.878 { 8054, 8154}, { 8055, 8155}, { 8056, 8184}, { 8057, 8185}, { 8058, 8170}, { 8059, 8171}, { 8060, 8186}, 22.879 { 8061, 8187}, { 8112, 8120}, { 8113, 8121}, { 8144, 8152}, { 8145, 8153}, { 8160, 8168}, { 8161, 8169}, 22.880 { 8165, 8172}, { 8560, 8544}, { 8561, 8545}, { 8562, 8546}, { 8563, 8547}, { 8564, 8548}, { 8565, 8549}, 22.881 { 8566, 8550}, { 8567, 8551}, { 8568, 8552}, { 8569, 8553}, { 8570, 8554}, { 8571, 8555}, { 8572, 8556}, 22.882 { 8573, 8557}, { 8574, 8558}, { 8575, 8559}, { 9424, 9398}, { 9425, 9399}, { 9426, 9400}, { 9427, 9401}, 22.883 { 9428, 9402}, { 9429, 9403}, { 9430, 9404}, { 9431, 9405}, { 9432, 9406}, { 9433, 9407}, { 9434, 9408}, 22.884 { 9435, 9409}, { 9436, 9410}, { 9437, 9411}, { 9438, 9412}, { 9439, 9413}, { 9440, 9414}, { 9441, 9415}, 22.885 { 9442, 9416}, { 9443, 9417}, { 9444, 9418}, { 9445, 9419}, { 9446, 9420}, { 9447, 9421}, { 9448, 9422}, 22.886 { 9449, 9423}, {65345,65313}, {65346,65314}, {65347,65315}, {65348,65316}, {65349,65317}, {65350,65318}, 22.887 {65351,65319}, {65352,65320}, {65353,65321}, {65354,65322}, {65355,65323}, {65356,65324}, {65357,65325}, 22.888 {65358,65326}, {65359,65327}, {65360,65328}, {65361,65329}, {65362,65330}, {65363,65331}, {65364,65332}, 22.889 {65365,65333}, {65366,65334}, {65367,65335}, {65368,65336}, {65369,65337}, {65370,65338}, {65535, 0}}; 22.890 22.891 static const GUnicodePairType UnicodeToLowerTable[] = { 22.892 { 65, 97}, { 66, 98}, { 67, 99}, { 68, 100}, { 69, 101}, { 70, 102}, { 71, 103}, 22.893 { 72, 104}, { 73, 105}, { 74, 106}, { 75, 107}, { 76, 108}, { 77, 109}, { 78, 110}, 22.894 { 79, 111}, { 80, 112}, { 81, 113}, { 82, 114}, { 83, 115}, { 84, 116}, { 85, 117}, 22.895 { 86, 118}, { 87, 119}, { 88, 120}, { 89, 121}, { 90, 122}, { 192, 224}, { 193, 225}, 22.896 { 194, 226}, { 195, 227}, { 196, 228}, { 197, 229}, { 198, 230}, { 199, 231}, { 200, 232}, 22.897 { 201, 233}, { 202, 234}, { 203, 235}, { 204, 236}, { 205, 237}, { 206, 238}, { 207, 239}, 22.898 { 208, 240}, { 209, 241}, { 210, 242}, { 211, 243}, { 212, 244}, { 213, 245}, { 214, 246}, 22.899 { 216, 248}, { 217, 249}, { 218, 250}, { 219, 251}, { 220, 252}, { 221, 253}, { 222, 254}, 22.900 { 256, 257}, { 258, 259}, { 260, 261}, { 262, 263}, { 264, 265}, { 266, 267}, { 268, 269}, 22.901 { 270, 271}, { 272, 273}, { 274, 275}, { 276, 277}, { 278, 279}, { 280, 281}, { 282, 283}, 22.902 { 284, 285}, { 286, 287}, { 288, 289}, { 290, 291}, { 292, 293}, { 294, 295}, { 296, 297}, 22.903 { 298, 299}, { 300, 301}, { 302, 303}, { 304, 105}, { 306, 307}, { 308, 309}, { 310, 311}, { 313, 314}, 22.904 { 315, 316}, { 317, 318}, { 319, 320}, { 321, 322}, { 323, 324}, { 325, 326}, { 327, 328}, 22.905 { 330, 331}, { 332, 333}, { 334, 335}, { 336, 337}, { 338, 339}, { 340, 341}, { 342, 343}, 22.906 { 344, 345}, { 346, 347}, { 348, 349}, { 350, 351}, { 352, 353}, { 354, 355}, { 356, 357}, 22.907 { 358, 359}, { 360, 361}, { 362, 363}, { 364, 365}, { 366, 367}, { 368, 369}, { 370, 371}, 22.908 { 372, 373}, { 374, 375}, { 376, 255}, { 377, 378}, { 379, 380}, { 381, 382}, { 385, 595}, 22.909 { 386, 387}, { 388, 389}, { 390, 596}, { 391, 392}, { 393, 598}, { 394, 599}, { 395, 396}, 22.910 { 398, 477}, { 399, 601}, { 400, 603}, { 401, 402}, { 403, 608}, { 404, 611}, { 406, 617}, 22.911 { 407, 616}, { 408, 409}, { 412, 623}, { 413, 626}, { 415, 629}, { 416, 417}, { 418, 419}, 22.912 { 420, 421}, { 423, 424}, { 425, 643}, { 428, 429}, { 430, 648}, { 431, 432}, { 433, 650}, 22.913 { 434, 651}, { 435, 436}, { 437, 438}, { 439, 658}, { 440, 441}, { 444, 445}, { 452, 454}, 22.914 { 455, 457}, { 458, 460}, { 461, 462}, { 463, 464}, { 465, 466}, { 467, 468}, { 469, 470}, 22.915 { 471, 472}, { 473, 474}, { 475, 476}, { 478, 479}, { 480, 481}, { 482, 483}, { 484, 485}, 22.916 { 486, 487}, { 488, 489}, { 490, 491}, { 492, 493}, { 494, 495}, { 497, 499}, { 500, 501}, 22.917 { 506, 507}, { 508, 509}, { 510, 511}, { 512, 513}, { 514, 515}, { 516, 517}, { 518, 519}, 22.918 { 520, 521}, { 522, 523}, { 524, 525}, { 526, 527}, { 528, 529}, { 530, 531}, { 532, 533}, 22.919 { 534, 535}, { 902, 940}, { 904, 941}, { 905, 942}, { 906, 943}, { 908, 972}, { 910, 973}, 22.920 { 911, 974}, { 913, 945}, { 914, 946}, { 915, 947}, { 916, 948}, { 917, 949}, { 918, 950}, 22.921 { 919, 951}, { 920, 952}, { 921, 953}, { 922, 954}, { 923, 955}, { 924, 956}, { 925, 957}, 22.922 { 926, 958}, { 927, 959}, { 928, 960}, { 929, 961}, { 931, 963}, { 932, 964}, { 933, 965}, 22.923 { 934, 966}, { 935, 967}, { 936, 968}, { 937, 969}, { 938, 970}, { 939, 971}, { 994, 995}, 22.924 { 996, 997}, { 998, 999}, { 1000, 1001}, { 1002, 1003}, { 1004, 1005}, { 1006, 1007}, { 1024, 1104}, { 1025, 1105}, 22.925 { 1026, 1106}, { 1027, 1107}, { 1028, 1108}, { 1029, 1109}, { 1030, 1110}, { 1031, 1111}, { 1032, 1112}, 22.926 { 1033, 1113}, { 1034, 1114}, { 1035, 1115}, { 1036, 1116}, { 1037, 1117}, { 1038, 1118}, { 1039, 1119}, { 1040, 1072}, 22.927 { 1041, 1073}, { 1042, 1074}, { 1043, 1075}, { 1044, 1076}, { 1045, 1077}, { 1046, 1078}, { 1047, 1079}, 22.928 { 1048, 1080}, { 1049, 1081}, { 1050, 1082}, { 1051, 1083}, { 1052, 1084}, { 1053, 1085}, { 1054, 1086}, 22.929 { 1055, 1087}, { 1056, 1088}, { 1057, 1089}, { 1058, 1090}, { 1059, 1091}, { 1060, 1092}, { 1061, 1093}, 22.930 { 1062, 1094}, { 1063, 1095}, { 1064, 1096}, { 1065, 1097}, { 1066, 1098}, { 1067, 1099}, { 1068, 1100}, 22.931 { 1069, 1101}, { 1070, 1102}, { 1071, 1103}, { 1120, 1121}, { 1122, 1123}, { 1124, 1125}, { 1126, 1127}, 22.932 { 1128, 1129}, { 1130, 1131}, { 1132, 1133}, { 1134, 1135}, { 1136, 1137}, { 1138, 1139}, { 1140, 1141}, 22.933 { 1142, 1143}, { 1144, 1145}, { 1146, 1147}, { 1148, 1149}, { 1150, 1151}, { 1152, 1153}, { 1168, 1169}, 22.934 { 1170, 1171}, { 1172, 1173}, { 1174, 1175}, { 1176, 1177}, { 1178, 1179}, { 1180, 1181}, { 1182, 1183}, 22.935 { 1184, 1185}, { 1186, 1187}, { 1188, 1189}, { 1190, 1191}, { 1192, 1193}, { 1194, 1195}, { 1196, 1197}, 22.936 { 1198, 1199}, { 1200, 1201}, { 1202, 1203}, { 1204, 1205}, { 1206, 1207}, { 1208, 1209}, { 1210, 1211}, 22.937 { 1212, 1213}, { 1214, 1215}, { 1217, 1218}, { 1219, 1220}, { 1223, 1224}, { 1227, 1228}, { 1232, 1233}, 22.938 { 1234, 1235}, { 1236, 1237}, { 1238, 1239}, { 1240, 1241}, { 1242, 1243}, { 1244, 1245}, { 1246, 1247}, 22.939 { 1248, 1249}, { 1250, 1251}, { 1252, 1253}, { 1254, 1255}, { 1256, 1257}, { 1258, 1259}, { 1262, 1263}, 22.940 { 1264, 1265}, { 1266, 1267}, { 1268, 1269}, { 1272, 1273}, { 1329, 1377}, { 1330, 1378}, { 1331, 1379}, 22.941 { 1332, 1380}, { 1333, 1381}, { 1334, 1382}, { 1335, 1383}, { 1336, 1384}, { 1337, 1385}, { 1338, 1386}, 22.942 { 1339, 1387}, { 1340, 1388}, { 1341, 1389}, { 1342, 1390}, { 1343, 1391}, { 1344, 1392}, { 1345, 1393}, 22.943 { 1346, 1394}, { 1347, 1395}, { 1348, 1396}, { 1349, 1397}, { 1350, 1398}, { 1351, 1399}, { 1352, 1400}, 22.944 { 1353, 1401}, { 1354, 1402}, { 1355, 1403}, { 1356, 1404}, { 1357, 1405}, { 1358, 1406}, { 1359, 1407}, 22.945 { 1360, 1408}, { 1361, 1409}, { 1362, 1410}, { 1363, 1411}, { 1364, 1412}, { 1365, 1413}, { 1366, 1414}, 22.946 { 4256, 4304}, { 4257, 4305}, { 4258, 4306}, { 4259, 4307}, { 4260, 4308}, { 4261, 4309}, { 4262, 4310}, 22.947 { 4263, 4311}, { 4264, 4312}, { 4265, 4313}, { 4266, 4314}, { 4267, 4315}, { 4268, 4316}, { 4269, 4317}, 22.948 { 4270, 4318}, { 4271, 4319}, { 4272, 4320}, { 4273, 4321}, { 4274, 4322}, { 4275, 4323}, { 4276, 4324}, 22.949 { 4277, 4325}, { 4278, 4326}, { 4279, 4327}, { 4280, 4328}, { 4281, 4329}, { 4282, 4330}, { 4283, 4331}, 22.950 { 4284, 4332}, { 4285, 4333}, { 4286, 4334}, { 4287, 4335}, { 4288, 4336}, { 4289, 4337}, { 4290, 4338}, 22.951 { 4291, 4339}, { 4292, 4340}, { 4293, 4341}, { 7680, 7681}, { 7682, 7683}, { 7684, 7685}, { 7686, 7687}, 22.952 { 7688, 7689}, { 7690, 7691}, { 7692, 7693}, { 7694, 7695}, { 7696, 7697}, { 7698, 7699}, { 7700, 7701}, 22.953 { 7702, 7703}, { 7704, 7705}, { 7706, 7707}, { 7708, 7709}, { 7710, 7711}, { 7712, 7713}, { 7714, 7715}, 22.954 { 7716, 7717}, { 7718, 7719}, { 7720, 7721}, { 7722, 7723}, { 7724, 7725}, { 7726, 7727}, { 7728, 7729}, 22.955 { 7730, 7731}, { 7732, 7733}, { 7734, 7735}, { 7736, 7737}, { 7738, 7739}, { 7740, 7741}, { 7742, 7743}, 22.956 { 7744, 7745}, { 7746, 7747}, { 7748, 7749}, { 7750, 7751}, { 7752, 7753}, { 7754, 7755}, { 7756, 7757}, 22.957 { 7758, 7759}, { 7760, 7761}, { 7762, 7763}, { 7764, 7765}, { 7766, 7767}, { 7768, 7769}, { 7770, 7771}, 22.958 { 7772, 7773}, { 7774, 7775}, { 7776, 7777}, { 7778, 7779}, { 7780, 7781}, { 7782, 7783}, { 7784, 7785}, 22.959 { 7786, 7787}, { 7788, 7789}, { 7790, 7791}, { 7792, 7793}, { 7794, 7795}, { 7796, 7797}, { 7798, 7799}, 22.960 { 7800, 7801}, { 7802, 7803}, { 7804, 7805}, { 7806, 7807}, { 7808, 7809}, { 7810, 7811}, { 7812, 7813}, 22.961 { 7814, 7815}, { 7816, 7817}, { 7818, 7819}, { 7820, 7821}, { 7822, 7823}, { 7824, 7825}, { 7826, 7827}, 22.962 { 7828, 7829}, { 7840, 7841}, { 7842, 7843}, { 7844, 7845}, { 7846, 7847}, { 7848, 7849}, { 7850, 7851}, 22.963 { 7852, 7853}, { 7854, 7855}, { 7856, 7857}, { 7858, 7859}, { 7860, 7861}, { 7862, 7863}, { 7864, 7865}, 22.964 { 7866, 7867}, { 7868, 7869}, { 7870, 7871}, { 7872, 7873}, { 7874, 7875}, { 7876, 7877}, { 7878, 7879}, 22.965 { 7880, 7881}, { 7882, 7883}, { 7884, 7885}, { 7886, 7887}, { 7888, 7889}, { 7890, 7891}, { 7892, 7893}, 22.966 { 7894, 7895}, { 7896, 7897}, { 7898, 7899}, { 7900, 7901}, { 7902, 7903}, { 7904, 7905}, { 7906, 7907}, 22.967 { 7908, 7909}, { 7910, 7911}, { 7912, 7913}, { 7914, 7915}, { 7916, 7917}, { 7918, 7919}, { 7920, 7921}, 22.968 { 7922, 7923}, { 7924, 7925}, { 7926, 7927}, { 7928, 7929}, { 7944, 7936}, { 7945, 7937}, { 7946, 7938}, 22.969 { 7947, 7939}, { 7948, 7940}, { 7949, 7941}, { 7950, 7942}, { 7951, 7943}, { 7960, 7952}, { 7961, 7953}, 22.970 { 7962, 7954}, { 7963, 7955}, { 7964, 7956}, { 7965, 7957}, { 7976, 7968}, { 7977, 7969}, { 7978, 7970}, 22.971 { 7979, 7971}, { 7980, 7972}, { 7981, 7973}, { 7982, 7974}, { 7983, 7975}, { 7992, 7984}, { 7993, 7985}, 22.972 { 7994, 7986}, { 7995, 7987}, { 7996, 7988}, { 7997, 7989}, { 7998, 7990}, { 7999, 7991}, { 8008, 8000}, 22.973 { 8009, 8001}, { 8010, 8002}, { 8011, 8003}, { 8012, 8004}, { 8013, 8005}, { 8025, 8017}, { 8027, 8019}, 22.974 { 8029, 8021}, { 8031, 8023}, { 8040, 8032}, { 8041, 8033}, { 8042, 8034}, { 8043, 8035}, { 8044, 8036}, 22.975 { 8045, 8037}, { 8046, 8038}, { 8047, 8039}, { 8120, 8112}, { 8121, 8113}, { 8122, 8048}, { 8123, 8049}, 22.976 { 8136, 8050}, { 8137, 8051}, { 8138, 8052}, { 8139, 8053}, { 8152, 8144}, { 8153, 8145}, { 8154, 8054}, 22.977 { 8155, 8055}, { 8168, 8160}, { 8169, 8161}, { 8170, 8058}, { 8171, 8059}, { 8172, 8165}, { 8184, 8056}, 22.978 { 8185, 8057}, { 8186, 8060}, { 8187, 8061}, { 8544, 8560}, { 8545, 8561}, { 8546, 8562}, { 8547, 8563}, 22.979 { 8548, 8564}, { 8549, 8565}, { 8550, 8566}, { 8551, 8567}, { 8552, 8568}, { 8553, 8569}, { 8554, 8570}, 22.980 { 8555, 8571}, { 8556, 8572}, { 8557, 8573}, { 8558, 8574}, { 8559, 8575}, { 9398, 9424}, { 9399, 9425}, 22.981 { 9400, 9426}, { 9401, 9427}, { 9402, 9428}, { 9403, 9429}, { 9404, 9430}, { 9405, 9431}, { 9406, 9432}, 22.982 { 9407, 9433}, { 9408, 9434}, { 9409, 9435}, { 9410, 9436}, { 9411, 9437}, { 9412, 9438}, { 9413, 9439}, 22.983 { 9414, 9440}, { 9415, 9441}, { 9416, 9442}, { 9417, 9443}, { 9418, 9444}, { 9419, 9445}, { 9420, 9446}, 22.984 { 9421, 9447}, { 9422, 9448}, { 9423, 9449}, {65313,65345}, {65314,65346}, {65315,65347}, {65316,65348}, 22.985 {65317,65349}, {65318,65350}, {65319,65351}, {65320,65352}, {65321,65353}, {65322,65354}, {65323,65355}, 22.986 {65324,65356}, {65325,65357}, {65326,65358}, {65327,65359}, {65328,65360}, {65329,65361}, {65330,65362}, 22.987 {65331,65363}, {65332,65364}, {65333,65365}, {65334,65366}, {65335,65367}, {65336,65368}, {65337,65369}, 22.988 {65338,65370}, {65535, 0}}; 22.989 22.990 int OVR_CDECL OVR_towupper(wchar_t charCode) 22.991 { 22.992 // Don't use UnicodeUpperBits! It differs from UnicodeToUpperBits. 22.993 if (UnicodeCharIs(UnicodeToUpperBits, charCode)) 22.994 { 22.995 // To protect from memory overrun in case the character is not found 22.996 // we use one extra fake element in the table {65536, 0}. 22.997 UPInt idx = Alg::LowerBoundSliced( 22.998 UnicodeToUpperTable, 22.999 0, 22.1000 sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1, 22.1001 (UInt16)charCode, 22.1002 CmpUnicodeKey); 22.1003 return UnicodeToUpperTable[idx].Value; 22.1004 } 22.1005 return charCode; 22.1006 } 22.1007 22.1008 int OVR_CDECL OVR_towlower(wchar_t charCode) 22.1009 { 22.1010 // Don't use UnicodeLowerBits! It differs from UnicodeToLowerBits. 22.1011 if (UnicodeCharIs(UnicodeToLowerBits, charCode)) 22.1012 { 22.1013 // To protect from memory overrun in case the character is not found 22.1014 // we use one extra fake element in the table {65536, 0}. 22.1015 UPInt idx = Alg::LowerBoundSliced( 22.1016 UnicodeToLowerTable, 22.1017 0, 22.1018 sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1, 22.1019 (UInt16)charCode, 22.1020 CmpUnicodeKey); 22.1021 return UnicodeToLowerTable[idx].Value; 22.1022 } 22.1023 return charCode; 22.1024 } 22.1025 22.1026 #endif //OVR_NO_WCTYPE 22.1027 22.1028 } // OVR 22.1029 \ No newline at end of file 22.1030 +/************************************************************************************ 22.1031 + 22.1032 +Filename : OVR_Std.cpp 22.1033 +Content : Standard C function implementation 22.1034 +Created : September 19, 2012 22.1035 +Notes : 22.1036 + 22.1037 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 22.1038 + 22.1039 +Use of this software is subject to the terms of the Oculus license 22.1040 +agreement provided at the time of installation or download, or which 22.1041 +otherwise accompanies this software in either electronic or hard copy form. 22.1042 + 22.1043 +************************************************************************************/ 22.1044 + 22.1045 +#include "OVR_Std.h" 22.1046 +#include "OVR_Alg.h" 22.1047 + 22.1048 +// localeconv() call in OVR_strtod() 22.1049 +#include <locale.h> 22.1050 + 22.1051 +namespace OVR { 22.1052 + 22.1053 +// Source for functions not available on all platforms is included here. 22.1054 + 22.1055 +// Case insensitive compare implemented in platform-specific way. 22.1056 +int OVR_CDECL OVR_stricmp(const char* a, const char* b) 22.1057 +{ 22.1058 +#if defined(OVR_OS_WIN32) 22.1059 + #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.1060 + return ::_stricmp(a, b); 22.1061 + #else 22.1062 + return ::stricmp(a, b); 22.1063 + #endif 22.1064 + 22.1065 +#else 22.1066 + return strcasecmp(a, b); 22.1067 +#endif 22.1068 +} 22.1069 + 22.1070 +int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count) 22.1071 +{ 22.1072 +#if defined(OVR_OS_WIN32) 22.1073 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.1074 + return ::_strnicmp(a, b, count); 22.1075 +#else 22.1076 + return ::strnicmp(a, b, count); 22.1077 +#endif 22.1078 + 22.1079 +#else 22.1080 + return strncasecmp(a, b, count); 22.1081 +#endif 22.1082 +} 22.1083 + 22.1084 +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src) 22.1085 +{ 22.1086 +#if defined(OVR_MSVC_SAFESTRING) 22.1087 + wcscpy_s(dest, destsize, src); 22.1088 + return dest; 22.1089 +#elif defined(OVR_OS_WIN32) 22.1090 + OVR_UNUSED(destsize); 22.1091 + wcscpy(dest, src); 22.1092 + return dest; 22.1093 +#else 22.1094 + UPInt l = OVR_wcslen(src) + 1; // incl term null 22.1095 + l = (l < destsize) ? l : destsize; 22.1096 + memcpy(dest, src, l * sizeof(wchar_t)); 22.1097 + return dest; 22.1098 +#endif 22.1099 +} 22.1100 + 22.1101 +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count) 22.1102 +{ 22.1103 +#if defined(OVR_MSVC_SAFESTRING) 22.1104 + wcsncpy_s(dest, destsize, src, count); 22.1105 + return dest; 22.1106 +#else 22.1107 + UPInt srclen = OVR_wcslen(src); 22.1108 + UPInt l = Alg::Min(srclen, count); 22.1109 + l = (l < destsize) ? l : destsize; 22.1110 + memcpy(dest, src, l * sizeof(wchar_t)); 22.1111 + if (count > srclen) 22.1112 + { 22.1113 + UPInt remLen = Alg::Min(destsize - l, (count - srclen)); 22.1114 + memset(&dest[l], 0, sizeof(wchar_t)*remLen); 22.1115 + } 22.1116 + else if (l < destsize) 22.1117 + dest[l] = 0; 22.1118 + return dest; 22.1119 +#endif 22.1120 +} 22.1121 + 22.1122 + 22.1123 +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src) 22.1124 +{ 22.1125 +#if defined(OVR_MSVC_SAFESTRING) 22.1126 + wcscat_s(dest, destsize, src); 22.1127 + return dest; 22.1128 +#elif defined(OVR_OS_WIN32) 22.1129 + OVR_UNUSED(destsize); 22.1130 + wcscat(dest, src); 22.1131 + return dest; 22.1132 +#else 22.1133 + UPInt dstlen = OVR_wcslen(dest); // do not incl term null 22.1134 + UPInt srclen = OVR_wcslen(src) + 1; // incl term null 22.1135 + UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen; 22.1136 + memcpy(dest + dstlen, src, copylen * sizeof(wchar_t)); 22.1137 + return dest; 22.1138 +#endif 22.1139 +} 22.1140 + 22.1141 +UPInt OVR_CDECL OVR_wcslen(const wchar_t* str) 22.1142 +{ 22.1143 +#if defined(OVR_OS_WIN32) 22.1144 + return wcslen(str); 22.1145 +#else 22.1146 + UPInt i = 0; 22.1147 + while(str[i] != '\0') 22.1148 + ++i; 22.1149 + return i; 22.1150 +#endif 22.1151 +} 22.1152 + 22.1153 +int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) 22.1154 +{ 22.1155 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) 22.1156 + return wcscmp(a, b); 22.1157 +#else 22.1158 + // not supported, use custom implementation 22.1159 + const wchar_t *pa = a, *pb = b; 22.1160 + while (*pa && *pb) 22.1161 + { 22.1162 + wchar_t ca = *pa; 22.1163 + wchar_t cb = *pb; 22.1164 + if (ca < cb) 22.1165 + return -1; 22.1166 + else if (ca > cb) 22.1167 + return 1; 22.1168 + pa++; 22.1169 + pb++; 22.1170 + } 22.1171 + if (*pa) 22.1172 + return 1; 22.1173 + else if (*pb) 22.1174 + return -1; 22.1175 + else 22.1176 + return 0; 22.1177 +#endif 22.1178 +} 22.1179 + 22.1180 +int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) 22.1181 +{ 22.1182 +#if defined(OVR_OS_WIN32) 22.1183 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 22.1184 + return ::_wcsicmp(a, b); 22.1185 +#else 22.1186 + return ::wcsicmp(a, b); 22.1187 +#endif 22.1188 +#elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE) 22.1189 + // not supported, use custom implementation 22.1190 + const wchar_t *pa = a, *pb = b; 22.1191 + while (*pa && *pb) 22.1192 + { 22.1193 + wchar_t ca = OVR_towlower(*pa); 22.1194 + wchar_t cb = OVR_towlower(*pb); 22.1195 + if (ca < cb) 22.1196 + return -1; 22.1197 + else if (ca > cb) 22.1198 + return 1; 22.1199 + pa++; 22.1200 + pb++; 22.1201 + } 22.1202 + if (*pa) 22.1203 + return 1; 22.1204 + else if (*pb) 22.1205 + return -1; 22.1206 + else 22.1207 + return 0; 22.1208 +#else 22.1209 + return wcscasecmp(a, b); 22.1210 +#endif 22.1211 +} 22.1212 + 22.1213 +// This function is not inline because of dependency on <locale.h> 22.1214 +double OVR_CDECL OVR_strtod(const char* string, char** tailptr) 22.1215 +{ 22.1216 +#if !defined(OVR_OS_ANDROID) 22.1217 + const char s = *localeconv()->decimal_point; 22.1218 + 22.1219 + if (s != '.') 22.1220 + { 22.1221 + char buffer[347 + 1]; 22.1222 + 22.1223 + OVR_strcpy(buffer, sizeof(buffer), string); 22.1224 + 22.1225 + for (char* c = buffer; *c != '\0'; ++c) 22.1226 + { 22.1227 + if (*c == '.') 22.1228 + { 22.1229 + *c = s; 22.1230 + break; 22.1231 + } 22.1232 + } 22.1233 + 22.1234 + return strtod(buffer, tailptr); 22.1235 + } 22.1236 +#endif 22.1237 + 22.1238 + return strtod(string, tailptr); 22.1239 +} 22.1240 + 22.1241 + 22.1242 +#ifndef OVR_NO_WCTYPE 22.1243 + 22.1244 +//// Use this class to generate Unicode bitsets. For example: 22.1245 +//// 22.1246 +//// UnicodeBitSet bitSet; 22.1247 +//// for(unsigned i = 0; i < 65536; ++i) 22.1248 +//// { 22.1249 +//// if (iswalpha(i)) 22.1250 +//// bitSet.Set(i); 22.1251 +//// } 22.1252 +//// bitSet.Dump(); 22.1253 +//// 22.1254 +////--------------------------------------------------------------- 22.1255 +//class UnicodeBitSet 22.1256 +//{ 22.1257 +//public: 22.1258 +// UnicodeBitSet() 22.1259 +// { 22.1260 +// memset(Offsets, 0, sizeof(Offsets)); 22.1261 +// memset(Bits, 0, sizeof(Bits)); 22.1262 +// } 22.1263 +// 22.1264 +// void Set(unsigned bit) { Bits[bit >> 8][(bit >> 4) & 15] |= 1 << (bit & 15); } 22.1265 +// 22.1266 +// void Dump() 22.1267 +// { 22.1268 +// unsigned i, j; 22.1269 +// unsigned offsetCount = 0; 22.1270 +// for(i = 0; i < 256; ++i) 22.1271 +// { 22.1272 +// if (isNull(i)) Offsets[i] = 0; 22.1273 +// else 22.1274 +// if (isFull(i)) Offsets[i] = 1; 22.1275 +// else Offsets[i] = UInt16(offsetCount++ * 16 + 256); 22.1276 +// } 22.1277 +// for(i = 0; i < 16; ++i) 22.1278 +// { 22.1279 +// for(j = 0; j < 16; ++j) 22.1280 +// { 22.1281 +// printf("%5u,", Offsets[i*16+j]); 22.1282 +// } 22.1283 +// printf("\n"); 22.1284 +// } 22.1285 +// for(i = 0; i < 256; ++i) 22.1286 +// { 22.1287 +// if (Offsets[i] > 255) 22.1288 +// { 22.1289 +// for(j = 0; j < 16; j++) 22.1290 +// { 22.1291 +// printf("%5u,", Bits[i][j]); 22.1292 +// } 22.1293 +// printf("\n"); 22.1294 +// } 22.1295 +// } 22.1296 +// } 22.1297 +// 22.1298 +//private: 22.1299 +// bool isNull(unsigned n) const 22.1300 +// { 22.1301 +// const UInt16* p = Bits[n]; 22.1302 +// for(unsigned i = 0; i < 16; ++i) 22.1303 +// if (p[i] != 0) return false; 22.1304 +// return true; 22.1305 +// } 22.1306 +// 22.1307 +// bool isFull(unsigned n) const 22.1308 +// { 22.1309 +// const UInt16* p = Bits[n]; 22.1310 +// for(unsigned i = 0; i < 16; ++i) 22.1311 +// if (p[i] != 0xFFFF) return false; 22.1312 +// return true; 22.1313 +// } 22.1314 +// 22.1315 +// UInt16 Offsets[256]; 22.1316 +// UInt16 Bits[256][16]; 22.1317 +//}; 22.1318 + 22.1319 + 22.1320 +const UInt16 UnicodeAlnumBits[] = { 22.1321 + 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.1322 + 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.1323 + 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1324 + 672, 688, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1325 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 704, 1, 1, 22.1326 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1327 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1328 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1329 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1330 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 22.1331 + 1, 1, 1, 1, 736, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.1332 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1333 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1334 + 1, 1, 1, 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 0, 22.1335 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1336 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 768, 784, 1, 800, 816, 832, 22.1337 + 0, 0, 0, 1023,65534, 2047,65534, 2047, 0, 0, 0, 524,65535,65407,65535,65407, 22.1338 +65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.1339 + 0, 0, 0, 0, 32, 0, 0, 1024,55104,65535,65531,65535,32767,64767,65535, 15, 22.1340 +65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.1341 + 0, 0, 0,65534,65535, 639,65534,65535, 255, 0, 0, 0, 0,65535, 2047, 7, 22.1342 + 0, 0,65534, 2047,65534, 63, 1023,65535,65535,65535,65535,65535,65535, 8175, 8702, 8191, 22.1343 + 0,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.1344 +65518,65535,65535,58367, 8191,65281,65487, 0,40942,65529,65023,50117, 6559,45184,65487, 3, 22.1345 +34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.1346 +40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.1347 +57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.1348 +57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 12, 22.1349 +65534,65535,65535, 2047,32767, 1023, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.1350 + 1, 0, 1023, 0,65279,65535, 2047,65534, 3843,65279,65535, 8191, 0, 0, 0, 0, 22.1351 +65535,65535,63227, 327, 1023, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 127, 22.1352 +65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.1353 +65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.1354 +32767,32573,65535,65535,65407, 2047,65024, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.1355 +65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.1356 +65535,65535,65535,65535,65535,65535,40959, 127,65534, 2047,65535,65535,65535,65535, 2047, 0, 22.1357 + 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 0, 1023, 0, 22.1358 + 0, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.1359 +65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.1360 +65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.1361 + 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.1362 +64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.1363 + 192, 0, 1022, 1792,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 2047, 22.1364 +65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.1365 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.1366 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.1367 +65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.1368 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.1369 +65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1370 + 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.1371 +65535,65535,65535,16383, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.1372 + 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.1373 + 0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.1374 + 22.1375 +const UInt16 UnicodeAlphaBits[] = { 22.1376 + 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.1377 + 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.1378 + 640, 656, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1379 + 672, 688, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1380 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 704, 1, 1, 22.1381 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1382 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1383 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1384 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1385 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 22.1386 + 1, 1, 1, 1, 736, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.1387 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1388 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1389 + 1, 1, 1, 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 0, 22.1390 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1391 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 768, 784, 1, 800, 816, 832, 22.1392 + 0, 0, 0, 0,65534, 2047,65534, 2047, 0, 0, 0, 0,65535,65407,65535,65407, 22.1393 +65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.1394 + 0, 0, 0, 0, 32, 0, 0, 1024,55104,65535,65531,65535,32767,64767,65535, 15, 22.1395 +65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.1396 + 0, 0, 0,65534,65535, 639,65534,65535, 255, 0, 0, 0, 0,65535, 2047, 7, 22.1397 + 0, 0,65534, 2047,65534, 63, 0,65535,65535,65535,65535,65535,65535, 8175, 8702, 7168, 22.1398 + 0,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.1399 +65518,65535,65535,58367, 8191,65281, 15, 0,40942,65529,65023,50117, 6559,45184, 15, 3, 22.1400 +34788,65529,65023,50029, 6535,24064, 0, 31,45038,65531,65023,58349, 7103, 1, 1, 0, 22.1401 +40942,65529,65023,58317, 6543,45248, 3, 0,51180,54845,50968,50111, 7623, 128, 0, 0, 22.1402 +57326,65533,65023,50159, 7647, 96, 3, 0,57324,65533,65023,50159, 7647,16480, 3, 0, 22.1403 +57324,65533,65023,50175, 7631, 128, 3, 0,65516,64639,65535,12283,32895,65375, 0, 12, 22.1404 +65534,65535,65535, 2047,32767, 0, 0, 0, 9622,65264,60590,15359, 8223,12288, 0, 0, 22.1405 + 1, 0, 0, 0,65279,65535, 2047,65534, 3843,65279,65535, 8191, 0, 0, 0, 0, 22.1406 +65535,65535,63227, 327, 0, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 127, 22.1407 +65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.1408 +65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.1409 +32767,32573,65535,65535,65407, 2047, 0, 0, 0, 0,65535,65535,65535,65535,65535, 31, 22.1410 +65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.1411 +65535,65535,65535,65535,65535,65535,40959, 127,65534, 2047,65535,65535,65535,65535, 2047, 0, 22.1412 + 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 0, 0, 0, 22.1413 + 0, 0,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.1414 +65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.1415 +65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.1416 + 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.1417 +64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.1418 + 192, 0, 1022, 1792,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 2047, 22.1419 +65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.1420 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.1421 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.1422 +65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.1423 +65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.1424 +65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1425 + 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.1426 +65535,65535,65535,16383, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.1427 + 0, 0, 0, 0, 0, 0, 0,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.1428 + 0, 0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.1429 + 22.1430 +const UInt16 UnicodeDigitBits[] = { 22.1431 + 256, 0, 0, 0, 0, 0, 272, 0, 0, 288, 304, 320, 336, 352, 368, 384, 22.1432 + 400, 0, 0, 416, 0, 0, 0, 432, 448, 0, 0, 0, 0, 0, 0, 0, 22.1433 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1434 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1435 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1436 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1437 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1438 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1439 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1440 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1441 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1442 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1443 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1444 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1445 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1446 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 464, 22.1447 + 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 22.1448 + 0, 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 22.1449 + 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.1450 + 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.1451 + 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65408, 0, 22.1452 + 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0,65472, 0, 22.1453 + 0, 0, 0, 0, 0, 0,65472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1454 + 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 0, 22.1455 + 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1456 + 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1457 + 0, 0, 0, 0, 0, 0,65024, 3, 0, 0, 0, 0, 0, 0, 0, 0, 22.1458 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1023, 0, 22.1459 + 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1460 + 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1461 + 22.1462 +const UInt16 UnicodeSpaceBits[] = { 22.1463 + 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1464 + 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1465 + 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1466 + 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1467 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1468 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1469 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1470 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1471 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1472 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1473 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1474 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1475 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1476 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1477 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1478 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1479 +15872, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 22.1480 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 22.1481 + 4095, 0,33536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1482 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1483 + 22.1484 +const UInt16 UnicodeXDigitBits[] = { 22.1485 + 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1486 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1487 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1488 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1489 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1490 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1491 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1492 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1493 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1494 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1495 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1496 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1497 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1498 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1499 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1500 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 272, 22.1501 + 0, 0, 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1502 + 0, 1023, 126, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1503 + 22.1504 +// Uncomment if necessary 22.1505 +//const UInt16 UnicodeCntrlBits[] = { 22.1506 +// 256, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 0, 0, 0, 22.1507 +// 0, 0, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 0, 0, 22.1508 +// 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1509 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1510 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1511 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1512 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1513 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1514 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1515 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1516 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1517 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1518 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1519 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1520 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1521 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 320, 336, 22.1522 +//65535,65535, 0, 0, 0, 0, 0,32768,65535,65535, 0, 0, 0, 0, 0, 0, 22.1523 +//32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1524 +//30720, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1525 +//61440, 0,31744, 0, 0, 0,64512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1526 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32768, 22.1527 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3584}; 22.1528 +// 22.1529 +//const UInt16 UnicodeGraphBits[] = { 22.1530 +// 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.1531 +// 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.1532 +// 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1533 +// 688, 704, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1534 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 1, 1, 22.1535 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1536 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1537 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1538 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1539 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 736, 22.1540 +// 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.1541 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1542 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1543 +// 1, 1, 1, 1, 1, 1, 1, 768, 0, 0, 0, 0, 0, 0, 0, 0, 22.1544 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1545 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 784, 800, 1, 816, 832, 848, 22.1546 +// 0, 0,65534,65535,65535,65535,65535,32767, 0, 0,65534,65535,65535,65535,65535,65535, 22.1547 +//65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.1548 +// 0, 0, 0, 0, 32, 0, 0,17408,55232,65535,65531,65535,32767,64767,65535, 15, 22.1549 +//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.1550 +// 0, 0, 0,65534,65535,65151,65534,65535, 1791, 0, 0,16384, 9,65535, 2047, 31, 22.1551 +// 4096,34816,65534, 2047,65534, 63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191, 22.1552 +//16383,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.1553 +//65518,65535,65535,58367, 8191,65281,65535, 1,40942,65529,65023,50117, 6559,45184,65487, 3, 22.1554 +//34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.1555 +//40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.1556 +//57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.1557 +//57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 28, 22.1558 +//65534,65535,65535, 2047,65535, 4095, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.1559 +//65521, 7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191, 0, 0, 0, 0, 22.1560 +//65535,65535,63227, 327,65535, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 2175, 22.1561 +//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.1562 +//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.1563 +//32767,32573,65535,65535,65407, 2047,65534, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.1564 +//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.1565 +//65535,65535,65535,65535,65535,65535,65535, 127,65534, 8191,65535,65535,65535,65535,16383, 0, 22.1566 +// 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 6128, 1023, 0, 22.1567 +// 2047, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.1568 +//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.1569 +//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.1570 +// 0,65535, 255,65535,16239, 0, 0,57344,24576, 0, 0, 0, 0, 0, 0, 0, 22.1571 +//64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.1572 +// 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1573 +//65486,65523, 1022, 1793,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 4095, 22.1574 +//65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.1575 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.1576 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.1577 +//65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.1578 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.1579 +//65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1580 +// 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.1581 +//65535,65535,65535,65535, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.1582 +// 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191, 22.1583 +//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.1584 +// 22.1585 +//const UInt16 UnicodePrintBits[] = { 22.1586 +// 256, 1, 272, 288, 304, 320, 336, 352, 0, 368, 384, 400, 416, 432, 448, 464, 22.1587 +// 480, 496, 512, 528, 544, 1, 560, 576, 592, 0, 0, 0, 0, 0, 608, 624, 22.1588 +// 640, 656, 0, 672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1589 +// 688, 704, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1590 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 720, 1, 1, 22.1591 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1592 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1593 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1594 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1595 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 736, 22.1596 +// 1, 1, 1, 1, 752, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 22.1597 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1598 +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22.1599 +// 1, 1, 1, 1, 1, 1, 1, 768, 0, 0, 0, 0, 0, 0, 0, 0, 22.1600 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1601 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 784, 800, 1, 816, 832, 848, 22.1602 +// 512, 0,65535,65535,65535,65535,65535,32767, 0, 0,65535,65535,65535,65535,65535,65535, 22.1603 +//65535,65535,65532, 15, 0,65535,65535,65535,65535,65535,16383,63999, 3, 0,16415, 0, 22.1604 +// 0, 0, 0, 0, 32, 0, 0,17408,55232,65535,65531,65535,32767,64767,65535, 15, 22.1605 +//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535, 831, 22.1606 +// 0, 0, 0,65534,65535,65151,65534,65535, 1791, 0, 0,16384, 9,65535, 2047, 31, 22.1607 +// 4096,34816,65534, 2047,65534, 63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191, 22.1608 +//16383,65535, 8191,65535, 0, 0, 0, 0,65535,65535,65535, 1, 0, 0, 0, 0, 22.1609 +//65518,65535,65535,58367, 8191,65281,65535, 1,40942,65529,65023,50117, 6559,45184,65487, 3, 22.1610 +//34788,65529,65023,50029, 6535,24064,65472, 31,45038,65531,65023,58349, 7103, 1,65473, 0, 22.1611 +//40942,65529,65023,58317, 6543,45248,65475, 0,51180,54845,50968,50111, 7623, 128,65408, 0, 22.1612 +//57326,65533,65023,50159, 7647, 96,65475, 0,57324,65533,65023,50159, 7647,16480,65475, 0, 22.1613 +//57324,65533,65023,50175, 7631, 128,65475, 0,65516,64639,65535,12283,32895,65375, 0, 28, 22.1614 +//65534,65535,65535, 2047,65535, 4095, 0, 0, 9622,65264,60590,15359, 8223,13311, 0, 0, 22.1615 +//65521, 7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191, 0, 0, 0, 0, 22.1616 +//65535,65535,63227, 327,65535, 1023, 0, 0, 0, 0,65535,65535, 63,65535,65535, 2175, 22.1617 +//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023, 22.1618 +//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535, 22.1619 +//32767,32573,65535,65535,65407, 2047,65534, 3, 0, 0,65535,65535,65535,65535,65535, 31, 22.1620 +//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 22.1621 +//65535,65535,65535,65535,65535,65535,65535, 127,65534, 8191,65535,65535,65535,65535,16383, 0, 22.1622 +// 0, 0, 0, 0, 0, 0, 0, 0,65535,65535,65535,65535, 511, 6128, 1023, 0, 22.1623 +// 2047, 1023,65535,65535,65527,65535,65535, 255,65535,65535, 1023, 0, 0, 0, 0, 0, 22.1624 +//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023, 22.1625 +//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156, 22.1626 +// 0,65535, 255,65535,16239, 0, 0,57344,24576, 0, 0, 0, 0, 0, 0, 0, 22.1627 +//64644,15919,48464, 1019, 0, 0,65535,65535, 15, 0, 0, 0, 0, 0, 0, 0, 22.1628 +// 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1629 +//65487,65523, 1022, 1793,65534,65535,65535,65535,65535, 31,65534,65535,65535,65535,65535, 4095, 22.1630 +//65504,65535, 8191,65534,65535,65535,65535,65535,32767, 0,65535, 255, 0, 0, 0, 0, 22.1631 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 22.1632 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 63, 0, 0, 0, 0, 0, 22.1633 +//65535,65535,65535,65535,65535,65535,65535,65535, 8191, 0, 0, 0, 0, 0, 0, 0, 22.1634 +//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 15, 0, 0, 0, 0, 0, 22.1635 +//65535,65535,16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1636 +// 127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535, 3, 0,65528,65535,65535, 22.1637 +//65535,65535,65535,65535, 0,65535,65535,65535,65535,65532,65535,65535, 255, 0, 0, 4095, 22.1638 +// 0, 0, 0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959, 22.1639 +//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420, 0, 0}; 22.1640 +// 22.1641 +//const UInt16 UnicodePunctBits[] = { 22.1642 +// 256, 0, 0, 272, 0, 288, 304, 320, 0, 336, 0, 0, 0, 352, 368, 384, 22.1643 +// 400, 0, 0, 416, 0, 0, 432, 448, 464, 0, 0, 0, 0, 0, 0, 0, 22.1644 +// 480, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1645 +// 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1646 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1647 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1648 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1649 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1650 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1651 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1652 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1653 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1654 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1655 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1656 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1657 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 528, 544, 560, 22.1658 +// 0, 0,65534,64512, 1,63488, 1,30720, 0, 0,65534,65535, 0, 128, 0, 128, 22.1659 +// 0, 0, 0, 0, 0, 0, 0,16384, 128, 0, 0, 0, 0, 0, 0, 0, 22.1660 +// 0, 0, 0, 0, 0,64512, 0, 0, 1536, 0, 0,16384, 9, 0, 0, 24, 22.1661 +// 4096,34816, 0, 0, 0, 0,15360, 0, 0, 0, 0, 0, 0, 16, 0, 0, 22.1662 +//16383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1663 +// 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, 22.1664 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 22.1665 +// 0, 0, 0, 0,32768, 3072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1666 +//65520, 7, 0,15360, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 22.1667 +// 0, 0, 0, 0,64512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2048, 22.1668 +// 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1669 +// 0, 0, 0, 0, 0, 0,24576, 0, 0, 6144, 0, 0, 0, 0,14336, 0, 22.1670 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6128, 0, 0, 22.1671 +// 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1672 +// 0,65535, 255,65535,16239, 0, 0,24576,24576, 0, 0, 0, 0, 0, 0, 0, 22.1673 +// 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1674 +//65294,65523, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2048, 22.1675 +// 0, 0, 0,49152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1676 +// 0, 0, 0,65535,65055,65527, 3339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1677 +//63470,35840, 1,47104, 0,10240, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1678 +// 22.1679 +//const UInt16 UnicodeLowerBits[] = { 22.1680 +// 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1681 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 22.1682 +// 384, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1683 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1684 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1685 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1686 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1687 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1688 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1689 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1690 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1691 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1692 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1693 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1694 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1695 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 432, 22.1696 +// 0, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0,32768,65535,65407, 22.1697 +//43690,43690,43690,21930,43861,43690,43690,54442,12585,20004,11562,58961,23392,46421,43690,43565, 22.1698 +//43690,43690,43688, 10, 0,65535,65535,65535,65535,65535,16383, 0, 0, 0, 0, 0, 22.1699 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,61440,65535,32767,43235,43690, 15, 22.1700 +// 0, 0, 0,65535,65535,65535,43690,43690,40962,43690,43690,43690, 4372,43690,43690, 554, 22.1701 +// 0, 0, 0, 0, 0, 0,65534,65535, 255, 0, 0, 0, 0, 0, 0, 0, 22.1702 +//43690,43690,43690,43690,43690,43690,43690,43690,43690, 4074,43690,43690,43690,43690,43690, 682, 22.1703 +// 255, 63, 255, 255, 63, 255, 255,16383,65535,65535,65535,20703, 4316, 207, 255, 4316, 22.1704 +// 0, 0, 0, 0, 0, 0, 0,32768, 0, 0, 0, 0, 0, 0, 0, 0, 22.1705 +//50176, 8,32768, 528, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1706 +// 127, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1707 +// 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1708 +// 22.1709 +//const UInt16 UnicodeUpperBits[] = { 22.1710 +// 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1711 +// 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 22.1712 +// 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1713 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1714 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1715 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1716 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1717 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1718 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1719 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1720 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1721 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1722 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1723 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1724 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1725 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 22.1726 +// 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,32639, 0, 0, 22.1727 +//21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53973, 4526,44464,19114,21845,21974, 22.1728 +//21845,21845,21844, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1729 +// 0, 0, 0, 0, 0, 0, 0, 0,55104,65534, 4091, 0, 0,21532,21845, 0, 22.1730 +//65535,65535,65535, 0, 0, 0,21845,21845,20481,21845,21845,21845, 2187,21845,21845, 277, 22.1731 +// 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1732 +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535,65535, 63, 0, 0, 0, 22.1733 +//21845,21845,21845,21845,21845,21845,21845,21845,21845, 21,21845,21845,21845,21845,21845, 341, 22.1734 +//65280,16128,65280,65280,16128,43520,65280, 0,65280,65280,65280, 7936, 7936, 3840, 7936, 7936, 22.1735 +//14468,15911,15696, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1736 +// 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1737 + 22.1738 + 22.1739 +// MA: March 19, 2010 22.1740 +// Modified ToUpper and ToLower tables to match values expected by AS3 tests. 22.1741 +// ToLower modifications: 22.1742 +// 304 -> 105 22.1743 +// 1024 -> 1104 * 22.1744 +// 1037 -> 1117 * 22.1745 +// UoUpper modifications: 22.1746 +// 255 -> 376 22.1747 +// 305 -> 73 22.1748 +// 383 -> 83 22.1749 +// 1104 -> 1024 * 22.1750 +// 1117 -> 1037 * 22.1751 +// Entries marked with a '*' don't make complete sense based on Unicode manual, although 22.1752 +// they match AS3. 22.1753 + 22.1754 + 22.1755 +static const UInt16 UnicodeToUpperBits[] = { 22.1756 + 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1757 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 368, 22.1758 + 0, 384, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1759 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1760 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1761 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1762 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1763 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1764 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1765 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1766 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1767 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1768 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1769 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1770 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1771 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 416, 22.1772 + 0, 0, 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,65407, 22.1773 +43690,43690,43690,21674,43349,43690,43690,54442, 4392, 516, 8490, 8785,21056,46421,43690,43048, // MA: Modified for AS3. 22.1774 +43690, 170, 0, 0, 0, 2776,33545, 36, 3336, 4, 0, 0, 0, 0, 0, 0, 22.1775 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,61440,65534,32767, 0,43688, 0, 22.1776 + 0, 0, 0,65535,65535,65535,43690,43690, 2,43690,43690,43690, 4372,43690,35498, 554, // MA: Modified for AS3. 22.1777 + 0, 0, 0, 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 22.1778 +43690,43690,43690,43690,43690,43690,43690,43690,43690, 42,43690,43690,43690,43690,43690, 682, 22.1779 + 255, 63, 255, 255, 63, 170, 255,16383, 0, 0, 0, 3, 0, 3, 35, 0, 22.1780 + 0, 0, 0, 0, 0, 0, 0,65535, 0, 0, 0, 0, 0, 0, 0, 0, 22.1781 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535, 1023, 0, 22.1782 + 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1783 + 22.1784 +static const UInt16 UnicodeToLowerBits[] = { 22.1785 + 256, 272, 288, 304, 320, 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1786 + 352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 368, 384, 22.1787 + 0, 400, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1788 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1789 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1790 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1791 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1792 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1793 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1794 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1795 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1796 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1797 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1798 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1799 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1800 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 432, 22.1801 + 0, 0, 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0,65535,32639, 0, 0, 22.1802 +21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53909, 4526,42128,19114,21845,21522,// MA: Modidied for AS3. 22.1803 +21845, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1804 + 0, 0, 0, 0, 0, 0, 0, 0,55104,65534, 4091, 0, 0, 0,21844, 0, 22.1805 +65535,65535,65535, 0, 0, 0,21845,21845, 1,21845,21845,21845, 2186,21845,17749, 277, 22.1806 + 0, 0, 0,65534,65535, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1807 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65535,65535, 63, 0, 0, 0, 22.1808 +21845,21845,21845,21845,21845,21845,21845,21845,21845, 21,21845,21845,21845,21845,21845, 341, 22.1809 +65280,16128,65280,65280,16128,43520,65280, 0, 0, 0, 0, 3840, 3840, 3840, 7936, 3840, 22.1810 + 0, 0, 0, 0, 0, 0,65535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22.1811 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,65472,65535, 0, 0, 0, 22.1812 + 0, 0,65534, 2047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 22.1813 + 22.1814 +struct GUnicodePairType 22.1815 +{ 22.1816 + UInt16 Key, Value; 22.1817 +}; 22.1818 + 22.1819 +static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key) 22.1820 +{ 22.1821 + return a.Key < key; 22.1822 +} 22.1823 + 22.1824 +static const GUnicodePairType UnicodeToUpperTable[] = { 22.1825 +{ 97, 65}, { 98, 66}, { 99, 67}, { 100, 68}, { 101, 69}, { 102, 70}, { 103, 71}, 22.1826 +{ 104, 72}, { 105, 73}, { 106, 74}, { 107, 75}, { 108, 76}, { 109, 77}, { 110, 78}, 22.1827 +{ 111, 79}, { 112, 80}, { 113, 81}, { 114, 82}, { 115, 83}, { 116, 84}, { 117, 85}, 22.1828 +{ 118, 86}, { 119, 87}, { 120, 88}, { 121, 89}, { 122, 90}, { 224, 192}, { 225, 193}, 22.1829 +{ 226, 194}, { 227, 195}, { 228, 196}, { 229, 197}, { 230, 198}, { 231, 199}, { 232, 200}, 22.1830 +{ 233, 201}, { 234, 202}, { 235, 203}, { 236, 204}, { 237, 205}, { 238, 206}, { 239, 207}, 22.1831 +{ 240, 208}, { 241, 209}, { 242, 210}, { 243, 211}, { 244, 212}, { 245, 213}, { 246, 214}, 22.1832 +{ 248, 216}, { 249, 217}, { 250, 218}, { 251, 219}, { 252, 220}, { 253, 221}, { 254, 222}, 22.1833 +{ 255, 376}, { 257, 256}, { 259, 258}, { 261, 260}, { 263, 262}, { 265, 264}, { 267, 266}, 22.1834 +{ 269, 268}, { 271, 270}, { 273, 272}, { 275, 274}, { 277, 276}, { 279, 278}, { 281, 280}, 22.1835 +{ 283, 282}, { 285, 284}, { 287, 286}, { 289, 288}, { 291, 290}, { 293, 292}, { 295, 294}, 22.1836 +{ 297, 296}, { 299, 298}, { 301, 300}, { 303, 302}, { 305, 73}, { 307, 306}, { 309, 308}, { 311, 310}, 22.1837 +{ 314, 313}, { 316, 315}, { 318, 317}, { 320, 319}, { 322, 321}, { 324, 323}, { 326, 325}, 22.1838 +{ 328, 327}, { 331, 330}, { 333, 332}, { 335, 334}, { 337, 336}, { 339, 338}, { 341, 340}, 22.1839 +{ 343, 342}, { 345, 344}, { 347, 346}, { 349, 348}, { 351, 350}, { 353, 352}, { 355, 354}, 22.1840 +{ 357, 356}, { 359, 358}, { 361, 360}, { 363, 362}, { 365, 364}, { 367, 366}, { 369, 368}, 22.1841 +{ 371, 370}, { 373, 372}, { 375, 374}, { 378, 377}, { 380, 379}, { 382, 381}, { 383, 83}, { 387, 386}, 22.1842 +{ 389, 388}, { 392, 391}, { 396, 395}, { 402, 401}, { 409, 408}, { 417, 416}, { 419, 418}, 22.1843 +{ 421, 420}, { 424, 423}, { 429, 428}, { 432, 431}, { 436, 435}, { 438, 437}, { 441, 440}, 22.1844 +{ 445, 444}, { 454, 452}, { 457, 455}, { 460, 458}, { 462, 461}, { 464, 463}, { 466, 465}, 22.1845 +{ 468, 467}, { 470, 469}, { 472, 471}, { 474, 473}, { 476, 475}, { 477, 398}, { 479, 478}, 22.1846 +{ 481, 480}, { 483, 482}, { 485, 484}, { 487, 486}, { 489, 488}, { 491, 490}, { 493, 492}, 22.1847 +{ 495, 494}, { 499, 497}, { 501, 500}, { 507, 506}, { 509, 508}, { 511, 510}, { 513, 512}, 22.1848 +{ 515, 514}, { 517, 516}, { 519, 518}, { 521, 520}, { 523, 522}, { 525, 524}, { 527, 526}, 22.1849 +{ 529, 528}, { 531, 530}, { 533, 532}, { 535, 534}, { 595, 385}, { 596, 390}, { 598, 393}, 22.1850 +{ 599, 394}, { 601, 399}, { 603, 400}, { 608, 403}, { 611, 404}, { 616, 407}, { 617, 406}, 22.1851 +{ 623, 412}, { 626, 413}, { 629, 415}, { 643, 425}, { 648, 430}, { 650, 433}, { 651, 434}, 22.1852 +{ 658, 439}, { 940, 902}, { 941, 904}, { 942, 905}, { 943, 906}, { 945, 913}, { 946, 914}, 22.1853 +{ 947, 915}, { 948, 916}, { 949, 917}, { 950, 918}, { 951, 919}, { 952, 920}, { 953, 921}, 22.1854 +{ 954, 922}, { 955, 923}, { 956, 924}, { 957, 925}, { 958, 926}, { 959, 927}, { 960, 928}, 22.1855 +{ 961, 929}, { 962, 931}, { 963, 931}, { 964, 932}, { 965, 933}, { 966, 934}, { 967, 935}, 22.1856 +{ 968, 936}, { 969, 937}, { 970, 938}, { 971, 939}, { 972, 908}, { 973, 910}, { 974, 911}, 22.1857 +{ 995, 994}, { 997, 996}, { 999, 998}, { 1001, 1000}, { 1003, 1002}, { 1005, 1004}, { 1007, 1006}, 22.1858 +{ 1072, 1040}, { 1073, 1041}, { 1074, 1042}, { 1075, 1043}, { 1076, 1044}, { 1077, 1045}, { 1078, 1046}, 22.1859 +{ 1079, 1047}, { 1080, 1048}, { 1081, 1049}, { 1082, 1050}, { 1083, 1051}, { 1084, 1052}, { 1085, 1053}, 22.1860 +{ 1086, 1054}, { 1087, 1055}, { 1088, 1056}, { 1089, 1057}, { 1090, 1058}, { 1091, 1059}, { 1092, 1060}, 22.1861 +{ 1093, 1061}, { 1094, 1062}, { 1095, 1063}, { 1096, 1064}, { 1097, 1065}, { 1098, 1066}, { 1099, 1067}, 22.1862 +{ 1100, 1068}, { 1101, 1069}, { 1102, 1070}, { 1103, 1071}, { 1104, 1024}, { 1105, 1025}, { 1106, 1026}, { 1107, 1027}, 22.1863 +{ 1108, 1028}, { 1109, 1029}, { 1110, 1030}, { 1111, 1031}, { 1112, 1032}, { 1113, 1033}, { 1114, 1034}, 22.1864 +{ 1115, 1035}, { 1116, 1036}, { 1117, 1037}, { 1118, 1038}, { 1119, 1039}, { 1121, 1120}, { 1123, 1122}, { 1125, 1124}, 22.1865 +{ 1127, 1126}, { 1129, 1128}, { 1131, 1130}, { 1133, 1132}, { 1135, 1134}, { 1137, 1136}, { 1139, 1138}, 22.1866 +{ 1141, 1140}, { 1143, 1142}, { 1145, 1144}, { 1147, 1146}, { 1149, 1148}, { 1151, 1150}, { 1153, 1152}, 22.1867 +{ 1169, 1168}, { 1171, 1170}, { 1173, 1172}, { 1175, 1174}, { 1177, 1176}, { 1179, 1178}, { 1181, 1180}, 22.1868 +{ 1183, 1182}, { 1185, 1184}, { 1187, 1186}, { 1189, 1188}, { 1191, 1190}, { 1193, 1192}, { 1195, 1194}, 22.1869 +{ 1197, 1196}, { 1199, 1198}, { 1201, 1200}, { 1203, 1202}, { 1205, 1204}, { 1207, 1206}, { 1209, 1208}, 22.1870 +{ 1211, 1210}, { 1213, 1212}, { 1215, 1214}, { 1218, 1217}, { 1220, 1219}, { 1224, 1223}, { 1228, 1227}, 22.1871 +{ 1233, 1232}, { 1235, 1234}, { 1237, 1236}, { 1239, 1238}, { 1241, 1240}, { 1243, 1242}, { 1245, 1244}, 22.1872 +{ 1247, 1246}, { 1249, 1248}, { 1251, 1250}, { 1253, 1252}, { 1255, 1254}, { 1257, 1256}, { 1259, 1258}, 22.1873 +{ 1263, 1262}, { 1265, 1264}, { 1267, 1266}, { 1269, 1268}, { 1273, 1272}, { 1377, 1329}, { 1378, 1330}, 22.1874 +{ 1379, 1331}, { 1380, 1332}, { 1381, 1333}, { 1382, 1334}, { 1383, 1335}, { 1384, 1336}, { 1385, 1337}, 22.1875 +{ 1386, 1338}, { 1387, 1339}, { 1388, 1340}, { 1389, 1341}, { 1390, 1342}, { 1391, 1343}, { 1392, 1344}, 22.1876 +{ 1393, 1345}, { 1394, 1346}, { 1395, 1347}, { 1396, 1348}, { 1397, 1349}, { 1398, 1350}, { 1399, 1351}, 22.1877 +{ 1400, 1352}, { 1401, 1353}, { 1402, 1354}, { 1403, 1355}, { 1404, 1356}, { 1405, 1357}, { 1406, 1358}, 22.1878 +{ 1407, 1359}, { 1408, 1360}, { 1409, 1361}, { 1410, 1362}, { 1411, 1363}, { 1412, 1364}, { 1413, 1365}, 22.1879 +{ 1414, 1366}, { 7681, 7680}, { 7683, 7682}, { 7685, 7684}, { 7687, 7686}, { 7689, 7688}, { 7691, 7690}, 22.1880 +{ 7693, 7692}, { 7695, 7694}, { 7697, 7696}, { 7699, 7698}, { 7701, 7700}, { 7703, 7702}, { 7705, 7704}, 22.1881 +{ 7707, 7706}, { 7709, 7708}, { 7711, 7710}, { 7713, 7712}, { 7715, 7714}, { 7717, 7716}, { 7719, 7718}, 22.1882 +{ 7721, 7720}, { 7723, 7722}, { 7725, 7724}, { 7727, 7726}, { 7729, 7728}, { 7731, 7730}, { 7733, 7732}, 22.1883 +{ 7735, 7734}, { 7737, 7736}, { 7739, 7738}, { 7741, 7740}, { 7743, 7742}, { 7745, 7744}, { 7747, 7746}, 22.1884 +{ 7749, 7748}, { 7751, 7750}, { 7753, 7752}, { 7755, 7754}, { 7757, 7756}, { 7759, 7758}, { 7761, 7760}, 22.1885 +{ 7763, 7762}, { 7765, 7764}, { 7767, 7766}, { 7769, 7768}, { 7771, 7770}, { 7773, 7772}, { 7775, 7774}, 22.1886 +{ 7777, 7776}, { 7779, 7778}, { 7781, 7780}, { 7783, 7782}, { 7785, 7784}, { 7787, 7786}, { 7789, 7788}, 22.1887 +{ 7791, 7790}, { 7793, 7792}, { 7795, 7794}, { 7797, 7796}, { 7799, 7798}, { 7801, 7800}, { 7803, 7802}, 22.1888 +{ 7805, 7804}, { 7807, 7806}, { 7809, 7808}, { 7811, 7810}, { 7813, 7812}, { 7815, 7814}, { 7817, 7816}, 22.1889 +{ 7819, 7818}, { 7821, 7820}, { 7823, 7822}, { 7825, 7824}, { 7827, 7826}, { 7829, 7828}, { 7841, 7840}, 22.1890 +{ 7843, 7842}, { 7845, 7844}, { 7847, 7846}, { 7849, 7848}, { 7851, 7850}, { 7853, 7852}, { 7855, 7854}, 22.1891 +{ 7857, 7856}, { 7859, 7858}, { 7861, 7860}, { 7863, 7862}, { 7865, 7864}, { 7867, 7866}, { 7869, 7868}, 22.1892 +{ 7871, 7870}, { 7873, 7872}, { 7875, 7874}, { 7877, 7876}, { 7879, 7878}, { 7881, 7880}, { 7883, 7882}, 22.1893 +{ 7885, 7884}, { 7887, 7886}, { 7889, 7888}, { 7891, 7890}, { 7893, 7892}, { 7895, 7894}, { 7897, 7896}, 22.1894 +{ 7899, 7898}, { 7901, 7900}, { 7903, 7902}, { 7905, 7904}, { 7907, 7906}, { 7909, 7908}, { 7911, 7910}, 22.1895 +{ 7913, 7912}, { 7915, 7914}, { 7917, 7916}, { 7919, 7918}, { 7921, 7920}, { 7923, 7922}, { 7925, 7924}, 22.1896 +{ 7927, 7926}, { 7929, 7928}, { 7936, 7944}, { 7937, 7945}, { 7938, 7946}, { 7939, 7947}, { 7940, 7948}, 22.1897 +{ 7941, 7949}, { 7942, 7950}, { 7943, 7951}, { 7952, 7960}, { 7953, 7961}, { 7954, 7962}, { 7955, 7963}, 22.1898 +{ 7956, 7964}, { 7957, 7965}, { 7968, 7976}, { 7969, 7977}, { 7970, 7978}, { 7971, 7979}, { 7972, 7980}, 22.1899 +{ 7973, 7981}, { 7974, 7982}, { 7975, 7983}, { 7984, 7992}, { 7985, 7993}, { 7986, 7994}, { 7987, 7995}, 22.1900 +{ 7988, 7996}, { 7989, 7997}, { 7990, 7998}, { 7991, 7999}, { 8000, 8008}, { 8001, 8009}, { 8002, 8010}, 22.1901 +{ 8003, 8011}, { 8004, 8012}, { 8005, 8013}, { 8017, 8025}, { 8019, 8027}, { 8021, 8029}, { 8023, 8031}, 22.1902 +{ 8032, 8040}, { 8033, 8041}, { 8034, 8042}, { 8035, 8043}, { 8036, 8044}, { 8037, 8045}, { 8038, 8046}, 22.1903 +{ 8039, 8047}, { 8048, 8122}, { 8049, 8123}, { 8050, 8136}, { 8051, 8137}, { 8052, 8138}, { 8053, 8139}, 22.1904 +{ 8054, 8154}, { 8055, 8155}, { 8056, 8184}, { 8057, 8185}, { 8058, 8170}, { 8059, 8171}, { 8060, 8186}, 22.1905 +{ 8061, 8187}, { 8112, 8120}, { 8113, 8121}, { 8144, 8152}, { 8145, 8153}, { 8160, 8168}, { 8161, 8169}, 22.1906 +{ 8165, 8172}, { 8560, 8544}, { 8561, 8545}, { 8562, 8546}, { 8563, 8547}, { 8564, 8548}, { 8565, 8549}, 22.1907 +{ 8566, 8550}, { 8567, 8551}, { 8568, 8552}, { 8569, 8553}, { 8570, 8554}, { 8571, 8555}, { 8572, 8556}, 22.1908 +{ 8573, 8557}, { 8574, 8558}, { 8575, 8559}, { 9424, 9398}, { 9425, 9399}, { 9426, 9400}, { 9427, 9401}, 22.1909 +{ 9428, 9402}, { 9429, 9403}, { 9430, 9404}, { 9431, 9405}, { 9432, 9406}, { 9433, 9407}, { 9434, 9408}, 22.1910 +{ 9435, 9409}, { 9436, 9410}, { 9437, 9411}, { 9438, 9412}, { 9439, 9413}, { 9440, 9414}, { 9441, 9415}, 22.1911 +{ 9442, 9416}, { 9443, 9417}, { 9444, 9418}, { 9445, 9419}, { 9446, 9420}, { 9447, 9421}, { 9448, 9422}, 22.1912 +{ 9449, 9423}, {65345,65313}, {65346,65314}, {65347,65315}, {65348,65316}, {65349,65317}, {65350,65318}, 22.1913 +{65351,65319}, {65352,65320}, {65353,65321}, {65354,65322}, {65355,65323}, {65356,65324}, {65357,65325}, 22.1914 +{65358,65326}, {65359,65327}, {65360,65328}, {65361,65329}, {65362,65330}, {65363,65331}, {65364,65332}, 22.1915 +{65365,65333}, {65366,65334}, {65367,65335}, {65368,65336}, {65369,65337}, {65370,65338}, {65535, 0}}; 22.1916 + 22.1917 +static const GUnicodePairType UnicodeToLowerTable[] = { 22.1918 +{ 65, 97}, { 66, 98}, { 67, 99}, { 68, 100}, { 69, 101}, { 70, 102}, { 71, 103}, 22.1919 +{ 72, 104}, { 73, 105}, { 74, 106}, { 75, 107}, { 76, 108}, { 77, 109}, { 78, 110}, 22.1920 +{ 79, 111}, { 80, 112}, { 81, 113}, { 82, 114}, { 83, 115}, { 84, 116}, { 85, 117}, 22.1921 +{ 86, 118}, { 87, 119}, { 88, 120}, { 89, 121}, { 90, 122}, { 192, 224}, { 193, 225}, 22.1922 +{ 194, 226}, { 195, 227}, { 196, 228}, { 197, 229}, { 198, 230}, { 199, 231}, { 200, 232}, 22.1923 +{ 201, 233}, { 202, 234}, { 203, 235}, { 204, 236}, { 205, 237}, { 206, 238}, { 207, 239}, 22.1924 +{ 208, 240}, { 209, 241}, { 210, 242}, { 211, 243}, { 212, 244}, { 213, 245}, { 214, 246}, 22.1925 +{ 216, 248}, { 217, 249}, { 218, 250}, { 219, 251}, { 220, 252}, { 221, 253}, { 222, 254}, 22.1926 +{ 256, 257}, { 258, 259}, { 260, 261}, { 262, 263}, { 264, 265}, { 266, 267}, { 268, 269}, 22.1927 +{ 270, 271}, { 272, 273}, { 274, 275}, { 276, 277}, { 278, 279}, { 280, 281}, { 282, 283}, 22.1928 +{ 284, 285}, { 286, 287}, { 288, 289}, { 290, 291}, { 292, 293}, { 294, 295}, { 296, 297}, 22.1929 +{ 298, 299}, { 300, 301}, { 302, 303}, { 304, 105}, { 306, 307}, { 308, 309}, { 310, 311}, { 313, 314}, 22.1930 +{ 315, 316}, { 317, 318}, { 319, 320}, { 321, 322}, { 323, 324}, { 325, 326}, { 327, 328}, 22.1931 +{ 330, 331}, { 332, 333}, { 334, 335}, { 336, 337}, { 338, 339}, { 340, 341}, { 342, 343}, 22.1932 +{ 344, 345}, { 346, 347}, { 348, 349}, { 350, 351}, { 352, 353}, { 354, 355}, { 356, 357}, 22.1933 +{ 358, 359}, { 360, 361}, { 362, 363}, { 364, 365}, { 366, 367}, { 368, 369}, { 370, 371}, 22.1934 +{ 372, 373}, { 374, 375}, { 376, 255}, { 377, 378}, { 379, 380}, { 381, 382}, { 385, 595}, 22.1935 +{ 386, 387}, { 388, 389}, { 390, 596}, { 391, 392}, { 393, 598}, { 394, 599}, { 395, 396}, 22.1936 +{ 398, 477}, { 399, 601}, { 400, 603}, { 401, 402}, { 403, 608}, { 404, 611}, { 406, 617}, 22.1937 +{ 407, 616}, { 408, 409}, { 412, 623}, { 413, 626}, { 415, 629}, { 416, 417}, { 418, 419}, 22.1938 +{ 420, 421}, { 423, 424}, { 425, 643}, { 428, 429}, { 430, 648}, { 431, 432}, { 433, 650}, 22.1939 +{ 434, 651}, { 435, 436}, { 437, 438}, { 439, 658}, { 440, 441}, { 444, 445}, { 452, 454}, 22.1940 +{ 455, 457}, { 458, 460}, { 461, 462}, { 463, 464}, { 465, 466}, { 467, 468}, { 469, 470}, 22.1941 +{ 471, 472}, { 473, 474}, { 475, 476}, { 478, 479}, { 480, 481}, { 482, 483}, { 484, 485}, 22.1942 +{ 486, 487}, { 488, 489}, { 490, 491}, { 492, 493}, { 494, 495}, { 497, 499}, { 500, 501}, 22.1943 +{ 506, 507}, { 508, 509}, { 510, 511}, { 512, 513}, { 514, 515}, { 516, 517}, { 518, 519}, 22.1944 +{ 520, 521}, { 522, 523}, { 524, 525}, { 526, 527}, { 528, 529}, { 530, 531}, { 532, 533}, 22.1945 +{ 534, 535}, { 902, 940}, { 904, 941}, { 905, 942}, { 906, 943}, { 908, 972}, { 910, 973}, 22.1946 +{ 911, 974}, { 913, 945}, { 914, 946}, { 915, 947}, { 916, 948}, { 917, 949}, { 918, 950}, 22.1947 +{ 919, 951}, { 920, 952}, { 921, 953}, { 922, 954}, { 923, 955}, { 924, 956}, { 925, 957}, 22.1948 +{ 926, 958}, { 927, 959}, { 928, 960}, { 929, 961}, { 931, 963}, { 932, 964}, { 933, 965}, 22.1949 +{ 934, 966}, { 935, 967}, { 936, 968}, { 937, 969}, { 938, 970}, { 939, 971}, { 994, 995}, 22.1950 +{ 996, 997}, { 998, 999}, { 1000, 1001}, { 1002, 1003}, { 1004, 1005}, { 1006, 1007}, { 1024, 1104}, { 1025, 1105}, 22.1951 +{ 1026, 1106}, { 1027, 1107}, { 1028, 1108}, { 1029, 1109}, { 1030, 1110}, { 1031, 1111}, { 1032, 1112}, 22.1952 +{ 1033, 1113}, { 1034, 1114}, { 1035, 1115}, { 1036, 1116}, { 1037, 1117}, { 1038, 1118}, { 1039, 1119}, { 1040, 1072}, 22.1953 +{ 1041, 1073}, { 1042, 1074}, { 1043, 1075}, { 1044, 1076}, { 1045, 1077}, { 1046, 1078}, { 1047, 1079}, 22.1954 +{ 1048, 1080}, { 1049, 1081}, { 1050, 1082}, { 1051, 1083}, { 1052, 1084}, { 1053, 1085}, { 1054, 1086}, 22.1955 +{ 1055, 1087}, { 1056, 1088}, { 1057, 1089}, { 1058, 1090}, { 1059, 1091}, { 1060, 1092}, { 1061, 1093}, 22.1956 +{ 1062, 1094}, { 1063, 1095}, { 1064, 1096}, { 1065, 1097}, { 1066, 1098}, { 1067, 1099}, { 1068, 1100}, 22.1957 +{ 1069, 1101}, { 1070, 1102}, { 1071, 1103}, { 1120, 1121}, { 1122, 1123}, { 1124, 1125}, { 1126, 1127}, 22.1958 +{ 1128, 1129}, { 1130, 1131}, { 1132, 1133}, { 1134, 1135}, { 1136, 1137}, { 1138, 1139}, { 1140, 1141}, 22.1959 +{ 1142, 1143}, { 1144, 1145}, { 1146, 1147}, { 1148, 1149}, { 1150, 1151}, { 1152, 1153}, { 1168, 1169}, 22.1960 +{ 1170, 1171}, { 1172, 1173}, { 1174, 1175}, { 1176, 1177}, { 1178, 1179}, { 1180, 1181}, { 1182, 1183}, 22.1961 +{ 1184, 1185}, { 1186, 1187}, { 1188, 1189}, { 1190, 1191}, { 1192, 1193}, { 1194, 1195}, { 1196, 1197}, 22.1962 +{ 1198, 1199}, { 1200, 1201}, { 1202, 1203}, { 1204, 1205}, { 1206, 1207}, { 1208, 1209}, { 1210, 1211}, 22.1963 +{ 1212, 1213}, { 1214, 1215}, { 1217, 1218}, { 1219, 1220}, { 1223, 1224}, { 1227, 1228}, { 1232, 1233}, 22.1964 +{ 1234, 1235}, { 1236, 1237}, { 1238, 1239}, { 1240, 1241}, { 1242, 1243}, { 1244, 1245}, { 1246, 1247}, 22.1965 +{ 1248, 1249}, { 1250, 1251}, { 1252, 1253}, { 1254, 1255}, { 1256, 1257}, { 1258, 1259}, { 1262, 1263}, 22.1966 +{ 1264, 1265}, { 1266, 1267}, { 1268, 1269}, { 1272, 1273}, { 1329, 1377}, { 1330, 1378}, { 1331, 1379}, 22.1967 +{ 1332, 1380}, { 1333, 1381}, { 1334, 1382}, { 1335, 1383}, { 1336, 1384}, { 1337, 1385}, { 1338, 1386}, 22.1968 +{ 1339, 1387}, { 1340, 1388}, { 1341, 1389}, { 1342, 1390}, { 1343, 1391}, { 1344, 1392}, { 1345, 1393}, 22.1969 +{ 1346, 1394}, { 1347, 1395}, { 1348, 1396}, { 1349, 1397}, { 1350, 1398}, { 1351, 1399}, { 1352, 1400}, 22.1970 +{ 1353, 1401}, { 1354, 1402}, { 1355, 1403}, { 1356, 1404}, { 1357, 1405}, { 1358, 1406}, { 1359, 1407}, 22.1971 +{ 1360, 1408}, { 1361, 1409}, { 1362, 1410}, { 1363, 1411}, { 1364, 1412}, { 1365, 1413}, { 1366, 1414}, 22.1972 +{ 4256, 4304}, { 4257, 4305}, { 4258, 4306}, { 4259, 4307}, { 4260, 4308}, { 4261, 4309}, { 4262, 4310}, 22.1973 +{ 4263, 4311}, { 4264, 4312}, { 4265, 4313}, { 4266, 4314}, { 4267, 4315}, { 4268, 4316}, { 4269, 4317}, 22.1974 +{ 4270, 4318}, { 4271, 4319}, { 4272, 4320}, { 4273, 4321}, { 4274, 4322}, { 4275, 4323}, { 4276, 4324}, 22.1975 +{ 4277, 4325}, { 4278, 4326}, { 4279, 4327}, { 4280, 4328}, { 4281, 4329}, { 4282, 4330}, { 4283, 4331}, 22.1976 +{ 4284, 4332}, { 4285, 4333}, { 4286, 4334}, { 4287, 4335}, { 4288, 4336}, { 4289, 4337}, { 4290, 4338}, 22.1977 +{ 4291, 4339}, { 4292, 4340}, { 4293, 4341}, { 7680, 7681}, { 7682, 7683}, { 7684, 7685}, { 7686, 7687}, 22.1978 +{ 7688, 7689}, { 7690, 7691}, { 7692, 7693}, { 7694, 7695}, { 7696, 7697}, { 7698, 7699}, { 7700, 7701}, 22.1979 +{ 7702, 7703}, { 7704, 7705}, { 7706, 7707}, { 7708, 7709}, { 7710, 7711}, { 7712, 7713}, { 7714, 7715}, 22.1980 +{ 7716, 7717}, { 7718, 7719}, { 7720, 7721}, { 7722, 7723}, { 7724, 7725}, { 7726, 7727}, { 7728, 7729}, 22.1981 +{ 7730, 7731}, { 7732, 7733}, { 7734, 7735}, { 7736, 7737}, { 7738, 7739}, { 7740, 7741}, { 7742, 7743}, 22.1982 +{ 7744, 7745}, { 7746, 7747}, { 7748, 7749}, { 7750, 7751}, { 7752, 7753}, { 7754, 7755}, { 7756, 7757}, 22.1983 +{ 7758, 7759}, { 7760, 7761}, { 7762, 7763}, { 7764, 7765}, { 7766, 7767}, { 7768, 7769}, { 7770, 7771}, 22.1984 +{ 7772, 7773}, { 7774, 7775}, { 7776, 7777}, { 7778, 7779}, { 7780, 7781}, { 7782, 7783}, { 7784, 7785}, 22.1985 +{ 7786, 7787}, { 7788, 7789}, { 7790, 7791}, { 7792, 7793}, { 7794, 7795}, { 7796, 7797}, { 7798, 7799}, 22.1986 +{ 7800, 7801}, { 7802, 7803}, { 7804, 7805}, { 7806, 7807}, { 7808, 7809}, { 7810, 7811}, { 7812, 7813}, 22.1987 +{ 7814, 7815}, { 7816, 7817}, { 7818, 7819}, { 7820, 7821}, { 7822, 7823}, { 7824, 7825}, { 7826, 7827}, 22.1988 +{ 7828, 7829}, { 7840, 7841}, { 7842, 7843}, { 7844, 7845}, { 7846, 7847}, { 7848, 7849}, { 7850, 7851}, 22.1989 +{ 7852, 7853}, { 7854, 7855}, { 7856, 7857}, { 7858, 7859}, { 7860, 7861}, { 7862, 7863}, { 7864, 7865}, 22.1990 +{ 7866, 7867}, { 7868, 7869}, { 7870, 7871}, { 7872, 7873}, { 7874, 7875}, { 7876, 7877}, { 7878, 7879}, 22.1991 +{ 7880, 7881}, { 7882, 7883}, { 7884, 7885}, { 7886, 7887}, { 7888, 7889}, { 7890, 7891}, { 7892, 7893}, 22.1992 +{ 7894, 7895}, { 7896, 7897}, { 7898, 7899}, { 7900, 7901}, { 7902, 7903}, { 7904, 7905}, { 7906, 7907}, 22.1993 +{ 7908, 7909}, { 7910, 7911}, { 7912, 7913}, { 7914, 7915}, { 7916, 7917}, { 7918, 7919}, { 7920, 7921}, 22.1994 +{ 7922, 7923}, { 7924, 7925}, { 7926, 7927}, { 7928, 7929}, { 7944, 7936}, { 7945, 7937}, { 7946, 7938}, 22.1995 +{ 7947, 7939}, { 7948, 7940}, { 7949, 7941}, { 7950, 7942}, { 7951, 7943}, { 7960, 7952}, { 7961, 7953}, 22.1996 +{ 7962, 7954}, { 7963, 7955}, { 7964, 7956}, { 7965, 7957}, { 7976, 7968}, { 7977, 7969}, { 7978, 7970}, 22.1997 +{ 7979, 7971}, { 7980, 7972}, { 7981, 7973}, { 7982, 7974}, { 7983, 7975}, { 7992, 7984}, { 7993, 7985}, 22.1998 +{ 7994, 7986}, { 7995, 7987}, { 7996, 7988}, { 7997, 7989}, { 7998, 7990}, { 7999, 7991}, { 8008, 8000}, 22.1999 +{ 8009, 8001}, { 8010, 8002}, { 8011, 8003}, { 8012, 8004}, { 8013, 8005}, { 8025, 8017}, { 8027, 8019}, 22.2000 +{ 8029, 8021}, { 8031, 8023}, { 8040, 8032}, { 8041, 8033}, { 8042, 8034}, { 8043, 8035}, { 8044, 8036}, 22.2001 +{ 8045, 8037}, { 8046, 8038}, { 8047, 8039}, { 8120, 8112}, { 8121, 8113}, { 8122, 8048}, { 8123, 8049}, 22.2002 +{ 8136, 8050}, { 8137, 8051}, { 8138, 8052}, { 8139, 8053}, { 8152, 8144}, { 8153, 8145}, { 8154, 8054}, 22.2003 +{ 8155, 8055}, { 8168, 8160}, { 8169, 8161}, { 8170, 8058}, { 8171, 8059}, { 8172, 8165}, { 8184, 8056}, 22.2004 +{ 8185, 8057}, { 8186, 8060}, { 8187, 8061}, { 8544, 8560}, { 8545, 8561}, { 8546, 8562}, { 8547, 8563}, 22.2005 +{ 8548, 8564}, { 8549, 8565}, { 8550, 8566}, { 8551, 8567}, { 8552, 8568}, { 8553, 8569}, { 8554, 8570}, 22.2006 +{ 8555, 8571}, { 8556, 8572}, { 8557, 8573}, { 8558, 8574}, { 8559, 8575}, { 9398, 9424}, { 9399, 9425}, 22.2007 +{ 9400, 9426}, { 9401, 9427}, { 9402, 9428}, { 9403, 9429}, { 9404, 9430}, { 9405, 9431}, { 9406, 9432}, 22.2008 +{ 9407, 9433}, { 9408, 9434}, { 9409, 9435}, { 9410, 9436}, { 9411, 9437}, { 9412, 9438}, { 9413, 9439}, 22.2009 +{ 9414, 9440}, { 9415, 9441}, { 9416, 9442}, { 9417, 9443}, { 9418, 9444}, { 9419, 9445}, { 9420, 9446}, 22.2010 +{ 9421, 9447}, { 9422, 9448}, { 9423, 9449}, {65313,65345}, {65314,65346}, {65315,65347}, {65316,65348}, 22.2011 +{65317,65349}, {65318,65350}, {65319,65351}, {65320,65352}, {65321,65353}, {65322,65354}, {65323,65355}, 22.2012 +{65324,65356}, {65325,65357}, {65326,65358}, {65327,65359}, {65328,65360}, {65329,65361}, {65330,65362}, 22.2013 +{65331,65363}, {65332,65364}, {65333,65365}, {65334,65366}, {65335,65367}, {65336,65368}, {65337,65369}, 22.2014 +{65338,65370}, {65535, 0}}; 22.2015 + 22.2016 +int OVR_CDECL OVR_towupper(wchar_t charCode) 22.2017 +{ 22.2018 + // Don't use UnicodeUpperBits! It differs from UnicodeToUpperBits. 22.2019 + if (UnicodeCharIs(UnicodeToUpperBits, charCode)) 22.2020 + { 22.2021 + // To protect from memory overrun in case the character is not found 22.2022 + // we use one extra fake element in the table {65536, 0}. 22.2023 + UPInt idx = Alg::LowerBoundSliced( 22.2024 + UnicodeToUpperTable, 22.2025 + 0, 22.2026 + sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1, 22.2027 + (UInt16)charCode, 22.2028 + CmpUnicodeKey); 22.2029 + return UnicodeToUpperTable[idx].Value; 22.2030 + } 22.2031 + return charCode; 22.2032 +} 22.2033 + 22.2034 +int OVR_CDECL OVR_towlower(wchar_t charCode) 22.2035 +{ 22.2036 + // Don't use UnicodeLowerBits! It differs from UnicodeToLowerBits. 22.2037 + if (UnicodeCharIs(UnicodeToLowerBits, charCode)) 22.2038 + { 22.2039 + // To protect from memory overrun in case the character is not found 22.2040 + // we use one extra fake element in the table {65536, 0}. 22.2041 + UPInt idx = Alg::LowerBoundSliced( 22.2042 + UnicodeToLowerTable, 22.2043 + 0, 22.2044 + sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1, 22.2045 + (UInt16)charCode, 22.2046 + CmpUnicodeKey); 22.2047 + return UnicodeToLowerTable[idx].Value; 22.2048 + } 22.2049 + return charCode; 22.2050 +} 22.2051 + 22.2052 +#endif //OVR_NO_WCTYPE 22.2053 + 22.2054 +} // OVR
23.1 --- a/libovr/Src/Kernel/OVR_Std.h Sat Sep 14 17:51:03 2013 +0300 23.2 +++ b/libovr/Src/Kernel/OVR_Std.h Sun Sep 15 04:10:05 2013 +0300 23.3 @@ -1,1 +1,503 @@ 23.4 -/************************************************************************************ 23.5 23.6 PublicHeader: OVR.h 23.7 Filename : OVR_Std.h 23.8 Content : Standard C function interface 23.9 Created : September 19, 2012 23.10 Notes : 23.11 23.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 23.13 23.14 Use of this software is subject to the terms of the Oculus license 23.15 agreement provided at the time of installation or download, or which 23.16 otherwise accompanies this software in either electronic or hard copy form. 23.17 23.18 ************************************************************************************/ 23.19 23.20 #ifndef OVR_Std_h 23.21 #define OVR_Std_h 23.22 23.23 #include "OVR_Types.h" 23.24 #include <stdarg.h> // for va_list args 23.25 #include <string.h> 23.26 #include <stdio.h> 23.27 #include <stdlib.h> 23.28 #include <ctype.h> 23.29 23.30 #if !defined(OVR_OS_WINCE) && defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 23.31 #define OVR_MSVC_SAFESTRING 23.32 #include <errno.h> 23.33 #endif 23.34 23.35 // Wide-char funcs 23.36 #include <wchar.h> 23.37 #include <wctype.h> 23.38 23.39 namespace OVR { 23.40 23.41 #if defined(OVR_OS_WIN32) 23.42 inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix) 23.43 { 23.44 #if defined(OVR_MSVC_SAFESTRING) 23.45 _itoa_s(val, dest, destsize, radix); 23.46 return dest; 23.47 #else 23.48 OVR_UNUSED(destsize); 23.49 return itoa(val, dest, radix); 23.50 #endif 23.51 } 23.52 #else // OVR_OS_WIN32 23.53 inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) 23.54 { 23.55 if (val == 0) 23.56 { 23.57 if (len > 1) 23.58 { 23.59 dest[0] = '0'; 23.60 dest[1] = '\0'; 23.61 } 23.62 return dest; 23.63 } 23.64 23.65 int cur = val; 23.66 unsigned int i = 0; 23.67 unsigned int sign = 0; 23.68 23.69 if (val < 0) 23.70 { 23.71 val = -val; 23.72 sign = 1; 23.73 } 23.74 23.75 while ((val != 0) && (i < (len - 1 - sign))) 23.76 { 23.77 cur = val % radix; 23.78 val /= radix; 23.79 23.80 if (radix == 16) 23.81 { 23.82 switch(cur) 23.83 { 23.84 case 10: 23.85 dest[i] = 'a'; 23.86 break; 23.87 case 11: 23.88 dest[i] = 'b'; 23.89 break; 23.90 case 12: 23.91 dest[i] = 'c'; 23.92 break; 23.93 case 13: 23.94 dest[i] = 'd'; 23.95 break; 23.96 case 14: 23.97 dest[i] = 'e'; 23.98 break; 23.99 case 15: 23.100 dest[i] = 'f'; 23.101 break; 23.102 default: 23.103 dest[i] = (char)('0' + cur); 23.104 break; 23.105 } 23.106 } 23.107 else 23.108 { 23.109 dest[i] = (char)('0' + cur); 23.110 } 23.111 ++i; 23.112 } 23.113 23.114 if (sign) 23.115 { 23.116 dest[i++] = '-'; 23.117 } 23.118 23.119 for (unsigned int j = 0; j < i / 2; ++j) 23.120 { 23.121 char tmp = dest[j]; 23.122 dest[j] = dest[i - 1 - j]; 23.123 dest[i - 1 - j] = tmp; 23.124 } 23.125 dest[i] = '\0'; 23.126 23.127 return dest; 23.128 } 23.129 23.130 #endif 23.131 23.132 23.133 // String functions 23.134 23.135 inline UPInt OVR_CDECL OVR_strlen(const char* str) 23.136 { 23.137 return strlen(str); 23.138 } 23.139 23.140 inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src) 23.141 { 23.142 #if defined(OVR_MSVC_SAFESTRING) 23.143 strcpy_s(dest, destsize, src); 23.144 return dest; 23.145 #else 23.146 OVR_UNUSED(destsize); 23.147 return strcpy(dest, src); 23.148 #endif 23.149 } 23.150 23.151 inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count) 23.152 { 23.153 #if defined(OVR_MSVC_SAFESTRING) 23.154 strncpy_s(dest, destsize, src, count); 23.155 return dest; 23.156 #else 23.157 OVR_UNUSED(destsize); 23.158 return strncpy(dest, src, count); 23.159 #endif 23.160 } 23.161 23.162 inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src) 23.163 { 23.164 #if defined(OVR_MSVC_SAFESTRING) 23.165 strcat_s(dest, destsize, src); 23.166 return dest; 23.167 #else 23.168 OVR_UNUSED(destsize); 23.169 return strcat(dest, src); 23.170 #endif 23.171 } 23.172 23.173 inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src) 23.174 { 23.175 return strcmp(dest, src); 23.176 } 23.177 23.178 inline const char* OVR_CDECL OVR_strchr(const char* str, char c) 23.179 { 23.180 return strchr(str, c); 23.181 } 23.182 23.183 inline char* OVR_CDECL OVR_strchr(char* str, char c) 23.184 { 23.185 return strchr(str, c); 23.186 } 23.187 23.188 inline const char* OVR_strrchr(const char* str, char c) 23.189 { 23.190 UPInt len = OVR_strlen(str); 23.191 for (UPInt i=len; i>0; i--) 23.192 if (str[i]==c) 23.193 return str+i; 23.194 return 0; 23.195 } 23.196 23.197 inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) 23.198 { 23.199 for (SPInt i = (SPInt)size - 1; i >= 0; i--) 23.200 { 23.201 if (str[i] == c) 23.202 return str + i; 23.203 } 23.204 return 0; 23.205 } 23.206 23.207 inline char* OVR_CDECL OVR_strrchr(char* str, char c) 23.208 { 23.209 UPInt len = OVR_strlen(str); 23.210 for (UPInt i=len; i>0; i--) 23.211 if (str[i]==c) 23.212 return str+i; 23.213 return 0; 23.214 } 23.215 23.216 23.217 double OVR_CDECL OVR_strtod(const char* string, char** tailptr); 23.218 23.219 inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix) 23.220 { 23.221 return strtol(string, tailptr, radix); 23.222 } 23.223 23.224 inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix) 23.225 { 23.226 return strtoul(string, tailptr, radix); 23.227 } 23.228 23.229 inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size) 23.230 { 23.231 return strncmp(ws1, ws2, size); 23.232 } 23.233 23.234 inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) 23.235 { 23.236 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.237 return _strtoui64(nptr, endptr, base); 23.238 #else 23.239 return strtoull(nptr, endptr, base); 23.240 #endif 23.241 } 23.242 23.243 inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) 23.244 { 23.245 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.246 return _strtoi64(nptr, endptr, base); 23.247 #else 23.248 return strtoll(nptr, endptr, base); 23.249 #endif 23.250 } 23.251 23.252 23.253 inline SInt64 OVR_CDECL OVR_atoq(const char* string) 23.254 { 23.255 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.256 return _atoi64(string); 23.257 #else 23.258 return atoll(string); 23.259 #endif 23.260 } 23.261 23.262 inline UInt64 OVR_CDECL OVR_atouq(const char* string) 23.263 { 23.264 return OVR_strtouq(string, NULL, 10); 23.265 } 23.266 23.267 23.268 // Implemented in GStd.cpp in platform-specific manner. 23.269 int OVR_CDECL OVR_stricmp(const char* dest, const char* src); 23.270 int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count); 23.271 23.272 inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...) 23.273 { 23.274 va_list argList; 23.275 va_start(argList,format); 23.276 UPInt ret; 23.277 #if defined(OVR_CC_MSVC) 23.278 #if defined(OVR_MSVC_SAFESTRING) 23.279 ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); 23.280 OVR_ASSERT(ret != -1); 23.281 #else 23.282 OVR_UNUSED(destsize); 23.283 ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character 23.284 OVR_ASSERT(ret != -1); 23.285 dest[destsize-1] = 0; 23.286 #endif 23.287 #else 23.288 OVR_UNUSED(destsize); 23.289 ret = vsprintf(dest, format, argList); 23.290 OVR_ASSERT(ret < destsize); 23.291 #endif 23.292 va_end(argList); 23.293 return ret; 23.294 } 23.295 23.296 inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList) 23.297 { 23.298 UPInt ret; 23.299 #if defined(OVR_CC_MSVC) 23.300 #if defined(OVR_MSVC_SAFESTRING) 23.301 dest[0] = '\0'; 23.302 int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); 23.303 if (rv == -1) 23.304 { 23.305 dest[destsize - 1] = '\0'; 23.306 ret = destsize - 1; 23.307 } 23.308 else 23.309 ret = (UPInt)rv; 23.310 #else 23.311 OVR_UNUSED(destsize); 23.312 int rv = _vsnprintf(dest, destsize - 1, format, argList); 23.313 OVR_ASSERT(rv != -1); 23.314 ret = (UPInt)rv; 23.315 dest[destsize-1] = 0; 23.316 #endif 23.317 #else 23.318 OVR_UNUSED(destsize); 23.319 ret = (UPInt)vsprintf(dest, format, argList); 23.320 OVR_ASSERT(ret < destsize); 23.321 #endif 23.322 return ret; 23.323 } 23.324 23.325 // Returns the number of characters in the formatted string. 23.326 inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList) 23.327 { 23.328 UPInt ret; 23.329 #if defined(OVR_CC_MSVC) 23.330 ret = (UPInt) _vscprintf(format, argList); 23.331 #else 23.332 ret = (UPInt) vsnprintf(NULL, 0, format, argList); 23.333 #endif 23.334 return ret; 23.335 } 23.336 23.337 23.338 wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src); 23.339 wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count); 23.340 wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src); 23.341 UPInt OVR_CDECL OVR_wcslen(const wchar_t* str); 23.342 int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b); 23.343 int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b); 23.344 23.345 inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) 23.346 { 23.347 #if defined(OVR_OS_WIN32) 23.348 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 23.349 return ::_wcsicoll(a, b); 23.350 #else 23.351 return ::wcsicoll(a, b); 23.352 #endif 23.353 #else 23.354 // not supported, use regular wcsicmp 23.355 return OVR_wcsicmp(a, b); 23.356 #endif 23.357 } 23.358 23.359 inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) 23.360 { 23.361 #if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) 23.362 return wcscoll(a, b); 23.363 #else 23.364 // not supported, use regular wcscmp 23.365 return OVR_wcscmp(a, b); 23.366 #endif 23.367 } 23.368 23.369 #ifndef OVR_NO_WCTYPE 23.370 23.371 inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) 23.372 { 23.373 unsigned offset = table[charCode >> 8]; 23.374 if (offset == 0) return 0; 23.375 if (offset == 1) return 1; 23.376 return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0; 23.377 } 23.378 23.379 extern const UInt16 UnicodeAlnumBits[]; 23.380 extern const UInt16 UnicodeAlphaBits[]; 23.381 extern const UInt16 UnicodeDigitBits[]; 23.382 extern const UInt16 UnicodeSpaceBits[]; 23.383 extern const UInt16 UnicodeXDigitBits[]; 23.384 23.385 // Uncomment if necessary 23.386 //extern const UInt16 UnicodeCntrlBits[]; 23.387 //extern const UInt16 UnicodeGraphBits[]; 23.388 //extern const UInt16 UnicodeLowerBits[]; 23.389 //extern const UInt16 UnicodePrintBits[]; 23.390 //extern const UInt16 UnicodePunctBits[]; 23.391 //extern const UInt16 UnicodeUpperBits[]; 23.392 23.393 inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits, charCode); } 23.394 inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits, charCode); } 23.395 inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits, charCode); } 23.396 inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits, charCode); } 23.397 inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); } 23.398 23.399 // Uncomment if necessary 23.400 //inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits, charCode); } 23.401 //inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits, charCode); } 23.402 //inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits, charCode); } 23.403 //inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits, charCode); } 23.404 //inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits, charCode); } 23.405 //inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits, charCode); } 23.406 23.407 int OVR_CDECL OVR_towupper(wchar_t charCode); 23.408 int OVR_CDECL OVR_towlower(wchar_t charCode); 23.409 23.410 #else // OVR_NO_WCTYPE 23.411 23.412 inline int OVR_CDECL OVR_iswspace(wchar_t c) 23.413 { 23.414 return iswspace(c); 23.415 } 23.416 23.417 inline int OVR_CDECL OVR_iswdigit(wchar_t c) 23.418 { 23.419 return iswdigit(c); 23.420 } 23.421 23.422 inline int OVR_CDECL OVR_iswxdigit(wchar_t c) 23.423 { 23.424 return iswxdigit(c); 23.425 } 23.426 23.427 inline int OVR_CDECL OVR_iswalpha(wchar_t c) 23.428 { 23.429 return iswalpha(c); 23.430 } 23.431 23.432 inline int OVR_CDECL OVR_iswalnum(wchar_t c) 23.433 { 23.434 return iswalnum(c); 23.435 } 23.436 23.437 inline wchar_t OVR_CDECL OVR_towlower(wchar_t c) 23.438 { 23.439 return (wchar_t)towlower(c); 23.440 } 23.441 23.442 inline wchar_t OVR_towupper(wchar_t c) 23.443 { 23.444 return (wchar_t)towupper(c); 23.445 } 23.446 23.447 #endif // OVR_NO_WCTYPE 23.448 23.449 // ASCII versions of tolower and toupper. Don't use "char" 23.450 inline int OVR_CDECL OVR_tolower(int c) 23.451 { 23.452 return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; 23.453 } 23.454 23.455 inline int OVR_CDECL OVR_toupper(int c) 23.456 { 23.457 return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; 23.458 } 23.459 23.460 23.461 23.462 inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr) 23.463 { 23.464 #if defined(OVR_OS_OTHER) 23.465 OVR_UNUSED(tailptr); 23.466 char buffer[64]; 23.467 char* tp = NULL; 23.468 UPInt max = OVR_wcslen(string); 23.469 if (max > 63) max = 63; 23.470 unsigned char c = 0; 23.471 for (UPInt i=0; i < max; i++) 23.472 { 23.473 c = (unsigned char)string[i]; 23.474 buffer[i] = ((c) < 128 ? (char)c : '!'); 23.475 } 23.476 buffer[max] = 0; 23.477 return OVR_strtod(buffer, &tp); 23.478 #else 23.479 return wcstod(string, tailptr); 23.480 #endif 23.481 } 23.482 23.483 inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix) 23.484 { 23.485 #if defined(OVR_OS_OTHER) 23.486 OVR_UNUSED(tailptr); 23.487 char buffer[64]; 23.488 char* tp = NULL; 23.489 UPInt max = OVR_wcslen(string); 23.490 if (max > 63) max = 63; 23.491 unsigned char c = 0; 23.492 for (UPInt i=0; i < max; i++) 23.493 { 23.494 c = (unsigned char)string[i]; 23.495 buffer[i] = ((c) < 128 ? (char)c : '!'); 23.496 } 23.497 buffer[max] = 0; 23.498 return strtol(buffer, &tp, radix); 23.499 #else 23.500 return wcstol(string, tailptr, radix); 23.501 #endif 23.502 } 23.503 23.504 } // OVR 23.505 23.506 #endif // OVR_Std_h 23.507 \ No newline at end of file 23.508 +/************************************************************************************ 23.509 + 23.510 +PublicHeader: OVR.h 23.511 +Filename : OVR_Std.h 23.512 +Content : Standard C function interface 23.513 +Created : September 19, 2012 23.514 +Notes : 23.515 + 23.516 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 23.517 + 23.518 +Use of this software is subject to the terms of the Oculus license 23.519 +agreement provided at the time of installation or download, or which 23.520 +otherwise accompanies this software in either electronic or hard copy form. 23.521 + 23.522 +************************************************************************************/ 23.523 + 23.524 +#ifndef OVR_Std_h 23.525 +#define OVR_Std_h 23.526 + 23.527 +#include "OVR_Types.h" 23.528 +#include <stdarg.h> // for va_list args 23.529 +#include <string.h> 23.530 +#include <stdio.h> 23.531 +#include <stdlib.h> 23.532 +#include <ctype.h> 23.533 + 23.534 +#if !defined(OVR_OS_WINCE) && defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 23.535 +#define OVR_MSVC_SAFESTRING 23.536 +#include <errno.h> 23.537 +#endif 23.538 + 23.539 +// Wide-char funcs 23.540 +#include <wchar.h> 23.541 +#include <wctype.h> 23.542 + 23.543 +namespace OVR { 23.544 + 23.545 +#if defined(OVR_OS_WIN32) 23.546 +inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix) 23.547 +{ 23.548 +#if defined(OVR_MSVC_SAFESTRING) 23.549 + _itoa_s(val, dest, destsize, radix); 23.550 + return dest; 23.551 +#else 23.552 + OVR_UNUSED(destsize); 23.553 + return itoa(val, dest, radix); 23.554 +#endif 23.555 +} 23.556 +#else // OVR_OS_WIN32 23.557 +inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix) 23.558 +{ 23.559 + if (val == 0) 23.560 + { 23.561 + if (len > 1) 23.562 + { 23.563 + dest[0] = '0'; 23.564 + dest[1] = '\0'; 23.565 + } 23.566 + return dest; 23.567 + } 23.568 + 23.569 + int cur = val; 23.570 + unsigned int i = 0; 23.571 + unsigned int sign = 0; 23.572 + 23.573 + if (val < 0) 23.574 + { 23.575 + val = -val; 23.576 + sign = 1; 23.577 + } 23.578 + 23.579 + while ((val != 0) && (i < (len - 1 - sign))) 23.580 + { 23.581 + cur = val % radix; 23.582 + val /= radix; 23.583 + 23.584 + if (radix == 16) 23.585 + { 23.586 + switch(cur) 23.587 + { 23.588 + case 10: 23.589 + dest[i] = 'a'; 23.590 + break; 23.591 + case 11: 23.592 + dest[i] = 'b'; 23.593 + break; 23.594 + case 12: 23.595 + dest[i] = 'c'; 23.596 + break; 23.597 + case 13: 23.598 + dest[i] = 'd'; 23.599 + break; 23.600 + case 14: 23.601 + dest[i] = 'e'; 23.602 + break; 23.603 + case 15: 23.604 + dest[i] = 'f'; 23.605 + break; 23.606 + default: 23.607 + dest[i] = (char)('0' + cur); 23.608 + break; 23.609 + } 23.610 + } 23.611 + else 23.612 + { 23.613 + dest[i] = (char)('0' + cur); 23.614 + } 23.615 + ++i; 23.616 + } 23.617 + 23.618 + if (sign) 23.619 + { 23.620 + dest[i++] = '-'; 23.621 + } 23.622 + 23.623 + for (unsigned int j = 0; j < i / 2; ++j) 23.624 + { 23.625 + char tmp = dest[j]; 23.626 + dest[j] = dest[i - 1 - j]; 23.627 + dest[i - 1 - j] = tmp; 23.628 + } 23.629 + dest[i] = '\0'; 23.630 + 23.631 + return dest; 23.632 +} 23.633 + 23.634 +#endif 23.635 + 23.636 + 23.637 +// String functions 23.638 + 23.639 +inline UPInt OVR_CDECL OVR_strlen(const char* str) 23.640 +{ 23.641 + return strlen(str); 23.642 +} 23.643 + 23.644 +inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src) 23.645 +{ 23.646 +#if defined(OVR_MSVC_SAFESTRING) 23.647 + strcpy_s(dest, destsize, src); 23.648 + return dest; 23.649 +#else 23.650 + OVR_UNUSED(destsize); 23.651 + return strcpy(dest, src); 23.652 +#endif 23.653 +} 23.654 + 23.655 +inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count) 23.656 +{ 23.657 +#if defined(OVR_MSVC_SAFESTRING) 23.658 + strncpy_s(dest, destsize, src, count); 23.659 + return dest; 23.660 +#else 23.661 + OVR_UNUSED(destsize); 23.662 + return strncpy(dest, src, count); 23.663 +#endif 23.664 +} 23.665 + 23.666 +inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src) 23.667 +{ 23.668 +#if defined(OVR_MSVC_SAFESTRING) 23.669 + strcat_s(dest, destsize, src); 23.670 + return dest; 23.671 +#else 23.672 + OVR_UNUSED(destsize); 23.673 + return strcat(dest, src); 23.674 +#endif 23.675 +} 23.676 + 23.677 +inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src) 23.678 +{ 23.679 + return strcmp(dest, src); 23.680 +} 23.681 + 23.682 +inline const char* OVR_CDECL OVR_strchr(const char* str, char c) 23.683 +{ 23.684 + return strchr(str, c); 23.685 +} 23.686 + 23.687 +inline char* OVR_CDECL OVR_strchr(char* str, char c) 23.688 +{ 23.689 + return strchr(str, c); 23.690 +} 23.691 + 23.692 +inline const char* OVR_strrchr(const char* str, char c) 23.693 +{ 23.694 + UPInt len = OVR_strlen(str); 23.695 + for (UPInt i=len; i>0; i--) 23.696 + if (str[i]==c) 23.697 + return str+i; 23.698 + return 0; 23.699 +} 23.700 + 23.701 +inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c) 23.702 +{ 23.703 + for (SPInt i = (SPInt)size - 1; i >= 0; i--) 23.704 + { 23.705 + if (str[i] == c) 23.706 + return str + i; 23.707 + } 23.708 + return 0; 23.709 +} 23.710 + 23.711 +inline char* OVR_CDECL OVR_strrchr(char* str, char c) 23.712 +{ 23.713 + UPInt len = OVR_strlen(str); 23.714 + for (UPInt i=len; i>0; i--) 23.715 + if (str[i]==c) 23.716 + return str+i; 23.717 + return 0; 23.718 +} 23.719 + 23.720 + 23.721 +double OVR_CDECL OVR_strtod(const char* string, char** tailptr); 23.722 + 23.723 +inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix) 23.724 +{ 23.725 + return strtol(string, tailptr, radix); 23.726 +} 23.727 + 23.728 +inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix) 23.729 +{ 23.730 + return strtoul(string, tailptr, radix); 23.731 +} 23.732 + 23.733 +inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size) 23.734 +{ 23.735 + return strncmp(ws1, ws2, size); 23.736 +} 23.737 + 23.738 +inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base) 23.739 +{ 23.740 +#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.741 + return _strtoui64(nptr, endptr, base); 23.742 +#else 23.743 + return strtoull(nptr, endptr, base); 23.744 +#endif 23.745 +} 23.746 + 23.747 +inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base) 23.748 +{ 23.749 +#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.750 + return _strtoi64(nptr, endptr, base); 23.751 +#else 23.752 + return strtoll(nptr, endptr, base); 23.753 +#endif 23.754 +} 23.755 + 23.756 + 23.757 +inline SInt64 OVR_CDECL OVR_atoq(const char* string) 23.758 +{ 23.759 +#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE) 23.760 + return _atoi64(string); 23.761 +#else 23.762 + return atoll(string); 23.763 +#endif 23.764 +} 23.765 + 23.766 +inline UInt64 OVR_CDECL OVR_atouq(const char* string) 23.767 +{ 23.768 + return OVR_strtouq(string, NULL, 10); 23.769 +} 23.770 + 23.771 + 23.772 +// Implemented in GStd.cpp in platform-specific manner. 23.773 +int OVR_CDECL OVR_stricmp(const char* dest, const char* src); 23.774 +int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count); 23.775 + 23.776 +inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...) 23.777 +{ 23.778 + va_list argList; 23.779 + va_start(argList,format); 23.780 + UPInt ret; 23.781 +#if defined(OVR_CC_MSVC) 23.782 + #if defined(OVR_MSVC_SAFESTRING) 23.783 + ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); 23.784 + OVR_ASSERT(ret != -1); 23.785 + #else 23.786 + OVR_UNUSED(destsize); 23.787 + ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character 23.788 + OVR_ASSERT(ret != -1); 23.789 + dest[destsize-1] = 0; 23.790 + #endif 23.791 +#else 23.792 + OVR_UNUSED(destsize); 23.793 + ret = vsprintf(dest, format, argList); 23.794 + OVR_ASSERT(ret < destsize); 23.795 +#endif 23.796 + va_end(argList); 23.797 + return ret; 23.798 +} 23.799 + 23.800 +inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList) 23.801 +{ 23.802 + UPInt ret; 23.803 +#if defined(OVR_CC_MSVC) 23.804 + #if defined(OVR_MSVC_SAFESTRING) 23.805 + dest[0] = '\0'; 23.806 + int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList); 23.807 + if (rv == -1) 23.808 + { 23.809 + dest[destsize - 1] = '\0'; 23.810 + ret = destsize - 1; 23.811 + } 23.812 + else 23.813 + ret = (UPInt)rv; 23.814 + #else 23.815 + OVR_UNUSED(destsize); 23.816 + int rv = _vsnprintf(dest, destsize - 1, format, argList); 23.817 + OVR_ASSERT(rv != -1); 23.818 + ret = (UPInt)rv; 23.819 + dest[destsize-1] = 0; 23.820 + #endif 23.821 +#else 23.822 + OVR_UNUSED(destsize); 23.823 + ret = (UPInt)vsprintf(dest, format, argList); 23.824 + OVR_ASSERT(ret < destsize); 23.825 +#endif 23.826 + return ret; 23.827 +} 23.828 + 23.829 +// Returns the number of characters in the formatted string. 23.830 +inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList) 23.831 +{ 23.832 + UPInt ret; 23.833 +#if defined(OVR_CC_MSVC) 23.834 + ret = (UPInt) _vscprintf(format, argList); 23.835 +#else 23.836 + ret = (UPInt) vsnprintf(NULL, 0, format, argList); 23.837 +#endif 23.838 + return ret; 23.839 +} 23.840 + 23.841 + 23.842 +wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src); 23.843 +wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count); 23.844 +wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src); 23.845 +UPInt OVR_CDECL OVR_wcslen(const wchar_t* str); 23.846 +int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b); 23.847 +int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b); 23.848 + 23.849 +inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) 23.850 +{ 23.851 +#if defined(OVR_OS_WIN32) 23.852 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) 23.853 + return ::_wcsicoll(a, b); 23.854 +#else 23.855 + return ::wcsicoll(a, b); 23.856 +#endif 23.857 +#else 23.858 + // not supported, use regular wcsicmp 23.859 + return OVR_wcsicmp(a, b); 23.860 +#endif 23.861 +} 23.862 + 23.863 +inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) 23.864 +{ 23.865 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) 23.866 + return wcscoll(a, b); 23.867 +#else 23.868 + // not supported, use regular wcscmp 23.869 + return OVR_wcscmp(a, b); 23.870 +#endif 23.871 +} 23.872 + 23.873 +#ifndef OVR_NO_WCTYPE 23.874 + 23.875 +inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode) 23.876 +{ 23.877 + unsigned offset = table[charCode >> 8]; 23.878 + if (offset == 0) return 0; 23.879 + if (offset == 1) return 1; 23.880 + return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0; 23.881 +} 23.882 + 23.883 +extern const UInt16 UnicodeAlnumBits[]; 23.884 +extern const UInt16 UnicodeAlphaBits[]; 23.885 +extern const UInt16 UnicodeDigitBits[]; 23.886 +extern const UInt16 UnicodeSpaceBits[]; 23.887 +extern const UInt16 UnicodeXDigitBits[]; 23.888 + 23.889 +// Uncomment if necessary 23.890 +//extern const UInt16 UnicodeCntrlBits[]; 23.891 +//extern const UInt16 UnicodeGraphBits[]; 23.892 +//extern const UInt16 UnicodeLowerBits[]; 23.893 +//extern const UInt16 UnicodePrintBits[]; 23.894 +//extern const UInt16 UnicodePunctBits[]; 23.895 +//extern const UInt16 UnicodeUpperBits[]; 23.896 + 23.897 +inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits, charCode); } 23.898 +inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits, charCode); } 23.899 +inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits, charCode); } 23.900 +inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits, charCode); } 23.901 +inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); } 23.902 + 23.903 +// Uncomment if necessary 23.904 +//inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits, charCode); } 23.905 +//inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits, charCode); } 23.906 +//inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits, charCode); } 23.907 +//inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits, charCode); } 23.908 +//inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits, charCode); } 23.909 +//inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits, charCode); } 23.910 + 23.911 +int OVR_CDECL OVR_towupper(wchar_t charCode); 23.912 +int OVR_CDECL OVR_towlower(wchar_t charCode); 23.913 + 23.914 +#else // OVR_NO_WCTYPE 23.915 + 23.916 +inline int OVR_CDECL OVR_iswspace(wchar_t c) 23.917 +{ 23.918 + return iswspace(c); 23.919 +} 23.920 + 23.921 +inline int OVR_CDECL OVR_iswdigit(wchar_t c) 23.922 +{ 23.923 + return iswdigit(c); 23.924 +} 23.925 + 23.926 +inline int OVR_CDECL OVR_iswxdigit(wchar_t c) 23.927 +{ 23.928 + return iswxdigit(c); 23.929 +} 23.930 + 23.931 +inline int OVR_CDECL OVR_iswalpha(wchar_t c) 23.932 +{ 23.933 + return iswalpha(c); 23.934 +} 23.935 + 23.936 +inline int OVR_CDECL OVR_iswalnum(wchar_t c) 23.937 +{ 23.938 + return iswalnum(c); 23.939 +} 23.940 + 23.941 +inline wchar_t OVR_CDECL OVR_towlower(wchar_t c) 23.942 +{ 23.943 + return (wchar_t)towlower(c); 23.944 +} 23.945 + 23.946 +inline wchar_t OVR_towupper(wchar_t c) 23.947 +{ 23.948 + return (wchar_t)towupper(c); 23.949 +} 23.950 + 23.951 +#endif // OVR_NO_WCTYPE 23.952 + 23.953 +// ASCII versions of tolower and toupper. Don't use "char" 23.954 +inline int OVR_CDECL OVR_tolower(int c) 23.955 +{ 23.956 + return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; 23.957 +} 23.958 + 23.959 +inline int OVR_CDECL OVR_toupper(int c) 23.960 +{ 23.961 + return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; 23.962 +} 23.963 + 23.964 + 23.965 + 23.966 +inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr) 23.967 +{ 23.968 +#if defined(OVR_OS_OTHER) 23.969 + OVR_UNUSED(tailptr); 23.970 + char buffer[64]; 23.971 + char* tp = NULL; 23.972 + UPInt max = OVR_wcslen(string); 23.973 + if (max > 63) max = 63; 23.974 + unsigned char c = 0; 23.975 + for (UPInt i=0; i < max; i++) 23.976 + { 23.977 + c = (unsigned char)string[i]; 23.978 + buffer[i] = ((c) < 128 ? (char)c : '!'); 23.979 + } 23.980 + buffer[max] = 0; 23.981 + return OVR_strtod(buffer, &tp); 23.982 +#else 23.983 + return wcstod(string, tailptr); 23.984 +#endif 23.985 +} 23.986 + 23.987 +inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix) 23.988 +{ 23.989 +#if defined(OVR_OS_OTHER) 23.990 + OVR_UNUSED(tailptr); 23.991 + char buffer[64]; 23.992 + char* tp = NULL; 23.993 + UPInt max = OVR_wcslen(string); 23.994 + if (max > 63) max = 63; 23.995 + unsigned char c = 0; 23.996 + for (UPInt i=0; i < max; i++) 23.997 + { 23.998 + c = (unsigned char)string[i]; 23.999 + buffer[i] = ((c) < 128 ? (char)c : '!'); 23.1000 + } 23.1001 + buffer[max] = 0; 23.1002 + return strtol(buffer, &tp, radix); 23.1003 +#else 23.1004 + return wcstol(string, tailptr, radix); 23.1005 +#endif 23.1006 +} 23.1007 + 23.1008 +} // OVR 23.1009 + 23.1010 +#endif // OVR_Std_h
24.1 --- a/libovr/Src/Kernel/OVR_String.cpp Sat Sep 14 17:51:03 2013 +0300 24.2 +++ b/libovr/Src/Kernel/OVR_String.cpp Sun Sep 15 04:10:05 2013 +0300 24.3 @@ -1,1 +1,752 @@ 24.4 -/************************************************************************************ 24.5 24.6 Filename : OVR_String.cpp 24.7 Content : String UTF8 string implementation with copy-on-write semantics 24.8 (thread-safe for assignment but not modification). 24.9 Created : September 19, 2012 24.10 Notes : 24.11 24.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 24.13 24.14 Use of this software is subject to the terms of the Oculus license 24.15 agreement provided at the time of installation or download, or which 24.16 otherwise accompanies this software in either electronic or hard copy form. 24.17 24.18 ************************************************************************************/ 24.19 24.20 #include "OVR_String.h" 24.21 24.22 #include <stdlib.h> 24.23 #include <ctype.h> 24.24 24.25 #ifdef OVR_OS_QNX 24.26 # include <strings.h> 24.27 #endif 24.28 24.29 namespace OVR { 24.30 24.31 #define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift) 24.32 24.33 String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} }; 24.34 24.35 24.36 String::String() 24.37 { 24.38 pData = &NullData; 24.39 pData->AddRef(); 24.40 }; 24.41 24.42 String::String(const char* pdata) 24.43 { 24.44 // Obtain length in bytes; it doesn't matter if _data is UTF8. 24.45 UPInt size = pdata ? OVR_strlen(pdata) : 0; 24.46 pData = AllocDataCopy1(size, 0, pdata, size); 24.47 }; 24.48 24.49 String::String(const char* pdata1, const char* pdata2, const char* pdata3) 24.50 { 24.51 // Obtain length in bytes; it doesn't matter if _data is UTF8. 24.52 UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 24.53 UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 24.54 UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 24.55 24.56 DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0, 24.57 pdata1, size1, pdata2, size2); 24.58 memcpy(pdataDesc->Data + size1 + size2, pdata3, size3); 24.59 pData = pdataDesc; 24.60 } 24.61 24.62 String::String(const char* pdata, UPInt size) 24.63 { 24.64 OVR_ASSERT((size == 0) || (pdata != 0)); 24.65 pData = AllocDataCopy1(size, 0, pdata, size); 24.66 }; 24.67 24.68 24.69 String::String(const InitStruct& src, UPInt size) 24.70 { 24.71 pData = AllocData(size, 0); 24.72 src.InitString(GetData()->Data, size); 24.73 } 24.74 24.75 String::String(const String& src) 24.76 { 24.77 pData = src.GetData(); 24.78 pData->AddRef(); 24.79 } 24.80 24.81 String::String(const StringBuffer& src) 24.82 { 24.83 pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()); 24.84 } 24.85 24.86 String::String(const wchar_t* data) 24.87 { 24.88 pData = &NullData; 24.89 pData->AddRef(); 24.90 // Simplified logic for wchar_t constructor. 24.91 if (data) 24.92 *this = data; 24.93 } 24.94 24.95 24.96 String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) 24.97 { 24.98 String::DataDesc* pdesc; 24.99 24.100 if (size == 0) 24.101 { 24.102 pdesc = &NullData; 24.103 pdesc->AddRef(); 24.104 return pdesc; 24.105 } 24.106 24.107 pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size); 24.108 pdesc->Data[size] = 0; 24.109 pdesc->RefCount = 1; 24.110 pdesc->Size = size | lengthIsSize; 24.111 return pdesc; 24.112 } 24.113 24.114 24.115 String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize, 24.116 const char* pdata, UPInt copySize) 24.117 { 24.118 String::DataDesc* pdesc = AllocData(size, lengthIsSize); 24.119 memcpy(pdesc->Data, pdata, copySize); 24.120 return pdesc; 24.121 } 24.122 24.123 String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, 24.124 const char* pdata1, UPInt copySize1, 24.125 const char* pdata2, UPInt copySize2) 24.126 { 24.127 String::DataDesc* pdesc = AllocData(size, lengthIsSize); 24.128 memcpy(pdesc->Data, pdata1, copySize1); 24.129 memcpy(pdesc->Data + copySize1, pdata2, copySize2); 24.130 return pdesc; 24.131 } 24.132 24.133 24.134 UPInt String::GetLength() const 24.135 { 24.136 // Optimize length accesses for non-UTF8 character strings. 24.137 DataDesc* pdata = GetData(); 24.138 UPInt length, size = pdata->GetSize(); 24.139 24.140 if (pdata->LengthIsSize()) 24.141 return size; 24.142 24.143 length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size); 24.144 24.145 if (length == size) 24.146 pdata->Size |= String_LengthIsSize; 24.147 24.148 return length; 24.149 } 24.150 24.151 24.152 //static UInt32 String_CharSearch(const char* buf, ) 24.153 24.154 24.155 UInt32 String::GetCharAt(UPInt index) const 24.156 { 24.157 SPInt i = (SPInt) index; 24.158 DataDesc* pdata = GetData(); 24.159 const char* buf = pdata->Data; 24.160 UInt32 c; 24.161 24.162 if (pdata->LengthIsSize()) 24.163 { 24.164 OVR_ASSERT(index < pdata->GetSize()); 24.165 buf += i; 24.166 return UTF8Util::DecodeNextChar_Advance0(&buf); 24.167 } 24.168 24.169 c = UTF8Util::GetCharAt(index, buf, pdata->GetSize()); 24.170 return c; 24.171 } 24.172 24.173 UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const 24.174 { 24.175 DataDesc* pdata = GetData(); 24.176 SPInt i = (SPInt) index; 24.177 const char* buf = pdata->Data; 24.178 const char* end = buf + pdata->GetSize(); 24.179 UInt32 c; 24.180 24.181 do 24.182 { 24.183 c = UTF8Util::DecodeNextChar_Advance0(&buf); 24.184 i--; 24.185 24.186 if (buf >= end) 24.187 { 24.188 // We've hit the end of the string; don't go further. 24.189 OVR_ASSERT(i == 0); 24.190 return c; 24.191 } 24.192 } while (i >= 0); 24.193 24.194 *offset = buf; 24.195 24.196 return c; 24.197 } 24.198 24.199 UInt32 String::GetNextChar(const char** offset) const 24.200 { 24.201 return UTF8Util::DecodeNextChar(offset); 24.202 } 24.203 24.204 24.205 24.206 void String::AppendChar(UInt32 ch) 24.207 { 24.208 DataDesc* pdata = GetData(); 24.209 UPInt size = pdata->GetSize(); 24.210 char buff[8]; 24.211 SPInt encodeSize = 0; 24.212 24.213 // Converts ch into UTF8 string and fills it into buff. 24.214 UTF8Util::EncodeChar(buff, &encodeSize, ch); 24.215 OVR_ASSERT(encodeSize >= 0); 24.216 24.217 SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0, 24.218 pdata->Data, size, buff, (UPInt)encodeSize)); 24.219 pdata->Release(); 24.220 } 24.221 24.222 24.223 void String::AppendString(const wchar_t* pstr, SPInt len) 24.224 { 24.225 if (!pstr) 24.226 return; 24.227 24.228 DataDesc* pdata = GetData(); 24.229 UPInt oldSize = pdata->GetSize(); 24.230 UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len); 24.231 24.232 DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0, 24.233 pdata->Data, oldSize); 24.234 UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len); 24.235 24.236 SetData(pnewData); 24.237 pdata->Release(); 24.238 } 24.239 24.240 24.241 void String::AppendString(const char* putf8str, SPInt utf8StrSz) 24.242 { 24.243 if (!putf8str || !utf8StrSz) 24.244 return; 24.245 if (utf8StrSz == -1) 24.246 utf8StrSz = (SPInt)OVR_strlen(putf8str); 24.247 24.248 DataDesc* pdata = GetData(); 24.249 UPInt oldSize = pdata->GetSize(); 24.250 24.251 SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0, 24.252 pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz)); 24.253 pdata->Release(); 24.254 } 24.255 24.256 void String::AssignString(const InitStruct& src, UPInt size) 24.257 { 24.258 DataDesc* poldData = GetData(); 24.259 DataDesc* pnewData = AllocData(size, 0); 24.260 src.InitString(pnewData->Data, size); 24.261 SetData(pnewData); 24.262 poldData->Release(); 24.263 } 24.264 24.265 void String::AssignString(const char* putf8str, UPInt size) 24.266 { 24.267 DataDesc* poldData = GetData(); 24.268 SetData(AllocDataCopy1(size, 0, putf8str, size)); 24.269 poldData->Release(); 24.270 } 24.271 24.272 void String::operator = (const char* pstr) 24.273 { 24.274 AssignString(pstr, pstr ? OVR_strlen(pstr) : 0); 24.275 } 24.276 24.277 void String::operator = (const wchar_t* pwstr) 24.278 { 24.279 DataDesc* poldData = GetData(); 24.280 UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0; 24.281 24.282 DataDesc* pnewData = AllocData(size, 0); 24.283 UTF8Util::EncodeString(pnewData->Data, pwstr); 24.284 SetData(pnewData); 24.285 poldData->Release(); 24.286 } 24.287 24.288 24.289 void String::operator = (const String& src) 24.290 { 24.291 DataDesc* psdata = src.GetData(); 24.292 DataDesc* pdata = GetData(); 24.293 24.294 SetData(psdata); 24.295 psdata->AddRef(); 24.296 pdata->Release(); 24.297 } 24.298 24.299 24.300 void String::operator = (const StringBuffer& src) 24.301 { 24.302 DataDesc* polddata = GetData(); 24.303 SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize())); 24.304 polddata->Release(); 24.305 } 24.306 24.307 void String::operator += (const String& src) 24.308 { 24.309 DataDesc *pourData = GetData(), 24.310 *psrcData = src.GetData(); 24.311 UPInt ourSize = pourData->GetSize(), 24.312 srcSize = psrcData->GetSize(); 24.313 UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); 24.314 24.315 SetData(AllocDataCopy2(ourSize + srcSize, lflag, 24.316 pourData->Data, ourSize, psrcData->Data, srcSize)); 24.317 pourData->Release(); 24.318 } 24.319 24.320 24.321 String String::operator + (const char* str) const 24.322 { 24.323 String tmp1(*this); 24.324 tmp1 += (str ? str : ""); 24.325 return tmp1; 24.326 } 24.327 24.328 String String::operator + (const String& src) const 24.329 { 24.330 String tmp1(*this); 24.331 tmp1 += src; 24.332 return tmp1; 24.333 } 24.334 24.335 void String::Remove(UPInt posAt, SPInt removeLength) 24.336 { 24.337 DataDesc* pdata = GetData(); 24.338 UPInt oldSize = pdata->GetSize(); 24.339 // Length indicates the number of characters to remove. 24.340 UPInt length = GetLength(); 24.341 24.342 // If index is past the string, nothing to remove. 24.343 if (posAt >= length) 24.344 return; 24.345 // Otherwise, cap removeLength to the length of the string. 24.346 if ((posAt + removeLength) > length) 24.347 removeLength = length - posAt; 24.348 24.349 // Get the byte position of the UTF8 char at position posAt. 24.350 SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); 24.351 SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); 24.352 24.353 SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(), 24.354 pdata->Data, bytePos, 24.355 pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize))); 24.356 pdata->Release(); 24.357 } 24.358 24.359 24.360 String String::Substring(UPInt start, UPInt end) const 24.361 { 24.362 UPInt length = GetLength(); 24.363 if ((start >= length) || (start >= end)) 24.364 return String(); 24.365 24.366 DataDesc* pdata = GetData(); 24.367 24.368 // If size matches, we know the exact index range. 24.369 if (pdata->LengthIsSize()) 24.370 return String(pdata->Data + start, end - start); 24.371 24.372 // Get position of starting character. 24.373 SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); 24.374 SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); 24.375 return String(pdata->Data + byteStart, (UPInt)byteSize); 24.376 } 24.377 24.378 void String::Clear() 24.379 { 24.380 NullData.AddRef(); 24.381 GetData()->Release(); 24.382 SetData(&NullData); 24.383 } 24.384 24.385 24.386 String String::ToUpper() const 24.387 { 24.388 UInt32 c; 24.389 const char* psource = GetData()->Data; 24.390 const char* pend = psource + GetData()->GetSize(); 24.391 String str; 24.392 SPInt bufferOffset = 0; 24.393 char buffer[512]; 24.394 24.395 while(psource < pend) 24.396 { 24.397 do { 24.398 c = UTF8Util::DecodeNextChar_Advance0(&psource); 24.399 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c))); 24.400 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); 24.401 24.402 // Append string a piece at a time. 24.403 str.AppendString(buffer, bufferOffset); 24.404 bufferOffset = 0; 24.405 } 24.406 24.407 return str; 24.408 } 24.409 24.410 String String::ToLower() const 24.411 { 24.412 UInt32 c; 24.413 const char* psource = GetData()->Data; 24.414 const char* pend = psource + GetData()->GetSize(); 24.415 String str; 24.416 SPInt bufferOffset = 0; 24.417 char buffer[512]; 24.418 24.419 while(psource < pend) 24.420 { 24.421 do { 24.422 c = UTF8Util::DecodeNextChar_Advance0(&psource); 24.423 UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c))); 24.424 } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); 24.425 24.426 // Append string a piece at a time. 24.427 str.AppendString(buffer, bufferOffset); 24.428 bufferOffset = 0; 24.429 } 24.430 24.431 return str; 24.432 } 24.433 24.434 24.435 24.436 String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) 24.437 { 24.438 DataDesc* poldData = GetData(); 24.439 UPInt oldSize = poldData->GetSize(); 24.440 UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize; 24.441 UPInt byteIndex = (poldData->LengthIsSize()) ? 24.442 posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); 24.443 24.444 OVR_ASSERT(byteIndex <= oldSize); 24.445 24.446 DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0, 24.447 poldData->Data, byteIndex, substr, insertSize); 24.448 memcpy(pnewData->Data + byteIndex + insertSize, 24.449 poldData->Data + byteIndex, oldSize - byteIndex); 24.450 SetData(pnewData); 24.451 poldData->Release(); 24.452 return *this; 24.453 } 24.454 24.455 /* 24.456 String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len) 24.457 { 24.458 for (SPInt i = 0; i < len; ++i) 24.459 { 24.460 UPInt charw = InsertCharAt(substr[i], posAt); 24.461 posAt += charw; 24.462 } 24.463 return *this; 24.464 } 24.465 */ 24.466 24.467 UPInt String::InsertCharAt(UInt32 c, UPInt posAt) 24.468 { 24.469 char buf[8]; 24.470 SPInt index = 0; 24.471 UTF8Util::EncodeChar(buf, &index, c); 24.472 OVR_ASSERT(index >= 0); 24.473 buf[(UPInt)index] = 0; 24.474 24.475 Insert(buf, posAt, index); 24.476 return (UPInt)index; 24.477 } 24.478 24.479 24.480 int String::CompareNoCase(const char* a, const char* b) 24.481 { 24.482 return OVR_stricmp(a, b); 24.483 } 24.484 24.485 int String::CompareNoCase(const char* a, const char* b, SPInt len) 24.486 { 24.487 if (len) 24.488 { 24.489 SPInt f,l; 24.490 SPInt slen = len; 24.491 const char *s = b; 24.492 do { 24.493 f = (SPInt)OVR_tolower((int)(*(a++))); 24.494 l = (SPInt)OVR_tolower((int)(*(b++))); 24.495 } while (--len && f && (f == l) && *b != 0); 24.496 24.497 if (f == l && (len != 0 || *b != 0)) 24.498 { 24.499 f = (SPInt)slen; 24.500 l = (SPInt)OVR_strlen(s); 24.501 return int(f - l); 24.502 } 24.503 24.504 return int(f - l); 24.505 } 24.506 else 24.507 return (0-(int)OVR_strlen(b)); 24.508 } 24.509 24.510 // ***** Implement hash static functions 24.511 24.512 // Hash function 24.513 UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) 24.514 { 24.515 const UByte* pdata = (const UByte*) pdataIn; 24.516 UPInt h = seed; 24.517 while (size > 0) 24.518 { 24.519 size--; 24.520 h = ((h << 5) + h) ^ (unsigned) pdata[size]; 24.521 } 24.522 24.523 return h; 24.524 } 24.525 24.526 // Hash function, case-insensitive 24.527 UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed) 24.528 { 24.529 const UByte* pdata = (const UByte*) pdataIn; 24.530 UPInt h = seed; 24.531 while (size > 0) 24.532 { 24.533 size--; 24.534 h = ((h << 5) + h) ^ OVR_tolower(pdata[size]); 24.535 } 24.536 24.537 // Alternative: "sdbm" hash function, suggested at same web page above. 24.538 // h = 0; 24.539 // for bytes { h = (h << 16) + (h << 6) - hash + *p; } 24.540 return h; 24.541 } 24.542 24.543 24.544 24.545 // ***** String Buffer used for Building Strings 24.546 24.547 24.548 #define OVR_SBUFF_DEFAULT_GROW_SIZE 512 24.549 // Constructors / Destructor. 24.550 StringBuffer::StringBuffer() 24.551 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.552 { 24.553 } 24.554 24.555 StringBuffer::StringBuffer(UPInt growSize) 24.556 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.557 { 24.558 SetGrowSize(growSize); 24.559 } 24.560 24.561 StringBuffer::StringBuffer(const char* data) 24.562 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.563 { 24.564 *this = data; 24.565 } 24.566 24.567 StringBuffer::StringBuffer(const char* data, UPInt dataSize) 24.568 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.569 { 24.570 AppendString(data, dataSize); 24.571 } 24.572 24.573 StringBuffer::StringBuffer(const String& src) 24.574 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.575 { 24.576 AppendString(src.ToCStr(), src.GetSize()); 24.577 } 24.578 24.579 StringBuffer::StringBuffer(const StringBuffer& src) 24.580 : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.581 { 24.582 AppendString(src.ToCStr(), src.GetSize()); 24.583 LengthIsSize = src.LengthIsSize; 24.584 } 24.585 24.586 StringBuffer::StringBuffer(const wchar_t* data) 24.587 : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.588 { 24.589 *this = data; 24.590 } 24.591 24.592 StringBuffer::~StringBuffer() 24.593 { 24.594 if (pData) 24.595 OVR_FREE(pData); 24.596 } 24.597 void StringBuffer::SetGrowSize(UPInt growSize) 24.598 { 24.599 if (growSize <= 16) 24.600 GrowSize = 16; 24.601 else 24.602 { 24.603 UByte bits = Alg::UpperBit(UInt32(growSize-1)); 24.604 UPInt size = 1<<bits; 24.605 GrowSize = size == growSize ? growSize : size; 24.606 } 24.607 } 24.608 24.609 UPInt StringBuffer::GetLength() const 24.610 { 24.611 UPInt length, size = GetSize(); 24.612 if (LengthIsSize) 24.613 return size; 24.614 24.615 length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize()); 24.616 24.617 if (length == GetSize()) 24.618 LengthIsSize = true; 24.619 return length; 24.620 } 24.621 24.622 void StringBuffer::Reserve(UPInt _size) 24.623 { 24.624 if (_size >= BufferSize) // >= because of trailing zero! (!AB) 24.625 { 24.626 BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1); 24.627 if (!pData) 24.628 pData = (char*)OVR_ALLOC(BufferSize); 24.629 else 24.630 pData = (char*)OVR_REALLOC(pData, BufferSize); 24.631 } 24.632 } 24.633 void StringBuffer::Resize(UPInt _size) 24.634 { 24.635 Reserve(_size); 24.636 LengthIsSize = false; 24.637 Size = _size; 24.638 if (pData) 24.639 pData[Size] = 0; 24.640 } 24.641 24.642 void StringBuffer::Clear() 24.643 { 24.644 Resize(0); 24.645 /* 24.646 if (pData != pEmptyNullData) 24.647 { 24.648 OVR_FREE(pHeap, pData); 24.649 pData = pEmptyNullData; 24.650 Size = BufferSize = 0; 24.651 LengthIsSize = false; 24.652 } 24.653 */ 24.654 } 24.655 // Appends a character 24.656 void StringBuffer::AppendChar(UInt32 ch) 24.657 { 24.658 char buff[8]; 24.659 UPInt origSize = GetSize(); 24.660 24.661 // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes 24.662 // in the UTF8 string. 24.663 SPInt srcSize = 0; 24.664 UTF8Util::EncodeChar(buff, &srcSize, ch); 24.665 OVR_ASSERT(srcSize >= 0); 24.666 24.667 UPInt size = origSize + srcSize; 24.668 Resize(size); 24.669 memcpy(pData + origSize, buff, srcSize); 24.670 } 24.671 24.672 // Append a string 24.673 void StringBuffer::AppendString(const wchar_t* pstr, SPInt len) 24.674 { 24.675 if (!pstr) 24.676 return; 24.677 24.678 SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len); 24.679 UPInt origSize = GetSize(); 24.680 UPInt size = srcSize + origSize; 24.681 24.682 Resize(size); 24.683 UTF8Util::EncodeString(pData + origSize, pstr, len); 24.684 } 24.685 24.686 void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz) 24.687 { 24.688 if (!putf8str || !utf8StrSz) 24.689 return; 24.690 if (utf8StrSz == -1) 24.691 utf8StrSz = (SPInt)OVR_strlen(putf8str); 24.692 24.693 UPInt origSize = GetSize(); 24.694 UPInt size = utf8StrSz + origSize; 24.695 24.696 Resize(size); 24.697 memcpy(pData + origSize, putf8str, utf8StrSz); 24.698 } 24.699 24.700 24.701 void StringBuffer::operator = (const char* pstr) 24.702 { 24.703 pstr = pstr ? pstr : ""; 24.704 UPInt size = OVR_strlen(pstr); 24.705 Resize(size); 24.706 memcpy(pData, pstr, size); 24.707 } 24.708 24.709 void StringBuffer::operator = (const wchar_t* pstr) 24.710 { 24.711 pstr = pstr ? pstr : L""; 24.712 UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr); 24.713 Resize(size); 24.714 UTF8Util::EncodeString(pData, pstr); 24.715 } 24.716 24.717 void StringBuffer::operator = (const String& src) 24.718 { 24.719 Resize(src.GetSize()); 24.720 memcpy(pData, src.ToCStr(), src.GetSize()); 24.721 } 24.722 24.723 24.724 // Inserts substr at posAt 24.725 void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) 24.726 { 24.727 UPInt oldSize = Size; 24.728 UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len; 24.729 UPInt byteIndex = LengthIsSize ? posAt : 24.730 (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size); 24.731 24.732 OVR_ASSERT(byteIndex <= oldSize); 24.733 Reserve(oldSize + insertSize); 24.734 24.735 memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1); 24.736 memcpy (pData + byteIndex, substr, insertSize); 24.737 LengthIsSize = false; 24.738 Size = oldSize + insertSize; 24.739 pData[Size] = 0; 24.740 } 24.741 24.742 // Inserts character at posAt 24.743 UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt) 24.744 { 24.745 char buf[8]; 24.746 SPInt len = 0; 24.747 UTF8Util::EncodeChar(buf, &len, c); 24.748 OVR_ASSERT(len >= 0); 24.749 buf[(UPInt)len] = 0; 24.750 24.751 Insert(buf, posAt, len); 24.752 return (UPInt)len; 24.753 } 24.754 24.755 } // OVR 24.756 \ No newline at end of file 24.757 +/************************************************************************************ 24.758 + 24.759 +Filename : OVR_String.cpp 24.760 +Content : String UTF8 string implementation with copy-on-write semantics 24.761 + (thread-safe for assignment but not modification). 24.762 +Created : September 19, 2012 24.763 +Notes : 24.764 + 24.765 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 24.766 + 24.767 +Use of this software is subject to the terms of the Oculus license 24.768 +agreement provided at the time of installation or download, or which 24.769 +otherwise accompanies this software in either electronic or hard copy form. 24.770 + 24.771 +************************************************************************************/ 24.772 + 24.773 +#include "OVR_String.h" 24.774 + 24.775 +#include <stdlib.h> 24.776 +#include <ctype.h> 24.777 + 24.778 +#ifdef OVR_OS_QNX 24.779 +# include <strings.h> 24.780 +#endif 24.781 + 24.782 +namespace OVR { 24.783 + 24.784 +#define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift) 24.785 + 24.786 +String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} }; 24.787 + 24.788 + 24.789 +String::String() 24.790 +{ 24.791 + pData = &NullData; 24.792 + pData->AddRef(); 24.793 +}; 24.794 + 24.795 +String::String(const char* pdata) 24.796 +{ 24.797 + // Obtain length in bytes; it doesn't matter if _data is UTF8. 24.798 + UPInt size = pdata ? OVR_strlen(pdata) : 0; 24.799 + pData = AllocDataCopy1(size, 0, pdata, size); 24.800 +}; 24.801 + 24.802 +String::String(const char* pdata1, const char* pdata2, const char* pdata3) 24.803 +{ 24.804 + // Obtain length in bytes; it doesn't matter if _data is UTF8. 24.805 + UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 24.806 + UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 24.807 + UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 24.808 + 24.809 + DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0, 24.810 + pdata1, size1, pdata2, size2); 24.811 + memcpy(pdataDesc->Data + size1 + size2, pdata3, size3); 24.812 + pData = pdataDesc; 24.813 +} 24.814 + 24.815 +String::String(const char* pdata, UPInt size) 24.816 +{ 24.817 + OVR_ASSERT((size == 0) || (pdata != 0)); 24.818 + pData = AllocDataCopy1(size, 0, pdata, size); 24.819 +}; 24.820 + 24.821 + 24.822 +String::String(const InitStruct& src, UPInt size) 24.823 +{ 24.824 + pData = AllocData(size, 0); 24.825 + src.InitString(GetData()->Data, size); 24.826 +} 24.827 + 24.828 +String::String(const String& src) 24.829 +{ 24.830 + pData = src.GetData(); 24.831 + pData->AddRef(); 24.832 +} 24.833 + 24.834 +String::String(const StringBuffer& src) 24.835 +{ 24.836 + pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()); 24.837 +} 24.838 + 24.839 +String::String(const wchar_t* data) 24.840 +{ 24.841 + pData = &NullData; 24.842 + pData->AddRef(); 24.843 + // Simplified logic for wchar_t constructor. 24.844 + if (data) 24.845 + *this = data; 24.846 +} 24.847 + 24.848 + 24.849 +String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize) 24.850 +{ 24.851 + String::DataDesc* pdesc; 24.852 + 24.853 + if (size == 0) 24.854 + { 24.855 + pdesc = &NullData; 24.856 + pdesc->AddRef(); 24.857 + return pdesc; 24.858 + } 24.859 + 24.860 + pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size); 24.861 + pdesc->Data[size] = 0; 24.862 + pdesc->RefCount = 1; 24.863 + pdesc->Size = size | lengthIsSize; 24.864 + return pdesc; 24.865 +} 24.866 + 24.867 + 24.868 +String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize, 24.869 + const char* pdata, UPInt copySize) 24.870 +{ 24.871 + String::DataDesc* pdesc = AllocData(size, lengthIsSize); 24.872 + memcpy(pdesc->Data, pdata, copySize); 24.873 + return pdesc; 24.874 +} 24.875 + 24.876 +String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize, 24.877 + const char* pdata1, UPInt copySize1, 24.878 + const char* pdata2, UPInt copySize2) 24.879 +{ 24.880 + String::DataDesc* pdesc = AllocData(size, lengthIsSize); 24.881 + memcpy(pdesc->Data, pdata1, copySize1); 24.882 + memcpy(pdesc->Data + copySize1, pdata2, copySize2); 24.883 + return pdesc; 24.884 +} 24.885 + 24.886 + 24.887 +UPInt String::GetLength() const 24.888 +{ 24.889 + // Optimize length accesses for non-UTF8 character strings. 24.890 + DataDesc* pdata = GetData(); 24.891 + UPInt length, size = pdata->GetSize(); 24.892 + 24.893 + if (pdata->LengthIsSize()) 24.894 + return size; 24.895 + 24.896 + length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size); 24.897 + 24.898 + if (length == size) 24.899 + pdata->Size |= String_LengthIsSize; 24.900 + 24.901 + return length; 24.902 +} 24.903 + 24.904 + 24.905 +//static UInt32 String_CharSearch(const char* buf, ) 24.906 + 24.907 + 24.908 +UInt32 String::GetCharAt(UPInt index) const 24.909 +{ 24.910 + SPInt i = (SPInt) index; 24.911 + DataDesc* pdata = GetData(); 24.912 + const char* buf = pdata->Data; 24.913 + UInt32 c; 24.914 + 24.915 + if (pdata->LengthIsSize()) 24.916 + { 24.917 + OVR_ASSERT(index < pdata->GetSize()); 24.918 + buf += i; 24.919 + return UTF8Util::DecodeNextChar_Advance0(&buf); 24.920 + } 24.921 + 24.922 + c = UTF8Util::GetCharAt(index, buf, pdata->GetSize()); 24.923 + return c; 24.924 +} 24.925 + 24.926 +UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const 24.927 +{ 24.928 + DataDesc* pdata = GetData(); 24.929 + SPInt i = (SPInt) index; 24.930 + const char* buf = pdata->Data; 24.931 + const char* end = buf + pdata->GetSize(); 24.932 + UInt32 c; 24.933 + 24.934 + do 24.935 + { 24.936 + c = UTF8Util::DecodeNextChar_Advance0(&buf); 24.937 + i--; 24.938 + 24.939 + if (buf >= end) 24.940 + { 24.941 + // We've hit the end of the string; don't go further. 24.942 + OVR_ASSERT(i == 0); 24.943 + return c; 24.944 + } 24.945 + } while (i >= 0); 24.946 + 24.947 + *offset = buf; 24.948 + 24.949 + return c; 24.950 +} 24.951 + 24.952 +UInt32 String::GetNextChar(const char** offset) const 24.953 +{ 24.954 + return UTF8Util::DecodeNextChar(offset); 24.955 +} 24.956 + 24.957 + 24.958 + 24.959 +void String::AppendChar(UInt32 ch) 24.960 +{ 24.961 + DataDesc* pdata = GetData(); 24.962 + UPInt size = pdata->GetSize(); 24.963 + char buff[8]; 24.964 + SPInt encodeSize = 0; 24.965 + 24.966 + // Converts ch into UTF8 string and fills it into buff. 24.967 + UTF8Util::EncodeChar(buff, &encodeSize, ch); 24.968 + OVR_ASSERT(encodeSize >= 0); 24.969 + 24.970 + SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0, 24.971 + pdata->Data, size, buff, (UPInt)encodeSize)); 24.972 + pdata->Release(); 24.973 +} 24.974 + 24.975 + 24.976 +void String::AppendString(const wchar_t* pstr, SPInt len) 24.977 +{ 24.978 + if (!pstr) 24.979 + return; 24.980 + 24.981 + DataDesc* pdata = GetData(); 24.982 + UPInt oldSize = pdata->GetSize(); 24.983 + UPInt encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len); 24.984 + 24.985 + DataDesc* pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0, 24.986 + pdata->Data, oldSize); 24.987 + UTF8Util::EncodeString(pnewData->Data + oldSize, pstr, len); 24.988 + 24.989 + SetData(pnewData); 24.990 + pdata->Release(); 24.991 +} 24.992 + 24.993 + 24.994 +void String::AppendString(const char* putf8str, SPInt utf8StrSz) 24.995 +{ 24.996 + if (!putf8str || !utf8StrSz) 24.997 + return; 24.998 + if (utf8StrSz == -1) 24.999 + utf8StrSz = (SPInt)OVR_strlen(putf8str); 24.1000 + 24.1001 + DataDesc* pdata = GetData(); 24.1002 + UPInt oldSize = pdata->GetSize(); 24.1003 + 24.1004 + SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0, 24.1005 + pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz)); 24.1006 + pdata->Release(); 24.1007 +} 24.1008 + 24.1009 +void String::AssignString(const InitStruct& src, UPInt size) 24.1010 +{ 24.1011 + DataDesc* poldData = GetData(); 24.1012 + DataDesc* pnewData = AllocData(size, 0); 24.1013 + src.InitString(pnewData->Data, size); 24.1014 + SetData(pnewData); 24.1015 + poldData->Release(); 24.1016 +} 24.1017 + 24.1018 +void String::AssignString(const char* putf8str, UPInt size) 24.1019 +{ 24.1020 + DataDesc* poldData = GetData(); 24.1021 + SetData(AllocDataCopy1(size, 0, putf8str, size)); 24.1022 + poldData->Release(); 24.1023 +} 24.1024 + 24.1025 +void String::operator = (const char* pstr) 24.1026 +{ 24.1027 + AssignString(pstr, pstr ? OVR_strlen(pstr) : 0); 24.1028 +} 24.1029 + 24.1030 +void String::operator = (const wchar_t* pwstr) 24.1031 +{ 24.1032 + DataDesc* poldData = GetData(); 24.1033 + UPInt size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0; 24.1034 + 24.1035 + DataDesc* pnewData = AllocData(size, 0); 24.1036 + UTF8Util::EncodeString(pnewData->Data, pwstr); 24.1037 + SetData(pnewData); 24.1038 + poldData->Release(); 24.1039 +} 24.1040 + 24.1041 + 24.1042 +void String::operator = (const String& src) 24.1043 +{ 24.1044 + DataDesc* psdata = src.GetData(); 24.1045 + DataDesc* pdata = GetData(); 24.1046 + 24.1047 + SetData(psdata); 24.1048 + psdata->AddRef(); 24.1049 + pdata->Release(); 24.1050 +} 24.1051 + 24.1052 + 24.1053 +void String::operator = (const StringBuffer& src) 24.1054 +{ 24.1055 + DataDesc* polddata = GetData(); 24.1056 + SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize())); 24.1057 + polddata->Release(); 24.1058 +} 24.1059 + 24.1060 +void String::operator += (const String& src) 24.1061 +{ 24.1062 + DataDesc *pourData = GetData(), 24.1063 + *psrcData = src.GetData(); 24.1064 + UPInt ourSize = pourData->GetSize(), 24.1065 + srcSize = psrcData->GetSize(); 24.1066 + UPInt lflag = pourData->GetLengthFlag() & psrcData->GetLengthFlag(); 24.1067 + 24.1068 + SetData(AllocDataCopy2(ourSize + srcSize, lflag, 24.1069 + pourData->Data, ourSize, psrcData->Data, srcSize)); 24.1070 + pourData->Release(); 24.1071 +} 24.1072 + 24.1073 + 24.1074 +String String::operator + (const char* str) const 24.1075 +{ 24.1076 + String tmp1(*this); 24.1077 + tmp1 += (str ? str : ""); 24.1078 + return tmp1; 24.1079 +} 24.1080 + 24.1081 +String String::operator + (const String& src) const 24.1082 +{ 24.1083 + String tmp1(*this); 24.1084 + tmp1 += src; 24.1085 + return tmp1; 24.1086 +} 24.1087 + 24.1088 +void String::Remove(UPInt posAt, SPInt removeLength) 24.1089 +{ 24.1090 + DataDesc* pdata = GetData(); 24.1091 + UPInt oldSize = pdata->GetSize(); 24.1092 + // Length indicates the number of characters to remove. 24.1093 + UPInt length = GetLength(); 24.1094 + 24.1095 + // If index is past the string, nothing to remove. 24.1096 + if (posAt >= length) 24.1097 + return; 24.1098 + // Otherwise, cap removeLength to the length of the string. 24.1099 + if ((posAt + removeLength) > length) 24.1100 + removeLength = length - posAt; 24.1101 + 24.1102 + // Get the byte position of the UTF8 char at position posAt. 24.1103 + SPInt bytePos = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize); 24.1104 + SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos); 24.1105 + 24.1106 + SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(), 24.1107 + pdata->Data, bytePos, 24.1108 + pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize))); 24.1109 + pdata->Release(); 24.1110 +} 24.1111 + 24.1112 + 24.1113 +String String::Substring(UPInt start, UPInt end) const 24.1114 +{ 24.1115 + UPInt length = GetLength(); 24.1116 + if ((start >= length) || (start >= end)) 24.1117 + return String(); 24.1118 + 24.1119 + DataDesc* pdata = GetData(); 24.1120 + 24.1121 + // If size matches, we know the exact index range. 24.1122 + if (pdata->LengthIsSize()) 24.1123 + return String(pdata->Data + start, end - start); 24.1124 + 24.1125 + // Get position of starting character. 24.1126 + SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize()); 24.1127 + SPInt byteSize = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart); 24.1128 + return String(pdata->Data + byteStart, (UPInt)byteSize); 24.1129 +} 24.1130 + 24.1131 +void String::Clear() 24.1132 +{ 24.1133 + NullData.AddRef(); 24.1134 + GetData()->Release(); 24.1135 + SetData(&NullData); 24.1136 +} 24.1137 + 24.1138 + 24.1139 +String String::ToUpper() const 24.1140 +{ 24.1141 + UInt32 c; 24.1142 + const char* psource = GetData()->Data; 24.1143 + const char* pend = psource + GetData()->GetSize(); 24.1144 + String str; 24.1145 + SPInt bufferOffset = 0; 24.1146 + char buffer[512]; 24.1147 + 24.1148 + while(psource < pend) 24.1149 + { 24.1150 + do { 24.1151 + c = UTF8Util::DecodeNextChar_Advance0(&psource); 24.1152 + UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c))); 24.1153 + } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); 24.1154 + 24.1155 + // Append string a piece at a time. 24.1156 + str.AppendString(buffer, bufferOffset); 24.1157 + bufferOffset = 0; 24.1158 + } 24.1159 + 24.1160 + return str; 24.1161 +} 24.1162 + 24.1163 +String String::ToLower() const 24.1164 +{ 24.1165 + UInt32 c; 24.1166 + const char* psource = GetData()->Data; 24.1167 + const char* pend = psource + GetData()->GetSize(); 24.1168 + String str; 24.1169 + SPInt bufferOffset = 0; 24.1170 + char buffer[512]; 24.1171 + 24.1172 + while(psource < pend) 24.1173 + { 24.1174 + do { 24.1175 + c = UTF8Util::DecodeNextChar_Advance0(&psource); 24.1176 + UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c))); 24.1177 + } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8))); 24.1178 + 24.1179 + // Append string a piece at a time. 24.1180 + str.AppendString(buffer, bufferOffset); 24.1181 + bufferOffset = 0; 24.1182 + } 24.1183 + 24.1184 + return str; 24.1185 +} 24.1186 + 24.1187 + 24.1188 + 24.1189 +String& String::Insert(const char* substr, UPInt posAt, SPInt strSize) 24.1190 +{ 24.1191 + DataDesc* poldData = GetData(); 24.1192 + UPInt oldSize = poldData->GetSize(); 24.1193 + UPInt insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize; 24.1194 + UPInt byteIndex = (poldData->LengthIsSize()) ? 24.1195 + posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize); 24.1196 + 24.1197 + OVR_ASSERT(byteIndex <= oldSize); 24.1198 + 24.1199 + DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0, 24.1200 + poldData->Data, byteIndex, substr, insertSize); 24.1201 + memcpy(pnewData->Data + byteIndex + insertSize, 24.1202 + poldData->Data + byteIndex, oldSize - byteIndex); 24.1203 + SetData(pnewData); 24.1204 + poldData->Release(); 24.1205 + return *this; 24.1206 +} 24.1207 + 24.1208 +/* 24.1209 +String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len) 24.1210 +{ 24.1211 + for (SPInt i = 0; i < len; ++i) 24.1212 + { 24.1213 + UPInt charw = InsertCharAt(substr[i], posAt); 24.1214 + posAt += charw; 24.1215 + } 24.1216 + return *this; 24.1217 +} 24.1218 +*/ 24.1219 + 24.1220 +UPInt String::InsertCharAt(UInt32 c, UPInt posAt) 24.1221 +{ 24.1222 + char buf[8]; 24.1223 + SPInt index = 0; 24.1224 + UTF8Util::EncodeChar(buf, &index, c); 24.1225 + OVR_ASSERT(index >= 0); 24.1226 + buf[(UPInt)index] = 0; 24.1227 + 24.1228 + Insert(buf, posAt, index); 24.1229 + return (UPInt)index; 24.1230 +} 24.1231 + 24.1232 + 24.1233 +int String::CompareNoCase(const char* a, const char* b) 24.1234 +{ 24.1235 + return OVR_stricmp(a, b); 24.1236 +} 24.1237 + 24.1238 +int String::CompareNoCase(const char* a, const char* b, SPInt len) 24.1239 +{ 24.1240 + if (len) 24.1241 + { 24.1242 + SPInt f,l; 24.1243 + SPInt slen = len; 24.1244 + const char *s = b; 24.1245 + do { 24.1246 + f = (SPInt)OVR_tolower((int)(*(a++))); 24.1247 + l = (SPInt)OVR_tolower((int)(*(b++))); 24.1248 + } while (--len && f && (f == l) && *b != 0); 24.1249 + 24.1250 + if (f == l && (len != 0 || *b != 0)) 24.1251 + { 24.1252 + f = (SPInt)slen; 24.1253 + l = (SPInt)OVR_strlen(s); 24.1254 + return int(f - l); 24.1255 + } 24.1256 + 24.1257 + return int(f - l); 24.1258 + } 24.1259 + else 24.1260 + return (0-(int)OVR_strlen(b)); 24.1261 +} 24.1262 + 24.1263 +// ***** Implement hash static functions 24.1264 + 24.1265 +// Hash function 24.1266 +UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed) 24.1267 +{ 24.1268 + const UByte* pdata = (const UByte*) pdataIn; 24.1269 + UPInt h = seed; 24.1270 + while (size > 0) 24.1271 + { 24.1272 + size--; 24.1273 + h = ((h << 5) + h) ^ (unsigned) pdata[size]; 24.1274 + } 24.1275 + 24.1276 + return h; 24.1277 +} 24.1278 + 24.1279 +// Hash function, case-insensitive 24.1280 +UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed) 24.1281 +{ 24.1282 + const UByte* pdata = (const UByte*) pdataIn; 24.1283 + UPInt h = seed; 24.1284 + while (size > 0) 24.1285 + { 24.1286 + size--; 24.1287 + h = ((h << 5) + h) ^ OVR_tolower(pdata[size]); 24.1288 + } 24.1289 + 24.1290 + // Alternative: "sdbm" hash function, suggested at same web page above. 24.1291 + // h = 0; 24.1292 + // for bytes { h = (h << 16) + (h << 6) - hash + *p; } 24.1293 + return h; 24.1294 +} 24.1295 + 24.1296 + 24.1297 + 24.1298 +// ***** String Buffer used for Building Strings 24.1299 + 24.1300 + 24.1301 +#define OVR_SBUFF_DEFAULT_GROW_SIZE 512 24.1302 +// Constructors / Destructor. 24.1303 +StringBuffer::StringBuffer() 24.1304 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1305 +{ 24.1306 +} 24.1307 + 24.1308 +StringBuffer::StringBuffer(UPInt growSize) 24.1309 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1310 +{ 24.1311 + SetGrowSize(growSize); 24.1312 +} 24.1313 + 24.1314 +StringBuffer::StringBuffer(const char* data) 24.1315 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1316 +{ 24.1317 + *this = data; 24.1318 +} 24.1319 + 24.1320 +StringBuffer::StringBuffer(const char* data, UPInt dataSize) 24.1321 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1322 +{ 24.1323 + AppendString(data, dataSize); 24.1324 +} 24.1325 + 24.1326 +StringBuffer::StringBuffer(const String& src) 24.1327 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1328 +{ 24.1329 + AppendString(src.ToCStr(), src.GetSize()); 24.1330 +} 24.1331 + 24.1332 +StringBuffer::StringBuffer(const StringBuffer& src) 24.1333 + : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1334 +{ 24.1335 + AppendString(src.ToCStr(), src.GetSize()); 24.1336 + LengthIsSize = src.LengthIsSize; 24.1337 +} 24.1338 + 24.1339 +StringBuffer::StringBuffer(const wchar_t* data) 24.1340 + : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false) 24.1341 +{ 24.1342 + *this = data; 24.1343 +} 24.1344 + 24.1345 +StringBuffer::~StringBuffer() 24.1346 +{ 24.1347 + if (pData) 24.1348 + OVR_FREE(pData); 24.1349 +} 24.1350 +void StringBuffer::SetGrowSize(UPInt growSize) 24.1351 +{ 24.1352 + if (growSize <= 16) 24.1353 + GrowSize = 16; 24.1354 + else 24.1355 + { 24.1356 + UByte bits = Alg::UpperBit(UInt32(growSize-1)); 24.1357 + UPInt size = 1<<bits; 24.1358 + GrowSize = size == growSize ? growSize : size; 24.1359 + } 24.1360 +} 24.1361 + 24.1362 +UPInt StringBuffer::GetLength() const 24.1363 +{ 24.1364 + UPInt length, size = GetSize(); 24.1365 + if (LengthIsSize) 24.1366 + return size; 24.1367 + 24.1368 + length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize()); 24.1369 + 24.1370 + if (length == GetSize()) 24.1371 + LengthIsSize = true; 24.1372 + return length; 24.1373 +} 24.1374 + 24.1375 +void StringBuffer::Reserve(UPInt _size) 24.1376 +{ 24.1377 + if (_size >= BufferSize) // >= because of trailing zero! (!AB) 24.1378 + { 24.1379 + BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1); 24.1380 + if (!pData) 24.1381 + pData = (char*)OVR_ALLOC(BufferSize); 24.1382 + else 24.1383 + pData = (char*)OVR_REALLOC(pData, BufferSize); 24.1384 + } 24.1385 +} 24.1386 +void StringBuffer::Resize(UPInt _size) 24.1387 +{ 24.1388 + Reserve(_size); 24.1389 + LengthIsSize = false; 24.1390 + Size = _size; 24.1391 + if (pData) 24.1392 + pData[Size] = 0; 24.1393 +} 24.1394 + 24.1395 +void StringBuffer::Clear() 24.1396 +{ 24.1397 + Resize(0); 24.1398 + /* 24.1399 + if (pData != pEmptyNullData) 24.1400 + { 24.1401 + OVR_FREE(pHeap, pData); 24.1402 + pData = pEmptyNullData; 24.1403 + Size = BufferSize = 0; 24.1404 + LengthIsSize = false; 24.1405 + } 24.1406 + */ 24.1407 +} 24.1408 +// Appends a character 24.1409 +void StringBuffer::AppendChar(UInt32 ch) 24.1410 +{ 24.1411 + char buff[8]; 24.1412 + UPInt origSize = GetSize(); 24.1413 + 24.1414 + // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes 24.1415 + // in the UTF8 string. 24.1416 + SPInt srcSize = 0; 24.1417 + UTF8Util::EncodeChar(buff, &srcSize, ch); 24.1418 + OVR_ASSERT(srcSize >= 0); 24.1419 + 24.1420 + UPInt size = origSize + srcSize; 24.1421 + Resize(size); 24.1422 + memcpy(pData + origSize, buff, srcSize); 24.1423 +} 24.1424 + 24.1425 +// Append a string 24.1426 +void StringBuffer::AppendString(const wchar_t* pstr, SPInt len) 24.1427 +{ 24.1428 + if (!pstr) 24.1429 + return; 24.1430 + 24.1431 + SPInt srcSize = UTF8Util::GetEncodeStringSize(pstr, len); 24.1432 + UPInt origSize = GetSize(); 24.1433 + UPInt size = srcSize + origSize; 24.1434 + 24.1435 + Resize(size); 24.1436 + UTF8Util::EncodeString(pData + origSize, pstr, len); 24.1437 +} 24.1438 + 24.1439 +void StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz) 24.1440 +{ 24.1441 + if (!putf8str || !utf8StrSz) 24.1442 + return; 24.1443 + if (utf8StrSz == -1) 24.1444 + utf8StrSz = (SPInt)OVR_strlen(putf8str); 24.1445 + 24.1446 + UPInt origSize = GetSize(); 24.1447 + UPInt size = utf8StrSz + origSize; 24.1448 + 24.1449 + Resize(size); 24.1450 + memcpy(pData + origSize, putf8str, utf8StrSz); 24.1451 +} 24.1452 + 24.1453 + 24.1454 +void StringBuffer::operator = (const char* pstr) 24.1455 +{ 24.1456 + pstr = pstr ? pstr : ""; 24.1457 + UPInt size = OVR_strlen(pstr); 24.1458 + Resize(size); 24.1459 + memcpy(pData, pstr, size); 24.1460 +} 24.1461 + 24.1462 +void StringBuffer::operator = (const wchar_t* pstr) 24.1463 +{ 24.1464 + pstr = pstr ? pstr : L""; 24.1465 + UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr); 24.1466 + Resize(size); 24.1467 + UTF8Util::EncodeString(pData, pstr); 24.1468 +} 24.1469 + 24.1470 +void StringBuffer::operator = (const String& src) 24.1471 +{ 24.1472 + Resize(src.GetSize()); 24.1473 + memcpy(pData, src.ToCStr(), src.GetSize()); 24.1474 +} 24.1475 + 24.1476 + 24.1477 +// Inserts substr at posAt 24.1478 +void StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len) 24.1479 +{ 24.1480 + UPInt oldSize = Size; 24.1481 + UPInt insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len; 24.1482 + UPInt byteIndex = LengthIsSize ? posAt : 24.1483 + (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size); 24.1484 + 24.1485 + OVR_ASSERT(byteIndex <= oldSize); 24.1486 + Reserve(oldSize + insertSize); 24.1487 + 24.1488 + memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1); 24.1489 + memcpy (pData + byteIndex, substr, insertSize); 24.1490 + LengthIsSize = false; 24.1491 + Size = oldSize + insertSize; 24.1492 + pData[Size] = 0; 24.1493 +} 24.1494 + 24.1495 +// Inserts character at posAt 24.1496 +UPInt StringBuffer::InsertCharAt(UInt32 c, UPInt posAt) 24.1497 +{ 24.1498 + char buf[8]; 24.1499 + SPInt len = 0; 24.1500 + UTF8Util::EncodeChar(buf, &len, c); 24.1501 + OVR_ASSERT(len >= 0); 24.1502 + buf[(UPInt)len] = 0; 24.1503 + 24.1504 + Insert(buf, posAt, len); 24.1505 + return (UPInt)len; 24.1506 +} 24.1507 + 24.1508 +} // OVR
25.1 --- a/libovr/Src/Kernel/OVR_String.h Sat Sep 14 17:51:03 2013 +0300 25.2 +++ b/libovr/Src/Kernel/OVR_String.h Sun Sep 15 04:10:05 2013 +0300 25.3 @@ -1,1 +1,645 @@ 25.4 -/************************************************************************************ 25.5 25.6 PublicHeader: OVR.h 25.7 Filename : OVR_String.h 25.8 Content : String UTF8 string implementation with copy-on-write semantics 25.9 (thread-safe for assignment but not modification). 25.10 Created : September 19, 2012 25.11 Notes : 25.12 25.13 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 25.14 25.15 Use of this software is subject to the terms of the Oculus license 25.16 agreement provided at the time of installation or download, or which 25.17 otherwise accompanies this software in either electronic or hard copy form. 25.18 25.19 ************************************************************************************/ 25.20 25.21 #ifndef OVR_String_h 25.22 #define OVR_String_h 25.23 25.24 #include "OVR_Types.h" 25.25 #include "OVR_Allocator.h" 25.26 #include "OVR_UTF8Util.h" 25.27 #include "OVR_Atomic.h" 25.28 #include "OVR_Std.h" 25.29 #include "OVR_Alg.h" 25.30 25.31 namespace OVR { 25.32 25.33 // ***** Classes 25.34 25.35 class String; 25.36 class StringBuffer; 25.37 25.38 25.39 //----------------------------------------------------------------------------------- 25.40 // ***** String Class 25.41 25.42 // String is UTF8 based string class with copy-on-write implementation 25.43 // for assignment. 25.44 25.45 class String 25.46 { 25.47 protected: 25.48 25.49 enum FlagConstants 25.50 { 25.51 //Flag_GetLength = 0x7FFFFFFF, 25.52 // This flag is set if GetLength() == GetSize() for a string. 25.53 // Avoid extra scanning is Substring and indexing logic. 25.54 Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1) 25.55 }; 25.56 25.57 25.58 // Internal structure to hold string data 25.59 struct DataDesc 25.60 { 25.61 // Number of bytes. Will be the same as the number of chars if the characters 25.62 // are ascii, may not be equal to number of chars in case string data is UTF8. 25.63 UPInt Size; 25.64 volatile SInt32 RefCount; 25.65 char Data[1]; 25.66 25.67 void AddRef() 25.68 { 25.69 AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1); 25.70 } 25.71 // Decrement ref count. This needs to be thread-safe, since 25.72 // a different thread could have also decremented the ref count. 25.73 // For example, if u start off with a ref count = 2. Now if u 25.74 // decrement the ref count and check against 0 in different 25.75 // statements, a different thread can also decrement the ref count 25.76 // in between our decrement and checking against 0 and will find 25.77 // the ref count = 0 and delete the object. This will lead to a crash 25.78 // when context switches to our thread and we'll be trying to delete 25.79 // an already deleted object. Hence decrementing the ref count and 25.80 // checking against 0 needs to made an atomic operation. 25.81 void Release() 25.82 { 25.83 if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 25.84 OVR_FREE(this); 25.85 } 25.86 25.87 static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; } 25.88 UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; } 25.89 UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); } 25.90 bool LengthIsSize() const { return GetLengthFlag() != 0; } 25.91 }; 25.92 25.93 // Heap type of the string is encoded in the lower bits. 25.94 enum HeapType 25.95 { 25.96 HT_Global = 0, // Heap is global. 25.97 HT_Local = 1, // SF::String_loc: Heap is determined based on string's address. 25.98 HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class. 25.99 HT_Mask = 3 25.100 }; 25.101 25.102 union { 25.103 DataDesc* pData; 25.104 UPInt HeapTypeBits; 25.105 }; 25.106 typedef union { 25.107 DataDesc* pData; 25.108 UPInt HeapTypeBits; 25.109 } DataDescUnion; 25.110 25.111 inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); } 25.112 25.113 inline DataDesc* GetData() const 25.114 { 25.115 DataDescUnion u; 25.116 u.pData = pData; 25.117 u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask); 25.118 return u.pData; 25.119 } 25.120 25.121 inline void SetData(DataDesc* pdesc) 25.122 { 25.123 HeapType ht = GetHeapType(); 25.124 pData = pdesc; 25.125 OVR_ASSERT((HeapTypeBits & HT_Mask) == 0); 25.126 HeapTypeBits |= ht; 25.127 } 25.128 25.129 25.130 DataDesc* AllocData(UPInt size, UPInt lengthIsSize); 25.131 DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize, 25.132 const char* pdata, UPInt copySize); 25.133 DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize, 25.134 const char* pdata1, UPInt copySize1, 25.135 const char* pdata2, UPInt copySize2); 25.136 25.137 // Special constructor to avoid data initalization when used in derived class. 25.138 struct NoConstructor { }; 25.139 String(const NoConstructor&) { } 25.140 25.141 public: 25.142 25.143 // For initializing string with dynamic buffer 25.144 struct InitStruct 25.145 { 25.146 virtual ~InitStruct() { } 25.147 virtual void InitString(char* pbuffer, UPInt size) const = 0; 25.148 }; 25.149 25.150 25.151 // Constructors / Destructors. 25.152 String(); 25.153 String(const char* data); 25.154 String(const char* data1, const char* pdata2, const char* pdata3 = 0); 25.155 String(const char* data, UPInt buflen); 25.156 String(const String& src); 25.157 String(const StringBuffer& src); 25.158 String(const InitStruct& src, UPInt size); 25.159 explicit String(const wchar_t* data); 25.160 25.161 // Destructor (Captain Obvious guarantees!) 25.162 ~String() 25.163 { 25.164 GetData()->Release(); 25.165 } 25.166 25.167 // Declaration of NullString 25.168 static DataDesc NullData; 25.169 25.170 25.171 // *** General Functions 25.172 25.173 void Clear(); 25.174 25.175 // For casting to a pointer to char. 25.176 operator const char*() const { return GetData()->Data; } 25.177 // Pointer to raw buffer. 25.178 const char* ToCStr() const { return GetData()->Data; } 25.179 25.180 // Returns number of bytes 25.181 UPInt GetSize() const { return GetData()->GetSize() ; } 25.182 // Tells whether or not the string is empty 25.183 bool IsEmpty() const { return GetSize() == 0; } 25.184 25.185 // Returns number of characters 25.186 UPInt GetLength() const; 25.187 25.188 // Returns character at the specified index 25.189 UInt32 GetCharAt(UPInt index) const; 25.190 UInt32 GetFirstCharAt(UPInt index, const char** offset) const; 25.191 UInt32 GetNextChar(const char** offset) const; 25.192 25.193 // Appends a character 25.194 void AppendChar(UInt32 ch); 25.195 25.196 // Append a string 25.197 void AppendString(const wchar_t* pstr, SPInt len = -1); 25.198 void AppendString(const char* putf8str, SPInt utf8StrSz = -1); 25.199 25.200 // Assigned a string with dynamic data (copied through initializer). 25.201 void AssignString(const InitStruct& src, UPInt size); 25.202 // Assigns string with known size. 25.203 void AssignString(const char* putf8str, UPInt size); 25.204 25.205 // Resize the string to the new size 25.206 // void Resize(UPInt _size); 25.207 25.208 // Removes the character at posAt 25.209 void Remove(UPInt posAt, SPInt len = 1); 25.210 25.211 // Returns a String that's a substring of this. 25.212 // -start is the index of the first UTF8 character you want to include. 25.213 // -end is the index one past the last UTF8 character you want to include. 25.214 String Substring(UPInt start, UPInt end) const; 25.215 25.216 // Case-conversion 25.217 String ToUpper() const; 25.218 String ToLower() const; 25.219 25.220 // Inserts substr at posAt 25.221 String& Insert (const char* substr, UPInt posAt, SPInt len = -1); 25.222 25.223 // Inserts character at posAt 25.224 UPInt InsertCharAt(UInt32 c, UPInt posAt); 25.225 25.226 // Inserts substr at posAt, which is an index of a character (not byte). 25.227 // Of size is specified, it is in bytes. 25.228 // String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1); 25.229 25.230 // Get Byte index of the character at position = index 25.231 UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); } 25.232 25.233 // Utility: case-insensitive string compare. stricmp() & strnicmp() are not 25.234 // ANSI or POSIX, do not seem to appear in Linux. 25.235 static int OVR_STDCALL CompareNoCase(const char* a, const char* b); 25.236 static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len); 25.237 25.238 // Hash function, case-insensitive 25.239 static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381); 25.240 25.241 // Hash function, case-sensitive 25.242 static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381); 25.243 25.244 25.245 // ***** File path parsing helper functions. 25.246 // Implemented in OVR_String_FilePath.cpp. 25.247 25.248 // Absolute paths can star with: 25.249 // - protocols: 'file://', 'http://' 25.250 // - windows drive: 'c:\' 25.251 // - UNC share name: '\\share' 25.252 // - unix root '/' 25.253 static bool HasAbsolutePath(const char* path); 25.254 static bool HasExtension(const char* path); 25.255 static bool HasProtocol(const char* path); 25.256 25.257 bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); } 25.258 bool HasExtension() const { return HasExtension(ToCStr()); } 25.259 bool HasProtocol() const { return HasProtocol(ToCStr()); } 25.260 25.261 String GetProtocol() const; // Returns protocol, if any, with trailing '://'. 25.262 String GetPath() const; // Returns path with trailing '/'. 25.263 String GetFilename() const; // Returns filename, including extension. 25.264 String GetExtension() const; // Returns extension with a dot. 25.265 25.266 void StripProtocol(); // Strips front protocol, if any, from the string. 25.267 void StripExtension(); // Strips off trailing extension. 25.268 25.269 25.270 // Operators 25.271 // Assignment 25.272 void operator = (const char* str); 25.273 void operator = (const wchar_t* str); 25.274 void operator = (const String& src); 25.275 void operator = (const StringBuffer& src); 25.276 25.277 // Addition 25.278 void operator += (const String& src); 25.279 void operator += (const char* psrc) { AppendString(psrc); } 25.280 void operator += (const wchar_t* psrc) { AppendString(psrc); } 25.281 void operator += (char ch) { AppendChar(ch); } 25.282 String operator + (const char* str) const; 25.283 String operator + (const String& src) const; 25.284 25.285 // Comparison 25.286 bool operator == (const String& str) const 25.287 { 25.288 return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0); 25.289 } 25.290 25.291 bool operator != (const String& str) const 25.292 { 25.293 return !operator == (str); 25.294 } 25.295 25.296 bool operator == (const char* str) const 25.297 { 25.298 return OVR_strcmp(GetData()->Data, str) == 0; 25.299 } 25.300 25.301 bool operator != (const char* str) const 25.302 { 25.303 return !operator == (str); 25.304 } 25.305 25.306 bool operator < (const char* pstr) const 25.307 { 25.308 return OVR_strcmp(GetData()->Data, pstr) < 0; 25.309 } 25.310 25.311 bool operator < (const String& str) const 25.312 { 25.313 return *this < str.GetData()->Data; 25.314 } 25.315 25.316 bool operator > (const char* pstr) const 25.317 { 25.318 return OVR_strcmp(GetData()->Data, pstr) > 0; 25.319 } 25.320 25.321 bool operator > (const String& str) const 25.322 { 25.323 return *this > str.GetData()->Data; 25.324 } 25.325 25.326 int CompareNoCase(const char* pstr) const 25.327 { 25.328 return CompareNoCase(GetData()->Data, pstr); 25.329 } 25.330 int CompareNoCase(const String& str) const 25.331 { 25.332 return CompareNoCase(GetData()->Data, str.ToCStr()); 25.333 } 25.334 25.335 // Accesses raw bytes 25.336 const char& operator [] (int index) const 25.337 { 25.338 OVR_ASSERT(index >= 0 && (UPInt)index < GetSize()); 25.339 return GetData()->Data[index]; 25.340 } 25.341 const char& operator [] (UPInt index) const 25.342 { 25.343 OVR_ASSERT(index < GetSize()); 25.344 return GetData()->Data[index]; 25.345 } 25.346 25.347 25.348 // Case insensitive keys are used to look up insensitive string in hash tables 25.349 // for SWF files with version before SWF 7. 25.350 struct NoCaseKey 25.351 { 25.352 const String* pStr; 25.353 NoCaseKey(const String &str) : pStr(&str){}; 25.354 }; 25.355 25.356 bool operator == (const NoCaseKey& strKey) const 25.357 { 25.358 return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 25.359 } 25.360 bool operator != (const NoCaseKey& strKey) const 25.361 { 25.362 return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 25.363 } 25.364 25.365 // Hash functor used for strings. 25.366 struct HashFunctor 25.367 { 25.368 UPInt operator()(const String& data) const 25.369 { 25.370 UPInt size = data.GetSize(); 25.371 return String::BernsteinHashFunction((const char*)data, size); 25.372 } 25.373 }; 25.374 // Case-insensitive hash functor used for strings. Supports additional 25.375 // lookup based on NoCaseKey. 25.376 struct NoCaseHashFunctor 25.377 { 25.378 UPInt operator()(const String& data) const 25.379 { 25.380 UPInt size = data.GetSize(); 25.381 return String::BernsteinHashFunctionCIS((const char*)data, size); 25.382 } 25.383 UPInt operator()(const NoCaseKey& data) const 25.384 { 25.385 UPInt size = data.pStr->GetSize(); 25.386 return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size); 25.387 } 25.388 }; 25.389 25.390 }; 25.391 25.392 25.393 //----------------------------------------------------------------------------------- 25.394 // ***** String Buffer used for Building Strings 25.395 25.396 class StringBuffer 25.397 { 25.398 char* pData; 25.399 UPInt Size; 25.400 UPInt BufferSize; 25.401 UPInt GrowSize; 25.402 mutable bool LengthIsSize; 25.403 25.404 public: 25.405 25.406 // Constructors / Destructor. 25.407 StringBuffer(); 25.408 explicit StringBuffer(UPInt growSize); 25.409 StringBuffer(const char* data); 25.410 StringBuffer(const char* data, UPInt buflen); 25.411 StringBuffer(const String& src); 25.412 StringBuffer(const StringBuffer& src); 25.413 explicit StringBuffer(const wchar_t* data); 25.414 ~StringBuffer(); 25.415 25.416 25.417 // Modify grow size used for growing/shrinking the buffer. 25.418 UPInt GetGrowSize() const { return GrowSize; } 25.419 void SetGrowSize(UPInt growSize); 25.420 25.421 25.422 // *** General Functions 25.423 // Does not release memory, just sets Size to 0 25.424 void Clear(); 25.425 25.426 // For casting to a pointer to char. 25.427 operator const char*() const { return (pData) ? pData : ""; } 25.428 // Pointer to raw buffer. 25.429 const char* ToCStr() const { return (pData) ? pData : ""; } 25.430 25.431 // Returns number of bytes. 25.432 UPInt GetSize() const { return Size ; } 25.433 // Tells whether or not the string is empty. 25.434 bool IsEmpty() const { return GetSize() == 0; } 25.435 25.436 // Returns number of characters 25.437 UPInt GetLength() const; 25.438 25.439 // Returns character at the specified index 25.440 UInt32 GetCharAt(UPInt index) const; 25.441 UInt32 GetFirstCharAt(UPInt index, const char** offset) const; 25.442 UInt32 GetNextChar(const char** offset) const; 25.443 25.444 25.445 // Resize the string to the new size 25.446 void Resize(UPInt _size); 25.447 void Reserve(UPInt _size); 25.448 25.449 // Appends a character 25.450 void AppendChar(UInt32 ch); 25.451 25.452 // Append a string 25.453 void AppendString(const wchar_t* pstr, SPInt len = -1); 25.454 void AppendString(const char* putf8str, SPInt utf8StrSz = -1); 25.455 void AppendFormat(const char* format, ...); 25.456 25.457 // Assigned a string with dynamic data (copied through initializer). 25.458 //void AssignString(const InitStruct& src, UPInt size); 25.459 25.460 // Inserts substr at posAt 25.461 void Insert (const char* substr, UPInt posAt, SPInt len = -1); 25.462 // Inserts character at posAt 25.463 UPInt InsertCharAt(UInt32 c, UPInt posAt); 25.464 25.465 // Assignment 25.466 void operator = (const char* str); 25.467 void operator = (const wchar_t* str); 25.468 void operator = (const String& src); 25.469 25.470 // Addition 25.471 void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); } 25.472 void operator += (const char* psrc) { AppendString(psrc); } 25.473 void operator += (const wchar_t* psrc) { AppendString(psrc); } 25.474 void operator += (char ch) { AppendChar(ch); } 25.475 //String operator + (const char* str) const ; 25.476 //String operator + (const String& src) const ; 25.477 25.478 // Accesses raw bytes 25.479 char& operator [] (int index) 25.480 { 25.481 OVR_ASSERT(((UPInt)index) < GetSize()); 25.482 return pData[index]; 25.483 } 25.484 char& operator [] (UPInt index) 25.485 { 25.486 OVR_ASSERT(index < GetSize()); 25.487 return pData[index]; 25.488 } 25.489 25.490 const char& operator [] (int index) const 25.491 { 25.492 OVR_ASSERT(((UPInt)index) < GetSize()); 25.493 return pData[index]; 25.494 } 25.495 const char& operator [] (UPInt index) const 25.496 { 25.497 OVR_ASSERT(index < GetSize()); 25.498 return pData[index]; 25.499 } 25.500 }; 25.501 25.502 25.503 // 25.504 // Wrapper for string data. The data must have a guaranteed 25.505 // lifespan throughout the usage of the wrapper. Not intended for 25.506 // cached usage. Not thread safe. 25.507 // 25.508 class StringDataPtr 25.509 { 25.510 public: 25.511 StringDataPtr() : pStr(NULL), Size(0) {} 25.512 StringDataPtr(const StringDataPtr& p) 25.513 : pStr(p.pStr), Size(p.Size) {} 25.514 StringDataPtr(const char* pstr, UPInt sz) 25.515 : pStr(pstr), Size(sz) {} 25.516 StringDataPtr(const char* pstr) 25.517 : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {} 25.518 explicit StringDataPtr(const String& str) 25.519 : pStr(str.ToCStr()), Size(str.GetSize()) {} 25.520 template <typename T, int N> 25.521 StringDataPtr(const T (&v)[N]) 25.522 : pStr(v), Size(N) {} 25.523 25.524 public: 25.525 const char* ToCStr() const { return pStr; } 25.526 UPInt GetSize() const { return Size; } 25.527 bool IsEmpty() const { return GetSize() == 0; } 25.528 25.529 // value is a prefix of this string 25.530 // Character's values are not compared. 25.531 bool IsPrefix(const StringDataPtr& value) const 25.532 { 25.533 return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize(); 25.534 } 25.535 // value is a suffix of this string 25.536 // Character's values are not compared. 25.537 bool IsSuffix(const StringDataPtr& value) const 25.538 { 25.539 return ToCStr() <= value.ToCStr() && (End()) == (value.End()); 25.540 } 25.541 25.542 // Find first character. 25.543 // init_ind - initial index. 25.544 SPInt FindChar(char c, UPInt init_ind = 0) const 25.545 { 25.546 for (UPInt i = init_ind; i < GetSize(); ++i) 25.547 if (pStr[i] == c) 25.548 return static_cast<SPInt>(i); 25.549 25.550 return -1; 25.551 } 25.552 25.553 // Find last character. 25.554 // init_ind - initial index. 25.555 SPInt FindLastChar(char c, UPInt init_ind = ~0) const 25.556 { 25.557 if (init_ind == (UPInt)~0 || init_ind > GetSize()) 25.558 init_ind = GetSize(); 25.559 else 25.560 ++init_ind; 25.561 25.562 for (UPInt i = init_ind; i > 0; --i) 25.563 if (pStr[i - 1] == c) 25.564 return static_cast<SPInt>(i - 1); 25.565 25.566 return -1; 25.567 } 25.568 25.569 // Create new object and trim size bytes from the left. 25.570 StringDataPtr GetTrimLeft(UPInt size) const 25.571 { 25.572 // Limit trim size to the size of the string. 25.573 size = Alg::PMin(GetSize(), size); 25.574 25.575 return StringDataPtr(ToCStr() + size, GetSize() - size); 25.576 } 25.577 // Create new object and trim size bytes from the right. 25.578 StringDataPtr GetTrimRight(UPInt size) const 25.579 { 25.580 // Limit trim to the size of the string. 25.581 size = Alg::PMin(GetSize(), size); 25.582 25.583 return StringDataPtr(ToCStr(), GetSize() - size); 25.584 } 25.585 25.586 // Create new object, which contains next token. 25.587 // Useful for parsing. 25.588 StringDataPtr GetNextToken(char separator = ':') const 25.589 { 25.590 UPInt cur_pos = 0; 25.591 const char* cur_str = ToCStr(); 25.592 25.593 for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos) 25.594 { 25.595 if (cur_str[cur_pos] == separator) 25.596 { 25.597 break; 25.598 } 25.599 } 25.600 25.601 return StringDataPtr(ToCStr(), cur_pos); 25.602 } 25.603 25.604 // Trim size bytes from the left. 25.605 StringDataPtr& TrimLeft(UPInt size) 25.606 { 25.607 // Limit trim size to the size of the string. 25.608 size = Alg::PMin(GetSize(), size); 25.609 pStr += size; 25.610 Size -= size; 25.611 25.612 return *this; 25.613 } 25.614 // Trim size bytes from the right. 25.615 StringDataPtr& TrimRight(UPInt size) 25.616 { 25.617 // Limit trim to the size of the string. 25.618 size = Alg::PMin(GetSize(), size); 25.619 Size -= size; 25.620 25.621 return *this; 25.622 } 25.623 25.624 const char* Begin() const { return ToCStr(); } 25.625 const char* End() const { return ToCStr() + GetSize(); } 25.626 25.627 // Hash functor used string data pointers 25.628 struct HashFunctor 25.629 { 25.630 UPInt operator()(const StringDataPtr& data) const 25.631 { 25.632 return String::BernsteinHashFunction(data.ToCStr(), data.GetSize()); 25.633 } 25.634 }; 25.635 25.636 bool operator== (const StringDataPtr& data) const 25.637 { 25.638 return (OVR_strncmp(pStr, data.pStr, data.Size) == 0); 25.639 } 25.640 25.641 protected: 25.642 const char* pStr; 25.643 UPInt Size; 25.644 }; 25.645 25.646 } // OVR 25.647 25.648 #endif 25.649 \ No newline at end of file 25.650 +/************************************************************************************ 25.651 + 25.652 +PublicHeader: OVR.h 25.653 +Filename : OVR_String.h 25.654 +Content : String UTF8 string implementation with copy-on-write semantics 25.655 + (thread-safe for assignment but not modification). 25.656 +Created : September 19, 2012 25.657 +Notes : 25.658 + 25.659 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 25.660 + 25.661 +Use of this software is subject to the terms of the Oculus license 25.662 +agreement provided at the time of installation or download, or which 25.663 +otherwise accompanies this software in either electronic or hard copy form. 25.664 + 25.665 +************************************************************************************/ 25.666 + 25.667 +#ifndef OVR_String_h 25.668 +#define OVR_String_h 25.669 + 25.670 +#include "OVR_Types.h" 25.671 +#include "OVR_Allocator.h" 25.672 +#include "OVR_UTF8Util.h" 25.673 +#include "OVR_Atomic.h" 25.674 +#include "OVR_Std.h" 25.675 +#include "OVR_Alg.h" 25.676 + 25.677 +namespace OVR { 25.678 + 25.679 +// ***** Classes 25.680 + 25.681 +class String; 25.682 +class StringBuffer; 25.683 + 25.684 + 25.685 +//----------------------------------------------------------------------------------- 25.686 +// ***** String Class 25.687 + 25.688 +// String is UTF8 based string class with copy-on-write implementation 25.689 +// for assignment. 25.690 + 25.691 +class String 25.692 +{ 25.693 +protected: 25.694 + 25.695 + enum FlagConstants 25.696 + { 25.697 + //Flag_GetLength = 0x7FFFFFFF, 25.698 + // This flag is set if GetLength() == GetSize() for a string. 25.699 + // Avoid extra scanning is Substring and indexing logic. 25.700 + Flag_LengthIsSizeShift = (sizeof(UPInt)*8 - 1) 25.701 + }; 25.702 + 25.703 + 25.704 + // Internal structure to hold string data 25.705 + struct DataDesc 25.706 + { 25.707 + // Number of bytes. Will be the same as the number of chars if the characters 25.708 + // are ascii, may not be equal to number of chars in case string data is UTF8. 25.709 + UPInt Size; 25.710 + volatile SInt32 RefCount; 25.711 + char Data[1]; 25.712 + 25.713 + void AddRef() 25.714 + { 25.715 + AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1); 25.716 + } 25.717 + // Decrement ref count. This needs to be thread-safe, since 25.718 + // a different thread could have also decremented the ref count. 25.719 + // For example, if u start off with a ref count = 2. Now if u 25.720 + // decrement the ref count and check against 0 in different 25.721 + // statements, a different thread can also decrement the ref count 25.722 + // in between our decrement and checking against 0 and will find 25.723 + // the ref count = 0 and delete the object. This will lead to a crash 25.724 + // when context switches to our thread and we'll be trying to delete 25.725 + // an already deleted object. Hence decrementing the ref count and 25.726 + // checking against 0 needs to made an atomic operation. 25.727 + void Release() 25.728 + { 25.729 + if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0) 25.730 + OVR_FREE(this); 25.731 + } 25.732 + 25.733 + static UPInt GetLengthFlagBit() { return UPInt(1) << Flag_LengthIsSizeShift; } 25.734 + UPInt GetSize() const { return Size & ~GetLengthFlagBit() ; } 25.735 + UPInt GetLengthFlag() const { return Size & GetLengthFlagBit(); } 25.736 + bool LengthIsSize() const { return GetLengthFlag() != 0; } 25.737 + }; 25.738 + 25.739 + // Heap type of the string is encoded in the lower bits. 25.740 + enum HeapType 25.741 + { 25.742 + HT_Global = 0, // Heap is global. 25.743 + HT_Local = 1, // SF::String_loc: Heap is determined based on string's address. 25.744 + HT_Dynamic = 2, // SF::String_temp: Heap is stored as a part of the class. 25.745 + HT_Mask = 3 25.746 + }; 25.747 + 25.748 + union { 25.749 + DataDesc* pData; 25.750 + UPInt HeapTypeBits; 25.751 + }; 25.752 + typedef union { 25.753 + DataDesc* pData; 25.754 + UPInt HeapTypeBits; 25.755 + } DataDescUnion; 25.756 + 25.757 + inline HeapType GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); } 25.758 + 25.759 + inline DataDesc* GetData() const 25.760 + { 25.761 + DataDescUnion u; 25.762 + u.pData = pData; 25.763 + u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask); 25.764 + return u.pData; 25.765 + } 25.766 + 25.767 + inline void SetData(DataDesc* pdesc) 25.768 + { 25.769 + HeapType ht = GetHeapType(); 25.770 + pData = pdesc; 25.771 + OVR_ASSERT((HeapTypeBits & HT_Mask) == 0); 25.772 + HeapTypeBits |= ht; 25.773 + } 25.774 + 25.775 + 25.776 + DataDesc* AllocData(UPInt size, UPInt lengthIsSize); 25.777 + DataDesc* AllocDataCopy1(UPInt size, UPInt lengthIsSize, 25.778 + const char* pdata, UPInt copySize); 25.779 + DataDesc* AllocDataCopy2(UPInt size, UPInt lengthIsSize, 25.780 + const char* pdata1, UPInt copySize1, 25.781 + const char* pdata2, UPInt copySize2); 25.782 + 25.783 + // Special constructor to avoid data initalization when used in derived class. 25.784 + struct NoConstructor { }; 25.785 + String(const NoConstructor&) { } 25.786 + 25.787 +public: 25.788 + 25.789 + // For initializing string with dynamic buffer 25.790 + struct InitStruct 25.791 + { 25.792 + virtual ~InitStruct() { } 25.793 + virtual void InitString(char* pbuffer, UPInt size) const = 0; 25.794 + }; 25.795 + 25.796 + 25.797 + // Constructors / Destructors. 25.798 + String(); 25.799 + String(const char* data); 25.800 + String(const char* data1, const char* pdata2, const char* pdata3 = 0); 25.801 + String(const char* data, UPInt buflen); 25.802 + String(const String& src); 25.803 + String(const StringBuffer& src); 25.804 + String(const InitStruct& src, UPInt size); 25.805 + explicit String(const wchar_t* data); 25.806 + 25.807 + // Destructor (Captain Obvious guarantees!) 25.808 + ~String() 25.809 + { 25.810 + GetData()->Release(); 25.811 + } 25.812 + 25.813 + // Declaration of NullString 25.814 + static DataDesc NullData; 25.815 + 25.816 + 25.817 + // *** General Functions 25.818 + 25.819 + void Clear(); 25.820 + 25.821 + // For casting to a pointer to char. 25.822 + operator const char*() const { return GetData()->Data; } 25.823 + // Pointer to raw buffer. 25.824 + const char* ToCStr() const { return GetData()->Data; } 25.825 + 25.826 + // Returns number of bytes 25.827 + UPInt GetSize() const { return GetData()->GetSize() ; } 25.828 + // Tells whether or not the string is empty 25.829 + bool IsEmpty() const { return GetSize() == 0; } 25.830 + 25.831 + // Returns number of characters 25.832 + UPInt GetLength() const; 25.833 + 25.834 + // Returns character at the specified index 25.835 + UInt32 GetCharAt(UPInt index) const; 25.836 + UInt32 GetFirstCharAt(UPInt index, const char** offset) const; 25.837 + UInt32 GetNextChar(const char** offset) const; 25.838 + 25.839 + // Appends a character 25.840 + void AppendChar(UInt32 ch); 25.841 + 25.842 + // Append a string 25.843 + void AppendString(const wchar_t* pstr, SPInt len = -1); 25.844 + void AppendString(const char* putf8str, SPInt utf8StrSz = -1); 25.845 + 25.846 + // Assigned a string with dynamic data (copied through initializer). 25.847 + void AssignString(const InitStruct& src, UPInt size); 25.848 + // Assigns string with known size. 25.849 + void AssignString(const char* putf8str, UPInt size); 25.850 + 25.851 + // Resize the string to the new size 25.852 +// void Resize(UPInt _size); 25.853 + 25.854 + // Removes the character at posAt 25.855 + void Remove(UPInt posAt, SPInt len = 1); 25.856 + 25.857 + // Returns a String that's a substring of this. 25.858 + // -start is the index of the first UTF8 character you want to include. 25.859 + // -end is the index one past the last UTF8 character you want to include. 25.860 + String Substring(UPInt start, UPInt end) const; 25.861 + 25.862 + // Case-conversion 25.863 + String ToUpper() const; 25.864 + String ToLower() const; 25.865 + 25.866 + // Inserts substr at posAt 25.867 + String& Insert (const char* substr, UPInt posAt, SPInt len = -1); 25.868 + 25.869 + // Inserts character at posAt 25.870 + UPInt InsertCharAt(UInt32 c, UPInt posAt); 25.871 + 25.872 + // Inserts substr at posAt, which is an index of a character (not byte). 25.873 + // Of size is specified, it is in bytes. 25.874 +// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1); 25.875 + 25.876 + // Get Byte index of the character at position = index 25.877 + UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); } 25.878 + 25.879 + // Utility: case-insensitive string compare. stricmp() & strnicmp() are not 25.880 + // ANSI or POSIX, do not seem to appear in Linux. 25.881 + static int OVR_STDCALL CompareNoCase(const char* a, const char* b); 25.882 + static int OVR_STDCALL CompareNoCase(const char* a, const char* b, SPInt len); 25.883 + 25.884 + // Hash function, case-insensitive 25.885 + static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381); 25.886 + 25.887 + // Hash function, case-sensitive 25.888 + static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381); 25.889 + 25.890 + 25.891 + // ***** File path parsing helper functions. 25.892 + // Implemented in OVR_String_FilePath.cpp. 25.893 + 25.894 + // Absolute paths can star with: 25.895 + // - protocols: 'file://', 'http://' 25.896 + // - windows drive: 'c:\' 25.897 + // - UNC share name: '\\share' 25.898 + // - unix root '/' 25.899 + static bool HasAbsolutePath(const char* path); 25.900 + static bool HasExtension(const char* path); 25.901 + static bool HasProtocol(const char* path); 25.902 + 25.903 + bool HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); } 25.904 + bool HasExtension() const { return HasExtension(ToCStr()); } 25.905 + bool HasProtocol() const { return HasProtocol(ToCStr()); } 25.906 + 25.907 + String GetProtocol() const; // Returns protocol, if any, with trailing '://'. 25.908 + String GetPath() const; // Returns path with trailing '/'. 25.909 + String GetFilename() const; // Returns filename, including extension. 25.910 + String GetExtension() const; // Returns extension with a dot. 25.911 + 25.912 + void StripProtocol(); // Strips front protocol, if any, from the string. 25.913 + void StripExtension(); // Strips off trailing extension. 25.914 + 25.915 + 25.916 + // Operators 25.917 + // Assignment 25.918 + void operator = (const char* str); 25.919 + void operator = (const wchar_t* str); 25.920 + void operator = (const String& src); 25.921 + void operator = (const StringBuffer& src); 25.922 + 25.923 + // Addition 25.924 + void operator += (const String& src); 25.925 + void operator += (const char* psrc) { AppendString(psrc); } 25.926 + void operator += (const wchar_t* psrc) { AppendString(psrc); } 25.927 + void operator += (char ch) { AppendChar(ch); } 25.928 + String operator + (const char* str) const; 25.929 + String operator + (const String& src) const; 25.930 + 25.931 + // Comparison 25.932 + bool operator == (const String& str) const 25.933 + { 25.934 + return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0); 25.935 + } 25.936 + 25.937 + bool operator != (const String& str) const 25.938 + { 25.939 + return !operator == (str); 25.940 + } 25.941 + 25.942 + bool operator == (const char* str) const 25.943 + { 25.944 + return OVR_strcmp(GetData()->Data, str) == 0; 25.945 + } 25.946 + 25.947 + bool operator != (const char* str) const 25.948 + { 25.949 + return !operator == (str); 25.950 + } 25.951 + 25.952 + bool operator < (const char* pstr) const 25.953 + { 25.954 + return OVR_strcmp(GetData()->Data, pstr) < 0; 25.955 + } 25.956 + 25.957 + bool operator < (const String& str) const 25.958 + { 25.959 + return *this < str.GetData()->Data; 25.960 + } 25.961 + 25.962 + bool operator > (const char* pstr) const 25.963 + { 25.964 + return OVR_strcmp(GetData()->Data, pstr) > 0; 25.965 + } 25.966 + 25.967 + bool operator > (const String& str) const 25.968 + { 25.969 + return *this > str.GetData()->Data; 25.970 + } 25.971 + 25.972 + int CompareNoCase(const char* pstr) const 25.973 + { 25.974 + return CompareNoCase(GetData()->Data, pstr); 25.975 + } 25.976 + int CompareNoCase(const String& str) const 25.977 + { 25.978 + return CompareNoCase(GetData()->Data, str.ToCStr()); 25.979 + } 25.980 + 25.981 + // Accesses raw bytes 25.982 + const char& operator [] (int index) const 25.983 + { 25.984 + OVR_ASSERT(index >= 0 && (UPInt)index < GetSize()); 25.985 + return GetData()->Data[index]; 25.986 + } 25.987 + const char& operator [] (UPInt index) const 25.988 + { 25.989 + OVR_ASSERT(index < GetSize()); 25.990 + return GetData()->Data[index]; 25.991 + } 25.992 + 25.993 + 25.994 + // Case insensitive keys are used to look up insensitive string in hash tables 25.995 + // for SWF files with version before SWF 7. 25.996 + struct NoCaseKey 25.997 + { 25.998 + const String* pStr; 25.999 + NoCaseKey(const String &str) : pStr(&str){}; 25.1000 + }; 25.1001 + 25.1002 + bool operator == (const NoCaseKey& strKey) const 25.1003 + { 25.1004 + return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 25.1005 + } 25.1006 + bool operator != (const NoCaseKey& strKey) const 25.1007 + { 25.1008 + return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0); 25.1009 + } 25.1010 + 25.1011 + // Hash functor used for strings. 25.1012 + struct HashFunctor 25.1013 + { 25.1014 + UPInt operator()(const String& data) const 25.1015 + { 25.1016 + UPInt size = data.GetSize(); 25.1017 + return String::BernsteinHashFunction((const char*)data, size); 25.1018 + } 25.1019 + }; 25.1020 + // Case-insensitive hash functor used for strings. Supports additional 25.1021 + // lookup based on NoCaseKey. 25.1022 + struct NoCaseHashFunctor 25.1023 + { 25.1024 + UPInt operator()(const String& data) const 25.1025 + { 25.1026 + UPInt size = data.GetSize(); 25.1027 + return String::BernsteinHashFunctionCIS((const char*)data, size); 25.1028 + } 25.1029 + UPInt operator()(const NoCaseKey& data) const 25.1030 + { 25.1031 + UPInt size = data.pStr->GetSize(); 25.1032 + return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size); 25.1033 + } 25.1034 + }; 25.1035 + 25.1036 +}; 25.1037 + 25.1038 + 25.1039 +//----------------------------------------------------------------------------------- 25.1040 +// ***** String Buffer used for Building Strings 25.1041 + 25.1042 +class StringBuffer 25.1043 +{ 25.1044 + char* pData; 25.1045 + UPInt Size; 25.1046 + UPInt BufferSize; 25.1047 + UPInt GrowSize; 25.1048 + mutable bool LengthIsSize; 25.1049 + 25.1050 +public: 25.1051 + 25.1052 + // Constructors / Destructor. 25.1053 + StringBuffer(); 25.1054 + explicit StringBuffer(UPInt growSize); 25.1055 + StringBuffer(const char* data); 25.1056 + StringBuffer(const char* data, UPInt buflen); 25.1057 + StringBuffer(const String& src); 25.1058 + StringBuffer(const StringBuffer& src); 25.1059 + explicit StringBuffer(const wchar_t* data); 25.1060 + ~StringBuffer(); 25.1061 + 25.1062 + 25.1063 + // Modify grow size used for growing/shrinking the buffer. 25.1064 + UPInt GetGrowSize() const { return GrowSize; } 25.1065 + void SetGrowSize(UPInt growSize); 25.1066 + 25.1067 + 25.1068 + // *** General Functions 25.1069 + // Does not release memory, just sets Size to 0 25.1070 + void Clear(); 25.1071 + 25.1072 + // For casting to a pointer to char. 25.1073 + operator const char*() const { return (pData) ? pData : ""; } 25.1074 + // Pointer to raw buffer. 25.1075 + const char* ToCStr() const { return (pData) ? pData : ""; } 25.1076 + 25.1077 + // Returns number of bytes. 25.1078 + UPInt GetSize() const { return Size ; } 25.1079 + // Tells whether or not the string is empty. 25.1080 + bool IsEmpty() const { return GetSize() == 0; } 25.1081 + 25.1082 + // Returns number of characters 25.1083 + UPInt GetLength() const; 25.1084 + 25.1085 + // Returns character at the specified index 25.1086 + UInt32 GetCharAt(UPInt index) const; 25.1087 + UInt32 GetFirstCharAt(UPInt index, const char** offset) const; 25.1088 + UInt32 GetNextChar(const char** offset) const; 25.1089 + 25.1090 + 25.1091 + // Resize the string to the new size 25.1092 + void Resize(UPInt _size); 25.1093 + void Reserve(UPInt _size); 25.1094 + 25.1095 + // Appends a character 25.1096 + void AppendChar(UInt32 ch); 25.1097 + 25.1098 + // Append a string 25.1099 + void AppendString(const wchar_t* pstr, SPInt len = -1); 25.1100 + void AppendString(const char* putf8str, SPInt utf8StrSz = -1); 25.1101 + void AppendFormat(const char* format, ...); 25.1102 + 25.1103 + // Assigned a string with dynamic data (copied through initializer). 25.1104 + //void AssignString(const InitStruct& src, UPInt size); 25.1105 + 25.1106 + // Inserts substr at posAt 25.1107 + void Insert (const char* substr, UPInt posAt, SPInt len = -1); 25.1108 + // Inserts character at posAt 25.1109 + UPInt InsertCharAt(UInt32 c, UPInt posAt); 25.1110 + 25.1111 + // Assignment 25.1112 + void operator = (const char* str); 25.1113 + void operator = (const wchar_t* str); 25.1114 + void operator = (const String& src); 25.1115 + 25.1116 + // Addition 25.1117 + void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); } 25.1118 + void operator += (const char* psrc) { AppendString(psrc); } 25.1119 + void operator += (const wchar_t* psrc) { AppendString(psrc); } 25.1120 + void operator += (char ch) { AppendChar(ch); } 25.1121 + //String operator + (const char* str) const ; 25.1122 + //String operator + (const String& src) const ; 25.1123 + 25.1124 + // Accesses raw bytes 25.1125 + char& operator [] (int index) 25.1126 + { 25.1127 + OVR_ASSERT(((UPInt)index) < GetSize()); 25.1128 + return pData[index]; 25.1129 + } 25.1130 + char& operator [] (UPInt index) 25.1131 + { 25.1132 + OVR_ASSERT(index < GetSize()); 25.1133 + return pData[index]; 25.1134 + } 25.1135 + 25.1136 + const char& operator [] (int index) const 25.1137 + { 25.1138 + OVR_ASSERT(((UPInt)index) < GetSize()); 25.1139 + return pData[index]; 25.1140 + } 25.1141 + const char& operator [] (UPInt index) const 25.1142 + { 25.1143 + OVR_ASSERT(index < GetSize()); 25.1144 + return pData[index]; 25.1145 + } 25.1146 +}; 25.1147 + 25.1148 + 25.1149 +// 25.1150 +// Wrapper for string data. The data must have a guaranteed 25.1151 +// lifespan throughout the usage of the wrapper. Not intended for 25.1152 +// cached usage. Not thread safe. 25.1153 +// 25.1154 +class StringDataPtr 25.1155 +{ 25.1156 +public: 25.1157 + StringDataPtr() : pStr(NULL), Size(0) {} 25.1158 + StringDataPtr(const StringDataPtr& p) 25.1159 + : pStr(p.pStr), Size(p.Size) {} 25.1160 + StringDataPtr(const char* pstr, UPInt sz) 25.1161 + : pStr(pstr), Size(sz) {} 25.1162 + StringDataPtr(const char* pstr) 25.1163 + : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {} 25.1164 + explicit StringDataPtr(const String& str) 25.1165 + : pStr(str.ToCStr()), Size(str.GetSize()) {} 25.1166 + template <typename T, int N> 25.1167 + StringDataPtr(const T (&v)[N]) 25.1168 + : pStr(v), Size(N) {} 25.1169 + 25.1170 +public: 25.1171 + const char* ToCStr() const { return pStr; } 25.1172 + UPInt GetSize() const { return Size; } 25.1173 + bool IsEmpty() const { return GetSize() == 0; } 25.1174 + 25.1175 + // value is a prefix of this string 25.1176 + // Character's values are not compared. 25.1177 + bool IsPrefix(const StringDataPtr& value) const 25.1178 + { 25.1179 + return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize(); 25.1180 + } 25.1181 + // value is a suffix of this string 25.1182 + // Character's values are not compared. 25.1183 + bool IsSuffix(const StringDataPtr& value) const 25.1184 + { 25.1185 + return ToCStr() <= value.ToCStr() && (End()) == (value.End()); 25.1186 + } 25.1187 + 25.1188 + // Find first character. 25.1189 + // init_ind - initial index. 25.1190 + SPInt FindChar(char c, UPInt init_ind = 0) const 25.1191 + { 25.1192 + for (UPInt i = init_ind; i < GetSize(); ++i) 25.1193 + if (pStr[i] == c) 25.1194 + return static_cast<SPInt>(i); 25.1195 + 25.1196 + return -1; 25.1197 + } 25.1198 + 25.1199 + // Find last character. 25.1200 + // init_ind - initial index. 25.1201 + SPInt FindLastChar(char c, UPInt init_ind = ~0) const 25.1202 + { 25.1203 + if (init_ind == (UPInt)~0 || init_ind > GetSize()) 25.1204 + init_ind = GetSize(); 25.1205 + else 25.1206 + ++init_ind; 25.1207 + 25.1208 + for (UPInt i = init_ind; i > 0; --i) 25.1209 + if (pStr[i - 1] == c) 25.1210 + return static_cast<SPInt>(i - 1); 25.1211 + 25.1212 + return -1; 25.1213 + } 25.1214 + 25.1215 + // Create new object and trim size bytes from the left. 25.1216 + StringDataPtr GetTrimLeft(UPInt size) const 25.1217 + { 25.1218 + // Limit trim size to the size of the string. 25.1219 + size = Alg::PMin(GetSize(), size); 25.1220 + 25.1221 + return StringDataPtr(ToCStr() + size, GetSize() - size); 25.1222 + } 25.1223 + // Create new object and trim size bytes from the right. 25.1224 + StringDataPtr GetTrimRight(UPInt size) const 25.1225 + { 25.1226 + // Limit trim to the size of the string. 25.1227 + size = Alg::PMin(GetSize(), size); 25.1228 + 25.1229 + return StringDataPtr(ToCStr(), GetSize() - size); 25.1230 + } 25.1231 + 25.1232 + // Create new object, which contains next token. 25.1233 + // Useful for parsing. 25.1234 + StringDataPtr GetNextToken(char separator = ':') const 25.1235 + { 25.1236 + UPInt cur_pos = 0; 25.1237 + const char* cur_str = ToCStr(); 25.1238 + 25.1239 + for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos) 25.1240 + { 25.1241 + if (cur_str[cur_pos] == separator) 25.1242 + { 25.1243 + break; 25.1244 + } 25.1245 + } 25.1246 + 25.1247 + return StringDataPtr(ToCStr(), cur_pos); 25.1248 + } 25.1249 + 25.1250 + // Trim size bytes from the left. 25.1251 + StringDataPtr& TrimLeft(UPInt size) 25.1252 + { 25.1253 + // Limit trim size to the size of the string. 25.1254 + size = Alg::PMin(GetSize(), size); 25.1255 + pStr += size; 25.1256 + Size -= size; 25.1257 + 25.1258 + return *this; 25.1259 + } 25.1260 + // Trim size bytes from the right. 25.1261 + StringDataPtr& TrimRight(UPInt size) 25.1262 + { 25.1263 + // Limit trim to the size of the string. 25.1264 + size = Alg::PMin(GetSize(), size); 25.1265 + Size -= size; 25.1266 + 25.1267 + return *this; 25.1268 + } 25.1269 + 25.1270 + const char* Begin() const { return ToCStr(); } 25.1271 + const char* End() const { return ToCStr() + GetSize(); } 25.1272 + 25.1273 + // Hash functor used string data pointers 25.1274 + struct HashFunctor 25.1275 + { 25.1276 + UPInt operator()(const StringDataPtr& data) const 25.1277 + { 25.1278 + return String::BernsteinHashFunction(data.ToCStr(), data.GetSize()); 25.1279 + } 25.1280 + }; 25.1281 + 25.1282 + bool operator== (const StringDataPtr& data) const 25.1283 + { 25.1284 + return (OVR_strncmp(pStr, data.pStr, data.Size) == 0); 25.1285 + } 25.1286 + 25.1287 +protected: 25.1288 + const char* pStr; 25.1289 + UPInt Size; 25.1290 +}; 25.1291 + 25.1292 +} // OVR 25.1293 + 25.1294 +#endif
26.1 --- a/libovr/Src/Kernel/OVR_StringHash.h Sat Sep 14 17:51:03 2013 +0300 26.2 +++ b/libovr/Src/Kernel/OVR_StringHash.h Sun Sep 15 04:10:05 2013 +0300 26.3 @@ -1,1 +1,89 @@ 26.4 -/************************************************************************************ 26.5 26.6 PublicHeader: None 26.7 Filename : OVR_StringHash.h 26.8 Content : String hash table used when optional case-insensitive 26.9 lookup is required. 26.10 Created : September 19, 2012 26.11 Notes : 26.12 26.13 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 26.14 26.15 Use of this software is subject to the terms of the Oculus license 26.16 agreement provided at the time of installation or download, or which 26.17 otherwise accompanies this software in either electronic or hard copy form. 26.18 26.19 ************************************************************************************/ 26.20 26.21 #ifndef OVR_StringHash_h 26.22 #define OVR_StringHash_h 26.23 26.24 #include "OVR_String.h" 26.25 #include "OVR_Hash.h" 26.26 26.27 namespace OVR { 26.28 26.29 //----------------------------------------------------------------------------------- 26.30 // *** StringHash 26.31 26.32 // This is a custom string hash table that supports case-insensitive 26.33 // searches through special functions such as GetCaseInsensitive, etc. 26.34 // This class is used for Flash labels, exports and other case-insensitive tables. 26.35 26.36 template<class U, class Allocator = ContainerAllocator<U> > 26.37 class StringHash : public Hash<String, U, String::NoCaseHashFunctor, Allocator> 26.38 { 26.39 public: 26.40 typedef U ValueType; 26.41 typedef StringHash<U, Allocator> SelfType; 26.42 typedef Hash<String, U, String::NoCaseHashFunctor, Allocator> BaseType; 26.43 26.44 public: 26.45 26.46 void operator = (const SelfType& src) { BaseType::operator = (src); } 26.47 26.48 bool GetCaseInsensitive(const String& key, U* pvalue) const 26.49 { 26.50 String::NoCaseKey ikey(key); 26.51 return BaseType::GetAlt(ikey, pvalue); 26.52 } 26.53 // Pointer-returning get variety. 26.54 const U* GetCaseInsensitive(const String& key) const 26.55 { 26.56 String::NoCaseKey ikey(key); 26.57 return BaseType::GetAlt(ikey); 26.58 } 26.59 U* GetCaseInsensitive(const String& key) 26.60 { 26.61 String::NoCaseKey ikey(key); 26.62 return BaseType::GetAlt(ikey); 26.63 } 26.64 26.65 26.66 typedef typename BaseType::Iterator base_iterator; 26.67 26.68 base_iterator FindCaseInsensitive(const String& key) 26.69 { 26.70 String::NoCaseKey ikey(key); 26.71 return BaseType::FindAlt(ikey); 26.72 } 26.73 26.74 // Set just uses a find and assigns value if found. The key is not modified; 26.75 // this behavior is identical to Flash string variable assignment. 26.76 void SetCaseInsensitive(const String& key, const U& value) 26.77 { 26.78 base_iterator it = FindCaseInsensitive(key); 26.79 if (it != BaseType::End()) 26.80 { 26.81 it->Second = value; 26.82 } 26.83 else 26.84 { 26.85 BaseType::Add(key, value); 26.86 } 26.87 } 26.88 }; 26.89 26.90 } // OVR 26.91 26.92 #endif 26.93 \ No newline at end of file 26.94 +/************************************************************************************ 26.95 + 26.96 +PublicHeader: None 26.97 +Filename : OVR_StringHash.h 26.98 +Content : String hash table used when optional case-insensitive 26.99 + lookup is required. 26.100 +Created : September 19, 2012 26.101 +Notes : 26.102 + 26.103 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 26.104 + 26.105 +Use of this software is subject to the terms of the Oculus license 26.106 +agreement provided at the time of installation or download, or which 26.107 +otherwise accompanies this software in either electronic or hard copy form. 26.108 + 26.109 +************************************************************************************/ 26.110 + 26.111 +#ifndef OVR_StringHash_h 26.112 +#define OVR_StringHash_h 26.113 + 26.114 +#include "OVR_String.h" 26.115 +#include "OVR_Hash.h" 26.116 + 26.117 +namespace OVR { 26.118 + 26.119 +//----------------------------------------------------------------------------------- 26.120 +// *** StringHash 26.121 + 26.122 +// This is a custom string hash table that supports case-insensitive 26.123 +// searches through special functions such as GetCaseInsensitive, etc. 26.124 +// This class is used for Flash labels, exports and other case-insensitive tables. 26.125 + 26.126 +template<class U, class Allocator = ContainerAllocator<U> > 26.127 +class StringHash : public Hash<String, U, String::NoCaseHashFunctor, Allocator> 26.128 +{ 26.129 +public: 26.130 + typedef U ValueType; 26.131 + typedef StringHash<U, Allocator> SelfType; 26.132 + typedef Hash<String, U, String::NoCaseHashFunctor, Allocator> BaseType; 26.133 + 26.134 +public: 26.135 + 26.136 + void operator = (const SelfType& src) { BaseType::operator = (src); } 26.137 + 26.138 + bool GetCaseInsensitive(const String& key, U* pvalue) const 26.139 + { 26.140 + String::NoCaseKey ikey(key); 26.141 + return BaseType::GetAlt(ikey, pvalue); 26.142 + } 26.143 + // Pointer-returning get variety. 26.144 + const U* GetCaseInsensitive(const String& key) const 26.145 + { 26.146 + String::NoCaseKey ikey(key); 26.147 + return BaseType::GetAlt(ikey); 26.148 + } 26.149 + U* GetCaseInsensitive(const String& key) 26.150 + { 26.151 + String::NoCaseKey ikey(key); 26.152 + return BaseType::GetAlt(ikey); 26.153 + } 26.154 + 26.155 + 26.156 + typedef typename BaseType::Iterator base_iterator; 26.157 + 26.158 + base_iterator FindCaseInsensitive(const String& key) 26.159 + { 26.160 + String::NoCaseKey ikey(key); 26.161 + return BaseType::FindAlt(ikey); 26.162 + } 26.163 + 26.164 + // Set just uses a find and assigns value if found. The key is not modified; 26.165 + // this behavior is identical to Flash string variable assignment. 26.166 + void SetCaseInsensitive(const String& key, const U& value) 26.167 + { 26.168 + base_iterator it = FindCaseInsensitive(key); 26.169 + if (it != BaseType::End()) 26.170 + { 26.171 + it->Second = value; 26.172 + } 26.173 + else 26.174 + { 26.175 + BaseType::Add(key, value); 26.176 + } 26.177 + } 26.178 +}; 26.179 + 26.180 +} // OVR 26.181 + 26.182 +#endif
27.1 --- a/libovr/Src/Kernel/OVR_String_FormatUtil.cpp Sat Sep 14 17:51:03 2013 +0300 27.2 +++ b/libovr/Src/Kernel/OVR_String_FormatUtil.cpp Sun Sep 15 04:10:05 2013 +0300 27.3 @@ -1,1 +1,42 @@ 27.4 -/************************************************************************************ 27.5 27.6 Filename : OVR_String_FormatUtil.cpp 27.7 Content : String format functions. 27.8 Created : February 27, 2013 27.9 Notes : 27.10 27.11 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 27.12 27.13 Use of this software is subject to the terms of the Oculus license 27.14 agreement provided at the time of installation or download, or which 27.15 otherwise accompanies this software in either electronic or hard copy form. 27.16 27.17 ************************************************************************************/ 27.18 27.19 #include "OVR_String.h" 27.20 #include "OVR_Log.h" 27.21 27.22 namespace OVR { 27.23 27.24 void StringBuffer::AppendFormat(const char* format, ...) 27.25 { 27.26 va_list argList; 27.27 27.28 va_start(argList, format); 27.29 UPInt size = OVR_vscprintf(format, argList); 27.30 va_end(argList); 27.31 27.32 char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1)); 27.33 27.34 va_start(argList, format); 27.35 UPInt result = OVR_vsprintf(buffer, size+1, format, argList); 27.36 OVR_UNUSED1(result); 27.37 va_end(argList); 27.38 OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf")); 27.39 27.40 AppendString(buffer); 27.41 27.42 OVR_FREE(buffer); 27.43 } 27.44 27.45 } // OVR 27.46 \ No newline at end of file 27.47 +/************************************************************************************ 27.48 + 27.49 +Filename : OVR_String_FormatUtil.cpp 27.50 +Content : String format functions. 27.51 +Created : February 27, 2013 27.52 +Notes : 27.53 + 27.54 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 27.55 + 27.56 +Use of this software is subject to the terms of the Oculus license 27.57 +agreement provided at the time of installation or download, or which 27.58 +otherwise accompanies this software in either electronic or hard copy form. 27.59 + 27.60 +************************************************************************************/ 27.61 + 27.62 +#include "OVR_String.h" 27.63 +#include "OVR_Log.h" 27.64 + 27.65 +namespace OVR { 27.66 + 27.67 +void StringBuffer::AppendFormat(const char* format, ...) 27.68 +{ 27.69 + va_list argList; 27.70 + 27.71 + va_start(argList, format); 27.72 + UPInt size = OVR_vscprintf(format, argList); 27.73 + va_end(argList); 27.74 + 27.75 + char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1)); 27.76 + 27.77 + va_start(argList, format); 27.78 + UPInt result = OVR_vsprintf(buffer, size+1, format, argList); 27.79 + OVR_UNUSED1(result); 27.80 + va_end(argList); 27.81 + OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf")); 27.82 + 27.83 + AppendString(buffer); 27.84 + 27.85 + OVR_FREE(buffer); 27.86 +} 27.87 + 27.88 +} // OVR
28.1 --- a/libovr/Src/Kernel/OVR_String_PathUtil.cpp Sat Sep 14 17:51:03 2013 +0300 28.2 +++ b/libovr/Src/Kernel/OVR_String_PathUtil.cpp Sun Sep 15 04:10:05 2013 +0300 28.3 @@ -1,1 +1,200 @@ 28.4 -/************************************************************************************ 28.5 28.6 Filename : OVR_String_PathUtil.cpp 28.7 Content : String filename/url helper function 28.8 Created : September 19, 2012 28.9 Notes : 28.10 28.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 28.12 28.13 Use of this software is subject to the terms of the Oculus license 28.14 agreement provided at the time of installation or download, or which 28.15 otherwise accompanies this software in either electronic or hard copy form. 28.16 28.17 ************************************************************************************/ 28.18 28.19 #include "OVR_String.h" 28.20 #include "OVR_UTF8Util.h" 28.21 28.22 namespace OVR { 28.23 28.24 //-------------------------------------------------------------------- 28.25 // ***** Path-Scanner helper function 28.26 28.27 // Scans file path finding filename start and extension start, fills in their addess. 28.28 void ScanFilePath(const char* url, const char** pfilename, const char** pext) 28.29 { 28.30 const char* urlStart = url; 28.31 const char *filename = 0; 28.32 const char *lastDot = 0; 28.33 28.34 UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.35 28.36 while (charVal != 0) 28.37 { 28.38 if ((charVal == '/') || (charVal == '\\')) 28.39 { 28.40 filename = url; 28.41 lastDot = 0; 28.42 } 28.43 else if (charVal == '.') 28.44 { 28.45 lastDot = url - 1; 28.46 } 28.47 28.48 charVal = UTF8Util::DecodeNextChar(&url); 28.49 } 28.50 28.51 if (pfilename) 28.52 { 28.53 // It was a naked filename 28.54 if (urlStart && (*urlStart != '.') && *urlStart) 28.55 *pfilename = urlStart; 28.56 else 28.57 *pfilename = filename; 28.58 } 28.59 28.60 if (pext) 28.61 { 28.62 *pext = lastDot; 28.63 } 28.64 } 28.65 28.66 // Scans till the end of protocol. Returns first character past protocol, 28.67 // 0 if not found. 28.68 // - protocol: 'file://', 'http://' 28.69 const char* ScanPathProtocol(const char* url) 28.70 { 28.71 UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.72 UInt32 charVal2; 28.73 28.74 while (charVal != 0) 28.75 { 28.76 // Treat a colon followed by a slash as absolute. 28.77 if (charVal == ':') 28.78 { 28.79 charVal2 = UTF8Util::DecodeNextChar(&url); 28.80 charVal = UTF8Util::DecodeNextChar(&url); 28.81 if ((charVal == '/') && (charVal2 == '\\')) 28.82 return url; 28.83 } 28.84 charVal = UTF8Util::DecodeNextChar(&url); 28.85 } 28.86 return 0; 28.87 } 28.88 28.89 28.90 //-------------------------------------------------------------------- 28.91 // ***** String Path API implementation 28.92 28.93 bool String::HasAbsolutePath(const char* url) 28.94 { 28.95 // Absolute paths can star with: 28.96 // - protocols: 'file://', 'http://' 28.97 // - windows drive: 'c:\' 28.98 // - UNC share name: '\\share' 28.99 // - unix root '/' 28.100 28.101 // On the other hand, relative paths are: 28.102 // - directory: 'directory/file' 28.103 // - this directory: './file' 28.104 // - parent directory: '../file' 28.105 // 28.106 // For now, we don't parse '.' or '..' out, but instead let it be concatenated 28.107 // to string and let the OS figure it out. This, however, is not good for file 28.108 // name matching in library/etc, so it should be improved. 28.109 28.110 if (!url || !*url) 28.111 return true; // Treat empty strings as absolute. 28.112 28.113 UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.114 28.115 // Fist character of '/' or '\\' means absolute url. 28.116 if ((charVal == '/') || (charVal == '\\')) 28.117 return true; 28.118 28.119 while (charVal != 0) 28.120 { 28.121 // Treat a colon followed by a slash as absolute. 28.122 if (charVal == ':') 28.123 { 28.124 charVal = UTF8Util::DecodeNextChar(&url); 28.125 // Protocol or windows drive. Absolute. 28.126 if ((charVal == '/') || (charVal == '\\')) 28.127 return true; 28.128 } 28.129 else if ((charVal == '/') || (charVal == '\\')) 28.130 { 28.131 // Not a first character (else 'if' above the loop would have caught it). 28.132 // Must be a relative url. 28.133 break; 28.134 } 28.135 28.136 charVal = UTF8Util::DecodeNextChar(&url); 28.137 } 28.138 28.139 // We get here for relative paths. 28.140 return false; 28.141 } 28.142 28.143 28.144 bool String::HasExtension(const char* path) 28.145 { 28.146 const char* ext = 0; 28.147 ScanFilePath(path, 0, &ext); 28.148 return ext != 0; 28.149 } 28.150 bool String::HasProtocol(const char* path) 28.151 { 28.152 return ScanPathProtocol(path) != 0; 28.153 } 28.154 28.155 28.156 String String::GetPath() const 28.157 { 28.158 const char* filename = 0; 28.159 ScanFilePath(ToCStr(), &filename, 0); 28.160 28.161 // Technically we can have extra logic somewhere for paths, 28.162 // such as enforcing protocol and '/' only based on flags, 28.163 // but we keep it simple for now. 28.164 return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize()); 28.165 } 28.166 28.167 String String::GetProtocol() const 28.168 { 28.169 const char* protocolEnd = ScanPathProtocol(ToCStr()); 28.170 return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0); 28.171 } 28.172 28.173 String String::GetFilename() const 28.174 { 28.175 const char* filename = 0; 28.176 ScanFilePath(ToCStr(), &filename, 0); 28.177 return String(filename); 28.178 } 28.179 String String::GetExtension() const 28.180 { 28.181 const char* ext = 0; 28.182 ScanFilePath(ToCStr(), 0, &ext); 28.183 return String(ext); 28.184 } 28.185 28.186 void String::StripExtension() 28.187 { 28.188 const char* ext = 0; 28.189 ScanFilePath(ToCStr(), 0, &ext); 28.190 if (ext) 28.191 { 28.192 *this = String(ToCStr(), ext-ToCStr()); 28.193 } 28.194 } 28.195 28.196 void String::StripProtocol() 28.197 { 28.198 const char* protocol = ScanPathProtocol(ToCStr()); 28.199 if (protocol) 28.200 AssignString(protocol, OVR_strlen(protocol)); 28.201 } 28.202 28.203 } // OVR 28.204 \ No newline at end of file 28.205 +/************************************************************************************ 28.206 + 28.207 +Filename : OVR_String_PathUtil.cpp 28.208 +Content : String filename/url helper function 28.209 +Created : September 19, 2012 28.210 +Notes : 28.211 + 28.212 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 28.213 + 28.214 +Use of this software is subject to the terms of the Oculus license 28.215 +agreement provided at the time of installation or download, or which 28.216 +otherwise accompanies this software in either electronic or hard copy form. 28.217 + 28.218 +************************************************************************************/ 28.219 + 28.220 +#include "OVR_String.h" 28.221 +#include "OVR_UTF8Util.h" 28.222 + 28.223 +namespace OVR { 28.224 + 28.225 +//-------------------------------------------------------------------- 28.226 +// ***** Path-Scanner helper function 28.227 + 28.228 +// Scans file path finding filename start and extension start, fills in their addess. 28.229 +void ScanFilePath(const char* url, const char** pfilename, const char** pext) 28.230 +{ 28.231 + const char* urlStart = url; 28.232 + const char *filename = 0; 28.233 + const char *lastDot = 0; 28.234 + 28.235 + UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.236 + 28.237 + while (charVal != 0) 28.238 + { 28.239 + if ((charVal == '/') || (charVal == '\\')) 28.240 + { 28.241 + filename = url; 28.242 + lastDot = 0; 28.243 + } 28.244 + else if (charVal == '.') 28.245 + { 28.246 + lastDot = url - 1; 28.247 + } 28.248 + 28.249 + charVal = UTF8Util::DecodeNextChar(&url); 28.250 + } 28.251 + 28.252 + if (pfilename) 28.253 + { 28.254 + // It was a naked filename 28.255 + if (urlStart && (*urlStart != '.') && *urlStart) 28.256 + *pfilename = urlStart; 28.257 + else 28.258 + *pfilename = filename; 28.259 + } 28.260 + 28.261 + if (pext) 28.262 + { 28.263 + *pext = lastDot; 28.264 + } 28.265 +} 28.266 + 28.267 +// Scans till the end of protocol. Returns first character past protocol, 28.268 +// 0 if not found. 28.269 +// - protocol: 'file://', 'http://' 28.270 +const char* ScanPathProtocol(const char* url) 28.271 +{ 28.272 + UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.273 + UInt32 charVal2; 28.274 + 28.275 + while (charVal != 0) 28.276 + { 28.277 + // Treat a colon followed by a slash as absolute. 28.278 + if (charVal == ':') 28.279 + { 28.280 + charVal2 = UTF8Util::DecodeNextChar(&url); 28.281 + charVal = UTF8Util::DecodeNextChar(&url); 28.282 + if ((charVal == '/') && (charVal2 == '\\')) 28.283 + return url; 28.284 + } 28.285 + charVal = UTF8Util::DecodeNextChar(&url); 28.286 + } 28.287 + return 0; 28.288 +} 28.289 + 28.290 + 28.291 +//-------------------------------------------------------------------- 28.292 +// ***** String Path API implementation 28.293 + 28.294 +bool String::HasAbsolutePath(const char* url) 28.295 +{ 28.296 + // Absolute paths can star with: 28.297 + // - protocols: 'file://', 'http://' 28.298 + // - windows drive: 'c:\' 28.299 + // - UNC share name: '\\share' 28.300 + // - unix root '/' 28.301 + 28.302 + // On the other hand, relative paths are: 28.303 + // - directory: 'directory/file' 28.304 + // - this directory: './file' 28.305 + // - parent directory: '../file' 28.306 + // 28.307 + // For now, we don't parse '.' or '..' out, but instead let it be concatenated 28.308 + // to string and let the OS figure it out. This, however, is not good for file 28.309 + // name matching in library/etc, so it should be improved. 28.310 + 28.311 + if (!url || !*url) 28.312 + return true; // Treat empty strings as absolute. 28.313 + 28.314 + UInt32 charVal = UTF8Util::DecodeNextChar(&url); 28.315 + 28.316 + // Fist character of '/' or '\\' means absolute url. 28.317 + if ((charVal == '/') || (charVal == '\\')) 28.318 + return true; 28.319 + 28.320 + while (charVal != 0) 28.321 + { 28.322 + // Treat a colon followed by a slash as absolute. 28.323 + if (charVal == ':') 28.324 + { 28.325 + charVal = UTF8Util::DecodeNextChar(&url); 28.326 + // Protocol or windows drive. Absolute. 28.327 + if ((charVal == '/') || (charVal == '\\')) 28.328 + return true; 28.329 + } 28.330 + else if ((charVal == '/') || (charVal == '\\')) 28.331 + { 28.332 + // Not a first character (else 'if' above the loop would have caught it). 28.333 + // Must be a relative url. 28.334 + break; 28.335 + } 28.336 + 28.337 + charVal = UTF8Util::DecodeNextChar(&url); 28.338 + } 28.339 + 28.340 + // We get here for relative paths. 28.341 + return false; 28.342 +} 28.343 + 28.344 + 28.345 +bool String::HasExtension(const char* path) 28.346 +{ 28.347 + const char* ext = 0; 28.348 + ScanFilePath(path, 0, &ext); 28.349 + return ext != 0; 28.350 +} 28.351 +bool String::HasProtocol(const char* path) 28.352 +{ 28.353 + return ScanPathProtocol(path) != 0; 28.354 +} 28.355 + 28.356 + 28.357 +String String::GetPath() const 28.358 +{ 28.359 + const char* filename = 0; 28.360 + ScanFilePath(ToCStr(), &filename, 0); 28.361 + 28.362 + // Technically we can have extra logic somewhere for paths, 28.363 + // such as enforcing protocol and '/' only based on flags, 28.364 + // but we keep it simple for now. 28.365 + return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize()); 28.366 +} 28.367 + 28.368 +String String::GetProtocol() const 28.369 +{ 28.370 + const char* protocolEnd = ScanPathProtocol(ToCStr()); 28.371 + return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0); 28.372 +} 28.373 + 28.374 +String String::GetFilename() const 28.375 +{ 28.376 + const char* filename = 0; 28.377 + ScanFilePath(ToCStr(), &filename, 0); 28.378 + return String(filename); 28.379 +} 28.380 +String String::GetExtension() const 28.381 +{ 28.382 + const char* ext = 0; 28.383 + ScanFilePath(ToCStr(), 0, &ext); 28.384 + return String(ext); 28.385 +} 28.386 + 28.387 +void String::StripExtension() 28.388 +{ 28.389 + const char* ext = 0; 28.390 + ScanFilePath(ToCStr(), 0, &ext); 28.391 + if (ext) 28.392 + { 28.393 + *this = String(ToCStr(), ext-ToCStr()); 28.394 + } 28.395 +} 28.396 + 28.397 +void String::StripProtocol() 28.398 +{ 28.399 + const char* protocol = ScanPathProtocol(ToCStr()); 28.400 + if (protocol) 28.401 + AssignString(protocol, OVR_strlen(protocol)); 28.402 +} 28.403 + 28.404 +} // OVR
29.1 --- a/libovr/Src/Kernel/OVR_SysFile.cpp Sat Sep 14 17:51:03 2013 +0300 29.2 +++ b/libovr/Src/Kernel/OVR_SysFile.cpp Sun Sep 15 04:10:05 2013 +0300 29.3 @@ -1,1 +1,125 @@ 29.4 -/************************************************************************** 29.5 29.6 Filename : OVR_SysFile.cpp 29.7 Content : File wrapper class implementation (Win32) 29.8 29.9 Created : April 5, 1999 29.10 Authors : Michael Antonov 29.11 29.12 Copyright : Copyright 2011 Oculus VR, Inc. All Rights reserved. 29.13 29.14 Use of this software is subject to the terms of the Oculus license 29.15 agreement provided at the time of installation or download, or which 29.16 otherwise accompanies this software in either electronic or hard copy form. 29.17 29.18 **************************************************************************/ 29.19 29.20 #define GFILE_CXX 29.21 29.22 // Standard C library (Captain Obvious guarantees!) 29.23 #include <stdio.h> 29.24 29.25 #include "OVR_SysFile.h" 29.26 29.27 namespace OVR { 29.28 29.29 // This is - a dummy file that fails on all calls. 29.30 29.31 class UnopenedFile : public File 29.32 { 29.33 public: 29.34 UnopenedFile() { } 29.35 ~UnopenedFile() { } 29.36 29.37 virtual const char* GetFilePath() { return 0; } 29.38 29.39 // ** File Information 29.40 virtual bool IsValid() { return 0; } 29.41 virtual bool IsWritable() { return 0; } 29.42 29.43 // Return position / file size 29.44 virtual int Tell() { return 0; } 29.45 virtual SInt64 LTell() { return 0; } 29.46 virtual int GetLength() { return 0; } 29.47 virtual SInt64 LGetLength() { return 0; } 29.48 29.49 // virtual bool Stat(FileStats *pfs) { return 0; } 29.50 virtual int GetErrorCode() { return Error_FileNotFound; } 29.51 29.52 // ** Stream implementation & I/O 29.53 virtual int Write(const UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } 29.54 virtual int Read(UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } 29.55 virtual int SkipBytes(int numBytes) { return 0; OVR_UNUSED(numBytes); } 29.56 virtual int BytesAvailable() { return 0; } 29.57 virtual bool Flush() { return 0; } 29.58 virtual int Seek(int offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } 29.59 virtual SInt64 LSeek(SInt64 offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } 29.60 29.61 virtual int CopyFromStream(File *pstream, int byteSize) { return -1; OVR_UNUSED2(pstream, byteSize); } 29.62 virtual bool Close() { return 0; } 29.63 }; 29.64 29.65 29.66 29.67 // ***** System File 29.68 29.69 // System file is created to access objects on file system directly 29.70 // This file can refer directly to path 29.71 29.72 // ** Constructor 29.73 SysFile::SysFile() : DelegatedFile(0) 29.74 { 29.75 pFile = *new UnopenedFile; 29.76 } 29.77 29.78 File* FileFILEOpen(const String& path, int flags, int mode); 29.79 29.80 // Opens a file 29.81 SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0) 29.82 { 29.83 Open(path, flags, mode); 29.84 } 29.85 29.86 29.87 // ** Open & management 29.88 // Will fail if file's already open 29.89 bool SysFile::Open(const String& path, int flags, int mode) 29.90 { 29.91 pFile = *FileFILEOpen(path, flags, mode); 29.92 if ((!pFile) || (!pFile->IsValid())) 29.93 { 29.94 pFile = *new UnopenedFile; 29.95 return 0; 29.96 } 29.97 //pFile = *OVR_NEW DelegatedFile(pFile); // MA Testing 29.98 if (flags & Open_Buffered) 29.99 pFile = *new BufferedFile(pFile); 29.100 return 1; 29.101 } 29.102 29.103 29.104 // ** Overrides 29.105 29.106 int SysFile::GetErrorCode() 29.107 { 29.108 return pFile ? pFile->GetErrorCode() : Error_FileNotFound; 29.109 } 29.110 29.111 29.112 // Overrides to provide re-open support 29.113 bool SysFile::IsValid() 29.114 { 29.115 return pFile && pFile->IsValid(); 29.116 } 29.117 bool SysFile::Close() 29.118 { 29.119 if (IsValid()) 29.120 { 29.121 DelegatedFile::Close(); 29.122 pFile = *new UnopenedFile; 29.123 return 1; 29.124 } 29.125 return 0; 29.126 } 29.127 29.128 } // OVR 29.129 \ No newline at end of file 29.130 +/************************************************************************** 29.131 + 29.132 +Filename : OVR_SysFile.cpp 29.133 +Content : File wrapper class implementation (Win32) 29.134 + 29.135 +Created : April 5, 1999 29.136 +Authors : Michael Antonov 29.137 + 29.138 +Copyright : Copyright 2011 Oculus VR, Inc. All Rights reserved. 29.139 + 29.140 +Use of this software is subject to the terms of the Oculus license 29.141 +agreement provided at the time of installation or download, or which 29.142 +otherwise accompanies this software in either electronic or hard copy form. 29.143 + 29.144 +**************************************************************************/ 29.145 + 29.146 +#define GFILE_CXX 29.147 + 29.148 +// Standard C library (Captain Obvious guarantees!) 29.149 +#include <stdio.h> 29.150 + 29.151 +#include "OVR_SysFile.h" 29.152 + 29.153 +namespace OVR { 29.154 + 29.155 +// This is - a dummy file that fails on all calls. 29.156 + 29.157 +class UnopenedFile : public File 29.158 +{ 29.159 +public: 29.160 + UnopenedFile() { } 29.161 + ~UnopenedFile() { } 29.162 + 29.163 + virtual const char* GetFilePath() { return 0; } 29.164 + 29.165 + // ** File Information 29.166 + virtual bool IsValid() { return 0; } 29.167 + virtual bool IsWritable() { return 0; } 29.168 + 29.169 + // Return position / file size 29.170 + virtual int Tell() { return 0; } 29.171 + virtual SInt64 LTell() { return 0; } 29.172 + virtual int GetLength() { return 0; } 29.173 + virtual SInt64 LGetLength() { return 0; } 29.174 + 29.175 +// virtual bool Stat(FileStats *pfs) { return 0; } 29.176 + virtual int GetErrorCode() { return Error_FileNotFound; } 29.177 + 29.178 + // ** Stream implementation & I/O 29.179 + virtual int Write(const UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } 29.180 + virtual int Read(UByte *pbuffer, int numBytes) { return -1; OVR_UNUSED2(pbuffer, numBytes); } 29.181 + virtual int SkipBytes(int numBytes) { return 0; OVR_UNUSED(numBytes); } 29.182 + virtual int BytesAvailable() { return 0; } 29.183 + virtual bool Flush() { return 0; } 29.184 + virtual int Seek(int offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } 29.185 + virtual SInt64 LSeek(SInt64 offset, int origin) { return -1; OVR_UNUSED2(offset, origin); } 29.186 + 29.187 + virtual int CopyFromStream(File *pstream, int byteSize) { return -1; OVR_UNUSED2(pstream, byteSize); } 29.188 + virtual bool Close() { return 0; } 29.189 +}; 29.190 + 29.191 + 29.192 + 29.193 +// ***** System File 29.194 + 29.195 +// System file is created to access objects on file system directly 29.196 +// This file can refer directly to path 29.197 + 29.198 +// ** Constructor 29.199 +SysFile::SysFile() : DelegatedFile(0) 29.200 +{ 29.201 + pFile = *new UnopenedFile; 29.202 +} 29.203 + 29.204 +File* FileFILEOpen(const String& path, int flags, int mode); 29.205 + 29.206 +// Opens a file 29.207 +SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0) 29.208 +{ 29.209 + Open(path, flags, mode); 29.210 +} 29.211 + 29.212 + 29.213 +// ** Open & management 29.214 +// Will fail if file's already open 29.215 +bool SysFile::Open(const String& path, int flags, int mode) 29.216 +{ 29.217 + pFile = *FileFILEOpen(path, flags, mode); 29.218 + if ((!pFile) || (!pFile->IsValid())) 29.219 + { 29.220 + pFile = *new UnopenedFile; 29.221 + return 0; 29.222 + } 29.223 + //pFile = *OVR_NEW DelegatedFile(pFile); // MA Testing 29.224 + if (flags & Open_Buffered) 29.225 + pFile = *new BufferedFile(pFile); 29.226 + return 1; 29.227 +} 29.228 + 29.229 + 29.230 +// ** Overrides 29.231 + 29.232 +int SysFile::GetErrorCode() 29.233 +{ 29.234 + return pFile ? pFile->GetErrorCode() : Error_FileNotFound; 29.235 +} 29.236 + 29.237 + 29.238 +// Overrides to provide re-open support 29.239 +bool SysFile::IsValid() 29.240 +{ 29.241 + return pFile && pFile->IsValid(); 29.242 +} 29.243 +bool SysFile::Close() 29.244 +{ 29.245 + if (IsValid()) 29.246 + { 29.247 + DelegatedFile::Close(); 29.248 + pFile = *new UnopenedFile; 29.249 + return 1; 29.250 + } 29.251 + return 0; 29.252 +} 29.253 + 29.254 +} // OVR
30.1 --- a/libovr/Src/Kernel/OVR_SysFile.h Sat Sep 14 17:51:03 2013 +0300 30.2 +++ b/libovr/Src/Kernel/OVR_SysFile.h Sun Sep 15 04:10:05 2013 +0300 30.3 @@ -1,1 +1,93 @@ 30.4 -/************************************************************************************ 30.5 30.6 PublicHeader: Kernel 30.7 Filename : OVR_SysFile.h 30.8 Content : Header for all internal file management - functions and structures 30.9 to be inherited by OS specific subclasses. 30.10 Created : September 19, 2012 30.11 Notes : 30.12 30.13 Notes : errno may not be preserved across use of GBaseFile member functions 30.14 : Directories cannot be deleted while files opened from them are in use 30.15 (For the GetFullName function) 30.16 30.17 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 30.18 30.19 Use of this software is subject to the terms of the Oculus license 30.20 agreement provided at the time of installation or download, or which 30.21 otherwise accompanies this software in either electronic or hard copy form. 30.22 30.23 ************************************************************************************/ 30.24 30.25 #ifndef OVR_SysFile_h 30.26 #define OVR_SysFile_h 30.27 30.28 #include "OVR_File.h" 30.29 30.30 namespace OVR { 30.31 30.32 // ***** Declared classes 30.33 class SysFile; 30.34 30.35 //----------------------------------------------------------------------------------- 30.36 // *** File Statistics 30.37 30.38 // This class contents are similar to _stat, providing 30.39 // creation, modify and other information about the file. 30.40 struct FileStat 30.41 { 30.42 // No change or create time because they are not available on most systems 30.43 SInt64 ModifyTime; 30.44 SInt64 AccessTime; 30.45 SInt64 FileSize; 30.46 30.47 bool operator== (const FileStat& stat) const 30.48 { 30.49 return ( (ModifyTime == stat.ModifyTime) && 30.50 (AccessTime == stat.AccessTime) && 30.51 (FileSize == stat.FileSize) ); 30.52 } 30.53 }; 30.54 30.55 //----------------------------------------------------------------------------------- 30.56 // *** System File 30.57 30.58 // System file is created to access objects on file system directly 30.59 // This file can refer directly to path. 30.60 // System file can be open & closed several times; however, such use is not recommended 30.61 // This class is realy a wrapper around an implementation of File interface for a 30.62 // particular platform. 30.63 30.64 class SysFile : public DelegatedFile 30.65 { 30.66 protected: 30.67 SysFile(const SysFile &source) : DelegatedFile () { OVR_UNUSED(source); } 30.68 public: 30.69 30.70 // ** Constructor 30.71 SysFile(); 30.72 // Opens a file 30.73 SysFile(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 30.74 30.75 // ** Open & management 30.76 bool Open(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 30.77 30.78 OVR_FORCE_INLINE bool Create(const String& path, int mode = Mode_ReadWrite) 30.79 { return Open(path, Open_ReadWrite|Open_Create, mode); } 30.80 30.81 // Helper function: obtain file statistics information. In GFx, this is used to detect file changes. 30.82 // Return 0 if function failed, most likely because the file doesn't exist. 30.83 static bool OVR_CDECL GetFileStat(FileStat* pfileStats, const String& path); 30.84 30.85 // ** Overrides 30.86 // Overridden to provide re-open support 30.87 virtual int GetErrorCode(); 30.88 30.89 virtual bool IsValid(); 30.90 30.91 virtual bool Close(); 30.92 }; 30.93 30.94 } // Scaleform 30.95 30.96 #endif 30.97 \ No newline at end of file 30.98 +/************************************************************************************ 30.99 + 30.100 +PublicHeader: Kernel 30.101 +Filename : OVR_SysFile.h 30.102 +Content : Header for all internal file management - functions and structures 30.103 + to be inherited by OS specific subclasses. 30.104 +Created : September 19, 2012 30.105 +Notes : 30.106 + 30.107 +Notes : errno may not be preserved across use of GBaseFile member functions 30.108 + : Directories cannot be deleted while files opened from them are in use 30.109 + (For the GetFullName function) 30.110 + 30.111 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 30.112 + 30.113 +Use of this software is subject to the terms of the Oculus license 30.114 +agreement provided at the time of installation or download, or which 30.115 +otherwise accompanies this software in either electronic or hard copy form. 30.116 + 30.117 +************************************************************************************/ 30.118 + 30.119 +#ifndef OVR_SysFile_h 30.120 +#define OVR_SysFile_h 30.121 + 30.122 +#include "OVR_File.h" 30.123 + 30.124 +namespace OVR { 30.125 + 30.126 +// ***** Declared classes 30.127 +class SysFile; 30.128 + 30.129 +//----------------------------------------------------------------------------------- 30.130 +// *** File Statistics 30.131 + 30.132 +// This class contents are similar to _stat, providing 30.133 +// creation, modify and other information about the file. 30.134 +struct FileStat 30.135 +{ 30.136 + // No change or create time because they are not available on most systems 30.137 + SInt64 ModifyTime; 30.138 + SInt64 AccessTime; 30.139 + SInt64 FileSize; 30.140 + 30.141 + bool operator== (const FileStat& stat) const 30.142 + { 30.143 + return ( (ModifyTime == stat.ModifyTime) && 30.144 + (AccessTime == stat.AccessTime) && 30.145 + (FileSize == stat.FileSize) ); 30.146 + } 30.147 +}; 30.148 + 30.149 +//----------------------------------------------------------------------------------- 30.150 +// *** System File 30.151 + 30.152 +// System file is created to access objects on file system directly 30.153 +// This file can refer directly to path. 30.154 +// System file can be open & closed several times; however, such use is not recommended 30.155 +// This class is realy a wrapper around an implementation of File interface for a 30.156 +// particular platform. 30.157 + 30.158 +class SysFile : public DelegatedFile 30.159 +{ 30.160 +protected: 30.161 + SysFile(const SysFile &source) : DelegatedFile () { OVR_UNUSED(source); } 30.162 +public: 30.163 + 30.164 + // ** Constructor 30.165 + SysFile(); 30.166 + // Opens a file 30.167 + SysFile(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 30.168 + 30.169 + // ** Open & management 30.170 + bool Open(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 30.171 + 30.172 + OVR_FORCE_INLINE bool Create(const String& path, int mode = Mode_ReadWrite) 30.173 + { return Open(path, Open_ReadWrite|Open_Create, mode); } 30.174 + 30.175 + // Helper function: obtain file statistics information. In GFx, this is used to detect file changes. 30.176 + // Return 0 if function failed, most likely because the file doesn't exist. 30.177 + static bool OVR_CDECL GetFileStat(FileStat* pfileStats, const String& path); 30.178 + 30.179 + // ** Overrides 30.180 + // Overridden to provide re-open support 30.181 + virtual int GetErrorCode(); 30.182 + 30.183 + virtual bool IsValid(); 30.184 + 30.185 + virtual bool Close(); 30.186 +}; 30.187 + 30.188 +} // Scaleform 30.189 + 30.190 +#endif
31.1 --- a/libovr/Src/Kernel/OVR_System.cpp Sat Sep 14 17:51:03 2013 +0300 31.2 +++ b/libovr/Src/Kernel/OVR_System.cpp Sun Sep 15 04:10:05 2013 +0300 31.3 @@ -1,1 +1,70 @@ 31.4 -/************************************************************************************ 31.5 31.6 Filename : OVR_System.cpp 31.7 Content : General kernel initialization/cleanup, including that 31.8 of the memory allocator. 31.9 Created : September 19, 2012 31.10 Notes : 31.11 31.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 31.13 31.14 Use of this software is subject to the terms of the Oculus license 31.15 agreement provided at the time of installation or download, or which 31.16 otherwise accompanies this software in either electronic or hard copy form. 31.17 31.18 ************************************************************************************/ 31.19 31.20 #include "OVR_System.h" 31.21 #include "OVR_Threads.h" 31.22 #include "OVR_Timer.h" 31.23 31.24 namespace OVR { 31.25 31.26 // ***** OVR::System Implementation 31.27 31.28 // Initializes System core, installing allocator. 31.29 void System::Init(Log* log, Allocator *palloc) 31.30 { 31.31 if (!Allocator::GetInstance()) 31.32 { 31.33 Log::SetGlobalLog(log); 31.34 Timer::initializeTimerSystem(); 31.35 Allocator::setInstance(palloc); 31.36 } 31.37 else 31.38 { 31.39 OVR_DEBUG_LOG(("System::Init failed - duplicate call.")); 31.40 } 31.41 } 31.42 31.43 void System::Destroy() 31.44 { 31.45 if (Allocator::GetInstance()) 31.46 { 31.47 // Wait for all threads to finish; this must be done so that memory 31.48 // allocator and all destructors finalize correctly. 31.49 #ifdef OVR_ENABLE_THREADS 31.50 Thread::FinishAllThreads(); 31.51 #endif 31.52 31.53 // Shutdown heap and destroy SysAlloc singleton, if any. 31.54 Allocator::GetInstance()->onSystemShutdown(); 31.55 Allocator::setInstance(0); 31.56 31.57 Timer::shutdownTimerSystem(); 31.58 Log::SetGlobalLog(Log::GetDefaultLog()); 31.59 } 31.60 else 31.61 { 31.62 OVR_DEBUG_LOG(("System::Destroy failed - System not initialized.")); 31.63 } 31.64 } 31.65 31.66 // Returns 'true' if system was properly initialized. 31.67 bool System::IsInitialized() 31.68 { 31.69 return Allocator::GetInstance() != 0; 31.70 } 31.71 31.72 } // OVR 31.73 31.74 \ No newline at end of file 31.75 +/************************************************************************************ 31.76 + 31.77 +Filename : OVR_System.cpp 31.78 +Content : General kernel initialization/cleanup, including that 31.79 + of the memory allocator. 31.80 +Created : September 19, 2012 31.81 +Notes : 31.82 + 31.83 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 31.84 + 31.85 +Use of this software is subject to the terms of the Oculus license 31.86 +agreement provided at the time of installation or download, or which 31.87 +otherwise accompanies this software in either electronic or hard copy form. 31.88 + 31.89 +************************************************************************************/ 31.90 + 31.91 +#include "OVR_System.h" 31.92 +#include "OVR_Threads.h" 31.93 +#include "OVR_Timer.h" 31.94 + 31.95 +namespace OVR { 31.96 + 31.97 +// ***** OVR::System Implementation 31.98 + 31.99 +// Initializes System core, installing allocator. 31.100 +void System::Init(Log* log, Allocator *palloc) 31.101 +{ 31.102 + if (!Allocator::GetInstance()) 31.103 + { 31.104 + Log::SetGlobalLog(log); 31.105 + Timer::initializeTimerSystem(); 31.106 + Allocator::setInstance(palloc); 31.107 + } 31.108 + else 31.109 + { 31.110 + OVR_DEBUG_LOG(("System::Init failed - duplicate call.")); 31.111 + } 31.112 +} 31.113 + 31.114 +void System::Destroy() 31.115 +{ 31.116 + if (Allocator::GetInstance()) 31.117 + { 31.118 + // Wait for all threads to finish; this must be done so that memory 31.119 + // allocator and all destructors finalize correctly. 31.120 +#ifdef OVR_ENABLE_THREADS 31.121 + Thread::FinishAllThreads(); 31.122 +#endif 31.123 + 31.124 + // Shutdown heap and destroy SysAlloc singleton, if any. 31.125 + Allocator::GetInstance()->onSystemShutdown(); 31.126 + Allocator::setInstance(0); 31.127 + 31.128 + Timer::shutdownTimerSystem(); 31.129 + Log::SetGlobalLog(Log::GetDefaultLog()); 31.130 + } 31.131 + else 31.132 + { 31.133 + OVR_DEBUG_LOG(("System::Destroy failed - System not initialized.")); 31.134 + } 31.135 +} 31.136 + 31.137 +// Returns 'true' if system was properly initialized. 31.138 +bool System::IsInitialized() 31.139 +{ 31.140 + return Allocator::GetInstance() != 0; 31.141 +} 31.142 + 31.143 +} // OVR 31.144 +
32.1 --- a/libovr/Src/Kernel/OVR_System.h Sat Sep 14 17:51:03 2013 +0300 32.2 +++ b/libovr/Src/Kernel/OVR_System.h Sun Sep 15 04:10:05 2013 +0300 32.3 @@ -1,1 +1,67 @@ 32.4 -/************************************************************************************ 32.5 32.6 PublicHeader: OVR 32.7 Filename : OVR_System.h 32.8 Content : General kernel initialization/cleanup, including that 32.9 of the memory allocator. 32.10 Created : September 19, 2012 32.11 Notes : 32.12 32.13 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 32.14 32.15 Use of this software is subject to the terms of the Oculus license 32.16 agreement provided at the time of installation or download, or which 32.17 otherwise accompanies this software in either electronic or hard copy form. 32.18 32.19 ************************************************************************************/ 32.20 32.21 #ifndef OVR_System_h 32.22 #define OVR_System_h 32.23 32.24 #include "OVR_Allocator.h" 32.25 #include "OVR_Log.h" 32.26 32.27 namespace OVR { 32.28 32.29 // ***** System Core Initialization class 32.30 32.31 // System initialization must take place before any other OVR_Kernel objects are used; 32.32 // this is done my calling System::Init(). Among other things, this is necessary to 32.33 // initialize the memory allocator. Similarly, System::Destroy must be 32.34 // called before program exist for proper cleanup. Both of these tasks can be achieved by 32.35 // simply creating System object first, allowing its constructor/destructor do the work. 32.36 32.37 // TBD: Require additional System class for Oculus Rift API? 32.38 32.39 class System 32.40 { 32.41 public: 32.42 32.43 // System constructor expects allocator to be specified, if it is being substituted. 32.44 System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), 32.45 Allocator* palloc = DefaultAllocator::InitSystemSingleton()) 32.46 { 32.47 Init(log, palloc); 32.48 } 32.49 32.50 ~System() 32.51 { 32.52 Destroy(); 32.53 } 32.54 32.55 // Returns 'true' if system was properly initialized. 32.56 static bool OVR_CDECL IsInitialized(); 32.57 32.58 // Initializes System core. Users can override memory implementation by passing 32.59 // a different Allocator here. 32.60 static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), 32.61 Allocator *palloc = DefaultAllocator::InitSystemSingleton()); 32.62 32.63 // De-initializes System more, finalizing the threading system and destroying 32.64 // the global memory allocator. 32.65 static void OVR_CDECL Destroy(); 32.66 }; 32.67 32.68 } // OVR 32.69 32.70 #endif 32.71 \ No newline at end of file 32.72 +/************************************************************************************ 32.73 + 32.74 +PublicHeader: OVR 32.75 +Filename : OVR_System.h 32.76 +Content : General kernel initialization/cleanup, including that 32.77 + of the memory allocator. 32.78 +Created : September 19, 2012 32.79 +Notes : 32.80 + 32.81 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 32.82 + 32.83 +Use of this software is subject to the terms of the Oculus license 32.84 +agreement provided at the time of installation or download, or which 32.85 +otherwise accompanies this software in either electronic or hard copy form. 32.86 + 32.87 +************************************************************************************/ 32.88 + 32.89 +#ifndef OVR_System_h 32.90 +#define OVR_System_h 32.91 + 32.92 +#include "OVR_Allocator.h" 32.93 +#include "OVR_Log.h" 32.94 + 32.95 +namespace OVR { 32.96 + 32.97 +// ***** System Core Initialization class 32.98 + 32.99 +// System initialization must take place before any other OVR_Kernel objects are used; 32.100 +// this is done my calling System::Init(). Among other things, this is necessary to 32.101 +// initialize the memory allocator. Similarly, System::Destroy must be 32.102 +// called before program exist for proper cleanup. Both of these tasks can be achieved by 32.103 +// simply creating System object first, allowing its constructor/destructor do the work. 32.104 + 32.105 +// TBD: Require additional System class for Oculus Rift API? 32.106 + 32.107 +class System 32.108 +{ 32.109 +public: 32.110 + 32.111 + // System constructor expects allocator to be specified, if it is being substituted. 32.112 + System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), 32.113 + Allocator* palloc = DefaultAllocator::InitSystemSingleton()) 32.114 + { 32.115 + Init(log, palloc); 32.116 + } 32.117 + 32.118 + ~System() 32.119 + { 32.120 + Destroy(); 32.121 + } 32.122 + 32.123 + // Returns 'true' if system was properly initialized. 32.124 + static bool OVR_CDECL IsInitialized(); 32.125 + 32.126 + // Initializes System core. Users can override memory implementation by passing 32.127 + // a different Allocator here. 32.128 + static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug), 32.129 + Allocator *palloc = DefaultAllocator::InitSystemSingleton()); 32.130 + 32.131 + // De-initializes System more, finalizing the threading system and destroying 32.132 + // the global memory allocator. 32.133 + static void OVR_CDECL Destroy(); 32.134 +}; 32.135 + 32.136 +} // OVR 32.137 + 32.138 +#endif
33.1 --- a/libovr/Src/Kernel/OVR_Threads.h Sat Sep 14 17:51:03 2013 +0300 33.2 +++ b/libovr/Src/Kernel/OVR_Threads.h Sun Sep 15 04:10:05 2013 +0300 33.3 @@ -1,1 +1,396 @@ 33.4 -/************************************************************************************ 33.5 33.6 PublicHeader: None 33.7 Filename : OVR_Threads.h 33.8 Content : Contains thread-related (safe) functionality 33.9 Created : September 19, 2012 33.10 Notes : 33.11 33.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 33.13 33.14 Use of this software is subject to the terms of the Oculus license 33.15 agreement provided at the time of installation or download, or which 33.16 otherwise accompanies this software in either electronic or hard copy form. 33.17 33.18 ************************************************************************************/ 33.19 #ifndef OVR_Threads_h 33.20 #define OVR_Threads_h 33.21 33.22 #include "OVR_Types.h" 33.23 #include "OVR_Atomic.h" 33.24 #include "OVR_RefCount.h" 33.25 #include "OVR_Array.h" 33.26 33.27 // Defines the infinite wait delay timeout 33.28 #define OVR_WAIT_INFINITE 0xFFFFFFFF 33.29 33.30 // To be defined in the project configuration options 33.31 #ifdef OVR_ENABLE_THREADS 33.32 33.33 33.34 namespace OVR { 33.35 33.36 //----------------------------------------------------------------------------------- 33.37 // ****** Declared classes 33.38 33.39 // Declared with thread support only 33.40 class Mutex; 33.41 class WaitCondition; 33.42 class Event; 33.43 // Implementation forward declarations 33.44 class MutexImpl; 33.45 class WaitConditionImpl; 33.46 33.47 33.48 33.49 //----------------------------------------------------------------------------------- 33.50 // ***** Mutex 33.51 33.52 // Mutex class represents a system Mutex synchronization object that provides access 33.53 // serialization between different threads, allowing one thread mutually exclusive access 33.54 // to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition. 33.55 33.56 class Mutex 33.57 { 33.58 friend class WaitConditionImpl; 33.59 friend class MutexImpl; 33.60 33.61 MutexImpl *pImpl; 33.62 33.63 public: 33.64 // Constructor/destructor 33.65 Mutex(bool recursive = 1); 33.66 ~Mutex(); 33.67 33.68 // Locking functions 33.69 void DoLock(); 33.70 bool TryLock(); 33.71 void Unlock(); 33.72 33.73 // Returns 1 if the mutes is currently locked by another thread 33.74 // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 33.75 bool IsLockedByAnotherThread(); 33.76 33.77 // Locker class; Used for automatic locking of a mutex withing scope 33.78 class Locker 33.79 { 33.80 public: 33.81 Mutex *pMutex; 33.82 Locker(Mutex *pmutex) 33.83 { pMutex = pmutex; pMutex->DoLock(); } 33.84 ~Locker() 33.85 { pMutex->Unlock(); } 33.86 }; 33.87 }; 33.88 33.89 33.90 //----------------------------------------------------------------------------------- 33.91 // ***** WaitCondition 33.92 33.93 /* 33.94 WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor. 33.95 Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that 33.96 call Notify() or NotifyAll(). 33.97 33.98 The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 33.99 starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same 33.100 resource, this ensures that any condition checked for while the mutex was locked does not change before 33.101 the wait on the condition is actually initiated. 33.102 */ 33.103 33.104 class WaitCondition 33.105 { 33.106 friend class WaitConditionImpl; 33.107 // Internal implementation structure 33.108 WaitConditionImpl *pImpl; 33.109 33.110 public: 33.111 // Constructor/destructor 33.112 WaitCondition(); 33.113 ~WaitCondition(); 33.114 33.115 // Release mutex and wait for condition. The mutex is re-aquired after the wait. 33.116 // Delay is specified in milliseconds (1/1000 of a second). 33.117 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 33.118 33.119 // Notify a condition, releasing at one object waiting 33.120 void Notify(); 33.121 // Notify a condition, releasing all objects waiting 33.122 void NotifyAll(); 33.123 }; 33.124 33.125 33.126 //----------------------------------------------------------------------------------- 33.127 // ***** Event 33.128 33.129 // Event is a wait-able synchronization object similar to Windows event. 33.130 // Event can be waited on until it's signaled by another thread calling 33.131 // either SetEvent or PulseEvent. 33.132 33.133 class Event 33.134 { 33.135 // Event state, its mutex and the wait condition 33.136 volatile bool State; 33.137 volatile bool Temporary; 33.138 mutable Mutex StateMutex; 33.139 WaitCondition StateWaitCondition; 33.140 33.141 void updateState(bool newState, bool newTemp, bool mustNotify); 33.142 33.143 public: 33.144 Event(bool setInitially = 0) : State(setInitially), Temporary(false) { } 33.145 ~Event() { } 33.146 33.147 // Wait on an event condition until it is set 33.148 // Delay is specified in milliseconds (1/1000 of a second). 33.149 bool Wait(unsigned delay = OVR_WAIT_INFINITE); 33.150 33.151 // Set an event, releasing objects waiting on it 33.152 void SetEvent() 33.153 { updateState(true, false, true); } 33.154 33.155 // Reset an event, un-signaling it 33.156 void ResetEvent() 33.157 { updateState(false, false, false); } 33.158 33.159 // Set and then reset an event once a waiter is released. 33.160 // If threads are already waiting, they will be notified and released 33.161 // If threads are not waiting, the event is set until the first thread comes in 33.162 void PulseEvent() 33.163 { updateState(true, true, true); } 33.164 }; 33.165 33.166 33.167 //----------------------------------------------------------------------------------- 33.168 // ***** Thread class 33.169 33.170 // ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and 33.171 // Thread::GetThreadId. 33.172 typedef void* ThreadId; 33.173 33.174 33.175 // *** Thread flags 33.176 33.177 // Indicates that the thread is has been started, i.e. Start method has been called, and threads 33.178 // OnExit() method has not yet been called/returned. 33.179 #define OVR_THREAD_STARTED 0x01 33.180 // This flag is set once the thread has ran, and finished. 33.181 #define OVR_THREAD_FINISHED 0x02 33.182 // This flag is set temporarily if this thread was started suspended. It is used internally. 33.183 #define OVR_THREAD_START_SUSPENDED 0x08 33.184 // This flag is used to ask a thread to exit. Message driven threads will usually check this flag 33.185 // and finish once it is set. 33.186 #define OVR_THREAD_EXIT 0x10 33.187 33.188 33.189 class Thread : public RefCountBase<Thread> 33.190 { // NOTE: Waitable must be the first base since it implements RefCountImpl. 33.191 33.192 public: 33.193 33.194 // *** Callback functions, can be used instead of overriding Run 33.195 33.196 // Run function prototypes. 33.197 // Thread function and user handle passed to it, executed by the default 33.198 // Thread::Run implementation if not null. 33.199 typedef int (*ThreadFn)(Thread *pthread, void* h); 33.200 33.201 // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried 33.202 ThreadFn ThreadFunction; 33.203 // User handle passes to a thread 33.204 void* UserHandle; 33.205 33.206 // Thread state to start a thread with 33.207 enum ThreadState 33.208 { 33.209 NotRunning = 0, 33.210 Running = 1, 33.211 Suspended = 2 33.212 }; 33.213 33.214 // Thread priority 33.215 enum ThreadPriority 33.216 { 33.217 CriticalPriority, 33.218 HighestPriority, 33.219 AboveNormalPriority, 33.220 NormalPriority, 33.221 BelowNormalPriority, 33.222 LowestPriority, 33.223 IdlePriority, 33.224 }; 33.225 33.226 // Thread constructor parameters 33.227 struct CreateParams 33.228 { 33.229 CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, 33.230 int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) 33.231 : threadFunction(func), userHandle(hand), stackSize(ssize), 33.232 processor(proc), initialState(state), priority(prior) {} 33.233 ThreadFn threadFunction; // Thread function 33.234 void* userHandle; // User handle passes to a thread 33.235 UPInt stackSize; // Thread stack size 33.236 int processor; // Thread hardware processor 33.237 ThreadState initialState; // 33.238 ThreadPriority priority; // Thread priority 33.239 }; 33.240 33.241 // *** Constructors 33.242 33.243 // A default constructor always creates a thread in NotRunning state, because 33.244 // the derived class has not yet been initialized. The derived class can call Start explicitly. 33.245 // "processor" parameter specifies which hardware processor this thread will be run on. 33.246 // -1 means OS decides this. Implemented only on Win32 33.247 Thread(UPInt stackSize = 128 * 1024, int processor = -1); 33.248 // Constructors that initialize the thread with a pointer to function. 33.249 // An option to start a thread is available, but it should not be used if classes are derived from Thread. 33.250 // "processor" parameter specifies which hardware processor this thread will be run on. 33.251 // -1 means OS decides this. Implemented only on Win32 33.252 Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024, 33.253 int processor = -1, ThreadState initialState = NotRunning); 33.254 // Constructors that initialize the thread with a create parameters structure. 33.255 explicit Thread(const CreateParams& params); 33.256 33.257 // Destructor. 33.258 virtual ~Thread(); 33.259 33.260 // Waits for all Threads to finish; should be called only from the root 33.261 // application thread. Once this function returns, we know that all other 33.262 // thread's references to Thread object have been released. 33.263 static void OVR_CDECL FinishAllThreads(); 33.264 33.265 33.266 // *** Overridable Run function for thread processing 33.267 33.268 // - returning from this method will end the execution of the thread 33.269 // - return value is usually 0 for success 33.270 virtual int Run(); 33.271 // Called after return/exit function 33.272 virtual void OnExit(); 33.273 33.274 33.275 // *** Thread management 33.276 33.277 // Starts the thread if its not already running 33.278 // - internally sets up the threading and calls Run() 33.279 // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing 33.280 // - returns the exit code 33.281 virtual bool Start(ThreadState initialState = Running); 33.282 33.283 // Quits with an exit code 33.284 virtual void Exit(int exitCode=0); 33.285 33.286 // Suspend the thread until resumed 33.287 // Returns 1 for success, 0 for failure. 33.288 bool Suspend(); 33.289 // Resumes currently suspended thread 33.290 // Returns 1 for success, 0 for failure. 33.291 bool Resume(); 33.292 33.293 // Static function to return a pointer to the current thread 33.294 //static Thread* GetThread(); 33.295 33.296 33.297 // *** Thread status query functions 33.298 33.299 bool GetExitFlag() const; 33.300 void SetExitFlag(bool exitFlag); 33.301 33.302 // Determines whether the thread was running and is now finished 33.303 bool IsFinished() const; 33.304 // Determines if the thread is currently suspended 33.305 bool IsSuspended() const; 33.306 // Returns current thread state 33.307 ThreadState GetThreadState() const; 33.308 33.309 // Returns the number of available CPUs on the system 33.310 static int GetCPUCount(); 33.311 33.312 // Returns the thread exit code. Exit code is initialized to 0, 33.313 // and set to the return value if Run function after the thread is finished. 33.314 inline int GetExitCode() const { return ExitCode; } 33.315 // Returns an OS handle 33.316 #if defined(OVR_OS_WIN32) 33.317 void* GetOSHandle() const { return ThreadHandle; } 33.318 #else 33.319 pthread_t GetOSHandle() const { return ThreadHandle; } 33.320 #endif 33.321 33.322 #if defined(OVR_OS_WIN32) 33.323 ThreadId GetThreadId() const { return IdValue; } 33.324 #else 33.325 ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } 33.326 #endif 33.327 33.328 static int GetOSPriority(ThreadPriority); 33.329 // *** Sleep 33.330 33.331 // Sleep secs seconds 33.332 static bool Sleep(unsigned secs); 33.333 // Sleep msecs milliseconds 33.334 static bool MSleep(unsigned msecs); 33.335 33.336 33.337 // *** Debugging functionality 33.338 #if defined(OVR_OS_WIN32) 33.339 virtual void SetThreadName( const char* name ); 33.340 #else 33.341 virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); } 33.342 #endif 33.343 33.344 private: 33.345 #if defined(OVR_OS_WIN32) 33.346 friend unsigned WINAPI Thread_Win32StartFn(void *pthread); 33.347 33.348 #else 33.349 friend void *Thread_PthreadStartFn(void * phandle); 33.350 33.351 static int InitAttr; 33.352 static pthread_attr_t Attr; 33.353 #endif 33.354 33.355 protected: 33.356 // Thread state flags 33.357 AtomicInt<UInt32> ThreadFlags; 33.358 AtomicInt<SInt32> SuspendCount; 33.359 UPInt StackSize; 33.360 33.361 // Hardware processor which this thread is running on. 33.362 int Processor; 33.363 ThreadPriority Priority; 33.364 33.365 #if defined(OVR_OS_WIN32) 33.366 void* ThreadHandle; 33.367 volatile ThreadId IdValue; 33.368 33.369 // System-specific cleanup function called from destructor 33.370 void CleanupSystemThread(); 33.371 33.372 #else 33.373 pthread_t ThreadHandle; 33.374 #endif 33.375 33.376 // Exit code of the thread, as returned by Run. 33.377 int ExitCode; 33.378 33.379 // Internal run function. 33.380 int PRun(); 33.381 // Finishes the thread and releases internal reference to it. 33.382 void FinishAndRelease(); 33.383 33.384 void Init(const CreateParams& params); 33.385 33.386 // Protected copy constructor 33.387 Thread(const Thread &source) { OVR_UNUSED(source); } 33.388 33.389 }; 33.390 33.391 // Returns the unique Id of a thread it is called on, intended for 33.392 // comparison purposes. 33.393 ThreadId GetCurrentThreadId(); 33.394 33.395 33.396 } // OVR 33.397 33.398 #endif // OVR_ENABLE_THREADS 33.399 #endif // OVR_Threads_h 33.400 \ No newline at end of file 33.401 +/************************************************************************************ 33.402 + 33.403 +PublicHeader: None 33.404 +Filename : OVR_Threads.h 33.405 +Content : Contains thread-related (safe) functionality 33.406 +Created : September 19, 2012 33.407 +Notes : 33.408 + 33.409 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 33.410 + 33.411 +Use of this software is subject to the terms of the Oculus license 33.412 +agreement provided at the time of installation or download, or which 33.413 +otherwise accompanies this software in either electronic or hard copy form. 33.414 + 33.415 +************************************************************************************/ 33.416 +#ifndef OVR_Threads_h 33.417 +#define OVR_Threads_h 33.418 + 33.419 +#include "OVR_Types.h" 33.420 +#include "OVR_Atomic.h" 33.421 +#include "OVR_RefCount.h" 33.422 +#include "OVR_Array.h" 33.423 + 33.424 +// Defines the infinite wait delay timeout 33.425 +#define OVR_WAIT_INFINITE 0xFFFFFFFF 33.426 + 33.427 +// To be defined in the project configuration options 33.428 +#ifdef OVR_ENABLE_THREADS 33.429 + 33.430 + 33.431 +namespace OVR { 33.432 + 33.433 +//----------------------------------------------------------------------------------- 33.434 +// ****** Declared classes 33.435 + 33.436 +// Declared with thread support only 33.437 +class Mutex; 33.438 +class WaitCondition; 33.439 +class Event; 33.440 +// Implementation forward declarations 33.441 +class MutexImpl; 33.442 +class WaitConditionImpl; 33.443 + 33.444 + 33.445 + 33.446 +//----------------------------------------------------------------------------------- 33.447 +// ***** Mutex 33.448 + 33.449 +// Mutex class represents a system Mutex synchronization object that provides access 33.450 +// serialization between different threads, allowing one thread mutually exclusive access 33.451 +// to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition. 33.452 + 33.453 +class Mutex 33.454 +{ 33.455 + friend class WaitConditionImpl; 33.456 + friend class MutexImpl; 33.457 + 33.458 + MutexImpl *pImpl; 33.459 + 33.460 +public: 33.461 + // Constructor/destructor 33.462 + Mutex(bool recursive = 1); 33.463 + ~Mutex(); 33.464 + 33.465 + // Locking functions 33.466 + void DoLock(); 33.467 + bool TryLock(); 33.468 + void Unlock(); 33.469 + 33.470 + // Returns 1 if the mutes is currently locked by another thread 33.471 + // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 33.472 + bool IsLockedByAnotherThread(); 33.473 + 33.474 + // Locker class; Used for automatic locking of a mutex withing scope 33.475 + class Locker 33.476 + { 33.477 + public: 33.478 + Mutex *pMutex; 33.479 + Locker(Mutex *pmutex) 33.480 + { pMutex = pmutex; pMutex->DoLock(); } 33.481 + ~Locker() 33.482 + { pMutex->Unlock(); } 33.483 + }; 33.484 +}; 33.485 + 33.486 + 33.487 +//----------------------------------------------------------------------------------- 33.488 +// ***** WaitCondition 33.489 + 33.490 +/* 33.491 + WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor. 33.492 + Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that 33.493 + call Notify() or NotifyAll(). 33.494 + 33.495 + The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 33.496 + starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same 33.497 + resource, this ensures that any condition checked for while the mutex was locked does not change before 33.498 + the wait on the condition is actually initiated. 33.499 +*/ 33.500 + 33.501 +class WaitCondition 33.502 +{ 33.503 + friend class WaitConditionImpl; 33.504 + // Internal implementation structure 33.505 + WaitConditionImpl *pImpl; 33.506 + 33.507 +public: 33.508 + // Constructor/destructor 33.509 + WaitCondition(); 33.510 + ~WaitCondition(); 33.511 + 33.512 + // Release mutex and wait for condition. The mutex is re-aquired after the wait. 33.513 + // Delay is specified in milliseconds (1/1000 of a second). 33.514 + bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 33.515 + 33.516 + // Notify a condition, releasing at one object waiting 33.517 + void Notify(); 33.518 + // Notify a condition, releasing all objects waiting 33.519 + void NotifyAll(); 33.520 +}; 33.521 + 33.522 + 33.523 +//----------------------------------------------------------------------------------- 33.524 +// ***** Event 33.525 + 33.526 +// Event is a wait-able synchronization object similar to Windows event. 33.527 +// Event can be waited on until it's signaled by another thread calling 33.528 +// either SetEvent or PulseEvent. 33.529 + 33.530 +class Event 33.531 +{ 33.532 + // Event state, its mutex and the wait condition 33.533 + volatile bool State; 33.534 + volatile bool Temporary; 33.535 + mutable Mutex StateMutex; 33.536 + WaitCondition StateWaitCondition; 33.537 + 33.538 + void updateState(bool newState, bool newTemp, bool mustNotify); 33.539 + 33.540 +public: 33.541 + Event(bool setInitially = 0) : State(setInitially), Temporary(false) { } 33.542 + ~Event() { } 33.543 + 33.544 + // Wait on an event condition until it is set 33.545 + // Delay is specified in milliseconds (1/1000 of a second). 33.546 + bool Wait(unsigned delay = OVR_WAIT_INFINITE); 33.547 + 33.548 + // Set an event, releasing objects waiting on it 33.549 + void SetEvent() 33.550 + { updateState(true, false, true); } 33.551 + 33.552 + // Reset an event, un-signaling it 33.553 + void ResetEvent() 33.554 + { updateState(false, false, false); } 33.555 + 33.556 + // Set and then reset an event once a waiter is released. 33.557 + // If threads are already waiting, they will be notified and released 33.558 + // If threads are not waiting, the event is set until the first thread comes in 33.559 + void PulseEvent() 33.560 + { updateState(true, true, true); } 33.561 +}; 33.562 + 33.563 + 33.564 +//----------------------------------------------------------------------------------- 33.565 +// ***** Thread class 33.566 + 33.567 +// ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and 33.568 +// Thread::GetThreadId. 33.569 +typedef void* ThreadId; 33.570 + 33.571 + 33.572 +// *** Thread flags 33.573 + 33.574 +// Indicates that the thread is has been started, i.e. Start method has been called, and threads 33.575 +// OnExit() method has not yet been called/returned. 33.576 +#define OVR_THREAD_STARTED 0x01 33.577 +// This flag is set once the thread has ran, and finished. 33.578 +#define OVR_THREAD_FINISHED 0x02 33.579 +// This flag is set temporarily if this thread was started suspended. It is used internally. 33.580 +#define OVR_THREAD_START_SUSPENDED 0x08 33.581 +// This flag is used to ask a thread to exit. Message driven threads will usually check this flag 33.582 +// and finish once it is set. 33.583 +#define OVR_THREAD_EXIT 0x10 33.584 + 33.585 + 33.586 +class Thread : public RefCountBase<Thread> 33.587 +{ // NOTE: Waitable must be the first base since it implements RefCountImpl. 33.588 + 33.589 +public: 33.590 + 33.591 + // *** Callback functions, can be used instead of overriding Run 33.592 + 33.593 + // Run function prototypes. 33.594 + // Thread function and user handle passed to it, executed by the default 33.595 + // Thread::Run implementation if not null. 33.596 + typedef int (*ThreadFn)(Thread *pthread, void* h); 33.597 + 33.598 + // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried 33.599 + ThreadFn ThreadFunction; 33.600 + // User handle passes to a thread 33.601 + void* UserHandle; 33.602 + 33.603 + // Thread state to start a thread with 33.604 + enum ThreadState 33.605 + { 33.606 + NotRunning = 0, 33.607 + Running = 1, 33.608 + Suspended = 2 33.609 + }; 33.610 + 33.611 + // Thread priority 33.612 + enum ThreadPriority 33.613 + { 33.614 + CriticalPriority, 33.615 + HighestPriority, 33.616 + AboveNormalPriority, 33.617 + NormalPriority, 33.618 + BelowNormalPriority, 33.619 + LowestPriority, 33.620 + IdlePriority, 33.621 + }; 33.622 + 33.623 + // Thread constructor parameters 33.624 + struct CreateParams 33.625 + { 33.626 + CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, 33.627 + int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority) 33.628 + : threadFunction(func), userHandle(hand), stackSize(ssize), 33.629 + processor(proc), initialState(state), priority(prior) {} 33.630 + ThreadFn threadFunction; // Thread function 33.631 + void* userHandle; // User handle passes to a thread 33.632 + UPInt stackSize; // Thread stack size 33.633 + int processor; // Thread hardware processor 33.634 + ThreadState initialState; // 33.635 + ThreadPriority priority; // Thread priority 33.636 + }; 33.637 + 33.638 + // *** Constructors 33.639 + 33.640 + // A default constructor always creates a thread in NotRunning state, because 33.641 + // the derived class has not yet been initialized. The derived class can call Start explicitly. 33.642 + // "processor" parameter specifies which hardware processor this thread will be run on. 33.643 + // -1 means OS decides this. Implemented only on Win32 33.644 + Thread(UPInt stackSize = 128 * 1024, int processor = -1); 33.645 + // Constructors that initialize the thread with a pointer to function. 33.646 + // An option to start a thread is available, but it should not be used if classes are derived from Thread. 33.647 + // "processor" parameter specifies which hardware processor this thread will be run on. 33.648 + // -1 means OS decides this. Implemented only on Win32 33.649 + Thread(ThreadFn threadFunction, void* userHandle = 0, UPInt stackSize = 128 * 1024, 33.650 + int processor = -1, ThreadState initialState = NotRunning); 33.651 + // Constructors that initialize the thread with a create parameters structure. 33.652 + explicit Thread(const CreateParams& params); 33.653 + 33.654 + // Destructor. 33.655 + virtual ~Thread(); 33.656 + 33.657 + // Waits for all Threads to finish; should be called only from the root 33.658 + // application thread. Once this function returns, we know that all other 33.659 + // thread's references to Thread object have been released. 33.660 + static void OVR_CDECL FinishAllThreads(); 33.661 + 33.662 + 33.663 + // *** Overridable Run function for thread processing 33.664 + 33.665 + // - returning from this method will end the execution of the thread 33.666 + // - return value is usually 0 for success 33.667 + virtual int Run(); 33.668 + // Called after return/exit function 33.669 + virtual void OnExit(); 33.670 + 33.671 + 33.672 + // *** Thread management 33.673 + 33.674 + // Starts the thread if its not already running 33.675 + // - internally sets up the threading and calls Run() 33.676 + // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing 33.677 + // - returns the exit code 33.678 + virtual bool Start(ThreadState initialState = Running); 33.679 + 33.680 + // Quits with an exit code 33.681 + virtual void Exit(int exitCode=0); 33.682 + 33.683 + // Suspend the thread until resumed 33.684 + // Returns 1 for success, 0 for failure. 33.685 + bool Suspend(); 33.686 + // Resumes currently suspended thread 33.687 + // Returns 1 for success, 0 for failure. 33.688 + bool Resume(); 33.689 + 33.690 + // Static function to return a pointer to the current thread 33.691 + //static Thread* GetThread(); 33.692 + 33.693 + 33.694 + // *** Thread status query functions 33.695 + 33.696 + bool GetExitFlag() const; 33.697 + void SetExitFlag(bool exitFlag); 33.698 + 33.699 + // Determines whether the thread was running and is now finished 33.700 + bool IsFinished() const; 33.701 + // Determines if the thread is currently suspended 33.702 + bool IsSuspended() const; 33.703 + // Returns current thread state 33.704 + ThreadState GetThreadState() const; 33.705 + 33.706 + // Returns the number of available CPUs on the system 33.707 + static int GetCPUCount(); 33.708 + 33.709 + // Returns the thread exit code. Exit code is initialized to 0, 33.710 + // and set to the return value if Run function after the thread is finished. 33.711 + inline int GetExitCode() const { return ExitCode; } 33.712 + // Returns an OS handle 33.713 +#if defined(OVR_OS_WIN32) 33.714 + void* GetOSHandle() const { return ThreadHandle; } 33.715 +#else 33.716 + pthread_t GetOSHandle() const { return ThreadHandle; } 33.717 +#endif 33.718 + 33.719 +#if defined(OVR_OS_WIN32) 33.720 + ThreadId GetThreadId() const { return IdValue; } 33.721 +#else 33.722 + ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } 33.723 +#endif 33.724 + 33.725 + static int GetOSPriority(ThreadPriority); 33.726 + // *** Sleep 33.727 + 33.728 + // Sleep secs seconds 33.729 + static bool Sleep(unsigned secs); 33.730 + // Sleep msecs milliseconds 33.731 + static bool MSleep(unsigned msecs); 33.732 + 33.733 + 33.734 + // *** Debugging functionality 33.735 +#if defined(OVR_OS_WIN32) 33.736 + virtual void SetThreadName( const char* name ); 33.737 +#else 33.738 + virtual void SetThreadName( const char* name ) { OVR_UNUSED(name); } 33.739 +#endif 33.740 + 33.741 +private: 33.742 +#if defined(OVR_OS_WIN32) 33.743 + friend unsigned WINAPI Thread_Win32StartFn(void *pthread); 33.744 + 33.745 +#else 33.746 + friend void *Thread_PthreadStartFn(void * phandle); 33.747 + 33.748 + static int InitAttr; 33.749 + static pthread_attr_t Attr; 33.750 +#endif 33.751 + 33.752 +protected: 33.753 + // Thread state flags 33.754 + AtomicInt<UInt32> ThreadFlags; 33.755 + AtomicInt<SInt32> SuspendCount; 33.756 + UPInt StackSize; 33.757 + 33.758 + // Hardware processor which this thread is running on. 33.759 + int Processor; 33.760 + ThreadPriority Priority; 33.761 + 33.762 +#if defined(OVR_OS_WIN32) 33.763 + void* ThreadHandle; 33.764 + volatile ThreadId IdValue; 33.765 + 33.766 + // System-specific cleanup function called from destructor 33.767 + void CleanupSystemThread(); 33.768 + 33.769 +#else 33.770 + pthread_t ThreadHandle; 33.771 +#endif 33.772 + 33.773 + // Exit code of the thread, as returned by Run. 33.774 + int ExitCode; 33.775 + 33.776 + // Internal run function. 33.777 + int PRun(); 33.778 + // Finishes the thread and releases internal reference to it. 33.779 + void FinishAndRelease(); 33.780 + 33.781 + void Init(const CreateParams& params); 33.782 + 33.783 + // Protected copy constructor 33.784 + Thread(const Thread &source) { OVR_UNUSED(source); } 33.785 + 33.786 +}; 33.787 + 33.788 +// Returns the unique Id of a thread it is called on, intended for 33.789 +// comparison purposes. 33.790 +ThreadId GetCurrentThreadId(); 33.791 + 33.792 + 33.793 +} // OVR 33.794 + 33.795 +#endif // OVR_ENABLE_THREADS 33.796 +#endif // OVR_Threads_h
34.1 --- a/libovr/Src/Kernel/OVR_Timer.cpp Sat Sep 14 17:51:03 2013 +0300 34.2 +++ b/libovr/Src/Kernel/OVR_Timer.cpp Sun Sep 15 04:10:05 2013 +0300 34.3 @@ -1,1 +1,156 @@ 34.4 -/************************************************************************************ 34.5 34.6 Filename : OVR_Timer.cpp 34.7 Content : Provides static functions for precise timing 34.8 Created : September 19, 2012 34.9 Notes : 34.10 34.11 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 34.12 34.13 Use of this software is subject to the terms of the Oculus license 34.14 agreement provided at the time of installation or download, or which 34.15 otherwise accompanies this software in either electronic or hard copy form. 34.16 34.17 ************************************************************************************/ 34.18 34.19 #include "OVR_Timer.h" 34.20 34.21 #if defined (OVR_OS_WIN32) 34.22 #include <windows.h> 34.23 34.24 #else 34.25 #include <sys/time.h> 34.26 #endif 34.27 34.28 namespace OVR { 34.29 34.30 //----------------------------------------------------------------------------------- 34.31 // ***** Timer Class 34.32 34.33 UInt64 Timer::GetProfileTicks() 34.34 { 34.35 return (GetRawTicks() * MksPerSecond) / GetRawFrequency(); 34.36 } 34.37 double Timer::GetProfileSeconds() 34.38 { 34.39 static UInt64 StartTime = GetProfileTicks(); 34.40 return TicksToSeconds(GetProfileTicks()-StartTime); 34.41 } 34.42 34.43 34.44 //------------------------------------------------------------------------ 34.45 // *** Win32 Specific Timer 34.46 34.47 #if (defined (OVR_OS_WIN32)) 34.48 34.49 CRITICAL_SECTION WinAPI_GetTimeCS; 34.50 volatile UInt32 WinAPI_OldTime = 0; 34.51 volatile UInt32 WinAPI_WrapCounter = 0; 34.52 34.53 34.54 UInt32 Timer::GetTicksMs() 34.55 { 34.56 return timeGetTime(); 34.57 } 34.58 34.59 UInt64 Timer::GetTicks() 34.60 { 34.61 DWORD ticks = timeGetTime(); 34.62 UInt64 result; 34.63 34.64 // On Win32 QueryPerformanceFrequency is unreliable due to SMP and 34.65 // performance levels, so use this logic to detect wrapping and track 34.66 // high bits. 34.67 ::EnterCriticalSection(&WinAPI_GetTimeCS); 34.68 34.69 if (WinAPI_OldTime > ticks) 34.70 WinAPI_WrapCounter++; 34.71 WinAPI_OldTime = ticks; 34.72 34.73 result = (UInt64(WinAPI_WrapCounter) << 32) | ticks; 34.74 ::LeaveCriticalSection(&WinAPI_GetTimeCS); 34.75 34.76 return result * MksPerMs; 34.77 } 34.78 34.79 UInt64 Timer::GetRawTicks() 34.80 { 34.81 LARGE_INTEGER li; 34.82 QueryPerformanceCounter(&li); 34.83 return li.QuadPart; 34.84 } 34.85 34.86 UInt64 Timer::GetRawFrequency() 34.87 { 34.88 static UInt64 perfFreq = 0; 34.89 if (perfFreq == 0) 34.90 { 34.91 LARGE_INTEGER freq; 34.92 QueryPerformanceFrequency(&freq); 34.93 perfFreq = freq.QuadPart; 34.94 } 34.95 return perfFreq; 34.96 } 34.97 34.98 void Timer::initializeTimerSystem() 34.99 { 34.100 timeBeginPeriod(1); 34.101 InitializeCriticalSection(&WinAPI_GetTimeCS); 34.102 34.103 } 34.104 void Timer::shutdownTimerSystem() 34.105 { 34.106 DeleteCriticalSection(&WinAPI_GetTimeCS); 34.107 timeEndPeriod(1); 34.108 } 34.109 34.110 #else // !OVR_OS_WIN32 34.111 34.112 34.113 //------------------------------------------------------------------------ 34.114 // *** Standard OS Timer 34.115 34.116 UInt32 Timer::GetTicksMs() 34.117 { 34.118 return (UInt32)(GetProfileTicks() / 1000); 34.119 } 34.120 // The profile ticks implementation is just fine for a normal timer. 34.121 UInt64 Timer::GetTicks() 34.122 { 34.123 return GetProfileTicks(); 34.124 } 34.125 34.126 void Timer::initializeTimerSystem() 34.127 { 34.128 } 34.129 void Timer::shutdownTimerSystem() 34.130 { 34.131 } 34.132 34.133 UInt64 Timer::GetRawTicks() 34.134 { 34.135 // TODO: prefer rdtsc when available? 34.136 34.137 // Return microseconds. 34.138 struct timeval tv; 34.139 UInt64 result; 34.140 34.141 gettimeofday(&tv, 0); 34.142 34.143 result = (UInt64)tv.tv_sec * 1000000; 34.144 result += tv.tv_usec; 34.145 34.146 return result; 34.147 } 34.148 34.149 UInt64 Timer::GetRawFrequency() 34.150 { 34.151 return MksPerSecond; 34.152 } 34.153 34.154 #endif // !OVR_OS_WIN32 34.155 34.156 34.157 34.158 } // OVR 34.159 34.160 \ No newline at end of file 34.161 +/************************************************************************************ 34.162 + 34.163 +Filename : OVR_Timer.cpp 34.164 +Content : Provides static functions for precise timing 34.165 +Created : September 19, 2012 34.166 +Notes : 34.167 + 34.168 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 34.169 + 34.170 +Use of this software is subject to the terms of the Oculus license 34.171 +agreement provided at the time of installation or download, or which 34.172 +otherwise accompanies this software in either electronic or hard copy form. 34.173 + 34.174 +************************************************************************************/ 34.175 + 34.176 +#include "OVR_Timer.h" 34.177 + 34.178 +#if defined (OVR_OS_WIN32) 34.179 +#include <windows.h> 34.180 + 34.181 +#else 34.182 +#include <sys/time.h> 34.183 +#endif 34.184 + 34.185 +namespace OVR { 34.186 + 34.187 +//----------------------------------------------------------------------------------- 34.188 +// ***** Timer Class 34.189 + 34.190 +UInt64 Timer::GetProfileTicks() 34.191 +{ 34.192 + return (GetRawTicks() * MksPerSecond) / GetRawFrequency(); 34.193 +} 34.194 +double Timer::GetProfileSeconds() 34.195 +{ 34.196 + static UInt64 StartTime = GetProfileTicks(); 34.197 + return TicksToSeconds(GetProfileTicks()-StartTime); 34.198 +} 34.199 + 34.200 + 34.201 +//------------------------------------------------------------------------ 34.202 +// *** Win32 Specific Timer 34.203 + 34.204 +#if (defined (OVR_OS_WIN32)) 34.205 + 34.206 +CRITICAL_SECTION WinAPI_GetTimeCS; 34.207 +volatile UInt32 WinAPI_OldTime = 0; 34.208 +volatile UInt32 WinAPI_WrapCounter = 0; 34.209 + 34.210 + 34.211 +UInt32 Timer::GetTicksMs() 34.212 +{ 34.213 + return timeGetTime(); 34.214 +} 34.215 + 34.216 +UInt64 Timer::GetTicks() 34.217 +{ 34.218 + DWORD ticks = timeGetTime(); 34.219 + UInt64 result; 34.220 + 34.221 + // On Win32 QueryPerformanceFrequency is unreliable due to SMP and 34.222 + // performance levels, so use this logic to detect wrapping and track 34.223 + // high bits. 34.224 + ::EnterCriticalSection(&WinAPI_GetTimeCS); 34.225 + 34.226 + if (WinAPI_OldTime > ticks) 34.227 + WinAPI_WrapCounter++; 34.228 + WinAPI_OldTime = ticks; 34.229 + 34.230 + result = (UInt64(WinAPI_WrapCounter) << 32) | ticks; 34.231 + ::LeaveCriticalSection(&WinAPI_GetTimeCS); 34.232 + 34.233 + return result * MksPerMs; 34.234 +} 34.235 + 34.236 +UInt64 Timer::GetRawTicks() 34.237 +{ 34.238 + LARGE_INTEGER li; 34.239 + QueryPerformanceCounter(&li); 34.240 + return li.QuadPart; 34.241 +} 34.242 + 34.243 +UInt64 Timer::GetRawFrequency() 34.244 +{ 34.245 + static UInt64 perfFreq = 0; 34.246 + if (perfFreq == 0) 34.247 + { 34.248 + LARGE_INTEGER freq; 34.249 + QueryPerformanceFrequency(&freq); 34.250 + perfFreq = freq.QuadPart; 34.251 + } 34.252 + return perfFreq; 34.253 +} 34.254 + 34.255 +void Timer::initializeTimerSystem() 34.256 +{ 34.257 + timeBeginPeriod(1); 34.258 + InitializeCriticalSection(&WinAPI_GetTimeCS); 34.259 + 34.260 +} 34.261 +void Timer::shutdownTimerSystem() 34.262 +{ 34.263 + DeleteCriticalSection(&WinAPI_GetTimeCS); 34.264 + timeEndPeriod(1); 34.265 +} 34.266 + 34.267 +#else // !OVR_OS_WIN32 34.268 + 34.269 + 34.270 +//------------------------------------------------------------------------ 34.271 +// *** Standard OS Timer 34.272 + 34.273 +UInt32 Timer::GetTicksMs() 34.274 +{ 34.275 + return (UInt32)(GetProfileTicks() / 1000); 34.276 +} 34.277 +// The profile ticks implementation is just fine for a normal timer. 34.278 +UInt64 Timer::GetTicks() 34.279 +{ 34.280 + return GetProfileTicks(); 34.281 +} 34.282 + 34.283 +void Timer::initializeTimerSystem() 34.284 +{ 34.285 +} 34.286 +void Timer::shutdownTimerSystem() 34.287 +{ 34.288 +} 34.289 + 34.290 +UInt64 Timer::GetRawTicks() 34.291 +{ 34.292 + // TODO: prefer rdtsc when available? 34.293 + 34.294 + // Return microseconds. 34.295 + struct timeval tv; 34.296 + UInt64 result; 34.297 + 34.298 + gettimeofday(&tv, 0); 34.299 + 34.300 + result = (UInt64)tv.tv_sec * 1000000; 34.301 + result += tv.tv_usec; 34.302 + 34.303 + return result; 34.304 +} 34.305 + 34.306 +UInt64 Timer::GetRawFrequency() 34.307 +{ 34.308 + return MksPerSecond; 34.309 +} 34.310 + 34.311 +#endif // !OVR_OS_WIN32 34.312 + 34.313 + 34.314 + 34.315 +} // OVR 34.316 +
35.1 --- a/libovr/Src/Kernel/OVR_Timer.h Sat Sep 14 17:51:03 2013 +0300 35.2 +++ b/libovr/Src/Kernel/OVR_Timer.h Sun Sep 15 04:10:05 2013 +0300 35.3 @@ -1,1 +1,100 @@ 35.4 -/************************************************************************************ 35.5 35.6 PublicHeader: OVR 35.7 Filename : OVR_Timer.h 35.8 Content : Provides static functions for precise timing 35.9 Created : September 19, 2012 35.10 Notes : 35.11 35.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 35.13 35.14 Use of this software is subject to the terms of the Oculus license 35.15 agreement provided at the time of installation or download, or which 35.16 otherwise accompanies this software in either electronic or hard copy form. 35.17 35.18 ************************************************************************************/ 35.19 35.20 #ifndef OVR_Timer_h 35.21 #define OVR_Timer_h 35.22 35.23 #include "OVR_Types.h" 35.24 35.25 namespace OVR { 35.26 35.27 //----------------------------------------------------------------------------------- 35.28 // ***** Timer 35.29 35.30 // Timer class defines a family of static functions used for application 35.31 // timing and profiling. 35.32 35.33 class Timer 35.34 { 35.35 public: 35.36 enum { 35.37 MsPerSecond = 1000, // Milliseconds in one second. 35.38 MksPerMs = 1000, // Microseconds in one millisecond. 35.39 MksPerSecond = MsPerSecond * MksPerMs 35.40 }; 35.41 35.42 35.43 // ***** Timing APIs for Application 35.44 // These APIs should be used to guide animation and other program functions 35.45 // that require precision. 35.46 35.47 // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 35.48 // 49.2 days. Use either time difference of two values of GetTicks to avoid 35.49 // wrap-around. GetTicksMs may perform better then GetTicks. 35.50 static UInt32 OVR_STDCALL GetTicksMs(); 35.51 35.52 // GetTicks returns general-purpose high resolution application timer value, 35.53 // measured in microseconds (mks, or 1/1000000 of a second). The actual precision 35.54 // is system-specific and may be much lower, such as 1 ms. 35.55 static UInt64 OVR_STDCALL GetTicks(); 35.56 35.57 35.58 // ***** Profiling APIs. 35.59 // These functions should be used for profiling, but may have system specific 35.60 // artifacts that make them less appropriate for general system use. 35.61 // On Win32, for example these rely on QueryPerformanceConter may have 35.62 // problems with thread-core switching and power modes. 35.63 35.64 // Return a hi-res timer value in mks (1/1000000 of a sec). 35.65 // Generally you want to call this at the start and end of an 35.66 // operation, and pass the difference to 35.67 // TicksToSeconds() to find out how long the operation took. 35.68 static UInt64 OVR_STDCALL GetProfileTicks(); 35.69 35.70 // More convenient zero-based profile timer in seconds. First call initializes 35.71 // the "zero" value; future calls return the difference. Not thread safe for first call. 35.72 // Due to low precision of Double, may malfunction after long runtime. 35.73 static double OVR_STDCALL GetProfileSeconds(); 35.74 35.75 // Get the raw cycle counter value, providing the maximum possible timer resolution. 35.76 static UInt64 OVR_STDCALL GetRawTicks(); 35.77 static UInt64 OVR_STDCALL GetRawFrequency(); 35.78 35.79 35.80 // ***** Tick and time unit conversion. 35.81 35.82 // Convert micro-second ticks value into seconds value. 35.83 static inline double TicksToSeconds(UInt64 ticks) 35.84 { 35.85 return static_cast<double>(ticks) * (1.0 / (double)MksPerSecond); 35.86 } 35.87 // Convert Raw or frequency-unit ticks to seconds based on specified frequency. 35.88 static inline double RawTicksToSeconds(UInt64 rawTicks, UInt64 rawFrequency) 35.89 { 35.90 return static_cast<double>(rawTicks) * rawFrequency; 35.91 } 35.92 35.93 private: 35.94 friend class System; 35.95 // System called during program startup/shutdown. 35.96 static void initializeTimerSystem(); 35.97 static void shutdownTimerSystem(); 35.98 }; 35.99 35.100 35.101 } // Scaleform::Timer 35.102 35.103 #endif 35.104 \ No newline at end of file 35.105 +/************************************************************************************ 35.106 + 35.107 +PublicHeader: OVR 35.108 +Filename : OVR_Timer.h 35.109 +Content : Provides static functions for precise timing 35.110 +Created : September 19, 2012 35.111 +Notes : 35.112 + 35.113 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 35.114 + 35.115 +Use of this software is subject to the terms of the Oculus license 35.116 +agreement provided at the time of installation or download, or which 35.117 +otherwise accompanies this software in either electronic or hard copy form. 35.118 + 35.119 +************************************************************************************/ 35.120 + 35.121 +#ifndef OVR_Timer_h 35.122 +#define OVR_Timer_h 35.123 + 35.124 +#include "OVR_Types.h" 35.125 + 35.126 +namespace OVR { 35.127 + 35.128 +//----------------------------------------------------------------------------------- 35.129 +// ***** Timer 35.130 + 35.131 +// Timer class defines a family of static functions used for application 35.132 +// timing and profiling. 35.133 + 35.134 +class Timer 35.135 +{ 35.136 +public: 35.137 + enum { 35.138 + MsPerSecond = 1000, // Milliseconds in one second. 35.139 + MksPerMs = 1000, // Microseconds in one millisecond. 35.140 + MksPerSecond = MsPerSecond * MksPerMs 35.141 + }; 35.142 + 35.143 + 35.144 + // ***** Timing APIs for Application 35.145 + // These APIs should be used to guide animation and other program functions 35.146 + // that require precision. 35.147 + 35.148 + // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 35.149 + // 49.2 days. Use either time difference of two values of GetTicks to avoid 35.150 + // wrap-around. GetTicksMs may perform better then GetTicks. 35.151 + static UInt32 OVR_STDCALL GetTicksMs(); 35.152 + 35.153 + // GetTicks returns general-purpose high resolution application timer value, 35.154 + // measured in microseconds (mks, or 1/1000000 of a second). The actual precision 35.155 + // is system-specific and may be much lower, such as 1 ms. 35.156 + static UInt64 OVR_STDCALL GetTicks(); 35.157 + 35.158 + 35.159 + // ***** Profiling APIs. 35.160 + // These functions should be used for profiling, but may have system specific 35.161 + // artifacts that make them less appropriate for general system use. 35.162 + // On Win32, for example these rely on QueryPerformanceConter may have 35.163 + // problems with thread-core switching and power modes. 35.164 + 35.165 + // Return a hi-res timer value in mks (1/1000000 of a sec). 35.166 + // Generally you want to call this at the start and end of an 35.167 + // operation, and pass the difference to 35.168 + // TicksToSeconds() to find out how long the operation took. 35.169 + static UInt64 OVR_STDCALL GetProfileTicks(); 35.170 + 35.171 + // More convenient zero-based profile timer in seconds. First call initializes 35.172 + // the "zero" value; future calls return the difference. Not thread safe for first call. 35.173 + // Due to low precision of Double, may malfunction after long runtime. 35.174 + static double OVR_STDCALL GetProfileSeconds(); 35.175 + 35.176 + // Get the raw cycle counter value, providing the maximum possible timer resolution. 35.177 + static UInt64 OVR_STDCALL GetRawTicks(); 35.178 + static UInt64 OVR_STDCALL GetRawFrequency(); 35.179 + 35.180 + 35.181 + // ***** Tick and time unit conversion. 35.182 + 35.183 + // Convert micro-second ticks value into seconds value. 35.184 + static inline double TicksToSeconds(UInt64 ticks) 35.185 + { 35.186 + return static_cast<double>(ticks) * (1.0 / (double)MksPerSecond); 35.187 + } 35.188 + // Convert Raw or frequency-unit ticks to seconds based on specified frequency. 35.189 + static inline double RawTicksToSeconds(UInt64 rawTicks, UInt64 rawFrequency) 35.190 + { 35.191 + return static_cast<double>(rawTicks) * rawFrequency; 35.192 + } 35.193 + 35.194 +private: 35.195 + friend class System; 35.196 + // System called during program startup/shutdown. 35.197 + static void initializeTimerSystem(); 35.198 + static void shutdownTimerSystem(); 35.199 +}; 35.200 + 35.201 + 35.202 +} // Scaleform::Timer 35.203 + 35.204 +#endif
36.1 --- a/libovr/Src/Kernel/OVR_Types.h Sat Sep 14 17:51:03 2013 +0300 36.2 +++ b/libovr/Src/Kernel/OVR_Types.h Sun Sep 15 04:10:05 2013 +0300 36.3 @@ -1,1 +1,456 @@ 36.4 -/************************************************************************************ 36.5 36.6 PublicHeader: OVR.h 36.7 Filename : OVR_Types.h 36.8 Content : Standard library defines and simple types 36.9 Created : September 19, 2012 36.10 Notes : 36.11 36.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 36.13 36.14 Use of this software is subject to the terms of the Oculus license 36.15 agreement provided at the time of installation or download, or which 36.16 otherwise accompanies this software in either electronic or hard copy form. 36.17 36.18 ************************************************************************************/ 36.19 36.20 #ifndef OVR_Types_H 36.21 #define OVR_Types_H 36.22 36.23 //----------------------------------------------------------------------------------- 36.24 // ****** Operating System 36.25 // 36.26 // Type definitions exist for the following operating systems: (OVR_OS_x) 36.27 // 36.28 // WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) 36.29 // DARWIN - Darwin OS (Mac OS X) 36.30 // LINUX - Linux 36.31 // ANDROID - Android 36.32 // IPHONE - iPhone 36.33 36.34 #if (defined(__APPLE__) && (defined(__GNUC__) ||\ 36.35 defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__) 36.36 # if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)) 36.37 # define OVR_OS_IPHONE 36.38 # else 36.39 # define OVR_OS_DARWIN 36.40 # define OVR_OS_MAC 36.41 # endif 36.42 #elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) 36.43 # define OVR_OS_WIN32 36.44 #elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) 36.45 # define OVR_OS_WIN32 36.46 #elif defined(__linux__) || defined(__linux) 36.47 # define OVR_OS_LINUX 36.48 #else 36.49 # define OVR_OS_OTHER 36.50 #endif 36.51 36.52 #if defined(ANDROID) 36.53 # define OVR_OS_ANDROID 36.54 #endif 36.55 36.56 36.57 //----------------------------------------------------------------------------------- 36.58 // ***** CPU Architecture 36.59 // 36.60 // The following CPUs are defined: (OVR_CPU_x) 36.61 // 36.62 // X86 - x86 (IA-32) 36.63 // X86_64 - x86_64 (amd64) 36.64 // PPC - PowerPC 36.65 // PPC64 - PowerPC64 36.66 // MIPS - MIPS 36.67 // OTHER - CPU for which no special support is present or needed 36.68 36.69 36.70 #if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 36.71 # define OVR_CPU_X86_64 36.72 # define OVR_64BIT_POINTERS 36.73 #elif defined(__i386__) || defined(OVR_OS_WIN32) 36.74 # define OVR_CPU_X86 36.75 #elif defined(__powerpc64__) 36.76 # define OVR_CPU_PPC64 36.77 #elif defined(__ppc__) 36.78 # define OVR_CPU_PPC 36.79 #elif defined(__mips__) || defined(__MIPSEL__) 36.80 # define OVR_CPU_MIPS 36.81 #elif defined(__arm__) 36.82 # define OVR_CPU_ARM 36.83 #else 36.84 # define OVR_CPU_OTHER 36.85 #endif 36.86 36.87 //----------------------------------------------------------------------------------- 36.88 // ***** Co-Processor Architecture 36.89 // 36.90 // The following co-processors are defined: (OVR_CPU_x) 36.91 // 36.92 // SSE - Available on all modern x86 processors. 36.93 // Altivec - Available on all modern ppc processors. 36.94 // Neon - Available on some armv7+ processors. 36.95 36.96 #if defined(__SSE__) || defined(OVR_OS_WIN32) 36.97 # define OVR_CPU_SSE 36.98 #endif // __SSE__ 36.99 36.100 #if defined( __ALTIVEC__ ) 36.101 # define OVR_CPU_ALTIVEC 36.102 #endif // __ALTIVEC__ 36.103 36.104 #if defined(__ARM_NEON__) 36.105 # define OVR_CPU_ARM_NEON 36.106 #endif // __ARM_NEON__ 36.107 36.108 36.109 //----------------------------------------------------------------------------------- 36.110 // ***** Compiler 36.111 // 36.112 // The following compilers are defined: (OVR_CC_x) 36.113 // 36.114 // MSVC - Microsoft Visual C/C++ 36.115 // INTEL - Intel C++ for Linux / Windows 36.116 // GNU - GNU C++ 36.117 // ARM - ARM C/C++ 36.118 36.119 #if defined(__INTEL_COMPILER) 36.120 // Intel 4.0 = 400 36.121 // Intel 5.0 = 500 36.122 // Intel 6.0 = 600 36.123 // Intel 8.0 = 800 36.124 // Intel 9.0 = 900 36.125 # define OVR_CC_INTEL __INTEL_COMPILER 36.126 36.127 #elif defined(_MSC_VER) 36.128 // MSVC 5.0 = 1100 36.129 // MSVC 6.0 = 1200 36.130 // MSVC 7.0 (VC2002) = 1300 36.131 // MSVC 7.1 (VC2003) = 1310 36.132 // MSVC 8.0 (VC2005) = 1400 36.133 // MSVC 9.0 (VC2008) = 1500 36.134 // MSVC 10.0 (VC2010) = 1600 36.135 # define OVR_CC_MSVC _MSC_VER 36.136 36.137 #elif defined(__GNUC__) 36.138 # define OVR_CC_GNU 36.139 36.140 #elif defined(__CC_ARM) 36.141 # define OVR_CC_ARM 36.142 36.143 #else 36.144 # error "Oculus does not support this Compiler" 36.145 #endif 36.146 36.147 36.148 //----------------------------------------------------------------------------------- 36.149 // ***** Compiler Warnings 36.150 36.151 // Disable MSVC warnings 36.152 #if defined(OVR_CC_MSVC) 36.153 # pragma warning(disable : 4127) // Inconsistent dll linkage 36.154 # pragma warning(disable : 4530) // Exception handling 36.155 # if (OVR_CC_MSVC<1300) 36.156 # pragma warning(disable : 4514) // Unreferenced inline function has been removed 36.157 # pragma warning(disable : 4710) // Function not inlined 36.158 # pragma warning(disable : 4714) // _force_inline not inlined 36.159 # pragma warning(disable : 4786) // Debug variable name longer than 255 chars 36.160 # endif // (OVR_CC_MSVC<1300) 36.161 #endif // (OVR_CC_MSVC) 36.162 36.163 36.164 36.165 // *** Linux Unicode - must come before Standard Includes 36.166 36.167 #ifdef OVR_OS_LINUX 36.168 // Use glibc unicode functions on linux. 36.169 # ifndef _GNU_SOURCE 36.170 # define _GNU_SOURCE 36.171 # endif 36.172 #endif 36.173 36.174 //----------------------------------------------------------------------------------- 36.175 // ***** Standard Includes 36.176 // 36.177 #include <stddef.h> 36.178 #include <limits.h> 36.179 #include <float.h> 36.180 36.181 36.182 // MSVC Based Memory Leak checking - for now 36.183 #if defined(OVR_CC_MSVC) && defined(OVR_BUILD_DEBUG) 36.184 # define _CRTDBG_MAP_ALLOC 36.185 # include <stdlib.h> 36.186 # include <crtdbg.h> 36.187 36.188 // Uncomment this to help debug memory leaks under Visual Studio in OVR apps only. 36.189 // This shouldn't be defined in customer releases. 36.190 # ifndef OVR_DEFINE_NEW 36.191 # define OVR_DEFINE_NEW new(__FILE__, __LINE__) 36.192 # define new OVR_DEFINE_NEW 36.193 # endif 36.194 36.195 #endif 36.196 36.197 36.198 //----------------------------------------------------------------------------------- 36.199 // ***** Type definitions for Common Systems 36.200 36.201 namespace OVR { 36.202 36.203 typedef char Char; 36.204 36.205 // Pointer-sized integer 36.206 typedef size_t UPInt; 36.207 typedef ptrdiff_t SPInt; 36.208 36.209 36.210 #if defined(OVR_OS_WIN32) 36.211 36.212 typedef char SByte; // 8 bit Integer (Byte) 36.213 typedef unsigned char UByte; 36.214 typedef short SInt16; // 16 bit Integer (Word) 36.215 typedef unsigned short UInt16; 36.216 typedef long SInt32; // 32 bit Integer 36.217 typedef unsigned long UInt32; 36.218 typedef __int64 SInt64; // 64 bit Integer (QWord) 36.219 typedef unsigned __int64 UInt64; 36.220 36.221 36.222 #elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU) 36.223 36.224 typedef int SByte __attribute__((__mode__ (__QI__))); 36.225 typedef unsigned int UByte __attribute__((__mode__ (__QI__))); 36.226 typedef int SInt16 __attribute__((__mode__ (__HI__))); 36.227 typedef unsigned int UInt16 __attribute__((__mode__ (__HI__))); 36.228 typedef int SInt32 __attribute__((__mode__ (__SI__))); 36.229 typedef unsigned int UInt32 __attribute__((__mode__ (__SI__))); 36.230 typedef int SInt64 __attribute__((__mode__ (__DI__))); 36.231 typedef unsigned int UInt64 __attribute__((__mode__ (__DI__))); 36.232 36.233 #else 36.234 36.235 #include <sys/types.h> 36.236 typedef int8_t SByte; 36.237 typedef uint8_t UByte; 36.238 typedef int16_t SInt16; 36.239 typedef uint16_t UInt16; 36.240 typedef int32_t SInt32; 36.241 typedef uint32_t UInt32; 36.242 typedef int64_t SInt64; 36.243 typedef uint64_t UInt64; 36.244 36.245 #endif 36.246 36.247 36.248 // ***** BaseTypes Namespace 36.249 36.250 // BaseTypes namespace is explicitly declared to allow base types to be used 36.251 // by customers directly without other contents of OVR namespace. 36.252 // 36.253 // Its is expected that GFx samples will declare 'using namespace OVR::BaseTypes' 36.254 // to allow using these directly without polluting the target scope with other 36.255 // OVR declarations, such as Ptr<>, String or Mutex. 36.256 namespace BaseTypes 36.257 { 36.258 using OVR::UPInt; 36.259 using OVR::SPInt; 36.260 using OVR::UByte; 36.261 using OVR::SByte; 36.262 using OVR::UInt16; 36.263 using OVR::SInt16; 36.264 using OVR::UInt32; 36.265 using OVR::SInt32; 36.266 using OVR::UInt64; 36.267 using OVR::SInt64; 36.268 } // OVR::BaseTypes 36.269 36.270 } // OVR 36.271 36.272 36.273 //----------------------------------------------------------------------------------- 36.274 // ***** Macro Definitions 36.275 // 36.276 // We define the following: 36.277 // 36.278 // OVR_BYTE_ORDER - Defined to either OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN 36.279 // OVR_FORCE_INLINE - Forces inline expansion of function 36.280 // OVR_ASM - Assembly language prefix 36.281 // OVR_STR - Prefixes string with L"" if building unicode 36.282 // 36.283 // OVR_STDCALL - Use stdcall calling convention (Pascal arg order) 36.284 // OVR_CDECL - Use cdecl calling convention (C argument order) 36.285 // OVR_FASTCALL - Use fastcall calling convention (registers) 36.286 // 36.287 36.288 // Byte order constants, OVR_BYTE_ORDER is defined to be one of these. 36.289 #define OVR_LITTLE_ENDIAN 1 36.290 #define OVR_BIG_ENDIAN 2 36.291 36.292 36.293 // Force inline substitute - goes before function declaration 36.294 #if defined(OVR_CC_MSVC) 36.295 # define OVR_FORCE_INLINE __forceinline 36.296 #elif defined(OVR_CC_GNU) 36.297 # define OVR_FORCE_INLINE __attribute__((always_inline)) inline 36.298 #else 36.299 # define OVR_FORCE_INLINE inline 36.300 #endif // OVR_CC_MSVC 36.301 36.302 36.303 #if defined(OVR_OS_WIN32) 36.304 36.305 // ***** Win32 36.306 36.307 // Byte order 36.308 #define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN 36.309 36.310 // Calling convention - goes after function return type but before function name 36.311 #ifdef __cplusplus_cli 36.312 # define OVR_FASTCALL __stdcall 36.313 #else 36.314 # define OVR_FASTCALL __fastcall 36.315 #endif 36.316 36.317 #define OVR_STDCALL __stdcall 36.318 #define OVR_CDECL __cdecl 36.319 36.320 36.321 // Assembly macros 36.322 #if defined(OVR_CC_MSVC) 36.323 # define OVR_ASM _asm 36.324 #else 36.325 # define OVR_ASM asm 36.326 #endif // (OVR_CC_MSVC) 36.327 36.328 #ifdef UNICODE 36.329 # define OVR_STR(str) L##str 36.330 #else 36.331 # define OVR_STR(str) str 36.332 #endif // UNICODE 36.333 36.334 #else 36.335 36.336 // **** Standard systems 36.337 36.338 #if (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN))|| \ 36.339 (defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) 36.340 # define OVR_BYTE_ORDER OVR_BIG_ENDIAN 36.341 #elif (defined(__ARMEB__) || defined(OVR_CPU_PPC) || defined(OVR_CPU_PPC64)) 36.342 # define OVR_BYTE_ORDER OVR_BIG_ENDIAN 36.343 #else 36.344 # define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN 36.345 #endif 36.346 36.347 // Assembly macros 36.348 #define OVR_ASM __asm__ 36.349 #define OVR_ASM_PROC(procname) OVR_ASM 36.350 #define OVR_ASM_END OVR_ASM 36.351 36.352 // Calling convention - goes after function return type but before function name 36.353 #define OVR_FASTCALL 36.354 #define OVR_STDCALL 36.355 #define OVR_CDECL 36.356 36.357 #endif // defined(OVR_OS_WIN32) 36.358 36.359 36.360 36.361 //----------------------------------------------------------------------------------- 36.362 // ***** OVR_DEBUG_BREAK, OVR_ASSERT 36.363 // 36.364 // If not in debug build, macros do nothing 36.365 #ifndef OVR_BUILD_DEBUG 36.366 36.367 # define OVR_DEBUG_BREAK ((void)0) 36.368 # define OVR_ASSERT(p) ((void)0) 36.369 36.370 #else 36.371 36.372 // Microsoft Win32 specific debugging support 36.373 #if defined(OVR_OS_WIN32) 36.374 # ifdef OVR_CPU_X86 36.375 # if defined(__cplusplus_cli) 36.376 # define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) 36.377 # elif defined(OVR_CC_GNU) 36.378 # define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) 36.379 # else 36.380 # define OVR_DEBUG_BREAK do { OVR_ASM int 3 } while (0) 36.381 # endif 36.382 # else 36.383 # define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) 36.384 # endif 36.385 // Unix specific debugging support 36.386 #elif defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) 36.387 # define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) 36.388 #else 36.389 # define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0) 36.390 #endif 36.391 36.392 // This will cause compiler breakpoint 36.393 #define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; } } while(0) 36.394 36.395 #endif // OVR_BUILD_DEBUG 36.396 36.397 36.398 // Compile-time assert; produces compiler error if condition is false 36.399 #define OVR_COMPILER_ASSERT(x) { int zero = 0; switch(zero) {case 0: case x:;} } 36.400 36.401 36.402 36.403 //----------------------------------------------------------------------------------- 36.404 // ***** OVR_UNUSED - Unused Argument handling 36.405 36.406 // Macro to quiet compiler warnings about unused parameters/variables. 36.407 #if defined(OVR_CC_GNU) 36.408 # define OVR_UNUSED(a) do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0) 36.409 #else 36.410 # define OVR_UNUSED(a) (a) 36.411 #endif 36.412 36.413 #define OVR_UNUSED1(a1) OVR_UNUSED(a1) 36.414 #define OVR_UNUSED2(a1,a2) OVR_UNUSED(a1); OVR_UNUSED(a2) 36.415 #define OVR_UNUSED3(a1,a2,a3) OVR_UNUSED2(a1,a2); OVR_UNUSED(a3) 36.416 #define OVR_UNUSED4(a1,a2,a3,a4) OVR_UNUSED3(a1,a2,a3); OVR_UNUSED(a4) 36.417 #define OVR_UNUSED5(a1,a2,a3,a4,a5) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED(a5) 36.418 #define OVR_UNUSED6(a1,a2,a3,a4,a5,a6) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED2(a5,a6) 36.419 #define OVR_UNUSED7(a1,a2,a3,a4,a5,a6,a7) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED3(a5,a6,a7) 36.420 #define OVR_UNUSED8(a1,a2,a3,a4,a5,a6,a7,a8) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED4(a5,a6,a7,a8) 36.421 #define OVR_UNUSED9(a1,a2,a3,a4,a5,a6,a7,a8,a9) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED5(a5,a6,a7,a8,a9) 36.422 36.423 36.424 //----------------------------------------------------------------------------------- 36.425 // ***** Configuration Macros 36.426 36.427 // SF Build type 36.428 #ifdef OVR_BUILD_DEBUG 36.429 # define OVR_BUILD_STRING "Debug" 36.430 #else 36.431 # define OVR_BUILD_STRING "Release" 36.432 #endif 36.433 36.434 36.435 //// Enables SF Debugging information 36.436 //# define OVR_BUILD_DEBUG 36.437 36.438 // OVR_DEBUG_STATEMENT injects a statement only in debug builds. 36.439 // OVR_DEBUG_SELECT injects first argument in debug builds, second argument otherwise. 36.440 #ifdef OVR_BUILD_DEBUG 36.441 #define OVR_DEBUG_STATEMENT(s) s 36.442 #define OVR_DEBUG_SELECT(d, nd) d 36.443 #else 36.444 #define OVR_DEBUG_STATEMENT(s) 36.445 #define OVR_DEBUG_SELECT(d, nd) nd 36.446 #endif 36.447 36.448 36.449 #define OVR_ENABLE_THREADS 36.450 // 36.451 // Prevents OVR from defining new within 36.452 // type macros, so developers can override 36.453 // new using the #define new new(...) trick 36.454 // - used with OVR_DEFINE_NEW macro 36.455 //# define OVR_BUILD_DEFINE_NEW 36.456 // 36.457 36.458 36.459 #endif // OVR_Types_h 36.460 \ No newline at end of file 36.461 +/************************************************************************************ 36.462 + 36.463 +PublicHeader: OVR.h 36.464 +Filename : OVR_Types.h 36.465 +Content : Standard library defines and simple types 36.466 +Created : September 19, 2012 36.467 +Notes : 36.468 + 36.469 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 36.470 + 36.471 +Use of this software is subject to the terms of the Oculus license 36.472 +agreement provided at the time of installation or download, or which 36.473 +otherwise accompanies this software in either electronic or hard copy form. 36.474 + 36.475 +************************************************************************************/ 36.476 + 36.477 +#ifndef OVR_Types_H 36.478 +#define OVR_Types_H 36.479 + 36.480 +//----------------------------------------------------------------------------------- 36.481 +// ****** Operating System 36.482 +// 36.483 +// Type definitions exist for the following operating systems: (OVR_OS_x) 36.484 +// 36.485 +// WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) 36.486 +// DARWIN - Darwin OS (Mac OS X) 36.487 +// LINUX - Linux 36.488 +// ANDROID - Android 36.489 +// IPHONE - iPhone 36.490 + 36.491 +#if (defined(__APPLE__) && (defined(__GNUC__) ||\ 36.492 + defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__) 36.493 +# if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)) 36.494 +# define OVR_OS_IPHONE 36.495 +# else 36.496 +# define OVR_OS_DARWIN 36.497 +# define OVR_OS_MAC 36.498 +# endif 36.499 +#elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) 36.500 +# define OVR_OS_WIN32 36.501 +#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) 36.502 +# define OVR_OS_WIN32 36.503 +#elif defined(__linux__) || defined(__linux) 36.504 +# define OVR_OS_LINUX 36.505 +#else 36.506 +# define OVR_OS_OTHER 36.507 +#endif 36.508 + 36.509 +#if defined(ANDROID) 36.510 +# define OVR_OS_ANDROID 36.511 +#endif 36.512 + 36.513 + 36.514 +//----------------------------------------------------------------------------------- 36.515 +// ***** CPU Architecture 36.516 +// 36.517 +// The following CPUs are defined: (OVR_CPU_x) 36.518 +// 36.519 +// X86 - x86 (IA-32) 36.520 +// X86_64 - x86_64 (amd64) 36.521 +// PPC - PowerPC 36.522 +// PPC64 - PowerPC64 36.523 +// MIPS - MIPS 36.524 +// OTHER - CPU for which no special support is present or needed 36.525 + 36.526 + 36.527 +#if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 36.528 +# define OVR_CPU_X86_64 36.529 +# define OVR_64BIT_POINTERS 36.530 +#elif defined(__i386__) || defined(OVR_OS_WIN32) 36.531 +# define OVR_CPU_X86 36.532 +#elif defined(__powerpc64__) 36.533 +# define OVR_CPU_PPC64 36.534 +#elif defined(__ppc__) 36.535 +# define OVR_CPU_PPC 36.536 +#elif defined(__mips__) || defined(__MIPSEL__) 36.537 +# define OVR_CPU_MIPS 36.538 +#elif defined(__arm__) 36.539 +# define OVR_CPU_ARM 36.540 +#else 36.541 +# define OVR_CPU_OTHER 36.542 +#endif 36.543 + 36.544 +//----------------------------------------------------------------------------------- 36.545 +// ***** Co-Processor Architecture 36.546 +// 36.547 +// The following co-processors are defined: (OVR_CPU_x) 36.548 +// 36.549 +// SSE - Available on all modern x86 processors. 36.550 +// Altivec - Available on all modern ppc processors. 36.551 +// Neon - Available on some armv7+ processors. 36.552 + 36.553 +#if defined(__SSE__) || defined(OVR_OS_WIN32) 36.554 +# define OVR_CPU_SSE 36.555 +#endif // __SSE__ 36.556 + 36.557 +#if defined( __ALTIVEC__ ) 36.558 +# define OVR_CPU_ALTIVEC 36.559 +#endif // __ALTIVEC__ 36.560 + 36.561 +#if defined(__ARM_NEON__) 36.562 +# define OVR_CPU_ARM_NEON 36.563 +#endif // __ARM_NEON__ 36.564 + 36.565 + 36.566 +//----------------------------------------------------------------------------------- 36.567 +// ***** Compiler 36.568 +// 36.569 +// The following compilers are defined: (OVR_CC_x) 36.570 +// 36.571 +// MSVC - Microsoft Visual C/C++ 36.572 +// INTEL - Intel C++ for Linux / Windows 36.573 +// GNU - GNU C++ 36.574 +// ARM - ARM C/C++ 36.575 + 36.576 +#if defined(__INTEL_COMPILER) 36.577 +// Intel 4.0 = 400 36.578 +// Intel 5.0 = 500 36.579 +// Intel 6.0 = 600 36.580 +// Intel 8.0 = 800 36.581 +// Intel 9.0 = 900 36.582 +# define OVR_CC_INTEL __INTEL_COMPILER 36.583 + 36.584 +#elif defined(_MSC_VER) 36.585 +// MSVC 5.0 = 1100 36.586 +// MSVC 6.0 = 1200 36.587 +// MSVC 7.0 (VC2002) = 1300 36.588 +// MSVC 7.1 (VC2003) = 1310 36.589 +// MSVC 8.0 (VC2005) = 1400 36.590 +// MSVC 9.0 (VC2008) = 1500 36.591 +// MSVC 10.0 (VC2010) = 1600 36.592 +# define OVR_CC_MSVC _MSC_VER 36.593 + 36.594 +#elif defined(__GNUC__) 36.595 +# define OVR_CC_GNU 36.596 + 36.597 +#elif defined(__CC_ARM) 36.598 +# define OVR_CC_ARM 36.599 + 36.600 +#else 36.601 +# error "Oculus does not support this Compiler" 36.602 +#endif 36.603 + 36.604 + 36.605 +//----------------------------------------------------------------------------------- 36.606 +// ***** Compiler Warnings 36.607 + 36.608 +// Disable MSVC warnings 36.609 +#if defined(OVR_CC_MSVC) 36.610 +# pragma warning(disable : 4127) // Inconsistent dll linkage 36.611 +# pragma warning(disable : 4530) // Exception handling 36.612 +# if (OVR_CC_MSVC<1300) 36.613 +# pragma warning(disable : 4514) // Unreferenced inline function has been removed 36.614 +# pragma warning(disable : 4710) // Function not inlined 36.615 +# pragma warning(disable : 4714) // _force_inline not inlined 36.616 +# pragma warning(disable : 4786) // Debug variable name longer than 255 chars 36.617 +# endif // (OVR_CC_MSVC<1300) 36.618 +#endif // (OVR_CC_MSVC) 36.619 + 36.620 + 36.621 + 36.622 +// *** Linux Unicode - must come before Standard Includes 36.623 + 36.624 +#ifdef OVR_OS_LINUX 36.625 +// Use glibc unicode functions on linux. 36.626 +# ifndef _GNU_SOURCE 36.627 +# define _GNU_SOURCE 36.628 +# endif 36.629 +#endif 36.630 + 36.631 +//----------------------------------------------------------------------------------- 36.632 +// ***** Standard Includes 36.633 +// 36.634 +#include <stddef.h> 36.635 +#include <limits.h> 36.636 +#include <float.h> 36.637 + 36.638 + 36.639 +// MSVC Based Memory Leak checking - for now 36.640 +#if defined(OVR_CC_MSVC) && defined(OVR_BUILD_DEBUG) 36.641 +# define _CRTDBG_MAP_ALLOC 36.642 +# include <stdlib.h> 36.643 +# include <crtdbg.h> 36.644 + 36.645 +// Uncomment this to help debug memory leaks under Visual Studio in OVR apps only. 36.646 +// This shouldn't be defined in customer releases. 36.647 +# ifndef OVR_DEFINE_NEW 36.648 +# define OVR_DEFINE_NEW new(__FILE__, __LINE__) 36.649 +# define new OVR_DEFINE_NEW 36.650 +# endif 36.651 + 36.652 +#endif 36.653 + 36.654 + 36.655 +//----------------------------------------------------------------------------------- 36.656 +// ***** Type definitions for Common Systems 36.657 + 36.658 +namespace OVR { 36.659 + 36.660 +typedef char Char; 36.661 + 36.662 +// Pointer-sized integer 36.663 +typedef size_t UPInt; 36.664 +typedef ptrdiff_t SPInt; 36.665 + 36.666 + 36.667 +#if defined(OVR_OS_WIN32) 36.668 + 36.669 +typedef char SByte; // 8 bit Integer (Byte) 36.670 +typedef unsigned char UByte; 36.671 +typedef short SInt16; // 16 bit Integer (Word) 36.672 +typedef unsigned short UInt16; 36.673 +typedef long SInt32; // 32 bit Integer 36.674 +typedef unsigned long UInt32; 36.675 +typedef __int64 SInt64; // 64 bit Integer (QWord) 36.676 +typedef unsigned __int64 UInt64; 36.677 + 36.678 + 36.679 +#elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU) 36.680 + 36.681 +typedef int SByte __attribute__((__mode__ (__QI__))); 36.682 +typedef unsigned int UByte __attribute__((__mode__ (__QI__))); 36.683 +typedef int SInt16 __attribute__((__mode__ (__HI__))); 36.684 +typedef unsigned int UInt16 __attribute__((__mode__ (__HI__))); 36.685 +typedef int SInt32 __attribute__((__mode__ (__SI__))); 36.686 +typedef unsigned int UInt32 __attribute__((__mode__ (__SI__))); 36.687 +typedef int SInt64 __attribute__((__mode__ (__DI__))); 36.688 +typedef unsigned int UInt64 __attribute__((__mode__ (__DI__))); 36.689 + 36.690 +#else 36.691 + 36.692 +#include <sys/types.h> 36.693 +typedef int8_t SByte; 36.694 +typedef uint8_t UByte; 36.695 +typedef int16_t SInt16; 36.696 +typedef uint16_t UInt16; 36.697 +typedef int32_t SInt32; 36.698 +typedef uint32_t UInt32; 36.699 +typedef int64_t SInt64; 36.700 +typedef uint64_t UInt64; 36.701 + 36.702 +#endif 36.703 + 36.704 + 36.705 +// ***** BaseTypes Namespace 36.706 + 36.707 +// BaseTypes namespace is explicitly declared to allow base types to be used 36.708 +// by customers directly without other contents of OVR namespace. 36.709 +// 36.710 +// Its is expected that GFx samples will declare 'using namespace OVR::BaseTypes' 36.711 +// to allow using these directly without polluting the target scope with other 36.712 +// OVR declarations, such as Ptr<>, String or Mutex. 36.713 +namespace BaseTypes 36.714 +{ 36.715 + using OVR::UPInt; 36.716 + using OVR::SPInt; 36.717 + using OVR::UByte; 36.718 + using OVR::SByte; 36.719 + using OVR::UInt16; 36.720 + using OVR::SInt16; 36.721 + using OVR::UInt32; 36.722 + using OVR::SInt32; 36.723 + using OVR::UInt64; 36.724 + using OVR::SInt64; 36.725 +} // OVR::BaseTypes 36.726 + 36.727 +} // OVR 36.728 + 36.729 + 36.730 +//----------------------------------------------------------------------------------- 36.731 +// ***** Macro Definitions 36.732 +// 36.733 +// We define the following: 36.734 +// 36.735 +// OVR_BYTE_ORDER - Defined to either OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN 36.736 +// OVR_FORCE_INLINE - Forces inline expansion of function 36.737 +// OVR_ASM - Assembly language prefix 36.738 +// OVR_STR - Prefixes string with L"" if building unicode 36.739 +// 36.740 +// OVR_STDCALL - Use stdcall calling convention (Pascal arg order) 36.741 +// OVR_CDECL - Use cdecl calling convention (C argument order) 36.742 +// OVR_FASTCALL - Use fastcall calling convention (registers) 36.743 +// 36.744 + 36.745 +// Byte order constants, OVR_BYTE_ORDER is defined to be one of these. 36.746 +#define OVR_LITTLE_ENDIAN 1 36.747 +#define OVR_BIG_ENDIAN 2 36.748 + 36.749 + 36.750 +// Force inline substitute - goes before function declaration 36.751 +#if defined(OVR_CC_MSVC) 36.752 +# define OVR_FORCE_INLINE __forceinline 36.753 +#elif defined(OVR_CC_GNU) 36.754 +# define OVR_FORCE_INLINE __attribute__((always_inline)) inline 36.755 +#else 36.756 +# define OVR_FORCE_INLINE inline 36.757 +#endif // OVR_CC_MSVC 36.758 + 36.759 + 36.760 +#if defined(OVR_OS_WIN32) 36.761 + 36.762 + // ***** Win32 36.763 + 36.764 + // Byte order 36.765 + #define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN 36.766 + 36.767 + // Calling convention - goes after function return type but before function name 36.768 + #ifdef __cplusplus_cli 36.769 + # define OVR_FASTCALL __stdcall 36.770 + #else 36.771 + # define OVR_FASTCALL __fastcall 36.772 + #endif 36.773 + 36.774 + #define OVR_STDCALL __stdcall 36.775 + #define OVR_CDECL __cdecl 36.776 + 36.777 + 36.778 + // Assembly macros 36.779 + #if defined(OVR_CC_MSVC) 36.780 + # define OVR_ASM _asm 36.781 + #else 36.782 + # define OVR_ASM asm 36.783 + #endif // (OVR_CC_MSVC) 36.784 + 36.785 + #ifdef UNICODE 36.786 + # define OVR_STR(str) L##str 36.787 + #else 36.788 + # define OVR_STR(str) str 36.789 + #endif // UNICODE 36.790 + 36.791 +#else 36.792 + 36.793 + // **** Standard systems 36.794 + 36.795 + #if (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN))|| \ 36.796 + (defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) 36.797 + # define OVR_BYTE_ORDER OVR_BIG_ENDIAN 36.798 + #elif (defined(__ARMEB__) || defined(OVR_CPU_PPC) || defined(OVR_CPU_PPC64)) 36.799 + # define OVR_BYTE_ORDER OVR_BIG_ENDIAN 36.800 + #else 36.801 + # define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN 36.802 + #endif 36.803 + 36.804 + // Assembly macros 36.805 + #define OVR_ASM __asm__ 36.806 + #define OVR_ASM_PROC(procname) OVR_ASM 36.807 + #define OVR_ASM_END OVR_ASM 36.808 + 36.809 + // Calling convention - goes after function return type but before function name 36.810 + #define OVR_FASTCALL 36.811 + #define OVR_STDCALL 36.812 + #define OVR_CDECL 36.813 + 36.814 +#endif // defined(OVR_OS_WIN32) 36.815 + 36.816 + 36.817 + 36.818 +//----------------------------------------------------------------------------------- 36.819 +// ***** OVR_DEBUG_BREAK, OVR_ASSERT 36.820 +// 36.821 +// If not in debug build, macros do nothing 36.822 +#ifndef OVR_BUILD_DEBUG 36.823 + 36.824 +# define OVR_DEBUG_BREAK ((void)0) 36.825 +# define OVR_ASSERT(p) ((void)0) 36.826 + 36.827 +#else 36.828 + 36.829 +// Microsoft Win32 specific debugging support 36.830 +#if defined(OVR_OS_WIN32) 36.831 +# ifdef OVR_CPU_X86 36.832 +# if defined(__cplusplus_cli) 36.833 +# define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) 36.834 +# elif defined(OVR_CC_GNU) 36.835 +# define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) 36.836 +# else 36.837 +# define OVR_DEBUG_BREAK do { OVR_ASM int 3 } while (0) 36.838 +# endif 36.839 +# else 36.840 +# define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) 36.841 +# endif 36.842 +// Unix specific debugging support 36.843 +#elif defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) 36.844 +# define OVR_DEBUG_BREAK do { OVR_ASM("int $3\n\t"); } while(0) 36.845 +#else 36.846 +# define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0) 36.847 +#endif 36.848 + 36.849 +// This will cause compiler breakpoint 36.850 +#define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; } } while(0) 36.851 + 36.852 +#endif // OVR_BUILD_DEBUG 36.853 + 36.854 + 36.855 +// Compile-time assert; produces compiler error if condition is false 36.856 +#define OVR_COMPILER_ASSERT(x) { int zero = 0; switch(zero) {case 0: case x:;} } 36.857 + 36.858 + 36.859 + 36.860 +//----------------------------------------------------------------------------------- 36.861 +// ***** OVR_UNUSED - Unused Argument handling 36.862 + 36.863 +// Macro to quiet compiler warnings about unused parameters/variables. 36.864 +#if defined(OVR_CC_GNU) 36.865 +# define OVR_UNUSED(a) do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0) 36.866 +#else 36.867 +# define OVR_UNUSED(a) (a) 36.868 +#endif 36.869 + 36.870 +#define OVR_UNUSED1(a1) OVR_UNUSED(a1) 36.871 +#define OVR_UNUSED2(a1,a2) OVR_UNUSED(a1); OVR_UNUSED(a2) 36.872 +#define OVR_UNUSED3(a1,a2,a3) OVR_UNUSED2(a1,a2); OVR_UNUSED(a3) 36.873 +#define OVR_UNUSED4(a1,a2,a3,a4) OVR_UNUSED3(a1,a2,a3); OVR_UNUSED(a4) 36.874 +#define OVR_UNUSED5(a1,a2,a3,a4,a5) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED(a5) 36.875 +#define OVR_UNUSED6(a1,a2,a3,a4,a5,a6) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED2(a5,a6) 36.876 +#define OVR_UNUSED7(a1,a2,a3,a4,a5,a6,a7) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED3(a5,a6,a7) 36.877 +#define OVR_UNUSED8(a1,a2,a3,a4,a5,a6,a7,a8) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED4(a5,a6,a7,a8) 36.878 +#define OVR_UNUSED9(a1,a2,a3,a4,a5,a6,a7,a8,a9) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED5(a5,a6,a7,a8,a9) 36.879 + 36.880 + 36.881 +//----------------------------------------------------------------------------------- 36.882 +// ***** Configuration Macros 36.883 + 36.884 +// SF Build type 36.885 +#ifdef OVR_BUILD_DEBUG 36.886 +# define OVR_BUILD_STRING "Debug" 36.887 +#else 36.888 +# define OVR_BUILD_STRING "Release" 36.889 +#endif 36.890 + 36.891 + 36.892 +//// Enables SF Debugging information 36.893 +//# define OVR_BUILD_DEBUG 36.894 + 36.895 +// OVR_DEBUG_STATEMENT injects a statement only in debug builds. 36.896 +// OVR_DEBUG_SELECT injects first argument in debug builds, second argument otherwise. 36.897 +#ifdef OVR_BUILD_DEBUG 36.898 +#define OVR_DEBUG_STATEMENT(s) s 36.899 +#define OVR_DEBUG_SELECT(d, nd) d 36.900 +#else 36.901 +#define OVR_DEBUG_STATEMENT(s) 36.902 +#define OVR_DEBUG_SELECT(d, nd) nd 36.903 +#endif 36.904 + 36.905 + 36.906 +#define OVR_ENABLE_THREADS 36.907 +// 36.908 +// Prevents OVR from defining new within 36.909 +// type macros, so developers can override 36.910 +// new using the #define new new(...) trick 36.911 +// - used with OVR_DEFINE_NEW macro 36.912 +//# define OVR_BUILD_DEFINE_NEW 36.913 +// 36.914 + 36.915 + 36.916 +#endif // OVR_Types_h
37.1 --- a/libovr/Src/Kernel/OVR_UTF8Util.cpp Sat Sep 14 17:51:03 2013 +0300 37.2 +++ b/libovr/Src/Kernel/OVR_UTF8Util.cpp Sun Sep 15 04:10:05 2013 +0300 37.3 @@ -1,1 +1,545 @@ 37.4 -/************************************************************************** 37.5 37.6 Filename : OVR_UTF8Util.cpp 37.7 Content : UTF8 Unicode character encoding/decoding support 37.8 Created : September 19, 2012 37.9 Notes : 37.10 Notes : Much useful info at "UTF-8 and Unicode FAQ" 37.11 http://www.cl.cam.ac.uk/~mgk25/unicode.html 37.12 37.13 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 37.14 37.15 Use of this software is subject to the terms of the Oculus license 37.16 agreement provided at the time of installation or download, or which 37.17 otherwise accompanies this software in either electronic or hard copy form. 37.18 37.19 ************************************************************************************/ 37.20 37.21 #include "OVR_UTF8Util.h" 37.22 37.23 namespace OVR { namespace UTF8Util { 37.24 37.25 SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) 37.26 { 37.27 const char* p = buf; 37.28 SPInt length = 0; 37.29 37.30 if (buflen != -1) 37.31 { 37.32 while (p - buf < buflen) 37.33 { 37.34 // We should be able to have ASStrings with 0 in the middle. 37.35 UTF8Util::DecodeNextChar_Advance0(&p); 37.36 length++; 37.37 } 37.38 } 37.39 else 37.40 { 37.41 while (UTF8Util::DecodeNextChar_Advance0(&p)) 37.42 length++; 37.43 } 37.44 37.45 return length; 37.46 } 37.47 37.48 UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) 37.49 { 37.50 const char* buf = putf8str; 37.51 UInt32 c = 0; 37.52 37.53 if (length != -1) 37.54 { 37.55 while (buf - putf8str < length) 37.56 { 37.57 c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.58 if (index == 0) 37.59 return c; 37.60 index--; 37.61 } 37.62 37.63 return c; 37.64 } 37.65 37.66 do 37.67 { 37.68 c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.69 index--; 37.70 37.71 if (c == 0) 37.72 { 37.73 // We've hit the end of the string; don't go further. 37.74 OVR_ASSERT(index == 0); 37.75 return c; 37.76 } 37.77 } while (index >= 0); 37.78 37.79 return c; 37.80 } 37.81 37.82 SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) 37.83 { 37.84 const char* buf = putf8str; 37.85 37.86 if (length != -1) 37.87 { 37.88 while ((buf - putf8str) < length && index > 0) 37.89 { 37.90 UTF8Util::DecodeNextChar_Advance0(&buf); 37.91 index--; 37.92 } 37.93 37.94 return buf-putf8str; 37.95 } 37.96 37.97 while (index > 0) 37.98 { 37.99 UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.100 index--; 37.101 37.102 if (c == 0) 37.103 return buf-putf8str; 37.104 }; 37.105 37.106 return buf-putf8str; 37.107 } 37.108 37.109 int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) 37.110 { 37.111 if (ucs_character <= 0x7F) 37.112 return 1; 37.113 else if (ucs_character <= 0x7FF) 37.114 return 2; 37.115 else if (ucs_character <= 0xFFFF) 37.116 return 3; 37.117 else if (ucs_character <= 0x1FFFFF) 37.118 return 4; 37.119 else if (ucs_character <= 0x3FFFFFF) 37.120 return 5; 37.121 else if (ucs_character <= 0x7FFFFFFF) 37.122 return 6; 37.123 else 37.124 return 0; 37.125 } 37.126 37.127 UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) 37.128 { 37.129 UInt32 uc; 37.130 char c; 37.131 37.132 // Security considerations: 37.133 // 37.134 // Changed, this is now only the case for DecodeNextChar: 37.135 // - If we hit a zero byte, we want to return 0 without stepping 37.136 // the buffer pointer past the 0. th 37.137 // 37.138 // If we hit an "overlong sequence"; i.e. a character encoded 37.139 // in a longer multibyte string than is necessary, then we 37.140 // need to discard the character. This is so attackers can't 37.141 // disguise dangerous characters or character sequences -- 37.142 // there is only one valid encoding for each character. 37.143 // 37.144 // If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE, 37.145 // 0xFFFF } then we ignore them; they are not valid in UTF-8. 37.146 37.147 // This isn't actually an invalid character; it's a valid char that 37.148 // looks like an inverted question mark. 37.149 #define INVALID_CHAR 0x0FFFD 37.150 37.151 #define FIRST_BYTE(mask, shift) \ 37.152 uc = (c & (mask)) << (shift); 37.153 37.154 #define NEXT_BYTE(shift) \ 37.155 c = **putf8Buffer; \ 37.156 if (c == 0) return 0; /* end of buffer, do not advance */ \ 37.157 if ((c & 0xC0) != 0x80) return INVALID_CHAR; /* standard check */ \ 37.158 (*putf8Buffer)++; \ 37.159 uc |= (c & 0x3F) << shift; 37.160 37.161 c = **putf8Buffer; 37.162 (*putf8Buffer)++; 37.163 if (c == 0) 37.164 return 0; // End of buffer. 37.165 37.166 if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII. 37.167 37.168 // Multi-byte sequences. 37.169 if ((c & 0xE0) == 0xC0) 37.170 { 37.171 // Two-byte sequence. 37.172 FIRST_BYTE(0x1F, 6); 37.173 NEXT_BYTE(0); 37.174 if (uc < 0x80) return INVALID_CHAR; // overlong 37.175 return uc; 37.176 } 37.177 else if ((c & 0xF0) == 0xE0) 37.178 { 37.179 // Three-byte sequence. 37.180 FIRST_BYTE(0x0F, 12); 37.181 NEXT_BYTE(6); 37.182 NEXT_BYTE(0); 37.183 if (uc < 0x800) return INVALID_CHAR; // overlong 37.184 // Not valid ISO 10646, but Flash requires these to work 37.185 // see AS3 test e15_5_3_2_3 for String.fromCharCode().charCodeAt(0) 37.186 // if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID_CHAR; 37.187 // if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID_CHAR; // not valid ISO 10646 37.188 return uc; 37.189 } 37.190 else if ((c & 0xF8) == 0xF0) 37.191 { 37.192 // Four-byte sequence. 37.193 FIRST_BYTE(0x07, 18); 37.194 NEXT_BYTE(12); 37.195 NEXT_BYTE(6); 37.196 NEXT_BYTE(0); 37.197 if (uc < 0x010000) return INVALID_CHAR; // overlong 37.198 return uc; 37.199 } 37.200 else if ((c & 0xFC) == 0xF8) 37.201 { 37.202 // Five-byte sequence. 37.203 FIRST_BYTE(0x03, 24); 37.204 NEXT_BYTE(18); 37.205 NEXT_BYTE(12); 37.206 NEXT_BYTE(6); 37.207 NEXT_BYTE(0); 37.208 if (uc < 0x0200000) return INVALID_CHAR; // overlong 37.209 return uc; 37.210 } 37.211 else if ((c & 0xFE) == 0xFC) 37.212 { 37.213 // Six-byte sequence. 37.214 FIRST_BYTE(0x01, 30); 37.215 NEXT_BYTE(24); 37.216 NEXT_BYTE(18); 37.217 NEXT_BYTE(12); 37.218 NEXT_BYTE(6); 37.219 NEXT_BYTE(0); 37.220 if (uc < 0x04000000) return INVALID_CHAR; // overlong 37.221 return uc; 37.222 } 37.223 else 37.224 { 37.225 // Invalid. 37.226 return INVALID_CHAR; 37.227 } 37.228 } 37.229 37.230 37.231 void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) 37.232 { 37.233 if (ucs_character <= 0x7F) 37.234 { 37.235 // Plain single-byte ASCII. 37.236 pbuffer[(*pindex)++] = (char) ucs_character; 37.237 } 37.238 else if (ucs_character <= 0x7FF) 37.239 { 37.240 // Two bytes. 37.241 pbuffer[(*pindex)++] = 0xC0 | (char)(ucs_character >> 6); 37.242 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.243 } 37.244 else if (ucs_character <= 0xFFFF) 37.245 { 37.246 // Three bytes. 37.247 pbuffer[(*pindex)++] = 0xE0 | (char)(ucs_character >> 12); 37.248 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.249 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.250 } 37.251 else if (ucs_character <= 0x1FFFFF) 37.252 { 37.253 // Four bytes. 37.254 pbuffer[(*pindex)++] = 0xF0 | (char)(ucs_character >> 18); 37.255 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.256 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.257 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.258 } 37.259 else if (ucs_character <= 0x3FFFFFF) 37.260 { 37.261 // Five bytes. 37.262 pbuffer[(*pindex)++] = 0xF8 | (char)(ucs_character >> 24); 37.263 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F); 37.264 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.265 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.266 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.267 } 37.268 else if (ucs_character <= 0x7FFFFFFF) 37.269 { 37.270 // Six bytes. 37.271 pbuffer[(*pindex)++] = 0xFC | (char)(ucs_character >> 30); 37.272 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 24) & 0x3F); 37.273 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F); 37.274 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.275 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.276 pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.277 } 37.278 else 37.279 { 37.280 // Invalid char; don't encode anything. 37.281 } 37.282 } 37.283 37.284 SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) 37.285 { 37.286 SPInt len = 0; 37.287 if (length != -1) 37.288 for (int i = 0; i < length; i++) 37.289 { 37.290 len += GetEncodeCharSize(pchar[i]); 37.291 } 37.292 else 37.293 for (int i = 0;; i++) 37.294 { 37.295 if (pchar[i] == 0) 37.296 return len; 37.297 len += GetEncodeCharSize(pchar[i]); 37.298 } 37.299 return len; 37.300 } 37.301 37.302 void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) 37.303 { 37.304 SPInt ofs = 0; 37.305 if (length != -1) 37.306 { 37.307 for (int i = 0; i < length; i++) 37.308 { 37.309 EncodeChar(pbuff, &ofs, pchar[i]); 37.310 } 37.311 } 37.312 else 37.313 { 37.314 for (int i = 0;; i++) 37.315 { 37.316 if (pchar[i] == 0) 37.317 break; 37.318 EncodeChar(pbuff, &ofs, pchar[i]); 37.319 } 37.320 } 37.321 pbuff[ofs] = 0; 37.322 } 37.323 37.324 UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen) 37.325 { 37.326 wchar_t *pbegin = pbuff; 37.327 if (bytesLen == -1) 37.328 { 37.329 while (1) 37.330 { 37.331 UInt32 ch = DecodeNextChar_Advance0(&putf8str); 37.332 if (ch == 0) 37.333 break; 37.334 else if (ch >= 0xFFFF) 37.335 ch = 0xFFFD; 37.336 *pbuff++ = wchar_t(ch); 37.337 } 37.338 } 37.339 else 37.340 { 37.341 const char* p = putf8str; 37.342 while ((p - putf8str) < bytesLen) 37.343 { 37.344 UInt32 ch = DecodeNextChar_Advance0(&p); 37.345 if (ch >= 0xFFFF) 37.346 ch = 0xFFFD; 37.347 *pbuff++ = wchar_t(ch); 37.348 } 37.349 } 37.350 37.351 *pbuff = 0; 37.352 return pbuff - pbegin; 37.353 } 37.354 37.355 37.356 #ifdef UTF8_UNIT_TEST 37.357 37.358 // Compile this test case with something like: 37.359 // 37.360 // gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test 37.361 // 37.362 // or 37.363 // 37.364 // cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I.. 37.365 // 37.366 // If possible, try running the test program with the first arg 37.367 // pointing at the file: 37.368 // 37.369 // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 37.370 // 37.371 // and examine the results by eye to make sure they are acceptable to 37.372 // you. 37.373 37.374 37.375 #include "base/utility.h" 37.376 #include <stdio.h> 37.377 37.378 37.379 bool check_equal(const char* utf8_in, const UInt32* ucs_in) 37.380 { 37.381 for (;;) 37.382 { 37.383 UInt32 next_ucs = *ucs_in++; 37.384 UInt32 next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); 37.385 if (next_ucs != next_ucs_from_utf8) 37.386 { 37.387 return false; 37.388 } 37.389 if (next_ucs == 0) 37.390 { 37.391 OVR_ASSERT(next_ucs_from_utf8 == 0); 37.392 break; 37.393 } 37.394 } 37.395 37.396 return true; 37.397 } 37.398 37.399 37.400 void log_ascii(const char* line) 37.401 { 37.402 for (;;) 37.403 { 37.404 unsigned char c = (unsigned char) *line++; 37.405 if (c == 0) 37.406 { 37.407 // End of line. 37.408 return; 37.409 } 37.410 else if (c != '\n' 37.411 && (c < 32 || c > 127)) 37.412 { 37.413 // Non-printable as plain ASCII. 37.414 printf("<0x%02X>", (int) c); 37.415 } 37.416 else 37.417 { 37.418 printf("%c", c); 37.419 } 37.420 } 37.421 } 37.422 37.423 37.424 void log_ucs(const UInt32* line) 37.425 { 37.426 for (;;) 37.427 { 37.428 UInt32 uc = *line++; 37.429 if (uc == 0) 37.430 { 37.431 // End of line. 37.432 return; 37.433 } 37.434 else if (uc != '\n' 37.435 && (uc < 32 || uc > 127)) 37.436 { 37.437 // Non-printable as plain ASCII. 37.438 printf("<U-%04X>", uc); 37.439 } 37.440 else 37.441 { 37.442 printf("%c", (char) uc); 37.443 } 37.444 } 37.445 } 37.446 37.447 37.448 // Simple canned test. 37.449 int main(int argc, const char* argv[]) 37.450 { 37.451 { 37.452 const char* test8 = "Ignacio Castaño"; 37.453 const UInt32 test32[] = 37.454 { 37.455 0x49, 0x67, 0x6E, 0x61, 0x63, 37.456 0x69, 0x6F, 0x20, 0x43, 0x61, 37.457 0x73, 0x74, 0x61, 0xF1, 0x6F, 37.458 0x00 37.459 }; 37.460 37.461 OVR_ASSERT(check_equal(test8, test32)); 37.462 } 37.463 37.464 // If user passed an arg, try reading the file as UTF-8 encoded text. 37.465 if (argc > 1) 37.466 { 37.467 const char* filename = argv[1]; 37.468 FILE* fp = fopen(filename, "rb"); 37.469 if (fp == NULL) 37.470 { 37.471 printf("Can't open file '%s'\n", filename); 37.472 return 1; 37.473 } 37.474 37.475 // Read lines from the file, encode/decode them, and highlight discrepancies. 37.476 const int LINE_SIZE = 200; // max line size 37.477 char line_buffer_utf8[LINE_SIZE]; 37.478 char reencoded_utf8[6 * LINE_SIZE]; 37.479 UInt32 line_buffer_ucs[LINE_SIZE]; 37.480 37.481 int byte_counter = 0; 37.482 for (;;) 37.483 { 37.484 int c = fgetc(fp); 37.485 if (c == EOF) 37.486 { 37.487 // Done. 37.488 break; 37.489 } 37.490 line_buffer_utf8[byte_counter++] = c; 37.491 if (c == '\n' || byte_counter >= LINE_SIZE - 2) 37.492 { 37.493 // End of line. Process the line. 37.494 line_buffer_utf8[byte_counter++] = 0; // terminate. 37.495 37.496 // Decode into UCS. 37.497 const char* p = line_buffer_utf8; 37.498 UInt32* q = line_buffer_ucs; 37.499 for (;;) 37.500 { 37.501 UInt32 uc = UTF8Util::DecodeNextChar(&p); 37.502 *q++ = uc; 37.503 37.504 OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE); 37.505 OVR_ASSERT(p < line_buffer_utf8 + LINE_SIZE); 37.506 37.507 if (uc == 0) break; 37.508 } 37.509 37.510 // Encode back into UTF-8. 37.511 q = line_buffer_ucs; 37.512 int index = 0; 37.513 for (;;) 37.514 { 37.515 UInt32 uc = *q++; 37.516 OVR_ASSERT(index < LINE_SIZE * 6 - 6); 37.517 int last_index = index; 37.518 UTF8Util::EncodeChar(reencoded_utf8, &index, uc); 37.519 OVR_ASSERT(index <= last_index + 6); 37.520 if (uc == 0) break; 37.521 } 37.522 37.523 // This can be useful for debugging. 37.524 #if 0 37.525 // Show the UCS and the re-encoded UTF-8. 37.526 log_ucs(line_buffer_ucs); 37.527 log_ascii(reencoded_utf8); 37.528 #endif // 0 37.529 37.530 OVR_ASSERT(check_equal(line_buffer_utf8, line_buffer_ucs)); 37.531 OVR_ASSERT(check_equal(reencoded_utf8, line_buffer_ucs)); 37.532 37.533 // Start next line. 37.534 byte_counter = 0; 37.535 } 37.536 } 37.537 37.538 fclose(fp); 37.539 } 37.540 37.541 return 0; 37.542 } 37.543 37.544 37.545 #endif // UTF8_UNIT_TEST 37.546 37.547 }} // namespace UTF8Util::OVR 37.548 37.549 \ No newline at end of file 37.550 +/************************************************************************** 37.551 + 37.552 +Filename : OVR_UTF8Util.cpp 37.553 +Content : UTF8 Unicode character encoding/decoding support 37.554 +Created : September 19, 2012 37.555 +Notes : 37.556 +Notes : Much useful info at "UTF-8 and Unicode FAQ" 37.557 + http://www.cl.cam.ac.uk/~mgk25/unicode.html 37.558 + 37.559 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 37.560 + 37.561 +Use of this software is subject to the terms of the Oculus license 37.562 +agreement provided at the time of installation or download, or which 37.563 +otherwise accompanies this software in either electronic or hard copy form. 37.564 + 37.565 +************************************************************************************/ 37.566 + 37.567 +#include "OVR_UTF8Util.h" 37.568 + 37.569 +namespace OVR { namespace UTF8Util { 37.570 + 37.571 +SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen) 37.572 +{ 37.573 + const char* p = buf; 37.574 + SPInt length = 0; 37.575 + 37.576 + if (buflen != -1) 37.577 + { 37.578 + while (p - buf < buflen) 37.579 + { 37.580 + // We should be able to have ASStrings with 0 in the middle. 37.581 + UTF8Util::DecodeNextChar_Advance0(&p); 37.582 + length++; 37.583 + } 37.584 + } 37.585 + else 37.586 + { 37.587 + while (UTF8Util::DecodeNextChar_Advance0(&p)) 37.588 + length++; 37.589 + } 37.590 + 37.591 + return length; 37.592 +} 37.593 + 37.594 +UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length) 37.595 +{ 37.596 + const char* buf = putf8str; 37.597 + UInt32 c = 0; 37.598 + 37.599 + if (length != -1) 37.600 + { 37.601 + while (buf - putf8str < length) 37.602 + { 37.603 + c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.604 + if (index == 0) 37.605 + return c; 37.606 + index--; 37.607 + } 37.608 + 37.609 + return c; 37.610 + } 37.611 + 37.612 + do 37.613 + { 37.614 + c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.615 + index--; 37.616 + 37.617 + if (c == 0) 37.618 + { 37.619 + // We've hit the end of the string; don't go further. 37.620 + OVR_ASSERT(index == 0); 37.621 + return c; 37.622 + } 37.623 + } while (index >= 0); 37.624 + 37.625 + return c; 37.626 +} 37.627 + 37.628 +SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length) 37.629 +{ 37.630 + const char* buf = putf8str; 37.631 + 37.632 + if (length != -1) 37.633 + { 37.634 + while ((buf - putf8str) < length && index > 0) 37.635 + { 37.636 + UTF8Util::DecodeNextChar_Advance0(&buf); 37.637 + index--; 37.638 + } 37.639 + 37.640 + return buf-putf8str; 37.641 + } 37.642 + 37.643 + while (index > 0) 37.644 + { 37.645 + UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf); 37.646 + index--; 37.647 + 37.648 + if (c == 0) 37.649 + return buf-putf8str; 37.650 + }; 37.651 + 37.652 + return buf-putf8str; 37.653 +} 37.654 + 37.655 +int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character) 37.656 +{ 37.657 + if (ucs_character <= 0x7F) 37.658 + return 1; 37.659 + else if (ucs_character <= 0x7FF) 37.660 + return 2; 37.661 + else if (ucs_character <= 0xFFFF) 37.662 + return 3; 37.663 + else if (ucs_character <= 0x1FFFFF) 37.664 + return 4; 37.665 + else if (ucs_character <= 0x3FFFFFF) 37.666 + return 5; 37.667 + else if (ucs_character <= 0x7FFFFFFF) 37.668 + return 6; 37.669 + else 37.670 + return 0; 37.671 +} 37.672 + 37.673 +UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer) 37.674 +{ 37.675 + UInt32 uc; 37.676 + char c; 37.677 + 37.678 + // Security considerations: 37.679 + // 37.680 + // Changed, this is now only the case for DecodeNextChar: 37.681 + // - If we hit a zero byte, we want to return 0 without stepping 37.682 + // the buffer pointer past the 0. th 37.683 + // 37.684 + // If we hit an "overlong sequence"; i.e. a character encoded 37.685 + // in a longer multibyte string than is necessary, then we 37.686 + // need to discard the character. This is so attackers can't 37.687 + // disguise dangerous characters or character sequences -- 37.688 + // there is only one valid encoding for each character. 37.689 + // 37.690 + // If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE, 37.691 + // 0xFFFF } then we ignore them; they are not valid in UTF-8. 37.692 + 37.693 + // This isn't actually an invalid character; it's a valid char that 37.694 + // looks like an inverted question mark. 37.695 +#define INVALID_CHAR 0x0FFFD 37.696 + 37.697 +#define FIRST_BYTE(mask, shift) \ 37.698 + uc = (c & (mask)) << (shift); 37.699 + 37.700 +#define NEXT_BYTE(shift) \ 37.701 + c = **putf8Buffer; \ 37.702 + if (c == 0) return 0; /* end of buffer, do not advance */ \ 37.703 + if ((c & 0xC0) != 0x80) return INVALID_CHAR; /* standard check */ \ 37.704 + (*putf8Buffer)++; \ 37.705 + uc |= (c & 0x3F) << shift; 37.706 + 37.707 + c = **putf8Buffer; 37.708 + (*putf8Buffer)++; 37.709 + if (c == 0) 37.710 + return 0; // End of buffer. 37.711 + 37.712 + if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII. 37.713 + 37.714 + // Multi-byte sequences. 37.715 + if ((c & 0xE0) == 0xC0) 37.716 + { 37.717 + // Two-byte sequence. 37.718 + FIRST_BYTE(0x1F, 6); 37.719 + NEXT_BYTE(0); 37.720 + if (uc < 0x80) return INVALID_CHAR; // overlong 37.721 + return uc; 37.722 + } 37.723 + else if ((c & 0xF0) == 0xE0) 37.724 + { 37.725 + // Three-byte sequence. 37.726 + FIRST_BYTE(0x0F, 12); 37.727 + NEXT_BYTE(6); 37.728 + NEXT_BYTE(0); 37.729 + if (uc < 0x800) return INVALID_CHAR; // overlong 37.730 + // Not valid ISO 10646, but Flash requires these to work 37.731 + // see AS3 test e15_5_3_2_3 for String.fromCharCode().charCodeAt(0) 37.732 + // if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID_CHAR; 37.733 + // if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID_CHAR; // not valid ISO 10646 37.734 + return uc; 37.735 + } 37.736 + else if ((c & 0xF8) == 0xF0) 37.737 + { 37.738 + // Four-byte sequence. 37.739 + FIRST_BYTE(0x07, 18); 37.740 + NEXT_BYTE(12); 37.741 + NEXT_BYTE(6); 37.742 + NEXT_BYTE(0); 37.743 + if (uc < 0x010000) return INVALID_CHAR; // overlong 37.744 + return uc; 37.745 + } 37.746 + else if ((c & 0xFC) == 0xF8) 37.747 + { 37.748 + // Five-byte sequence. 37.749 + FIRST_BYTE(0x03, 24); 37.750 + NEXT_BYTE(18); 37.751 + NEXT_BYTE(12); 37.752 + NEXT_BYTE(6); 37.753 + NEXT_BYTE(0); 37.754 + if (uc < 0x0200000) return INVALID_CHAR; // overlong 37.755 + return uc; 37.756 + } 37.757 + else if ((c & 0xFE) == 0xFC) 37.758 + { 37.759 + // Six-byte sequence. 37.760 + FIRST_BYTE(0x01, 30); 37.761 + NEXT_BYTE(24); 37.762 + NEXT_BYTE(18); 37.763 + NEXT_BYTE(12); 37.764 + NEXT_BYTE(6); 37.765 + NEXT_BYTE(0); 37.766 + if (uc < 0x04000000) return INVALID_CHAR; // overlong 37.767 + return uc; 37.768 + } 37.769 + else 37.770 + { 37.771 + // Invalid. 37.772 + return INVALID_CHAR; 37.773 + } 37.774 +} 37.775 + 37.776 + 37.777 +void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character) 37.778 +{ 37.779 + if (ucs_character <= 0x7F) 37.780 + { 37.781 + // Plain single-byte ASCII. 37.782 + pbuffer[(*pindex)++] = (char) ucs_character; 37.783 + } 37.784 + else if (ucs_character <= 0x7FF) 37.785 + { 37.786 + // Two bytes. 37.787 + pbuffer[(*pindex)++] = 0xC0 | (char)(ucs_character >> 6); 37.788 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.789 + } 37.790 + else if (ucs_character <= 0xFFFF) 37.791 + { 37.792 + // Three bytes. 37.793 + pbuffer[(*pindex)++] = 0xE0 | (char)(ucs_character >> 12); 37.794 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.795 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.796 + } 37.797 + else if (ucs_character <= 0x1FFFFF) 37.798 + { 37.799 + // Four bytes. 37.800 + pbuffer[(*pindex)++] = 0xF0 | (char)(ucs_character >> 18); 37.801 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.802 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.803 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.804 + } 37.805 + else if (ucs_character <= 0x3FFFFFF) 37.806 + { 37.807 + // Five bytes. 37.808 + pbuffer[(*pindex)++] = 0xF8 | (char)(ucs_character >> 24); 37.809 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F); 37.810 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.811 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.812 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.813 + } 37.814 + else if (ucs_character <= 0x7FFFFFFF) 37.815 + { 37.816 + // Six bytes. 37.817 + pbuffer[(*pindex)++] = 0xFC | (char)(ucs_character >> 30); 37.818 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 24) & 0x3F); 37.819 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F); 37.820 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F); 37.821 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F); 37.822 + pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F); 37.823 + } 37.824 + else 37.825 + { 37.826 + // Invalid char; don't encode anything. 37.827 + } 37.828 +} 37.829 + 37.830 +SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length) 37.831 +{ 37.832 + SPInt len = 0; 37.833 + if (length != -1) 37.834 + for (int i = 0; i < length; i++) 37.835 + { 37.836 + len += GetEncodeCharSize(pchar[i]); 37.837 + } 37.838 + else 37.839 + for (int i = 0;; i++) 37.840 + { 37.841 + if (pchar[i] == 0) 37.842 + return len; 37.843 + len += GetEncodeCharSize(pchar[i]); 37.844 + } 37.845 + return len; 37.846 +} 37.847 + 37.848 +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length) 37.849 +{ 37.850 + SPInt ofs = 0; 37.851 + if (length != -1) 37.852 + { 37.853 + for (int i = 0; i < length; i++) 37.854 + { 37.855 + EncodeChar(pbuff, &ofs, pchar[i]); 37.856 + } 37.857 + } 37.858 + else 37.859 + { 37.860 + for (int i = 0;; i++) 37.861 + { 37.862 + if (pchar[i] == 0) 37.863 + break; 37.864 + EncodeChar(pbuff, &ofs, pchar[i]); 37.865 + } 37.866 + } 37.867 + pbuff[ofs] = 0; 37.868 +} 37.869 + 37.870 +UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen) 37.871 +{ 37.872 + wchar_t *pbegin = pbuff; 37.873 + if (bytesLen == -1) 37.874 + { 37.875 + while (1) 37.876 + { 37.877 + UInt32 ch = DecodeNextChar_Advance0(&putf8str); 37.878 + if (ch == 0) 37.879 + break; 37.880 + else if (ch >= 0xFFFF) 37.881 + ch = 0xFFFD; 37.882 + *pbuff++ = wchar_t(ch); 37.883 + } 37.884 + } 37.885 + else 37.886 + { 37.887 + const char* p = putf8str; 37.888 + while ((p - putf8str) < bytesLen) 37.889 + { 37.890 + UInt32 ch = DecodeNextChar_Advance0(&p); 37.891 + if (ch >= 0xFFFF) 37.892 + ch = 0xFFFD; 37.893 + *pbuff++ = wchar_t(ch); 37.894 + } 37.895 + } 37.896 + 37.897 + *pbuff = 0; 37.898 + return pbuff - pbegin; 37.899 +} 37.900 + 37.901 + 37.902 +#ifdef UTF8_UNIT_TEST 37.903 + 37.904 +// Compile this test case with something like: 37.905 +// 37.906 +// gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test 37.907 +// 37.908 +// or 37.909 +// 37.910 +// cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I.. 37.911 +// 37.912 +// If possible, try running the test program with the first arg 37.913 +// pointing at the file: 37.914 +// 37.915 +// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 37.916 +// 37.917 +// and examine the results by eye to make sure they are acceptable to 37.918 +// you. 37.919 + 37.920 + 37.921 +#include "base/utility.h" 37.922 +#include <stdio.h> 37.923 + 37.924 + 37.925 +bool check_equal(const char* utf8_in, const UInt32* ucs_in) 37.926 +{ 37.927 + for (;;) 37.928 + { 37.929 + UInt32 next_ucs = *ucs_in++; 37.930 + UInt32 next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in); 37.931 + if (next_ucs != next_ucs_from_utf8) 37.932 + { 37.933 + return false; 37.934 + } 37.935 + if (next_ucs == 0) 37.936 + { 37.937 + OVR_ASSERT(next_ucs_from_utf8 == 0); 37.938 + break; 37.939 + } 37.940 + } 37.941 + 37.942 + return true; 37.943 +} 37.944 + 37.945 + 37.946 +void log_ascii(const char* line) 37.947 +{ 37.948 + for (;;) 37.949 + { 37.950 + unsigned char c = (unsigned char) *line++; 37.951 + if (c == 0) 37.952 + { 37.953 + // End of line. 37.954 + return; 37.955 + } 37.956 + else if (c != '\n' 37.957 + && (c < 32 || c > 127)) 37.958 + { 37.959 + // Non-printable as plain ASCII. 37.960 + printf("<0x%02X>", (int) c); 37.961 + } 37.962 + else 37.963 + { 37.964 + printf("%c", c); 37.965 + } 37.966 + } 37.967 +} 37.968 + 37.969 + 37.970 +void log_ucs(const UInt32* line) 37.971 +{ 37.972 + for (;;) 37.973 + { 37.974 + UInt32 uc = *line++; 37.975 + if (uc == 0) 37.976 + { 37.977 + // End of line. 37.978 + return; 37.979 + } 37.980 + else if (uc != '\n' 37.981 + && (uc < 32 || uc > 127)) 37.982 + { 37.983 + // Non-printable as plain ASCII. 37.984 + printf("<U-%04X>", uc); 37.985 + } 37.986 + else 37.987 + { 37.988 + printf("%c", (char) uc); 37.989 + } 37.990 + } 37.991 +} 37.992 + 37.993 + 37.994 +// Simple canned test. 37.995 +int main(int argc, const char* argv[]) 37.996 +{ 37.997 + { 37.998 + const char* test8 = "Ignacio Castaño"; 37.999 + const UInt32 test32[] = 37.1000 + { 37.1001 + 0x49, 0x67, 0x6E, 0x61, 0x63, 37.1002 + 0x69, 0x6F, 0x20, 0x43, 0x61, 37.1003 + 0x73, 0x74, 0x61, 0xF1, 0x6F, 37.1004 + 0x00 37.1005 + }; 37.1006 + 37.1007 + OVR_ASSERT(check_equal(test8, test32)); 37.1008 + } 37.1009 + 37.1010 + // If user passed an arg, try reading the file as UTF-8 encoded text. 37.1011 + if (argc > 1) 37.1012 + { 37.1013 + const char* filename = argv[1]; 37.1014 + FILE* fp = fopen(filename, "rb"); 37.1015 + if (fp == NULL) 37.1016 + { 37.1017 + printf("Can't open file '%s'\n", filename); 37.1018 + return 1; 37.1019 + } 37.1020 + 37.1021 + // Read lines from the file, encode/decode them, and highlight discrepancies. 37.1022 + const int LINE_SIZE = 200; // max line size 37.1023 + char line_buffer_utf8[LINE_SIZE]; 37.1024 + char reencoded_utf8[6 * LINE_SIZE]; 37.1025 + UInt32 line_buffer_ucs[LINE_SIZE]; 37.1026 + 37.1027 + int byte_counter = 0; 37.1028 + for (;;) 37.1029 + { 37.1030 + int c = fgetc(fp); 37.1031 + if (c == EOF) 37.1032 + { 37.1033 + // Done. 37.1034 + break; 37.1035 + } 37.1036 + line_buffer_utf8[byte_counter++] = c; 37.1037 + if (c == '\n' || byte_counter >= LINE_SIZE - 2) 37.1038 + { 37.1039 + // End of line. Process the line. 37.1040 + line_buffer_utf8[byte_counter++] = 0; // terminate. 37.1041 + 37.1042 + // Decode into UCS. 37.1043 + const char* p = line_buffer_utf8; 37.1044 + UInt32* q = line_buffer_ucs; 37.1045 + for (;;) 37.1046 + { 37.1047 + UInt32 uc = UTF8Util::DecodeNextChar(&p); 37.1048 + *q++ = uc; 37.1049 + 37.1050 + OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE); 37.1051 + OVR_ASSERT(p < line_buffer_utf8 + LINE_SIZE); 37.1052 + 37.1053 + if (uc == 0) break; 37.1054 + } 37.1055 + 37.1056 + // Encode back into UTF-8. 37.1057 + q = line_buffer_ucs; 37.1058 + int index = 0; 37.1059 + for (;;) 37.1060 + { 37.1061 + UInt32 uc = *q++; 37.1062 + OVR_ASSERT(index < LINE_SIZE * 6 - 6); 37.1063 + int last_index = index; 37.1064 + UTF8Util::EncodeChar(reencoded_utf8, &index, uc); 37.1065 + OVR_ASSERT(index <= last_index + 6); 37.1066 + if (uc == 0) break; 37.1067 + } 37.1068 + 37.1069 + // This can be useful for debugging. 37.1070 +#if 0 37.1071 + // Show the UCS and the re-encoded UTF-8. 37.1072 + log_ucs(line_buffer_ucs); 37.1073 + log_ascii(reencoded_utf8); 37.1074 +#endif // 0 37.1075 + 37.1076 + OVR_ASSERT(check_equal(line_buffer_utf8, line_buffer_ucs)); 37.1077 + OVR_ASSERT(check_equal(reencoded_utf8, line_buffer_ucs)); 37.1078 + 37.1079 + // Start next line. 37.1080 + byte_counter = 0; 37.1081 + } 37.1082 + } 37.1083 + 37.1084 + fclose(fp); 37.1085 + } 37.1086 + 37.1087 + return 0; 37.1088 +} 37.1089 + 37.1090 + 37.1091 +#endif // UTF8_UNIT_TEST 37.1092 + 37.1093 +}} // namespace UTF8Util::OVR 37.1094 +
38.1 --- a/libovr/Src/Kernel/OVR_UTF8Util.h Sat Sep 14 17:51:03 2013 +0300 38.2 +++ b/libovr/Src/Kernel/OVR_UTF8Util.h Sun Sep 15 04:10:05 2013 +0300 38.3 @@ -1,1 +1,88 @@ 38.4 -/************************************************************************************ 38.5 38.6 PublicHeader: OVR.h 38.7 Filename : OVR_UTF8Util.h 38.8 Content : UTF8 Unicode character encoding/decoding support 38.9 Created : September 19, 2012 38.10 Notes : 38.11 38.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 38.13 38.14 Use of this software is subject to the terms of the Oculus license 38.15 agreement provided at the time of installation or download, or which 38.16 otherwise accompanies this software in either electronic or hard copy form. 38.17 38.18 ************************************************************************************/ 38.19 38.20 #ifndef OVR_UTF8Util_h 38.21 #define OVR_UTF8Util_h 38.22 38.23 #include "OVR_Types.h" 38.24 38.25 namespace OVR { namespace UTF8Util { 38.26 38.27 //----------------------------------------------------------------------------------- 38.28 38.29 // *** UTF8 string length and indexing. 38.30 38.31 // Determines the length of UTF8 string in characters. 38.32 // If source length is specified (in bytes), null 0 character is counted properly. 38.33 SPInt OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1); 38.34 38.35 // Gets a decoded UTF8 character at index; you can access up to the index returned 38.36 // by GetLength. 0 will be returned for out of bounds access. 38.37 UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1); 38.38 38.39 // Converts UTF8 character index into byte offset. 38.40 // -1 is returned if index was out of bounds. 38.41 SPInt OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1); 38.42 38.43 38.44 // *** 16-bit Unicode string Encoding/Decoding routines. 38.45 38.46 // Determines the number of bytes necessary to encode a string. 38.47 // Does not count the terminating 0 (null) character. 38.48 SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1); 38.49 38.50 // Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at 38.51 // least GetEncodeStringSize() + 1. 38.52 void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1); 38.53 38.54 // Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available. 38.55 // Characters over 0xFFFF are replaced with 0xFFFD. 38.56 // Returns the length of resulting string (number of characters) 38.57 UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1); 38.58 38.59 38.60 // *** Individual character Encoding/Decoding. 38.61 38.62 // Determined the number of bytes necessary to encode a UCS character. 38.63 int OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter); 38.64 38.65 // Encodes the given UCS character into the given UTF-8 buffer. 38.66 // Writes the data starting at buffer[offset], and 38.67 // increments offset by the number of bytes written. 38.68 // May write up to 6 bytes, so make sure there's room in the buffer 38.69 void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter); 38.70 38.71 // Return the next Unicode character in the UTF-8 encoded buffer. 38.72 // Invalid UTF-8 sequences produce a U+FFFD character as output. 38.73 // Advances *utf8_buffer past the character returned. Pointer advance 38.74 // occurs even if the terminating 0 character is hit, since that allows 38.75 // strings with middle '\0' characters to be supported. 38.76 UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); 38.77 38.78 // Safer version of DecodeNextChar, which doesn't advance pointer if 38.79 // null character is hit. 38.80 inline UInt32 DecodeNextChar(const char** putf8Buffer) 38.81 { 38.82 UInt32 ch = DecodeNextChar_Advance0(putf8Buffer); 38.83 if (ch == 0) 38.84 (*putf8Buffer)--; 38.85 return ch; 38.86 } 38.87 38.88 38.89 }} // OVR::UTF8Util 38.90 38.91 #endif 38.92 \ No newline at end of file 38.93 +/************************************************************************************ 38.94 + 38.95 +PublicHeader: OVR.h 38.96 +Filename : OVR_UTF8Util.h 38.97 +Content : UTF8 Unicode character encoding/decoding support 38.98 +Created : September 19, 2012 38.99 +Notes : 38.100 + 38.101 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 38.102 + 38.103 +Use of this software is subject to the terms of the Oculus license 38.104 +agreement provided at the time of installation or download, or which 38.105 +otherwise accompanies this software in either electronic or hard copy form. 38.106 + 38.107 +************************************************************************************/ 38.108 + 38.109 +#ifndef OVR_UTF8Util_h 38.110 +#define OVR_UTF8Util_h 38.111 + 38.112 +#include "OVR_Types.h" 38.113 + 38.114 +namespace OVR { namespace UTF8Util { 38.115 + 38.116 +//----------------------------------------------------------------------------------- 38.117 + 38.118 +// *** UTF8 string length and indexing. 38.119 + 38.120 +// Determines the length of UTF8 string in characters. 38.121 +// If source length is specified (in bytes), null 0 character is counted properly. 38.122 +SPInt OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1); 38.123 + 38.124 +// Gets a decoded UTF8 character at index; you can access up to the index returned 38.125 +// by GetLength. 0 will be returned for out of bounds access. 38.126 +UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1); 38.127 + 38.128 +// Converts UTF8 character index into byte offset. 38.129 +// -1 is returned if index was out of bounds. 38.130 +SPInt OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1); 38.131 + 38.132 + 38.133 +// *** 16-bit Unicode string Encoding/Decoding routines. 38.134 + 38.135 +// Determines the number of bytes necessary to encode a string. 38.136 +// Does not count the terminating 0 (null) character. 38.137 +SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1); 38.138 + 38.139 +// Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at 38.140 +// least GetEncodeStringSize() + 1. 38.141 +void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1); 38.142 + 38.143 +// Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available. 38.144 +// Characters over 0xFFFF are replaced with 0xFFFD. 38.145 +// Returns the length of resulting string (number of characters) 38.146 +UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1); 38.147 + 38.148 + 38.149 +// *** Individual character Encoding/Decoding. 38.150 + 38.151 +// Determined the number of bytes necessary to encode a UCS character. 38.152 +int OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter); 38.153 + 38.154 +// Encodes the given UCS character into the given UTF-8 buffer. 38.155 +// Writes the data starting at buffer[offset], and 38.156 +// increments offset by the number of bytes written. 38.157 +// May write up to 6 bytes, so make sure there's room in the buffer 38.158 +void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter); 38.159 + 38.160 +// Return the next Unicode character in the UTF-8 encoded buffer. 38.161 +// Invalid UTF-8 sequences produce a U+FFFD character as output. 38.162 +// Advances *utf8_buffer past the character returned. Pointer advance 38.163 +// occurs even if the terminating 0 character is hit, since that allows 38.164 +// strings with middle '\0' characters to be supported. 38.165 +UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer); 38.166 + 38.167 +// Safer version of DecodeNextChar, which doesn't advance pointer if 38.168 +// null character is hit. 38.169 +inline UInt32 DecodeNextChar(const char** putf8Buffer) 38.170 +{ 38.171 + UInt32 ch = DecodeNextChar_Advance0(putf8Buffer); 38.172 + if (ch == 0) 38.173 + (*putf8Buffer)--; 38.174 + return ch; 38.175 +} 38.176 + 38.177 + 38.178 +}} // OVR::UTF8Util 38.179 + 38.180 +#endif
39.1 --- a/libovr/Src/Util/Util_LatencyTest.cpp Sat Sep 14 17:51:03 2013 +0300 39.2 +++ b/libovr/Src/Util/Util_LatencyTest.cpp Sun Sep 15 04:10:05 2013 +0300 39.3 @@ -1,1 +1,571 @@ 39.4 -/************************************************************************************ 39.5 39.6 Filename : Util_LatencyTest.cpp 39.7 Content : Wraps the lower level LatencyTester interface and adds functionality. 39.8 Created : February 14, 2013 39.9 Authors : Lee Cooper 39.10 39.11 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 39.12 39.13 Use of this software is subject to the terms of the Oculus license 39.14 agreement provided at the time of installation or download, or which 39.15 otherwise accompanies this software in either electronic or hard copy form. 39.16 39.17 *************************************************************************************/ 39.18 39.19 #include "Util_LatencyTest.h" 39.20 39.21 #include "../Kernel/OVR_Log.h" 39.22 #include "../Kernel/OVR_Timer.h" 39.23 39.24 namespace OVR { namespace Util { 39.25 39.26 static const UInt32 TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION = 16*10; 39.27 static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION = 16*10; 39.28 static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT = 16*5; 39.29 static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS = 16*5; 39.30 static const UInt32 DEFAULT_NUMBER_OF_SAMPLES = 10; // For both color 1->2 and color 2->1 transitions. 39.31 static const UInt32 INITIAL_SAMPLES_TO_IGNORE = 4; 39.32 static const UInt32 TIMEOUT_WAITING_FOR_TEST_STARTED = 1000; 39.33 static const UInt32 TIMEOUT_WAITING_FOR_COLOR_DETECTED = 4000; 39.34 static const Color CALIBRATE_BLACK(0, 0, 0); 39.35 static const Color CALIBRATE_WHITE(255, 255, 255); 39.36 static const Color COLOR1(0, 0, 0); 39.37 static const Color COLOR2(255, 255, 255); 39.38 static const Color SENSOR_DETECT_THRESHOLD(128, 255, 255); 39.39 static const float BIG_FLOAT = 1000000.0f; 39.40 static const float SMALL_FLOAT = -1000000.0f; 39.41 39.42 //------------------------------------------------------------------------------------- 39.43 // ***** LatencyTest 39.44 39.45 LatencyTest::LatencyTest(LatencyTestDevice* device) 39.46 : Handler(getThis()) 39.47 { 39.48 if (device != NULL) 39.49 { 39.50 SetDevice(device); 39.51 } 39.52 39.53 reset(); 39.54 39.55 srand(Timer::GetTicksMs()); 39.56 } 39.57 39.58 LatencyTest::~LatencyTest() 39.59 { 39.60 clearMeasurementResults(); 39.61 } 39.62 39.63 bool LatencyTest::SetDevice(LatencyTestDevice* device) 39.64 { 39.65 39.66 if (device != Device) 39.67 { 39.68 if (device != NULL) 39.69 { 39.70 if (device->GetMessageHandler() != NULL) 39.71 { 39.72 OVR_DEBUG_LOG( 39.73 ("LatencyTest::AttachToDevice failed - device %p already has handler", device)); 39.74 return false; 39.75 } 39.76 } 39.77 39.78 if (Device != NULL) 39.79 { 39.80 Device->SetMessageHandler(0); 39.81 } 39.82 Device = device; 39.83 39.84 if (Device != NULL) 39.85 { 39.86 Device->SetMessageHandler(&Handler); 39.87 39.88 // Set trigger threshold. 39.89 LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false); // No samples streaming. 39.90 Device->SetConfiguration(configuration, true); 39.91 39.92 // Set display to intial (3 dashes). 39.93 LatencyTestDisplay ltd(2, 0x40400040); 39.94 Device->SetDisplay(ltd); 39.95 } 39.96 } 39.97 39.98 return true; 39.99 } 39.100 39.101 UInt32 LatencyTest::getRandomComponent(UInt32 range) 39.102 { 39.103 UInt32 val = rand() % range; 39.104 return val; 39.105 } 39.106 39.107 void LatencyTest::BeginTest() 39.108 { 39.109 if (State == State_WaitingForButton) 39.110 { 39.111 // Set color to black and wait a while. 39.112 RenderColor = CALIBRATE_BLACK; 39.113 39.114 State = State_WaitingForSettlePreCalibrationColorBlack; 39.115 OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack.")); 39.116 39.117 setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); 39.118 } 39.119 } 39.120 39.121 void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage) 39.122 { 39.123 // For debugging. 39.124 /* if (msg.Type == Message_LatencyTestSamples) 39.125 { 39.126 MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg; 39.127 39.128 if (pSamples->Samples.GetSize() > 0) 39.129 { 39.130 // Just show the first one for now. 39.131 Color c = pSamples->Samples[0]; 39.132 OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B)); 39.133 } 39.134 return; 39.135 } 39.136 */ 39.137 39.138 if (latencyTestMessage == LatencyTest_Timer) 39.139 { 39.140 if (!Device) 39.141 { 39.142 reset(); 39.143 return; 39.144 } 39.145 39.146 if (State == State_WaitingForSettlePreCalibrationColorBlack) 39.147 { 39.148 // Send calibrate message to device and wait a while. 39.149 Device->SetCalibrate(CALIBRATE_BLACK); 39.150 39.151 State = State_WaitingForSettlePostCalibrationColorBlack; 39.152 OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack.")); 39.153 39.154 setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); 39.155 } 39.156 else if (State == State_WaitingForSettlePostCalibrationColorBlack) 39.157 { 39.158 // Change color to white and wait a while. 39.159 RenderColor = CALIBRATE_WHITE; 39.160 39.161 State = State_WaitingForSettlePreCalibrationColorWhite; 39.162 OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite.")); 39.163 39.164 setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); 39.165 } 39.166 else if (State == State_WaitingForSettlePreCalibrationColorWhite) 39.167 { 39.168 // Send calibrate message to device and wait a while. 39.169 Device->SetCalibrate(CALIBRATE_WHITE); 39.170 39.171 State = State_WaitingForSettlePostCalibrationColorWhite; 39.172 OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite.")); 39.173 39.174 setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); 39.175 } 39.176 else if (State == State_WaitingForSettlePostCalibrationColorWhite) 39.177 { 39.178 // Calibration is done. Switch to color 1 and wait for it to settle. 39.179 RenderColor = COLOR1; 39.180 39.181 State = State_WaitingForSettlePostMeasurement; 39.182 OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement.")); 39.183 39.184 UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.185 setTimer(waitTime); 39.186 } 39.187 else if (State == State_WaitingForSettlePostMeasurement) 39.188 { 39.189 // Prepare for next measurement. 39.190 39.191 // Create a new result object. 39.192 MeasurementResult* pResult = new MeasurementResult(); 39.193 Results.PushBack(pResult); 39.194 39.195 State = State_WaitingToTakeMeasurement; 39.196 OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement.")); 39.197 } 39.198 else if (State == State_WaitingForTestStarted) 39.199 { 39.200 // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next. 39.201 getActiveResult()->TimedOutWaitingForTestStarted = true; 39.202 39.203 State = State_WaitingForSettlePostMeasurement; 39.204 OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'.")); 39.205 OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement.")); 39.206 39.207 UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.208 setTimer(waitTime); 39.209 } 39.210 else if (State == State_WaitingForColorDetected) 39.211 { 39.212 // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next. 39.213 getActiveResult()->TimedOutWaitingForColorDetected = true; 39.214 39.215 State = State_WaitingForSettlePostMeasurement; 39.216 OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'.")); 39.217 OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); 39.218 39.219 UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.220 setTimer(waitTime); 39.221 } 39.222 } 39.223 else if (latencyTestMessage == LatencyTest_ProcessInputs) 39.224 { 39.225 if (State == State_WaitingToTakeMeasurement) 39.226 { 39.227 if (!Device) 39.228 { 39.229 reset(); 39.230 return; 39.231 } 39.232 39.233 // Send 'StartTest' feature report with opposite target color. 39.234 if (RenderColor == COLOR1) 39.235 { 39.236 RenderColor = COLOR2; 39.237 } 39.238 else 39.239 { 39.240 RenderColor = COLOR1; 39.241 } 39.242 39.243 getActiveResult()->TargetColor = RenderColor; 39.244 39.245 // Record time so we can determine usb roundtrip time. 39.246 getActiveResult()->StartTestTicksMicroS = Timer::GetTicks(); 39.247 39.248 Device->SetStartTest(RenderColor); 39.249 39.250 State = State_WaitingForTestStarted; 39.251 OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted.")); 39.252 39.253 setTimer(TIMEOUT_WAITING_FOR_TEST_STARTED); 39.254 39.255 LatencyTestDisplay ltd(2, 0x40090040); 39.256 Device->SetDisplay(ltd); 39.257 } 39.258 } 39.259 else if (msg.Type == Message_LatencyTestButton) 39.260 { 39.261 BeginTest(); 39.262 } 39.263 else if (msg.Type == Message_LatencyTestStarted) 39.264 { 39.265 if (State == State_WaitingForTestStarted) 39.266 { 39.267 clearTimer(); 39.268 39.269 // Record time so we can determine usb roundtrip time. 39.270 getActiveResult()->TestStartedTicksMicroS = Timer::GetTicks(); 39.271 39.272 State = State_WaitingForColorDetected; 39.273 OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected.")); 39.274 39.275 setTimer(TIMEOUT_WAITING_FOR_COLOR_DETECTED); 39.276 } 39.277 } 39.278 else if (msg.Type == Message_LatencyTestColorDetected) 39.279 { 39.280 if (State == State_WaitingForColorDetected) 39.281 { 39.282 // Record time to detect color. 39.283 MessageLatencyTestColorDetected* pDetected = (MessageLatencyTestColorDetected*) &msg; 39.284 UInt16 elapsedTime = pDetected->Elapsed; 39.285 OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime)); 39.286 39.287 getActiveResult()->DeviceMeasuredElapsedMilliS = elapsedTime; 39.288 39.289 if (areResultsComplete()) 39.290 { 39.291 // We're done. 39.292 processResults(); 39.293 reset(); 39.294 } 39.295 else 39.296 { 39.297 // Run another measurement. 39.298 State = State_WaitingForSettlePostMeasurement; 39.299 OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); 39.300 39.301 UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.302 setTimer(waitTime); 39.303 39.304 LatencyTestDisplay ltd(2, 0x40400040); 39.305 Device->SetDisplay(ltd); 39.306 } 39.307 } 39.308 } 39.309 else if (msg.Type == Message_DeviceRemoved) 39.310 { 39.311 reset(); 39.312 } 39.313 } 39.314 39.315 LatencyTest::MeasurementResult* LatencyTest::getActiveResult() 39.316 { 39.317 OVR_ASSERT(!Results.IsEmpty()); 39.318 return Results.GetLast(); 39.319 } 39.320 39.321 void LatencyTest::setTimer(UInt32 timeMilliS) 39.322 { 39.323 ActiveTimerMilliS = timeMilliS; 39.324 } 39.325 39.326 void LatencyTest::clearTimer() 39.327 { 39.328 ActiveTimerMilliS = 0; 39.329 } 39.330 39.331 void LatencyTest::reset() 39.332 { 39.333 clearMeasurementResults(); 39.334 State = State_WaitingForButton; 39.335 39.336 HaveOldTime = false; 39.337 ActiveTimerMilliS = 0; 39.338 } 39.339 39.340 void LatencyTest::clearMeasurementResults() 39.341 { 39.342 while(!Results.IsEmpty()) 39.343 { 39.344 MeasurementResult* pElem = Results.GetFirst(); 39.345 pElem->RemoveNode(); 39.346 delete pElem; 39.347 } 39.348 } 39.349 39.350 LatencyTest::LatencyTestHandler::~LatencyTestHandler() 39.351 { 39.352 RemoveHandlerFromDevices(); 39.353 } 39.354 39.355 void LatencyTest::LatencyTestHandler::OnMessage(const Message& msg) 39.356 { 39.357 pLatencyTestUtil->handleMessage(msg); 39.358 } 39.359 39.360 void LatencyTest::ProcessInputs() 39.361 { 39.362 updateForTimeouts(); 39.363 handleMessage(Message(), LatencyTest_ProcessInputs); 39.364 } 39.365 39.366 bool LatencyTest::DisplayScreenColor(Color& colorToDisplay) 39.367 { 39.368 updateForTimeouts(); 39.369 39.370 if (State == State_WaitingForButton) 39.371 { 39.372 return false; 39.373 } 39.374 39.375 colorToDisplay = RenderColor; 39.376 return true; 39.377 } 39.378 39.379 const char* LatencyTest::GetResultsString() 39.380 { 39.381 if (!ResultsString.IsEmpty() && ReturnedResultString != ResultsString.ToCStr()) 39.382 { 39.383 ReturnedResultString = ResultsString; 39.384 return ReturnedResultString.ToCStr(); 39.385 } 39.386 39.387 return NULL; 39.388 } 39.389 39.390 bool LatencyTest::areResultsComplete() 39.391 { 39.392 UInt32 initialMeasurements = 0; 39.393 39.394 UInt32 measurements1to2 = 0; 39.395 UInt32 measurements2to1 = 0; 39.396 39.397 MeasurementResult* pCurr = Results.GetFirst(); 39.398 while(true) 39.399 { 39.400 // Process. 39.401 if (!pCurr->TimedOutWaitingForTestStarted && 39.402 !pCurr->TimedOutWaitingForColorDetected) 39.403 { 39.404 initialMeasurements++; 39.405 39.406 if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE) 39.407 { 39.408 if (pCurr->TargetColor == COLOR2) 39.409 { 39.410 measurements1to2++; 39.411 } 39.412 else 39.413 { 39.414 measurements2to1++; 39.415 } 39.416 } 39.417 } 39.418 39.419 if (Results.IsLast(pCurr)) 39.420 { 39.421 break; 39.422 } 39.423 pCurr = Results.GetNext(pCurr); 39.424 } 39.425 39.426 if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && 39.427 measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) 39.428 { 39.429 return true; 39.430 } 39.431 39.432 return false; 39.433 } 39.434 39.435 void LatencyTest::processResults() 39.436 { 39.437 39.438 UInt32 minTime1To2 = UINT_MAX; 39.439 UInt32 maxTime1To2 = 0; 39.440 float averageTime1To2 = 0.0f; 39.441 UInt32 minTime2To1 = UINT_MAX; 39.442 UInt32 maxTime2To1 = 0; 39.443 float averageTime2To1 = 0.0f; 39.444 39.445 float minUSBTripMilliS = BIG_FLOAT; 39.446 float maxUSBTripMilliS = SMALL_FLOAT; 39.447 float averageUSBTripMilliS = 0.0f; 39.448 UInt32 countUSBTripTime = 0; 39.449 39.450 UInt32 measurementsCount = 0; 39.451 UInt32 measurements1to2 = 0; 39.452 UInt32 measurements2to1 = 0; 39.453 39.454 MeasurementResult* pCurr = Results.GetFirst(); 39.455 UInt32 count = 0; 39.456 while(true) 39.457 { 39.458 count++; 39.459 39.460 if (!pCurr->TimedOutWaitingForTestStarted && 39.461 !pCurr->TimedOutWaitingForColorDetected) 39.462 { 39.463 measurementsCount++; 39.464 39.465 if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE) 39.466 { 39.467 if (pCurr->TargetColor == COLOR2) 39.468 { 39.469 measurements1to2++; 39.470 39.471 if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES) 39.472 { 39.473 UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; 39.474 39.475 minTime1To2 = Alg::Min(elapsed, minTime1To2); 39.476 maxTime1To2 = Alg::Max(elapsed, maxTime1To2); 39.477 39.478 averageTime1To2 += (float) elapsed; 39.479 } 39.480 } 39.481 else 39.482 { 39.483 measurements2to1++; 39.484 39.485 if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES) 39.486 { 39.487 UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; 39.488 39.489 minTime2To1 = Alg::Min(elapsed, minTime2To1); 39.490 maxTime2To1 = Alg::Max(elapsed, maxTime2To1); 39.491 39.492 averageTime2To1 += (float) elapsed; 39.493 } 39.494 } 39.495 39.496 float usbRountripElapsedMilliS = 0.001f * (float) (pCurr->TestStartedTicksMicroS - pCurr->StartTestTicksMicroS); 39.497 minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS); 39.498 maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS); 39.499 averageUSBTripMilliS += usbRountripElapsedMilliS; 39.500 countUSBTripTime++; 39.501 } 39.502 } 39.503 39.504 if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && 39.505 measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) 39.506 { 39.507 break; 39.508 } 39.509 39.510 if (Results.IsLast(pCurr)) 39.511 { 39.512 break; 39.513 } 39.514 pCurr = Results.GetNext(pCurr); 39.515 } 39.516 39.517 averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES; 39.518 averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES; 39.519 39.520 averageUSBTripMilliS /= countUSBTripTime; 39.521 39.522 float finalResult = 0.5f * (averageTime1To2 + averageTime2To1); 39.523 finalResult += averageUSBTripMilliS; 39.524 39.525 ResultsString.Clear(); 39.526 ResultsString.AppendFormat("RESULT=%.1f (add half Tracker period) [b->w %d|%.1f|%d] [w->b %d|%.1f|%d] [usb rndtrp %.1f|%.1f|%.1f] [cnt %d] [tmouts %d]", 39.527 finalResult, 39.528 minTime1To2, averageTime1To2, maxTime1To2, 39.529 minTime2To1, averageTime2To1, maxTime2To1, 39.530 minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS, 39.531 DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount); 39.532 39.533 // Display result on latency tester display. 39.534 LatencyTestDisplay ltd(1, (int)finalResult); 39.535 Device->SetDisplay(ltd); 39.536 } 39.537 39.538 void LatencyTest::updateForTimeouts() 39.539 { 39.540 if (!HaveOldTime) 39.541 { 39.542 HaveOldTime = true; 39.543 OldTime = Timer::GetTicksMs(); 39.544 return; 39.545 } 39.546 39.547 UInt32 newTime = Timer::GetTicksMs(); 39.548 UInt32 elapsedMilliS = newTime - OldTime; 39.549 if (newTime < OldTime) 39.550 { 39.551 elapsedMilliS = OldTime - newTime; 39.552 elapsedMilliS = UINT_MAX - elapsedMilliS; 39.553 } 39.554 OldTime = newTime; 39.555 39.556 elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100); // Clamp at 100mS in case we're not being called very often. 39.557 39.558 39.559 if (ActiveTimerMilliS == 0) 39.560 { 39.561 return; 39.562 } 39.563 39.564 if (elapsedMilliS >= ActiveTimerMilliS) 39.565 { 39.566 ActiveTimerMilliS = 0; 39.567 handleMessage(Message(), LatencyTest_Timer); 39.568 return; 39.569 } 39.570 39.571 ActiveTimerMilliS -= elapsedMilliS; 39.572 } 39.573 39.574 }} // namespace OVR::Util 39.575 \ No newline at end of file 39.576 +/************************************************************************************ 39.577 + 39.578 +Filename : Util_LatencyTest.cpp 39.579 +Content : Wraps the lower level LatencyTester interface and adds functionality. 39.580 +Created : February 14, 2013 39.581 +Authors : Lee Cooper 39.582 + 39.583 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 39.584 + 39.585 +Use of this software is subject to the terms of the Oculus license 39.586 +agreement provided at the time of installation or download, or which 39.587 +otherwise accompanies this software in either electronic or hard copy form. 39.588 + 39.589 +*************************************************************************************/ 39.590 + 39.591 +#include "Util_LatencyTest.h" 39.592 + 39.593 +#include "../Kernel/OVR_Log.h" 39.594 +#include "../Kernel/OVR_Timer.h" 39.595 + 39.596 +namespace OVR { namespace Util { 39.597 + 39.598 +static const UInt32 TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION = 16*10; 39.599 +static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION = 16*10; 39.600 +static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT = 16*5; 39.601 +static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS = 16*5; 39.602 +static const UInt32 DEFAULT_NUMBER_OF_SAMPLES = 10; // For both color 1->2 and color 2->1 transitions. 39.603 +static const UInt32 INITIAL_SAMPLES_TO_IGNORE = 4; 39.604 +static const UInt32 TIMEOUT_WAITING_FOR_TEST_STARTED = 1000; 39.605 +static const UInt32 TIMEOUT_WAITING_FOR_COLOR_DETECTED = 4000; 39.606 +static const Color CALIBRATE_BLACK(0, 0, 0); 39.607 +static const Color CALIBRATE_WHITE(255, 255, 255); 39.608 +static const Color COLOR1(0, 0, 0); 39.609 +static const Color COLOR2(255, 255, 255); 39.610 +static const Color SENSOR_DETECT_THRESHOLD(128, 255, 255); 39.611 +static const float BIG_FLOAT = 1000000.0f; 39.612 +static const float SMALL_FLOAT = -1000000.0f; 39.613 + 39.614 +//------------------------------------------------------------------------------------- 39.615 +// ***** LatencyTest 39.616 + 39.617 +LatencyTest::LatencyTest(LatencyTestDevice* device) 39.618 + : Handler(getThis()) 39.619 +{ 39.620 + if (device != NULL) 39.621 + { 39.622 + SetDevice(device); 39.623 + } 39.624 + 39.625 + reset(); 39.626 + 39.627 + srand(Timer::GetTicksMs()); 39.628 +} 39.629 + 39.630 +LatencyTest::~LatencyTest() 39.631 +{ 39.632 + clearMeasurementResults(); 39.633 +} 39.634 + 39.635 +bool LatencyTest::SetDevice(LatencyTestDevice* device) 39.636 +{ 39.637 + 39.638 + if (device != Device) 39.639 + { 39.640 + if (device != NULL) 39.641 + { 39.642 + if (device->GetMessageHandler() != NULL) 39.643 + { 39.644 + OVR_DEBUG_LOG( 39.645 + ("LatencyTest::AttachToDevice failed - device %p already has handler", device)); 39.646 + return false; 39.647 + } 39.648 + } 39.649 + 39.650 + if (Device != NULL) 39.651 + { 39.652 + Device->SetMessageHandler(0); 39.653 + } 39.654 + Device = device; 39.655 + 39.656 + if (Device != NULL) 39.657 + { 39.658 + Device->SetMessageHandler(&Handler); 39.659 + 39.660 + // Set trigger threshold. 39.661 + LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false); // No samples streaming. 39.662 + Device->SetConfiguration(configuration, true); 39.663 + 39.664 + // Set display to intial (3 dashes). 39.665 + LatencyTestDisplay ltd(2, 0x40400040); 39.666 + Device->SetDisplay(ltd); 39.667 + } 39.668 + } 39.669 + 39.670 + return true; 39.671 +} 39.672 + 39.673 +UInt32 LatencyTest::getRandomComponent(UInt32 range) 39.674 +{ 39.675 + UInt32 val = rand() % range; 39.676 + return val; 39.677 +} 39.678 + 39.679 +void LatencyTest::BeginTest() 39.680 +{ 39.681 + if (State == State_WaitingForButton) 39.682 + { 39.683 + // Set color to black and wait a while. 39.684 + RenderColor = CALIBRATE_BLACK; 39.685 + 39.686 + State = State_WaitingForSettlePreCalibrationColorBlack; 39.687 + OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack.")); 39.688 + 39.689 + setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); 39.690 + } 39.691 +} 39.692 + 39.693 +void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage) 39.694 +{ 39.695 + // For debugging. 39.696 +/* if (msg.Type == Message_LatencyTestSamples) 39.697 + { 39.698 + MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg; 39.699 + 39.700 + if (pSamples->Samples.GetSize() > 0) 39.701 + { 39.702 + // Just show the first one for now. 39.703 + Color c = pSamples->Samples[0]; 39.704 + OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B)); 39.705 + } 39.706 + return; 39.707 + } 39.708 +*/ 39.709 + 39.710 + if (latencyTestMessage == LatencyTest_Timer) 39.711 + { 39.712 + if (!Device) 39.713 + { 39.714 + reset(); 39.715 + return; 39.716 + } 39.717 + 39.718 + if (State == State_WaitingForSettlePreCalibrationColorBlack) 39.719 + { 39.720 + // Send calibrate message to device and wait a while. 39.721 + Device->SetCalibrate(CALIBRATE_BLACK); 39.722 + 39.723 + State = State_WaitingForSettlePostCalibrationColorBlack; 39.724 + OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack.")); 39.725 + 39.726 + setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); 39.727 + } 39.728 + else if (State == State_WaitingForSettlePostCalibrationColorBlack) 39.729 + { 39.730 + // Change color to white and wait a while. 39.731 + RenderColor = CALIBRATE_WHITE; 39.732 + 39.733 + State = State_WaitingForSettlePreCalibrationColorWhite; 39.734 + OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite.")); 39.735 + 39.736 + setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); 39.737 + } 39.738 + else if (State == State_WaitingForSettlePreCalibrationColorWhite) 39.739 + { 39.740 + // Send calibrate message to device and wait a while. 39.741 + Device->SetCalibrate(CALIBRATE_WHITE); 39.742 + 39.743 + State = State_WaitingForSettlePostCalibrationColorWhite; 39.744 + OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite.")); 39.745 + 39.746 + setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); 39.747 + } 39.748 + else if (State == State_WaitingForSettlePostCalibrationColorWhite) 39.749 + { 39.750 + // Calibration is done. Switch to color 1 and wait for it to settle. 39.751 + RenderColor = COLOR1; 39.752 + 39.753 + State = State_WaitingForSettlePostMeasurement; 39.754 + OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement.")); 39.755 + 39.756 + UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.757 + setTimer(waitTime); 39.758 + } 39.759 + else if (State == State_WaitingForSettlePostMeasurement) 39.760 + { 39.761 + // Prepare for next measurement. 39.762 + 39.763 + // Create a new result object. 39.764 + MeasurementResult* pResult = new MeasurementResult(); 39.765 + Results.PushBack(pResult); 39.766 + 39.767 + State = State_WaitingToTakeMeasurement; 39.768 + OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement.")); 39.769 + } 39.770 + else if (State == State_WaitingForTestStarted) 39.771 + { 39.772 + // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next. 39.773 + getActiveResult()->TimedOutWaitingForTestStarted = true; 39.774 + 39.775 + State = State_WaitingForSettlePostMeasurement; 39.776 + OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'.")); 39.777 + OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement.")); 39.778 + 39.779 + UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.780 + setTimer(waitTime); 39.781 + } 39.782 + else if (State == State_WaitingForColorDetected) 39.783 + { 39.784 + // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next. 39.785 + getActiveResult()->TimedOutWaitingForColorDetected = true; 39.786 + 39.787 + State = State_WaitingForSettlePostMeasurement; 39.788 + OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'.")); 39.789 + OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); 39.790 + 39.791 + UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.792 + setTimer(waitTime); 39.793 + } 39.794 + } 39.795 + else if (latencyTestMessage == LatencyTest_ProcessInputs) 39.796 + { 39.797 + if (State == State_WaitingToTakeMeasurement) 39.798 + { 39.799 + if (!Device) 39.800 + { 39.801 + reset(); 39.802 + return; 39.803 + } 39.804 + 39.805 + // Send 'StartTest' feature report with opposite target color. 39.806 + if (RenderColor == COLOR1) 39.807 + { 39.808 + RenderColor = COLOR2; 39.809 + } 39.810 + else 39.811 + { 39.812 + RenderColor = COLOR1; 39.813 + } 39.814 + 39.815 + getActiveResult()->TargetColor = RenderColor; 39.816 + 39.817 + // Record time so we can determine usb roundtrip time. 39.818 + getActiveResult()->StartTestTicksMicroS = Timer::GetTicks(); 39.819 + 39.820 + Device->SetStartTest(RenderColor); 39.821 + 39.822 + State = State_WaitingForTestStarted; 39.823 + OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted.")); 39.824 + 39.825 + setTimer(TIMEOUT_WAITING_FOR_TEST_STARTED); 39.826 + 39.827 + LatencyTestDisplay ltd(2, 0x40090040); 39.828 + Device->SetDisplay(ltd); 39.829 + } 39.830 + } 39.831 + else if (msg.Type == Message_LatencyTestButton) 39.832 + { 39.833 + BeginTest(); 39.834 + } 39.835 + else if (msg.Type == Message_LatencyTestStarted) 39.836 + { 39.837 + if (State == State_WaitingForTestStarted) 39.838 + { 39.839 + clearTimer(); 39.840 + 39.841 + // Record time so we can determine usb roundtrip time. 39.842 + getActiveResult()->TestStartedTicksMicroS = Timer::GetTicks(); 39.843 + 39.844 + State = State_WaitingForColorDetected; 39.845 + OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected.")); 39.846 + 39.847 + setTimer(TIMEOUT_WAITING_FOR_COLOR_DETECTED); 39.848 + } 39.849 + } 39.850 + else if (msg.Type == Message_LatencyTestColorDetected) 39.851 + { 39.852 + if (State == State_WaitingForColorDetected) 39.853 + { 39.854 + // Record time to detect color. 39.855 + MessageLatencyTestColorDetected* pDetected = (MessageLatencyTestColorDetected*) &msg; 39.856 + UInt16 elapsedTime = pDetected->Elapsed; 39.857 + OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime)); 39.858 + 39.859 + getActiveResult()->DeviceMeasuredElapsedMilliS = elapsedTime; 39.860 + 39.861 + if (areResultsComplete()) 39.862 + { 39.863 + // We're done. 39.864 + processResults(); 39.865 + reset(); 39.866 + } 39.867 + else 39.868 + { 39.869 + // Run another measurement. 39.870 + State = State_WaitingForSettlePostMeasurement; 39.871 + OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); 39.872 + 39.873 + UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); 39.874 + setTimer(waitTime); 39.875 + 39.876 + LatencyTestDisplay ltd(2, 0x40400040); 39.877 + Device->SetDisplay(ltd); 39.878 + } 39.879 + } 39.880 + } 39.881 + else if (msg.Type == Message_DeviceRemoved) 39.882 + { 39.883 + reset(); 39.884 + } 39.885 +} 39.886 + 39.887 +LatencyTest::MeasurementResult* LatencyTest::getActiveResult() 39.888 +{ 39.889 + OVR_ASSERT(!Results.IsEmpty()); 39.890 + return Results.GetLast(); 39.891 +} 39.892 + 39.893 +void LatencyTest::setTimer(UInt32 timeMilliS) 39.894 +{ 39.895 + ActiveTimerMilliS = timeMilliS; 39.896 +} 39.897 + 39.898 +void LatencyTest::clearTimer() 39.899 +{ 39.900 + ActiveTimerMilliS = 0; 39.901 +} 39.902 + 39.903 +void LatencyTest::reset() 39.904 +{ 39.905 + clearMeasurementResults(); 39.906 + State = State_WaitingForButton; 39.907 + 39.908 + HaveOldTime = false; 39.909 + ActiveTimerMilliS = 0; 39.910 +} 39.911 + 39.912 +void LatencyTest::clearMeasurementResults() 39.913 +{ 39.914 + while(!Results.IsEmpty()) 39.915 + { 39.916 + MeasurementResult* pElem = Results.GetFirst(); 39.917 + pElem->RemoveNode(); 39.918 + delete pElem; 39.919 + } 39.920 +} 39.921 + 39.922 +LatencyTest::LatencyTestHandler::~LatencyTestHandler() 39.923 +{ 39.924 + RemoveHandlerFromDevices(); 39.925 +} 39.926 + 39.927 +void LatencyTest::LatencyTestHandler::OnMessage(const Message& msg) 39.928 +{ 39.929 + pLatencyTestUtil->handleMessage(msg); 39.930 +} 39.931 + 39.932 +void LatencyTest::ProcessInputs() 39.933 +{ 39.934 + updateForTimeouts(); 39.935 + handleMessage(Message(), LatencyTest_ProcessInputs); 39.936 +} 39.937 + 39.938 +bool LatencyTest::DisplayScreenColor(Color& colorToDisplay) 39.939 +{ 39.940 + updateForTimeouts(); 39.941 + 39.942 + if (State == State_WaitingForButton) 39.943 + { 39.944 + return false; 39.945 + } 39.946 + 39.947 + colorToDisplay = RenderColor; 39.948 + return true; 39.949 +} 39.950 + 39.951 +const char* LatencyTest::GetResultsString() 39.952 +{ 39.953 + if (!ResultsString.IsEmpty() && ReturnedResultString != ResultsString.ToCStr()) 39.954 + { 39.955 + ReturnedResultString = ResultsString; 39.956 + return ReturnedResultString.ToCStr(); 39.957 + } 39.958 + 39.959 + return NULL; 39.960 +} 39.961 + 39.962 +bool LatencyTest::areResultsComplete() 39.963 +{ 39.964 + UInt32 initialMeasurements = 0; 39.965 + 39.966 + UInt32 measurements1to2 = 0; 39.967 + UInt32 measurements2to1 = 0; 39.968 + 39.969 + MeasurementResult* pCurr = Results.GetFirst(); 39.970 + while(true) 39.971 + { 39.972 + // Process. 39.973 + if (!pCurr->TimedOutWaitingForTestStarted && 39.974 + !pCurr->TimedOutWaitingForColorDetected) 39.975 + { 39.976 + initialMeasurements++; 39.977 + 39.978 + if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE) 39.979 + { 39.980 + if (pCurr->TargetColor == COLOR2) 39.981 + { 39.982 + measurements1to2++; 39.983 + } 39.984 + else 39.985 + { 39.986 + measurements2to1++; 39.987 + } 39.988 + } 39.989 + } 39.990 + 39.991 + if (Results.IsLast(pCurr)) 39.992 + { 39.993 + break; 39.994 + } 39.995 + pCurr = Results.GetNext(pCurr); 39.996 + } 39.997 + 39.998 + if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && 39.999 + measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) 39.1000 + { 39.1001 + return true; 39.1002 + } 39.1003 + 39.1004 + return false; 39.1005 +} 39.1006 + 39.1007 +void LatencyTest::processResults() 39.1008 +{ 39.1009 + 39.1010 + UInt32 minTime1To2 = UINT_MAX; 39.1011 + UInt32 maxTime1To2 = 0; 39.1012 + float averageTime1To2 = 0.0f; 39.1013 + UInt32 minTime2To1 = UINT_MAX; 39.1014 + UInt32 maxTime2To1 = 0; 39.1015 + float averageTime2To1 = 0.0f; 39.1016 + 39.1017 + float minUSBTripMilliS = BIG_FLOAT; 39.1018 + float maxUSBTripMilliS = SMALL_FLOAT; 39.1019 + float averageUSBTripMilliS = 0.0f; 39.1020 + UInt32 countUSBTripTime = 0; 39.1021 + 39.1022 + UInt32 measurementsCount = 0; 39.1023 + UInt32 measurements1to2 = 0; 39.1024 + UInt32 measurements2to1 = 0; 39.1025 + 39.1026 + MeasurementResult* pCurr = Results.GetFirst(); 39.1027 + UInt32 count = 0; 39.1028 + while(true) 39.1029 + { 39.1030 + count++; 39.1031 + 39.1032 + if (!pCurr->TimedOutWaitingForTestStarted && 39.1033 + !pCurr->TimedOutWaitingForColorDetected) 39.1034 + { 39.1035 + measurementsCount++; 39.1036 + 39.1037 + if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE) 39.1038 + { 39.1039 + if (pCurr->TargetColor == COLOR2) 39.1040 + { 39.1041 + measurements1to2++; 39.1042 + 39.1043 + if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES) 39.1044 + { 39.1045 + UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; 39.1046 + 39.1047 + minTime1To2 = Alg::Min(elapsed, minTime1To2); 39.1048 + maxTime1To2 = Alg::Max(elapsed, maxTime1To2); 39.1049 + 39.1050 + averageTime1To2 += (float) elapsed; 39.1051 + } 39.1052 + } 39.1053 + else 39.1054 + { 39.1055 + measurements2to1++; 39.1056 + 39.1057 + if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES) 39.1058 + { 39.1059 + UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; 39.1060 + 39.1061 + minTime2To1 = Alg::Min(elapsed, minTime2To1); 39.1062 + maxTime2To1 = Alg::Max(elapsed, maxTime2To1); 39.1063 + 39.1064 + averageTime2To1 += (float) elapsed; 39.1065 + } 39.1066 + } 39.1067 + 39.1068 + float usbRountripElapsedMilliS = 0.001f * (float) (pCurr->TestStartedTicksMicroS - pCurr->StartTestTicksMicroS); 39.1069 + minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS); 39.1070 + maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS); 39.1071 + averageUSBTripMilliS += usbRountripElapsedMilliS; 39.1072 + countUSBTripTime++; 39.1073 + } 39.1074 + } 39.1075 + 39.1076 + if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && 39.1077 + measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) 39.1078 + { 39.1079 + break; 39.1080 + } 39.1081 + 39.1082 + if (Results.IsLast(pCurr)) 39.1083 + { 39.1084 + break; 39.1085 + } 39.1086 + pCurr = Results.GetNext(pCurr); 39.1087 + } 39.1088 + 39.1089 + averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES; 39.1090 + averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES; 39.1091 + 39.1092 + averageUSBTripMilliS /= countUSBTripTime; 39.1093 + 39.1094 + float finalResult = 0.5f * (averageTime1To2 + averageTime2To1); 39.1095 + finalResult += averageUSBTripMilliS; 39.1096 + 39.1097 + ResultsString.Clear(); 39.1098 + ResultsString.AppendFormat("RESULT=%.1f (add half Tracker period) [b->w %d|%.1f|%d] [w->b %d|%.1f|%d] [usb rndtrp %.1f|%.1f|%.1f] [cnt %d] [tmouts %d]", 39.1099 + finalResult, 39.1100 + minTime1To2, averageTime1To2, maxTime1To2, 39.1101 + minTime2To1, averageTime2To1, maxTime2To1, 39.1102 + minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS, 39.1103 + DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount); 39.1104 + 39.1105 + // Display result on latency tester display. 39.1106 + LatencyTestDisplay ltd(1, (int)finalResult); 39.1107 + Device->SetDisplay(ltd); 39.1108 +} 39.1109 + 39.1110 +void LatencyTest::updateForTimeouts() 39.1111 +{ 39.1112 + if (!HaveOldTime) 39.1113 + { 39.1114 + HaveOldTime = true; 39.1115 + OldTime = Timer::GetTicksMs(); 39.1116 + return; 39.1117 + } 39.1118 + 39.1119 + UInt32 newTime = Timer::GetTicksMs(); 39.1120 + UInt32 elapsedMilliS = newTime - OldTime; 39.1121 + if (newTime < OldTime) 39.1122 + { 39.1123 + elapsedMilliS = OldTime - newTime; 39.1124 + elapsedMilliS = UINT_MAX - elapsedMilliS; 39.1125 + } 39.1126 + OldTime = newTime; 39.1127 + 39.1128 + elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100); // Clamp at 100mS in case we're not being called very often. 39.1129 + 39.1130 + 39.1131 + if (ActiveTimerMilliS == 0) 39.1132 + { 39.1133 + return; 39.1134 + } 39.1135 + 39.1136 + if (elapsedMilliS >= ActiveTimerMilliS) 39.1137 + { 39.1138 + ActiveTimerMilliS = 0; 39.1139 + handleMessage(Message(), LatencyTest_Timer); 39.1140 + return; 39.1141 + } 39.1142 + 39.1143 + ActiveTimerMilliS -= elapsedMilliS; 39.1144 +} 39.1145 + 39.1146 +}} // namespace OVR::Util
40.1 --- a/libovr/Src/Util/Util_LatencyTest.h Sat Sep 14 17:51:03 2013 +0300 40.2 +++ b/libovr/Src/Util/Util_LatencyTest.h Sun Sep 15 04:10:05 2013 +0300 40.3 @@ -1,1 +1,160 @@ 40.4 -/************************************************************************************ 40.5 40.6 PublicHeader: OVR.h 40.7 Filename : Util_LatencyTest.h 40.8 Content : Wraps the lower level LatencyTesterDevice and adds functionality. 40.9 Created : February 14, 2013 40.10 Authors : Lee Cooper 40.11 40.12 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 40.13 40.14 Use of this software is subject to the terms of the Oculus license 40.15 agreement provided at the time of installation or download, or which 40.16 otherwise accompanies this software in either electronic or hard copy form. 40.17 40.18 *************************************************************************************/ 40.19 40.20 #ifndef OVR_Util_LatencyTest_h 40.21 #define OVR_Util_LatencyTest_h 40.22 40.23 #include "../OVR_Device.h" 40.24 40.25 #include "../Kernel/OVR_String.h" 40.26 #include "../Kernel/OVR_List.h" 40.27 40.28 namespace OVR { namespace Util { 40.29 40.30 40.31 //------------------------------------------------------------------------------------- 40.32 // ***** LatencyTest 40.33 // 40.34 // LatencyTest utility class wraps the low level LatencyTestDevice and manages the scheduling 40.35 // of a latency test. A single test is composed of a series of individual latency measurements 40.36 // which are used to derive min, max, and an average latency value. 40.37 // 40.38 // Developers are required to call the following methods: 40.39 // SetDevice - Sets the LatencyTestDevice to be used for the tests. 40.40 // ProcessInputs - This should be called at the same place in the code where the game engine 40.41 // reads the headset orientation from LibOVR (typically done by calling 40.42 // 'GetOrientation' on the SensorFusion object). Calling this at the right time 40.43 // enables us to measure the same latency that occurs for headset orientation 40.44 // changes. 40.45 // DisplayScreenColor - The latency tester works by sensing the color of the pixels directly 40.46 // beneath it. The color of these pixels can be set by drawing a small 40.47 // quad at the end of the rendering stage. The quad should be small 40.48 // such that it doesn't significantly impact the rendering of the scene, 40.49 // but large enough to be 'seen' by the sensor. See the SDK 40.50 // documentation for more information. 40.51 // GetResultsString - Call this to get a string containing the most recent results. 40.52 // If the string has already been gotten then NULL will be returned. 40.53 // The string pointer will remain valid until the next time this 40.54 // method is called. 40.55 // 40.56 40.57 class LatencyTest : public NewOverrideBase 40.58 { 40.59 public: 40.60 LatencyTest(LatencyTestDevice* device = NULL); 40.61 ~LatencyTest(); 40.62 40.63 // Set the Latency Tester device that we'll use to send commands to and receive 40.64 // notification messages from. 40.65 bool SetDevice(LatencyTestDevice* device); 40.66 40.67 // Returns true if this LatencyTestUtil has a Latency Tester device. 40.68 bool HasDevice() const 40.69 { return Handler.IsHandlerInstalled(); } 40.70 40.71 void ProcessInputs(); 40.72 bool DisplayScreenColor(Color& colorToDisplay); 40.73 const char* GetResultsString(); 40.74 40.75 // Begin test. Equivalent to pressing the button on the latency tester. 40.76 void BeginTest(); 40.77 40.78 private: 40.79 LatencyTest* getThis() { return this; } 40.80 40.81 enum LatencyTestMessageType 40.82 { 40.83 LatencyTest_None, 40.84 LatencyTest_Timer, 40.85 LatencyTest_ProcessInputs, 40.86 }; 40.87 40.88 UInt32 getRandomComponent(UInt32 range); 40.89 void handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage = LatencyTest_None); 40.90 void reset(); 40.91 void setTimer(UInt32 timeMilliS); 40.92 void clearTimer(); 40.93 40.94 class LatencyTestHandler : public MessageHandler 40.95 { 40.96 LatencyTest* pLatencyTestUtil; 40.97 public: 40.98 LatencyTestHandler(LatencyTest* latencyTester) : pLatencyTestUtil(latencyTester) { } 40.99 ~LatencyTestHandler(); 40.100 40.101 virtual void OnMessage(const Message& msg); 40.102 }; 40.103 40.104 bool areResultsComplete(); 40.105 void processResults(); 40.106 void updateForTimeouts(); 40.107 40.108 Ptr<LatencyTestDevice> Device; 40.109 LatencyTestHandler Handler; 40.110 40.111 enum TesterState 40.112 { 40.113 State_WaitingForButton, 40.114 State_WaitingForSettlePreCalibrationColorBlack, 40.115 State_WaitingForSettlePostCalibrationColorBlack, 40.116 State_WaitingForSettlePreCalibrationColorWhite, 40.117 State_WaitingForSettlePostCalibrationColorWhite, 40.118 State_WaitingToTakeMeasurement, 40.119 State_WaitingForTestStarted, 40.120 State_WaitingForColorDetected, 40.121 State_WaitingForSettlePostMeasurement 40.122 }; 40.123 TesterState State; 40.124 40.125 bool HaveOldTime; 40.126 UInt32 OldTime; 40.127 UInt32 ActiveTimerMilliS; 40.128 40.129 Color RenderColor; 40.130 40.131 struct MeasurementResult : public ListNode<MeasurementResult>, public NewOverrideBase 40.132 { 40.133 MeasurementResult() 40.134 : DeviceMeasuredElapsedMilliS(0), 40.135 TimedOutWaitingForTestStarted(false), 40.136 TimedOutWaitingForColorDetected(false), 40.137 StartTestTicksMicroS(0), 40.138 TestStartedTicksMicroS(0) 40.139 {} 40.140 40.141 Color TargetColor; 40.142 40.143 UInt32 DeviceMeasuredElapsedMilliS; 40.144 40.145 bool TimedOutWaitingForTestStarted; 40.146 bool TimedOutWaitingForColorDetected; 40.147 40.148 UInt64 StartTestTicksMicroS; 40.149 UInt64 TestStartedTicksMicroS; 40.150 }; 40.151 40.152 List<MeasurementResult> Results; 40.153 void clearMeasurementResults(); 40.154 40.155 MeasurementResult* getActiveResult(); 40.156 40.157 StringBuffer ResultsString; 40.158 String ReturnedResultString; 40.159 }; 40.160 40.161 }} // namespace OVR::Util 40.162 40.163 #endif // OVR_Util_LatencyTest_h 40.164 \ No newline at end of file 40.165 +/************************************************************************************ 40.166 + 40.167 +PublicHeader: OVR.h 40.168 +Filename : Util_LatencyTest.h 40.169 +Content : Wraps the lower level LatencyTesterDevice and adds functionality. 40.170 +Created : February 14, 2013 40.171 +Authors : Lee Cooper 40.172 + 40.173 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 40.174 + 40.175 +Use of this software is subject to the terms of the Oculus license 40.176 +agreement provided at the time of installation or download, or which 40.177 +otherwise accompanies this software in either electronic or hard copy form. 40.178 + 40.179 +*************************************************************************************/ 40.180 + 40.181 +#ifndef OVR_Util_LatencyTest_h 40.182 +#define OVR_Util_LatencyTest_h 40.183 + 40.184 +#include "../OVR_Device.h" 40.185 + 40.186 +#include "../Kernel/OVR_String.h" 40.187 +#include "../Kernel/OVR_List.h" 40.188 + 40.189 +namespace OVR { namespace Util { 40.190 + 40.191 + 40.192 +//------------------------------------------------------------------------------------- 40.193 +// ***** LatencyTest 40.194 +// 40.195 +// LatencyTest utility class wraps the low level LatencyTestDevice and manages the scheduling 40.196 +// of a latency test. A single test is composed of a series of individual latency measurements 40.197 +// which are used to derive min, max, and an average latency value. 40.198 +// 40.199 +// Developers are required to call the following methods: 40.200 +// SetDevice - Sets the LatencyTestDevice to be used for the tests. 40.201 +// ProcessInputs - This should be called at the same place in the code where the game engine 40.202 +// reads the headset orientation from LibOVR (typically done by calling 40.203 +// 'GetOrientation' on the SensorFusion object). Calling this at the right time 40.204 +// enables us to measure the same latency that occurs for headset orientation 40.205 +// changes. 40.206 +// DisplayScreenColor - The latency tester works by sensing the color of the pixels directly 40.207 +// beneath it. The color of these pixels can be set by drawing a small 40.208 +// quad at the end of the rendering stage. The quad should be small 40.209 +// such that it doesn't significantly impact the rendering of the scene, 40.210 +// but large enough to be 'seen' by the sensor. See the SDK 40.211 +// documentation for more information. 40.212 +// GetResultsString - Call this to get a string containing the most recent results. 40.213 +// If the string has already been gotten then NULL will be returned. 40.214 +// The string pointer will remain valid until the next time this 40.215 +// method is called. 40.216 +// 40.217 + 40.218 +class LatencyTest : public NewOverrideBase 40.219 +{ 40.220 +public: 40.221 + LatencyTest(LatencyTestDevice* device = NULL); 40.222 + ~LatencyTest(); 40.223 + 40.224 + // Set the Latency Tester device that we'll use to send commands to and receive 40.225 + // notification messages from. 40.226 + bool SetDevice(LatencyTestDevice* device); 40.227 + 40.228 + // Returns true if this LatencyTestUtil has a Latency Tester device. 40.229 + bool HasDevice() const 40.230 + { return Handler.IsHandlerInstalled(); } 40.231 + 40.232 + void ProcessInputs(); 40.233 + bool DisplayScreenColor(Color& colorToDisplay); 40.234 + const char* GetResultsString(); 40.235 + 40.236 + // Begin test. Equivalent to pressing the button on the latency tester. 40.237 + void BeginTest(); 40.238 + 40.239 +private: 40.240 + LatencyTest* getThis() { return this; } 40.241 + 40.242 + enum LatencyTestMessageType 40.243 + { 40.244 + LatencyTest_None, 40.245 + LatencyTest_Timer, 40.246 + LatencyTest_ProcessInputs, 40.247 + }; 40.248 + 40.249 + UInt32 getRandomComponent(UInt32 range); 40.250 + void handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage = LatencyTest_None); 40.251 + void reset(); 40.252 + void setTimer(UInt32 timeMilliS); 40.253 + void clearTimer(); 40.254 + 40.255 + class LatencyTestHandler : public MessageHandler 40.256 + { 40.257 + LatencyTest* pLatencyTestUtil; 40.258 + public: 40.259 + LatencyTestHandler(LatencyTest* latencyTester) : pLatencyTestUtil(latencyTester) { } 40.260 + ~LatencyTestHandler(); 40.261 + 40.262 + virtual void OnMessage(const Message& msg); 40.263 + }; 40.264 + 40.265 + bool areResultsComplete(); 40.266 + void processResults(); 40.267 + void updateForTimeouts(); 40.268 + 40.269 + Ptr<LatencyTestDevice> Device; 40.270 + LatencyTestHandler Handler; 40.271 + 40.272 + enum TesterState 40.273 + { 40.274 + State_WaitingForButton, 40.275 + State_WaitingForSettlePreCalibrationColorBlack, 40.276 + State_WaitingForSettlePostCalibrationColorBlack, 40.277 + State_WaitingForSettlePreCalibrationColorWhite, 40.278 + State_WaitingForSettlePostCalibrationColorWhite, 40.279 + State_WaitingToTakeMeasurement, 40.280 + State_WaitingForTestStarted, 40.281 + State_WaitingForColorDetected, 40.282 + State_WaitingForSettlePostMeasurement 40.283 + }; 40.284 + TesterState State; 40.285 + 40.286 + bool HaveOldTime; 40.287 + UInt32 OldTime; 40.288 + UInt32 ActiveTimerMilliS; 40.289 + 40.290 + Color RenderColor; 40.291 + 40.292 + struct MeasurementResult : public ListNode<MeasurementResult>, public NewOverrideBase 40.293 + { 40.294 + MeasurementResult() 40.295 + : DeviceMeasuredElapsedMilliS(0), 40.296 + TimedOutWaitingForTestStarted(false), 40.297 + TimedOutWaitingForColorDetected(false), 40.298 + StartTestTicksMicroS(0), 40.299 + TestStartedTicksMicroS(0) 40.300 + {} 40.301 + 40.302 + Color TargetColor; 40.303 + 40.304 + UInt32 DeviceMeasuredElapsedMilliS; 40.305 + 40.306 + bool TimedOutWaitingForTestStarted; 40.307 + bool TimedOutWaitingForColorDetected; 40.308 + 40.309 + UInt64 StartTestTicksMicroS; 40.310 + UInt64 TestStartedTicksMicroS; 40.311 + }; 40.312 + 40.313 + List<MeasurementResult> Results; 40.314 + void clearMeasurementResults(); 40.315 + 40.316 + MeasurementResult* getActiveResult(); 40.317 + 40.318 + StringBuffer ResultsString; 40.319 + String ReturnedResultString; 40.320 +}; 40.321 + 40.322 +}} // namespace OVR::Util 40.323 + 40.324 +#endif // OVR_Util_LatencyTest_h
41.1 --- a/libovr/Src/Util/Util_MagCalibration.cpp Sat Sep 14 17:51:03 2013 +0300 41.2 +++ b/libovr/Src/Util/Util_MagCalibration.cpp Sun Sep 15 04:10:05 2013 +0300 41.3 @@ -1,1 +1,227 @@ 41.4 -/************************************************************************************ 41.5 41.6 Filename : Util_MagCalibration.cpp 41.7 Content : Procedures for calibrating the magnetometer 41.8 Created : April 16, 2013 41.9 Authors : Steve LaValle, Andrew Reisse 41.10 41.11 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 41.12 41.13 Use of this software is subject to the terms of the Oculus license 41.14 agreement provided at the time of installation or download, or which 41.15 otherwise accompanies this software in either electronic or hard copy form. 41.16 41.17 *************************************************************************************/ 41.18 41.19 #include "Util_MagCalibration.h" 41.20 41.21 namespace OVR { namespace Util { 41.22 41.23 void MagCalibration::BeginAutoCalibration(SensorFusion& sf) 41.24 { 41.25 Stat = Mag_AutoCalibrating; 41.26 // This is a "hard" reset of the mag, so need to clear stored values 41.27 sf.ClearMagCalibration(); 41.28 SampleCount = 0; 41.29 41.30 // reset the statistics 41.31 MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); 41.32 MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); 41.33 MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); 41.34 MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); 41.35 } 41.36 41.37 unsigned MagCalibration::UpdateAutoCalibration(SensorFusion& sf) 41.38 { 41.39 if (Stat != Mag_AutoCalibrating) 41.40 return Stat; 41.41 41.42 Quatf q = sf.GetOrientation(); 41.43 Vector3f m = sf.GetMagnetometer(); 41.44 41.45 InsertIfAcceptable(q, m); 41.46 41.47 if ((SampleCount == 4) && (Stat == Mag_AutoCalibrating)) 41.48 { 41.49 //LogText("Magnetometer Output Spread: %f %f %f\n",MagSpread.x,MagSpread.y,MagSpread.z); 41.50 //LogText("Quaternion Spread: %f %f %f %f\n",QuatSpread.x,QuatSpread.y,QuatSpread.z,QuatSpread.w); 41.51 SetCalibration(sf); 41.52 } 41.53 41.54 return Stat; 41.55 41.56 } 41.57 41.58 void MagCalibration::BeginManualCalibration(SensorFusion& sf) 41.59 { 41.60 Stat = Mag_ManuallyCalibrating; 41.61 sf.ClearMagCalibration(); 41.62 SampleCount = 0; 41.63 } 41.64 41.65 bool MagCalibration::IsAcceptableSample(const Quatf& q, const Vector3f& m) 41.66 { 41.67 switch (SampleCount) 41.68 { 41.69 // Initial sample is always acceptable 41.70 case 0: 41.71 return true; 41.72 break; 41.73 case 1: 41.74 return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.75 ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq); 41.76 break; 41.77 case 2: 41.78 return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.79 (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& 41.80 ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq)&& 41.81 ((m - MagSamples[1]).LengthSq() > MinMagDistanceSq); 41.82 break; 41.83 case 3: 41.84 return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.85 (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& 41.86 (q.DistanceSq(QuatSamples[2]) > MinQuatDistanceSq)&& 41.87 ((PointToPlaneDistance(MagSamples[0],MagSamples[1],MagSamples[2],m) > MinMagDistance)|| 41.88 (PointToPlaneDistance(MagSamples[1],MagSamples[2],m,MagSamples[0]) > MinMagDistance)|| 41.89 (PointToPlaneDistance(MagSamples[2],m,MagSamples[0],MagSamples[1]) > MinMagDistance)|| 41.90 (PointToPlaneDistance(m,MagSamples[0],MagSamples[1],MagSamples[2]) > MinMagDistance)); 41.91 } 41.92 41.93 return false; 41.94 } 41.95 41.96 41.97 bool MagCalibration::InsertIfAcceptable(const Quatf& q, const Vector3f& m) 41.98 { 41.99 // Update some statistics 41.100 if (m.x < MinMagValues.x) 41.101 MinMagValues.x = m.x; 41.102 if (m.y < MinMagValues.y) 41.103 MinMagValues.y = m.y; 41.104 if (m.z < MinMagValues.z) 41.105 MinMagValues.z = m.z; 41.106 if (m.x > MaxMagValues.x) 41.107 MaxMagValues.x = m.x; 41.108 if (m.y > MaxMagValues.y) 41.109 MaxMagValues.y = m.y; 41.110 if (m.z > MaxMagValues.z) 41.111 MaxMagValues.z = m.z; 41.112 if (q.x < MinQuatValues.x) 41.113 MinQuatValues.x = q.x; 41.114 if (q.y < MinQuatValues.y) 41.115 MinQuatValues.y = q.y; 41.116 if (q.z < MinQuatValues.z) 41.117 MinQuatValues.z = q.z; 41.118 if (q.w < MinQuatValues.w) 41.119 MinQuatValues.w = q.w; 41.120 if (q.x > MaxQuatValues.x) 41.121 MaxQuatValues.x = q.x; 41.122 if (q.y > MaxQuatValues.y) 41.123 MaxQuatValues.y = q.y; 41.124 if (q.z > MaxQuatValues.z) 41.125 MaxQuatValues.z = q.z; 41.126 if (q.w > MaxQuatValues.w) 41.127 MaxQuatValues.w = q.w; 41.128 MagSpread = MaxMagValues - MinMagValues; 41.129 QuatSpread = MaxQuatValues - MinQuatValues; 41.130 41.131 if (IsAcceptableSample(q, m)) 41.132 { 41.133 MagSamples[SampleCount] = m; 41.134 QuatSamples[SampleCount] = q; 41.135 SampleCount++; 41.136 return true; 41.137 } 41.138 41.139 return false; 41.140 } 41.141 41.142 Matrix4f MagCalibration::GetMagCalibration() const 41.143 { 41.144 Matrix4f calMat = Matrix4f(); 41.145 calMat.M[0][3] = -MagCenter.x; 41.146 calMat.M[1][3] = -MagCenter.y; 41.147 calMat.M[2][3] = -MagCenter.z; 41.148 return calMat; 41.149 } 41.150 41.151 bool MagCalibration::SetCalibration(SensorFusion& sf) 41.152 { 41.153 if (SampleCount < 4) 41.154 return false; 41.155 41.156 MagCenter = CalculateSphereCenter(MagSamples[0],MagSamples[1],MagSamples[2],MagSamples[3]); 41.157 Matrix4f calMat = GetMagCalibration(); 41.158 sf.SetMagCalibration(calMat); 41.159 Stat = Mag_Calibrated; 41.160 //LogText("MagCenter: %f %f %f\n",MagCenter.x,MagCenter.y,MagCenter.z); 41.161 41.162 return true; 41.163 } 41.164 41.165 41.166 // Calculate the center of a sphere that passes through p1, p2, p3, p4 41.167 Vector3f MagCalibration::CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, 41.168 const Vector3f& p3, const Vector3f& p4) 41.169 { 41.170 Matrix4f A; 41.171 int i; 41.172 Vector3f p[4]; 41.173 p[0] = p1; 41.174 p[1] = p2; 41.175 p[2] = p3; 41.176 p[3] = p4; 41.177 41.178 for (i = 0; i < 4; i++) 41.179 { 41.180 A.M[i][0] = p[i].x; 41.181 A.M[i][1] = p[i].y; 41.182 A.M[i][2] = p[i].z; 41.183 A.M[i][3] = 1.0f; 41.184 } 41.185 float m11 = A.Determinant(); 41.186 OVR_ASSERT(m11 != 0.0f); 41.187 41.188 for (i = 0; i < 4; i++) 41.189 { 41.190 A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.191 A.M[i][1] = p[i].y; 41.192 A.M[i][2] = p[i].z; 41.193 A.M[i][3] = 1.0f; 41.194 } 41.195 float m12 = A.Determinant(); 41.196 41.197 for (i = 0; i < 4; i++) 41.198 { 41.199 A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.200 A.M[i][1] = p[i].x; 41.201 A.M[i][2] = p[i].z; 41.202 A.M[i][3] = 1.0f; 41.203 } 41.204 float m13 = A.Determinant(); 41.205 41.206 for (i = 0; i < 4; i++) 41.207 { 41.208 A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.209 A.M[i][1] = p[i].x; 41.210 A.M[i][2] = p[i].y; 41.211 A.M[i][3] = 1.0f; 41.212 } 41.213 float m14 = A.Determinant(); 41.214 41.215 float c = 0.5f / m11; 41.216 return Vector3f(c*m12, -c*m13, c*m14); 41.217 } 41.218 41.219 // Distance from p4 to the nearest point on a plane through p1, p2, p3 41.220 float MagCalibration::PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, 41.221 const Vector3f& p3, const Vector3f& p4) 41.222 { 41.223 Vector3f v1 = p1 - p2; 41.224 Vector3f v2 = p1 - p3; 41.225 Vector3f planeNormal = v1.Cross(v2); 41.226 planeNormal.Normalize(); 41.227 return (fabs((planeNormal * p4) - planeNormal * p1)); 41.228 } 41.229 41.230 }} 41.231 \ No newline at end of file 41.232 +/************************************************************************************ 41.233 + 41.234 +Filename : Util_MagCalibration.cpp 41.235 +Content : Procedures for calibrating the magnetometer 41.236 +Created : April 16, 2013 41.237 +Authors : Steve LaValle, Andrew Reisse 41.238 + 41.239 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 41.240 + 41.241 +Use of this software is subject to the terms of the Oculus license 41.242 +agreement provided at the time of installation or download, or which 41.243 +otherwise accompanies this software in either electronic or hard copy form. 41.244 + 41.245 +*************************************************************************************/ 41.246 + 41.247 +#include "Util_MagCalibration.h" 41.248 + 41.249 +namespace OVR { namespace Util { 41.250 + 41.251 +void MagCalibration::BeginAutoCalibration(SensorFusion& sf) 41.252 +{ 41.253 + Stat = Mag_AutoCalibrating; 41.254 + // This is a "hard" reset of the mag, so need to clear stored values 41.255 + sf.ClearMagCalibration(); 41.256 + SampleCount = 0; 41.257 + 41.258 + // reset the statistics 41.259 + MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); 41.260 + MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); 41.261 + MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); 41.262 + MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); 41.263 +} 41.264 + 41.265 +unsigned MagCalibration::UpdateAutoCalibration(SensorFusion& sf) 41.266 +{ 41.267 + if (Stat != Mag_AutoCalibrating) 41.268 + return Stat; 41.269 + 41.270 + Quatf q = sf.GetOrientation(); 41.271 + Vector3f m = sf.GetMagnetometer(); 41.272 + 41.273 + InsertIfAcceptable(q, m); 41.274 + 41.275 + if ((SampleCount == 4) && (Stat == Mag_AutoCalibrating)) 41.276 + { 41.277 + //LogText("Magnetometer Output Spread: %f %f %f\n",MagSpread.x,MagSpread.y,MagSpread.z); 41.278 + //LogText("Quaternion Spread: %f %f %f %f\n",QuatSpread.x,QuatSpread.y,QuatSpread.z,QuatSpread.w); 41.279 + SetCalibration(sf); 41.280 + } 41.281 + 41.282 + return Stat; 41.283 + 41.284 +} 41.285 + 41.286 +void MagCalibration::BeginManualCalibration(SensorFusion& sf) 41.287 +{ 41.288 + Stat = Mag_ManuallyCalibrating; 41.289 + sf.ClearMagCalibration(); 41.290 + SampleCount = 0; 41.291 +} 41.292 + 41.293 +bool MagCalibration::IsAcceptableSample(const Quatf& q, const Vector3f& m) 41.294 +{ 41.295 + switch (SampleCount) 41.296 + { 41.297 + // Initial sample is always acceptable 41.298 + case 0: 41.299 + return true; 41.300 + break; 41.301 + case 1: 41.302 + return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.303 + ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq); 41.304 + break; 41.305 + case 2: 41.306 + return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.307 + (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& 41.308 + ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq)&& 41.309 + ((m - MagSamples[1]).LengthSq() > MinMagDistanceSq); 41.310 + break; 41.311 + case 3: 41.312 + return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& 41.313 + (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& 41.314 + (q.DistanceSq(QuatSamples[2]) > MinQuatDistanceSq)&& 41.315 + ((PointToPlaneDistance(MagSamples[0],MagSamples[1],MagSamples[2],m) > MinMagDistance)|| 41.316 + (PointToPlaneDistance(MagSamples[1],MagSamples[2],m,MagSamples[0]) > MinMagDistance)|| 41.317 + (PointToPlaneDistance(MagSamples[2],m,MagSamples[0],MagSamples[1]) > MinMagDistance)|| 41.318 + (PointToPlaneDistance(m,MagSamples[0],MagSamples[1],MagSamples[2]) > MinMagDistance)); 41.319 + } 41.320 + 41.321 + return false; 41.322 +} 41.323 + 41.324 + 41.325 +bool MagCalibration::InsertIfAcceptable(const Quatf& q, const Vector3f& m) 41.326 +{ 41.327 + // Update some statistics 41.328 + if (m.x < MinMagValues.x) 41.329 + MinMagValues.x = m.x; 41.330 + if (m.y < MinMagValues.y) 41.331 + MinMagValues.y = m.y; 41.332 + if (m.z < MinMagValues.z) 41.333 + MinMagValues.z = m.z; 41.334 + if (m.x > MaxMagValues.x) 41.335 + MaxMagValues.x = m.x; 41.336 + if (m.y > MaxMagValues.y) 41.337 + MaxMagValues.y = m.y; 41.338 + if (m.z > MaxMagValues.z) 41.339 + MaxMagValues.z = m.z; 41.340 + if (q.x < MinQuatValues.x) 41.341 + MinQuatValues.x = q.x; 41.342 + if (q.y < MinQuatValues.y) 41.343 + MinQuatValues.y = q.y; 41.344 + if (q.z < MinQuatValues.z) 41.345 + MinQuatValues.z = q.z; 41.346 + if (q.w < MinQuatValues.w) 41.347 + MinQuatValues.w = q.w; 41.348 + if (q.x > MaxQuatValues.x) 41.349 + MaxQuatValues.x = q.x; 41.350 + if (q.y > MaxQuatValues.y) 41.351 + MaxQuatValues.y = q.y; 41.352 + if (q.z > MaxQuatValues.z) 41.353 + MaxQuatValues.z = q.z; 41.354 + if (q.w > MaxQuatValues.w) 41.355 + MaxQuatValues.w = q.w; 41.356 + MagSpread = MaxMagValues - MinMagValues; 41.357 + QuatSpread = MaxQuatValues - MinQuatValues; 41.358 + 41.359 + if (IsAcceptableSample(q, m)) 41.360 + { 41.361 + MagSamples[SampleCount] = m; 41.362 + QuatSamples[SampleCount] = q; 41.363 + SampleCount++; 41.364 + return true; 41.365 + } 41.366 + 41.367 + return false; 41.368 +} 41.369 + 41.370 +Matrix4f MagCalibration::GetMagCalibration() const 41.371 +{ 41.372 + Matrix4f calMat = Matrix4f(); 41.373 + calMat.M[0][3] = -MagCenter.x; 41.374 + calMat.M[1][3] = -MagCenter.y; 41.375 + calMat.M[2][3] = -MagCenter.z; 41.376 + return calMat; 41.377 +} 41.378 + 41.379 +bool MagCalibration::SetCalibration(SensorFusion& sf) 41.380 +{ 41.381 + if (SampleCount < 4) 41.382 + return false; 41.383 + 41.384 + MagCenter = CalculateSphereCenter(MagSamples[0],MagSamples[1],MagSamples[2],MagSamples[3]); 41.385 + Matrix4f calMat = GetMagCalibration(); 41.386 + sf.SetMagCalibration(calMat); 41.387 + Stat = Mag_Calibrated; 41.388 + //LogText("MagCenter: %f %f %f\n",MagCenter.x,MagCenter.y,MagCenter.z); 41.389 + 41.390 + return true; 41.391 +} 41.392 + 41.393 + 41.394 +// Calculate the center of a sphere that passes through p1, p2, p3, p4 41.395 +Vector3f MagCalibration::CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, 41.396 + const Vector3f& p3, const Vector3f& p4) 41.397 +{ 41.398 + Matrix4f A; 41.399 + int i; 41.400 + Vector3f p[4]; 41.401 + p[0] = p1; 41.402 + p[1] = p2; 41.403 + p[2] = p3; 41.404 + p[3] = p4; 41.405 + 41.406 + for (i = 0; i < 4; i++) 41.407 + { 41.408 + A.M[i][0] = p[i].x; 41.409 + A.M[i][1] = p[i].y; 41.410 + A.M[i][2] = p[i].z; 41.411 + A.M[i][3] = 1.0f; 41.412 + } 41.413 + float m11 = A.Determinant(); 41.414 + OVR_ASSERT(m11 != 0.0f); 41.415 + 41.416 + for (i = 0; i < 4; i++) 41.417 + { 41.418 + A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.419 + A.M[i][1] = p[i].y; 41.420 + A.M[i][2] = p[i].z; 41.421 + A.M[i][3] = 1.0f; 41.422 + } 41.423 + float m12 = A.Determinant(); 41.424 + 41.425 + for (i = 0; i < 4; i++) 41.426 + { 41.427 + A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.428 + A.M[i][1] = p[i].x; 41.429 + A.M[i][2] = p[i].z; 41.430 + A.M[i][3] = 1.0f; 41.431 + } 41.432 + float m13 = A.Determinant(); 41.433 + 41.434 + for (i = 0; i < 4; i++) 41.435 + { 41.436 + A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; 41.437 + A.M[i][1] = p[i].x; 41.438 + A.M[i][2] = p[i].y; 41.439 + A.M[i][3] = 1.0f; 41.440 + } 41.441 + float m14 = A.Determinant(); 41.442 + 41.443 + float c = 0.5f / m11; 41.444 + return Vector3f(c*m12, -c*m13, c*m14); 41.445 +} 41.446 + 41.447 +// Distance from p4 to the nearest point on a plane through p1, p2, p3 41.448 +float MagCalibration::PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, 41.449 + const Vector3f& p3, const Vector3f& p4) 41.450 +{ 41.451 + Vector3f v1 = p1 - p2; 41.452 + Vector3f v2 = p1 - p3; 41.453 + Vector3f planeNormal = v1.Cross(v2); 41.454 + planeNormal.Normalize(); 41.455 + return (fabs((planeNormal * p4) - planeNormal * p1)); 41.456 +} 41.457 + 41.458 +}}
42.1 --- a/libovr/Src/Util/Util_MagCalibration.h Sat Sep 14 17:51:03 2013 +0300 42.2 +++ b/libovr/Src/Util/Util_MagCalibration.h Sun Sep 15 04:10:05 2013 +0300 42.3 @@ -1,1 +1,138 @@ 42.4 -/************************************************************************************ 42.5 42.6 PublicHeader: OVR.h 42.7 Filename : Util_MagCalibration.h 42.8 Content : Procedures for calibrating the magnetometer 42.9 Created : April 16, 2013 42.10 Authors : Steve LaValle, Andrew Reisse 42.11 42.12 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 42.13 42.14 Use of this software is subject to the terms of the Oculus license 42.15 agreement provided at the time of installation or download, or which 42.16 otherwise accompanies this software in either electronic or hard copy form. 42.17 42.18 *************************************************************************************/ 42.19 42.20 #ifndef OVR_Util_MagCalibration_h 42.21 #define OVR_Util_MagCalibration_h 42.22 42.23 #include "../OVR_SensorFusion.h" 42.24 #include "../Kernel/OVR_String.h" 42.25 #include "../Kernel/OVR_Log.h" 42.26 42.27 namespace OVR { namespace Util { 42.28 42.29 class MagCalibration 42.30 { 42.31 public: 42.32 enum MagStatus 42.33 { 42.34 Mag_Uninitialized = 0, 42.35 Mag_AutoCalibrating = 1, 42.36 Mag_ManuallyCalibrating = 2, 42.37 Mag_Calibrated = 3 42.38 }; 42.39 42.40 MagCalibration() : 42.41 Stat(Mag_Uninitialized), 42.42 MinMagDistance(0.2f), MinQuatDistance(0.5f), 42.43 SampleCount(0) 42.44 { 42.45 MinMagDistanceSq = MinMagDistance * MinMagDistance; 42.46 MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; 42.47 MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); 42.48 MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); 42.49 MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); 42.50 MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); 42.51 } 42.52 42.53 // Methods that are useful for either auto or manual calibration 42.54 bool IsUnitialized() const { return Stat == Mag_Uninitialized; } 42.55 bool IsCalibrated() const { return Stat == Mag_Calibrated; } 42.56 int NumberOfSamples() const { return SampleCount; } 42.57 int RequiredSampleCount() const { return 4; } 42.58 void AbortCalibration() 42.59 { 42.60 Stat = Mag_Uninitialized; 42.61 SampleCount = 0; 42.62 } 42.63 42.64 void ClearCalibration(SensorFusion& sf) 42.65 { 42.66 Stat = Mag_Uninitialized; 42.67 SampleCount = 0; 42.68 sf.ClearMagCalibration(); 42.69 }; 42.70 42.71 // Methods for automatic magnetometer calibration 42.72 void BeginAutoCalibration(SensorFusion& sf); 42.73 unsigned UpdateAutoCalibration(SensorFusion& sf); 42.74 bool IsAutoCalibrating() const { return Stat == Mag_AutoCalibrating; } 42.75 42.76 // Methods for building a manual (user-guided) calibraton procedure 42.77 void BeginManualCalibration(SensorFusion& sf); 42.78 bool IsAcceptableSample(const Quatf& q, const Vector3f& m); 42.79 bool InsertIfAcceptable(const Quatf& q, const Vector3f& m); 42.80 // Returns true if successful, requiring that SampleCount = 4 42.81 bool SetCalibration(SensorFusion& sf); 42.82 bool IsManuallyCalibrating() const { return Stat == Mag_ManuallyCalibrating; } 42.83 42.84 // This is the minimum acceptable distance (Euclidean) between raw 42.85 // magnetometer values to be acceptable for usage in calibration. 42.86 void SetMinMagDistance(float dist) 42.87 { 42.88 MinMagDistance = dist; 42.89 MinMagDistanceSq = MinMagDistance * MinMagDistance; 42.90 } 42.91 42.92 // The minimum acceptable distance (4D Euclidean) between orientations 42.93 // to be acceptable for calibration usage. 42.94 void SetMinQuatDistance(float dist) 42.95 { 42.96 MinQuatDistance = dist; 42.97 MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; 42.98 } 42.99 42.100 // A result of the calibration, which is the center of a sphere that 42.101 // roughly approximates the magnetometer data. 42.102 Vector3f GetMagCenter() const { return MagCenter; } 42.103 // Retrieves the full magnetometer calibration matrix 42.104 Matrix4f GetMagCalibration() const; 42.105 // Retrieves the range of each quaternion term during calibration 42.106 Quatf GetCalibrationQuatSpread() const { return QuatSpread; } 42.107 // Retrieves the range of each magnetometer term during calibration 42.108 Vector3f GetCalibrationMagSpread() const { return MagSpread; } 42.109 42.110 private: 42.111 // Determine the unique sphere through 4 non-coplanar points 42.112 Vector3f CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, 42.113 const Vector3f& p3, const Vector3f& p4); 42.114 42.115 // Distance from p4 to the nearest point on a plane through p1, p2, p3 42.116 float PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, 42.117 const Vector3f& p3, const Vector3f& p4); 42.118 42.119 Vector3f MagCenter; 42.120 unsigned Stat; 42.121 float MinMagDistance; 42.122 float MinQuatDistance; 42.123 float MinMagDistanceSq; 42.124 float MinQuatDistanceSq; 42.125 // For gathering statistics during calibration 42.126 Vector3f MinMagValues; 42.127 Vector3f MaxMagValues; 42.128 Vector3f MagSpread; 42.129 Quatf MinQuatValues; 42.130 Quatf MaxQuatValues; 42.131 Quatf QuatSpread; 42.132 42.133 unsigned SampleCount; 42.134 Vector3f MagSamples[4]; 42.135 Quatf QuatSamples[4]; 42.136 42.137 }; 42.138 42.139 }} 42.140 42.141 #endif 42.142 \ No newline at end of file 42.143 +/************************************************************************************ 42.144 + 42.145 +PublicHeader: OVR.h 42.146 +Filename : Util_MagCalibration.h 42.147 +Content : Procedures for calibrating the magnetometer 42.148 +Created : April 16, 2013 42.149 +Authors : Steve LaValle, Andrew Reisse 42.150 + 42.151 +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. 42.152 + 42.153 +Use of this software is subject to the terms of the Oculus license 42.154 +agreement provided at the time of installation or download, or which 42.155 +otherwise accompanies this software in either electronic or hard copy form. 42.156 + 42.157 +*************************************************************************************/ 42.158 + 42.159 +#ifndef OVR_Util_MagCalibration_h 42.160 +#define OVR_Util_MagCalibration_h 42.161 + 42.162 +#include "../OVR_SensorFusion.h" 42.163 +#include "../Kernel/OVR_String.h" 42.164 +#include "../Kernel/OVR_Log.h" 42.165 + 42.166 +namespace OVR { namespace Util { 42.167 + 42.168 +class MagCalibration 42.169 +{ 42.170 +public: 42.171 + enum MagStatus 42.172 + { 42.173 + Mag_Uninitialized = 0, 42.174 + Mag_AutoCalibrating = 1, 42.175 + Mag_ManuallyCalibrating = 2, 42.176 + Mag_Calibrated = 3 42.177 + }; 42.178 + 42.179 + MagCalibration() : 42.180 + Stat(Mag_Uninitialized), 42.181 + MinMagDistance(0.2f), MinQuatDistance(0.5f), 42.182 + SampleCount(0) 42.183 + { 42.184 + MinMagDistanceSq = MinMagDistance * MinMagDistance; 42.185 + MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; 42.186 + MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); 42.187 + MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); 42.188 + MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); 42.189 + MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); 42.190 + } 42.191 + 42.192 + // Methods that are useful for either auto or manual calibration 42.193 + bool IsUnitialized() const { return Stat == Mag_Uninitialized; } 42.194 + bool IsCalibrated() const { return Stat == Mag_Calibrated; } 42.195 + int NumberOfSamples() const { return SampleCount; } 42.196 + int RequiredSampleCount() const { return 4; } 42.197 + void AbortCalibration() 42.198 + { 42.199 + Stat = Mag_Uninitialized; 42.200 + SampleCount = 0; 42.201 + } 42.202 + 42.203 + void ClearCalibration(SensorFusion& sf) 42.204 + { 42.205 + Stat = Mag_Uninitialized; 42.206 + SampleCount = 0; 42.207 + sf.ClearMagCalibration(); 42.208 + }; 42.209 + 42.210 + // Methods for automatic magnetometer calibration 42.211 + void BeginAutoCalibration(SensorFusion& sf); 42.212 + unsigned UpdateAutoCalibration(SensorFusion& sf); 42.213 + bool IsAutoCalibrating() const { return Stat == Mag_AutoCalibrating; } 42.214 + 42.215 + // Methods for building a manual (user-guided) calibraton procedure 42.216 + void BeginManualCalibration(SensorFusion& sf); 42.217 + bool IsAcceptableSample(const Quatf& q, const Vector3f& m); 42.218 + bool InsertIfAcceptable(const Quatf& q, const Vector3f& m); 42.219 + // Returns true if successful, requiring that SampleCount = 4 42.220 + bool SetCalibration(SensorFusion& sf); 42.221 + bool IsManuallyCalibrating() const { return Stat == Mag_ManuallyCalibrating; } 42.222 + 42.223 + // This is the minimum acceptable distance (Euclidean) between raw 42.224 + // magnetometer values to be acceptable for usage in calibration. 42.225 + void SetMinMagDistance(float dist) 42.226 + { 42.227 + MinMagDistance = dist; 42.228 + MinMagDistanceSq = MinMagDistance * MinMagDistance; 42.229 + } 42.230 + 42.231 + // The minimum acceptable distance (4D Euclidean) between orientations 42.232 + // to be acceptable for calibration usage. 42.233 + void SetMinQuatDistance(float dist) 42.234 + { 42.235 + MinQuatDistance = dist; 42.236 + MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; 42.237 + } 42.238 + 42.239 + // A result of the calibration, which is the center of a sphere that 42.240 + // roughly approximates the magnetometer data. 42.241 + Vector3f GetMagCenter() const { return MagCenter; } 42.242 + // Retrieves the full magnetometer calibration matrix 42.243 + Matrix4f GetMagCalibration() const; 42.244 + // Retrieves the range of each quaternion term during calibration 42.245 + Quatf GetCalibrationQuatSpread() const { return QuatSpread; } 42.246 + // Retrieves the range of each magnetometer term during calibration 42.247 + Vector3f GetCalibrationMagSpread() const { return MagSpread; } 42.248 + 42.249 +private: 42.250 + // Determine the unique sphere through 4 non-coplanar points 42.251 + Vector3f CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, 42.252 + const Vector3f& p3, const Vector3f& p4); 42.253 + 42.254 + // Distance from p4 to the nearest point on a plane through p1, p2, p3 42.255 + float PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, 42.256 + const Vector3f& p3, const Vector3f& p4); 42.257 + 42.258 + Vector3f MagCenter; 42.259 + unsigned Stat; 42.260 + float MinMagDistance; 42.261 + float MinQuatDistance; 42.262 + float MinMagDistanceSq; 42.263 + float MinQuatDistanceSq; 42.264 + // For gathering statistics during calibration 42.265 + Vector3f MinMagValues; 42.266 + Vector3f MaxMagValues; 42.267 + Vector3f MagSpread; 42.268 + Quatf MinQuatValues; 42.269 + Quatf MaxQuatValues; 42.270 + Quatf QuatSpread; 42.271 + 42.272 + unsigned SampleCount; 42.273 + Vector3f MagSamples[4]; 42.274 + Quatf QuatSamples[4]; 42.275 + 42.276 +}; 42.277 + 42.278 +}} 42.279 + 42.280 +#endif
43.1 --- a/libovr/Src/Util/Util_Render_Stereo.cpp Sat Sep 14 17:51:03 2013 +0300 43.2 +++ b/libovr/Src/Util/Util_Render_Stereo.cpp Sun Sep 15 04:10:05 2013 +0300 43.3 @@ -1,1 +1,314 @@ 43.4 -/************************************************************************************ 43.5 43.6 Filename : Util_Render_Stereo.cpp 43.7 Content : Stereo rendering configuration implementation 43.8 Created : October 22, 2012 43.9 Authors : Michael Antonov, Andrew Reisse 43.10 43.11 Copyright : Copyright 2012 Oculus, Inc. All Rights reserved. 43.12 43.13 Use of this software is subject to the terms of the Oculus Inc license 43.14 agreement provided at the time of installation or download, or which 43.15 otherwise accompanies this software in either electronic or hard copy form. 43.16 43.17 *************************************************************************************/ 43.18 43.19 #include "Util_Render_Stereo.h" 43.20 43.21 namespace OVR { namespace Util { namespace Render { 43.22 43.23 43.24 //----------------------------------------------------------------------------------- 43.25 43.26 // DistortionFnInverse computes the inverse of the distortion function on an argument. 43.27 float DistortionConfig::DistortionFnInverse(float r) 43.28 { 43.29 OVR_ASSERT((r <= 10.0f)); 43.30 43.31 float s, d; 43.32 float delta = r * 0.25f; 43.33 43.34 s = r * 0.5f; 43.35 d = fabs(r - DistortionFn(s)); 43.36 43.37 for (int i = 0; i < 20; i++) 43.38 { 43.39 float sUp = s + delta; 43.40 float sDown = s - delta; 43.41 float dUp = fabs(r - DistortionFn(sUp)); 43.42 float dDown = fabs(r - DistortionFn(sDown)); 43.43 43.44 if (dUp < d) 43.45 { 43.46 s = sUp; 43.47 d = dUp; 43.48 } 43.49 else if (dDown < d) 43.50 { 43.51 s = sDown; 43.52 d = dDown; 43.53 } 43.54 else 43.55 { 43.56 delta *= 0.5f; 43.57 } 43.58 } 43.59 43.60 return s; 43.61 } 43.62 43.63 43.64 //----------------------------------------------------------------------------------- 43.65 // **** StereoConfig Implementation 43.66 43.67 StereoConfig::StereoConfig(StereoMode mode, const Viewport& vp) 43.68 : Mode(mode), 43.69 InterpupillaryDistance(0.064f), AspectMultiplier(1.0f), 43.70 FullView(vp), DirtyFlag(true), IPDOverride(false), 43.71 YFov(0), Aspect(vp.w / float(vp.h)), ProjectionCenterOffset(0), 43.72 OrthoPixelOffset(0) 43.73 { 43.74 // And default distortion for it. 43.75 Distortion.SetCoefficients(1.0f, 0.22f, 0.24f); 43.76 Distortion.Scale = 1.0f; // Will be computed later. 43.77 43.78 // Fit left of the image. 43.79 DistortionFitX = -1.0f; 43.80 DistortionFitY = 0.0f; 43.81 43.82 // Initialize "fake" default HMD values for testing without HMD plugged in. 43.83 // These default values match those returned by the HMD. 43.84 HMD.HResolution = 1280; 43.85 HMD.VResolution = 800; 43.86 HMD.HScreenSize = 0.14976f; 43.87 HMD.VScreenSize = HMD.HScreenSize / (1280.0f / 800.0f); 43.88 HMD.InterpupillaryDistance = InterpupillaryDistance; 43.89 HMD.LensSeparationDistance = 0.0635f; 43.90 HMD.EyeToScreenDistance = 0.041f; 43.91 HMD.DistortionK[0] = Distortion.K[0]; 43.92 HMD.DistortionK[1] = Distortion.K[1]; 43.93 HMD.DistortionK[2] = Distortion.K[2]; 43.94 HMD.DistortionK[3] = 0; 43.95 43.96 Set2DAreaFov(DegreeToRad(85.0f)); 43.97 } 43.98 43.99 void StereoConfig::SetFullViewport(const Viewport& vp) 43.100 { 43.101 if (vp != FullView) 43.102 { 43.103 FullView = vp; 43.104 DirtyFlag = true; 43.105 } 43.106 } 43.107 43.108 void StereoConfig::SetHMDInfo(const HMDInfo& hmd) 43.109 { 43.110 HMD = hmd; 43.111 Distortion.K[0] = hmd.DistortionK[0]; 43.112 Distortion.K[1] = hmd.DistortionK[1]; 43.113 Distortion.K[2] = hmd.DistortionK[2]; 43.114 Distortion.K[3] = hmd.DistortionK[3]; 43.115 43.116 Distortion.SetChromaticAberration(hmd.ChromaAbCorrection[0], hmd.ChromaAbCorrection[1], 43.117 hmd.ChromaAbCorrection[2], hmd.ChromaAbCorrection[3]); 43.118 43.119 if (!IPDOverride) 43.120 InterpupillaryDistance = HMD.InterpupillaryDistance; 43.121 43.122 DirtyFlag = true; 43.123 } 43.124 43.125 void StereoConfig::SetDistortionFitPointVP(float x, float y) 43.126 { 43.127 DistortionFitX = x; 43.128 DistortionFitY = y; 43.129 DirtyFlag = true; 43.130 } 43.131 43.132 void StereoConfig::SetDistortionFitPointPixels(float x, float y) 43.133 { 43.134 DistortionFitX = (4 * x / float(FullView.w)) - 1.0f; 43.135 DistortionFitY = (2 * y / float(FullView.h)) - 1.0f; 43.136 DirtyFlag = true; 43.137 } 43.138 43.139 void StereoConfig::Set2DAreaFov(float fovRadians) 43.140 { 43.141 Area2DFov = fovRadians; 43.142 DirtyFlag = true; 43.143 } 43.144 43.145 43.146 const StereoEyeParams& StereoConfig::GetEyeRenderParams(StereoEye eye) 43.147 { 43.148 static const UByte eyeParamIndices[3] = { 0, 0, 1 }; 43.149 43.150 updateIfDirty(); 43.151 OVR_ASSERT(eye < sizeof(eyeParamIndices)); 43.152 return EyeRenderParams[eyeParamIndices[eye]]; 43.153 } 43.154 43.155 43.156 void StereoConfig::updateComputedState() 43.157 { 43.158 // Need to compute all of the following: 43.159 // - Aspect Ratio 43.160 // - FOV 43.161 // - Projection offsets for 3D 43.162 // - Distortion XCenterOffset 43.163 // - Update 2D 43.164 // - Initialize EyeRenderParams 43.165 43.166 // Compute aspect ratio. Stereo mode cuts width in half. 43.167 Aspect = float(FullView.w) / float(FullView.h); 43.168 Aspect *= (Mode == Stereo_None) ? 1.0f : 0.5f; 43.169 Aspect *= AspectMultiplier; 43.170 43.171 updateDistortionOffsetAndScale(); 43.172 43.173 // Compute Vertical FOV based on distance, distortion, etc. 43.174 // Distance from vertical center to render vertical edge perceived through the lens. 43.175 // This will be larger then normal screen size due to magnification & distortion. 43.176 // 43.177 // This percievedHalfRTDistance equation should hold as long as the render target 43.178 // and display have the same aspect ratios. What we'd like to know is where the edge 43.179 // of the render target will on the perceived screen surface. With NO LENS, 43.180 // the answer would be: 43.181 // 43.182 // halfRTDistance = (VScreenSize / 2) * aspect * 43.183 // DistortionFn_Inverse( DistortionScale / aspect ) 43.184 // 43.185 // To model the optical lens we eliminates DistortionFn_Inverse. Aspect ratios 43.186 // cancel out, so we get: 43.187 // 43.188 // halfRTDistance = (VScreenSize / 2) * DistortionScale 43.189 // 43.190 if (Mode == Stereo_None) 43.191 { 43.192 YFov = DegreeToRad(80.0f); 43.193 } 43.194 else 43.195 { 43.196 float percievedHalfRTDistance = (HMD.VScreenSize / 2) * Distortion.Scale; 43.197 YFov = 2.0f * atan(percievedHalfRTDistance/HMD.EyeToScreenDistance); 43.198 } 43.199 43.200 updateProjectionOffset(); 43.201 update2D(); 43.202 updateEyeParams(); 43.203 43.204 DirtyFlag = false; 43.205 } 43.206 43.207 void StereoConfig::updateDistortionOffsetAndScale() 43.208 { 43.209 // Distortion center shift is stored separately, since it isn't affected 43.210 // by the eye distance. 43.211 float lensOffset = HMD.LensSeparationDistance * 0.5f; 43.212 float lensShift = HMD.HScreenSize * 0.25f - lensOffset; 43.213 float lensViewportShift = 4.0f * lensShift / HMD.HScreenSize; 43.214 Distortion.XCenterOffset= lensViewportShift; 43.215 43.216 // Compute distortion scale from DistortionFitX & DistortionFitY. 43.217 // Fit value of 0.0 means "no fit". 43.218 if ((fabs(DistortionFitX) < 0.0001f) && (fabs(DistortionFitY) < 0.0001f)) 43.219 { 43.220 Distortion.Scale = 1.0f; 43.221 } 43.222 else 43.223 { 43.224 // Convert fit value to distortion-centered coordinates before fit radius 43.225 // calculation. 43.226 float stereoAspect = 0.5f * float(FullView.w) / float(FullView.h); 43.227 float dx = DistortionFitX - Distortion.XCenterOffset; 43.228 float dy = DistortionFitY / stereoAspect; 43.229 float fitRadius = sqrt(dx * dx + dy * dy); 43.230 Distortion.Scale = Distortion.DistortionFn(fitRadius)/fitRadius; 43.231 } 43.232 } 43.233 43.234 void StereoConfig::updateProjectionOffset() 43.235 { 43.236 // Post-projection viewport coordinates range from (-1.0, 1.0), with the 43.237 // center of the left viewport falling at (1/4) of horizontal screen size. 43.238 // We need to shift this projection center to match with the lens center; 43.239 // note that we don't use the IPD here due to collimated light property of the lens. 43.240 // We compute this shift in physical units (meters) to 43.241 // correct for different screen sizes and then rescale to viewport coordinates. 43.242 float viewCenter = HMD.HScreenSize * 0.25f; 43.243 float eyeProjectionShift = viewCenter - HMD.LensSeparationDistance*0.5f; 43.244 ProjectionCenterOffset = 4.0f * eyeProjectionShift / HMD.HScreenSize; 43.245 } 43.246 43.247 void StereoConfig::update2D() 43.248 { 43.249 // Orthographic projection fakes a screen at a distance of 0.8m from the 43.250 // eye, where hmd screen projection surface is at 0.05m distance. 43.251 // This introduces an extra off-center pixel projection shift based on eye distance. 43.252 // This offCenterShift is the pixel offset of the other camera's center 43.253 // in your reference camera based on surface distance. 43.254 float metersToPixels = (HMD.HResolution / HMD.HScreenSize); 43.255 float lensDistanceScreenPixels= metersToPixels * HMD.LensSeparationDistance; 43.256 float eyeDistanceScreenPixels = metersToPixels * InterpupillaryDistance; 43.257 float offCenterShiftPixels = (HMD.EyeToScreenDistance / 0.8f) * eyeDistanceScreenPixels; 43.258 float leftPixelCenter = (HMD.HResolution / 2) - lensDistanceScreenPixels * 0.5f; 43.259 float rightPixelCenter = lensDistanceScreenPixels * 0.5f; 43.260 float pixelDifference = leftPixelCenter - rightPixelCenter; 43.261 43.262 // This computes the number of pixels that fit within specified 2D FOV (assuming 43.263 // distortion scaling will be done). 43.264 float percievedHalfScreenDistance = tan(Area2DFov * 0.5f) * HMD.EyeToScreenDistance; 43.265 float vfovSize = 2.0f * percievedHalfScreenDistance / Distortion.Scale; 43.266 FovPixels = HMD.VResolution * vfovSize / HMD.VScreenSize; 43.267 43.268 // Create orthographic matrix. 43.269 Matrix4f& m = OrthoCenter; 43.270 m.SetIdentity(); 43.271 m.M[0][0] = FovPixels / (FullView.w * 0.5f); 43.272 m.M[1][1] = -FovPixels / FullView.h; 43.273 m.M[0][3] = 0; 43.274 m.M[1][3] = 0; 43.275 m.M[2][2] = 0; 43.276 43.277 float orthoPixelOffset = (pixelDifference + offCenterShiftPixels/Distortion.Scale) * 0.5f; 43.278 OrthoPixelOffset = orthoPixelOffset * 2.0f / FovPixels; 43.279 } 43.280 43.281 void StereoConfig::updateEyeParams() 43.282 { 43.283 // Projection matrix for the center eye, which the left/right matrices are based on. 43.284 Matrix4f projCenter = Matrix4f::PerspectiveRH(YFov, Aspect, 0.01f, 2000.0f); 43.285 43.286 switch(Mode) 43.287 { 43.288 case Stereo_None: 43.289 { 43.290 EyeRenderParams[0].Init(StereoEye_Center, FullView, 0, projCenter, OrthoCenter); 43.291 } 43.292 break; 43.293 43.294 case Stereo_LeftRight_Multipass: 43.295 { 43.296 Matrix4f projLeft = Matrix4f::Translation(ProjectionCenterOffset, 0, 0) * projCenter, 43.297 projRight = Matrix4f::Translation(-ProjectionCenterOffset, 0, 0) * projCenter; 43.298 43.299 EyeRenderParams[0].Init(StereoEye_Left, 43.300 Viewport(FullView.x, FullView.y, FullView.w/2, FullView.h), 43.301 +InterpupillaryDistance * 0.5f, // World view shift. 43.302 projLeft, OrthoCenter * Matrix4f::Translation(OrthoPixelOffset, 0, 0), 43.303 &Distortion); 43.304 EyeRenderParams[1].Init(StereoEye_Right, 43.305 Viewport(FullView.x + FullView.w/2, FullView.y, FullView.w/2, FullView.h), 43.306 -InterpupillaryDistance * 0.5f, 43.307 projRight, OrthoCenter * Matrix4f::Translation(-OrthoPixelOffset, 0, 0), 43.308 &Distortion); 43.309 } 43.310 break; 43.311 } 43.312 43.313 } 43.314 43.315 43.316 }}} // OVR::Util::Render 43.317 43.318 \ No newline at end of file 43.319 +/************************************************************************************ 43.320 + 43.321 +Filename : Util_Render_Stereo.cpp 43.322 +Content : Stereo rendering configuration implementation 43.323 +Created : October 22, 2012 43.324 +Authors : Michael Antonov, Andrew Reisse 43.325 + 43.326 +Copyright : Copyright 2012 Oculus, Inc. All Rights reserved. 43.327 + 43.328 +Use of this software is subject to the terms of the Oculus Inc license 43.329 +agreement provided at the time of installation or download, or which 43.330 +otherwise accompanies this software in either electronic or hard copy form. 43.331 + 43.332 +*************************************************************************************/ 43.333 + 43.334 +#include "Util_Render_Stereo.h" 43.335 + 43.336 +namespace OVR { namespace Util { namespace Render { 43.337 + 43.338 + 43.339 +//----------------------------------------------------------------------------------- 43.340 + 43.341 +// DistortionFnInverse computes the inverse of the distortion function on an argument. 43.342 +float DistortionConfig::DistortionFnInverse(float r) 43.343 +{ 43.344 + OVR_ASSERT((r <= 10.0f)); 43.345 + 43.346 + float s, d; 43.347 + float delta = r * 0.25f; 43.348 + 43.349 + s = r * 0.5f; 43.350 + d = fabs(r - DistortionFn(s)); 43.351 + 43.352 + for (int i = 0; i < 20; i++) 43.353 + { 43.354 + float sUp = s + delta; 43.355 + float sDown = s - delta; 43.356 + float dUp = fabs(r - DistortionFn(sUp)); 43.357 + float dDown = fabs(r - DistortionFn(sDown)); 43.358 + 43.359 + if (dUp < d) 43.360 + { 43.361 + s = sUp; 43.362 + d = dUp; 43.363 + } 43.364 + else if (dDown < d) 43.365 + { 43.366 + s = sDown; 43.367 + d = dDown; 43.368 + } 43.369 + else 43.370 + { 43.371 + delta *= 0.5f; 43.372 + } 43.373 + } 43.374 + 43.375 + return s; 43.376 +} 43.377 + 43.378 + 43.379 +//----------------------------------------------------------------------------------- 43.380 +// **** StereoConfig Implementation 43.381 + 43.382 +StereoConfig::StereoConfig(StereoMode mode, const Viewport& vp) 43.383 + : Mode(mode), 43.384 + InterpupillaryDistance(0.064f), AspectMultiplier(1.0f), 43.385 + FullView(vp), DirtyFlag(true), IPDOverride(false), 43.386 + YFov(0), Aspect(vp.w / float(vp.h)), ProjectionCenterOffset(0), 43.387 + OrthoPixelOffset(0) 43.388 +{ 43.389 + // And default distortion for it. 43.390 + Distortion.SetCoefficients(1.0f, 0.22f, 0.24f); 43.391 + Distortion.Scale = 1.0f; // Will be computed later. 43.392 + 43.393 + // Fit left of the image. 43.394 + DistortionFitX = -1.0f; 43.395 + DistortionFitY = 0.0f; 43.396 + 43.397 + // Initialize "fake" default HMD values for testing without HMD plugged in. 43.398 + // These default values match those returned by the HMD. 43.399 + HMD.HResolution = 1280; 43.400 + HMD.VResolution = 800; 43.401 + HMD.HScreenSize = 0.14976f; 43.402 + HMD.VScreenSize = HMD.HScreenSize / (1280.0f / 800.0f); 43.403 + HMD.InterpupillaryDistance = InterpupillaryDistance; 43.404 + HMD.LensSeparationDistance = 0.0635f; 43.405 + HMD.EyeToScreenDistance = 0.041f; 43.406 + HMD.DistortionK[0] = Distortion.K[0]; 43.407 + HMD.DistortionK[1] = Distortion.K[1]; 43.408 + HMD.DistortionK[2] = Distortion.K[2]; 43.409 + HMD.DistortionK[3] = 0; 43.410 + 43.411 + Set2DAreaFov(DegreeToRad(85.0f)); 43.412 +} 43.413 + 43.414 +void StereoConfig::SetFullViewport(const Viewport& vp) 43.415 +{ 43.416 + if (vp != FullView) 43.417 + { 43.418 + FullView = vp; 43.419 + DirtyFlag = true; 43.420 + } 43.421 +} 43.422 + 43.423 +void StereoConfig::SetHMDInfo(const HMDInfo& hmd) 43.424 +{ 43.425 + HMD = hmd; 43.426 + Distortion.K[0] = hmd.DistortionK[0]; 43.427 + Distortion.K[1] = hmd.DistortionK[1]; 43.428 + Distortion.K[2] = hmd.DistortionK[2]; 43.429 + Distortion.K[3] = hmd.DistortionK[3]; 43.430 + 43.431 + Distortion.SetChromaticAberration(hmd.ChromaAbCorrection[0], hmd.ChromaAbCorrection[1], 43.432 + hmd.ChromaAbCorrection[2], hmd.ChromaAbCorrection[3]); 43.433 + 43.434 + if (!IPDOverride) 43.435 + InterpupillaryDistance = HMD.InterpupillaryDistance; 43.436 + 43.437 + DirtyFlag = true; 43.438 +} 43.439 + 43.440 +void StereoConfig::SetDistortionFitPointVP(float x, float y) 43.441 +{ 43.442 + DistortionFitX = x; 43.443 + DistortionFitY = y; 43.444 + DirtyFlag = true; 43.445 +} 43.446 + 43.447 +void StereoConfig::SetDistortionFitPointPixels(float x, float y) 43.448 +{ 43.449 + DistortionFitX = (4 * x / float(FullView.w)) - 1.0f; 43.450 + DistortionFitY = (2 * y / float(FullView.h)) - 1.0f; 43.451 + DirtyFlag = true; 43.452 +} 43.453 + 43.454 +void StereoConfig::Set2DAreaFov(float fovRadians) 43.455 +{ 43.456 + Area2DFov = fovRadians; 43.457 + DirtyFlag = true; 43.458 +} 43.459 + 43.460 + 43.461 +const StereoEyeParams& StereoConfig::GetEyeRenderParams(StereoEye eye) 43.462 +{ 43.463 + static const UByte eyeParamIndices[3] = { 0, 0, 1 }; 43.464 + 43.465 + updateIfDirty(); 43.466 + OVR_ASSERT(eye < sizeof(eyeParamIndices)); 43.467 + return EyeRenderParams[eyeParamIndices[eye]]; 43.468 +} 43.469 + 43.470 + 43.471 +void StereoConfig::updateComputedState() 43.472 +{ 43.473 + // Need to compute all of the following: 43.474 + // - Aspect Ratio 43.475 + // - FOV 43.476 + // - Projection offsets for 3D 43.477 + // - Distortion XCenterOffset 43.478 + // - Update 2D 43.479 + // - Initialize EyeRenderParams 43.480 + 43.481 + // Compute aspect ratio. Stereo mode cuts width in half. 43.482 + Aspect = float(FullView.w) / float(FullView.h); 43.483 + Aspect *= (Mode == Stereo_None) ? 1.0f : 0.5f; 43.484 + Aspect *= AspectMultiplier; 43.485 + 43.486 + updateDistortionOffsetAndScale(); 43.487 + 43.488 + // Compute Vertical FOV based on distance, distortion, etc. 43.489 + // Distance from vertical center to render vertical edge perceived through the lens. 43.490 + // This will be larger then normal screen size due to magnification & distortion. 43.491 + // 43.492 + // This percievedHalfRTDistance equation should hold as long as the render target 43.493 + // and display have the same aspect ratios. What we'd like to know is where the edge 43.494 + // of the render target will on the perceived screen surface. With NO LENS, 43.495 + // the answer would be: 43.496 + // 43.497 + // halfRTDistance = (VScreenSize / 2) * aspect * 43.498 + // DistortionFn_Inverse( DistortionScale / aspect ) 43.499 + // 43.500 + // To model the optical lens we eliminates DistortionFn_Inverse. Aspect ratios 43.501 + // cancel out, so we get: 43.502 + // 43.503 + // halfRTDistance = (VScreenSize / 2) * DistortionScale 43.504 + // 43.505 + if (Mode == Stereo_None) 43.506 + { 43.507 + YFov = DegreeToRad(80.0f); 43.508 + } 43.509 + else 43.510 + { 43.511 + float percievedHalfRTDistance = (HMD.VScreenSize / 2) * Distortion.Scale; 43.512 + YFov = 2.0f * atan(percievedHalfRTDistance/HMD.EyeToScreenDistance); 43.513 + } 43.514 + 43.515 + updateProjectionOffset(); 43.516 + update2D(); 43.517 + updateEyeParams(); 43.518 + 43.519 + DirtyFlag = false; 43.520 +} 43.521 + 43.522 +void StereoConfig::updateDistortionOffsetAndScale() 43.523 +{ 43.524 + // Distortion center shift is stored separately, since it isn't affected 43.525 + // by the eye distance. 43.526 + float lensOffset = HMD.LensSeparationDistance * 0.5f; 43.527 + float lensShift = HMD.HScreenSize * 0.25f - lensOffset; 43.528 + float lensViewportShift = 4.0f * lensShift / HMD.HScreenSize; 43.529 + Distortion.XCenterOffset= lensViewportShift; 43.530 + 43.531 + // Compute distortion scale from DistortionFitX & DistortionFitY. 43.532 + // Fit value of 0.0 means "no fit". 43.533 + if ((fabs(DistortionFitX) < 0.0001f) && (fabs(DistortionFitY) < 0.0001f)) 43.534 + { 43.535 + Distortion.Scale = 1.0f; 43.536 + } 43.537 + else 43.538 + { 43.539 + // Convert fit value to distortion-centered coordinates before fit radius 43.540 + // calculation. 43.541 + float stereoAspect = 0.5f * float(FullView.w) / float(FullView.h); 43.542 + float dx = DistortionFitX - Distortion.XCenterOffset; 43.543 + float dy = DistortionFitY / stereoAspect; 43.544 + float fitRadius = sqrt(dx * dx + dy * dy); 43.545 + Distortion.Scale = Distortion.DistortionFn(fitRadius)/fitRadius; 43.546 + } 43.547 +} 43.548 + 43.549 +void StereoConfig::updateProjectionOffset() 43.550 +{ 43.551 + // Post-projection viewport coordinates range from (-1.0, 1.0), with the 43.552 + // center of the left viewport falling at (1/4) of horizontal screen size. 43.553 + // We need to shift this projection center to match with the lens center; 43.554 + // note that we don't use the IPD here due to collimated light property of the lens. 43.555 + // We compute this shift in physical units (meters) to 43.556 + // correct for different screen sizes and then rescale to viewport coordinates. 43.557 + float viewCenter = HMD.HScreenSize * 0.25f; 43.558 + float eyeProjectionShift = viewCenter - HMD.LensSeparationDistance*0.5f; 43.559 + ProjectionCenterOffset = 4.0f * eyeProjectionShift / HMD.HScreenSize; 43.560 +} 43.561 + 43.562 +void StereoConfig::update2D() 43.563 +{ 43.564 + // Orthographic projection fakes a screen at a distance of 0.8m from the 43.565 + // eye, where hmd screen projection surface is at 0.05m distance. 43.566 + // This introduces an extra off-center pixel projection shift based on eye distance. 43.567 + // This offCenterShift is the pixel offset of the other camera's center 43.568 + // in your reference camera based on surface distance. 43.569 + float metersToPixels = (HMD.HResolution / HMD.HScreenSize); 43.570 + float lensDistanceScreenPixels= metersToPixels * HMD.LensSeparationDistance; 43.571 + float eyeDistanceScreenPixels = metersToPixels * InterpupillaryDistance; 43.572 + float offCenterShiftPixels = (HMD.EyeToScreenDistance / 0.8f) * eyeDistanceScreenPixels; 43.573 + float leftPixelCenter = (HMD.HResolution / 2) - lensDistanceScreenPixels * 0.5f; 43.574 + float rightPixelCenter = lensDistanceScreenPixels * 0.5f; 43.575 + float pixelDifference = leftPixelCenter - rightPixelCenter; 43.576 + 43.577 + // This computes the number of pixels that fit within specified 2D FOV (assuming 43.578 + // distortion scaling will be done). 43.579 + float percievedHalfScreenDistance = tan(Area2DFov * 0.5f) * HMD.EyeToScreenDistance; 43.580 + float vfovSize = 2.0f * percievedHalfScreenDistance / Distortion.Scale; 43.581 + FovPixels = HMD.VResolution * vfovSize / HMD.VScreenSize; 43.582 + 43.583 + // Create orthographic matrix. 43.584 + Matrix4f& m = OrthoCenter; 43.585 + m.SetIdentity(); 43.586 + m.M[0][0] = FovPixels / (FullView.w * 0.5f); 43.587 + m.M[1][1] = -FovPixels / FullView.h; 43.588 + m.M[0][3] = 0; 43.589 + m.M[1][3] = 0; 43.590 + m.M[2][2] = 0; 43.591 + 43.592 + float orthoPixelOffset = (pixelDifference + offCenterShiftPixels/Distortion.Scale) * 0.5f; 43.593 + OrthoPixelOffset = orthoPixelOffset * 2.0f / FovPixels; 43.594 +} 43.595 + 43.596 +void StereoConfig::updateEyeParams() 43.597 +{ 43.598 + // Projection matrix for the center eye, which the left/right matrices are based on. 43.599 + Matrix4f projCenter = Matrix4f::PerspectiveRH(YFov, Aspect, 0.01f, 2000.0f); 43.600 + 43.601 + switch(Mode) 43.602 + { 43.603 + case Stereo_None: 43.604 + { 43.605 + EyeRenderParams[0].Init(StereoEye_Center, FullView, 0, projCenter, OrthoCenter); 43.606 + } 43.607 + break; 43.608 + 43.609 + case Stereo_LeftRight_Multipass: 43.610 + { 43.611 + Matrix4f projLeft = Matrix4f::Translation(ProjectionCenterOffset, 0, 0) * projCenter, 43.612 + projRight = Matrix4f::Translation(-ProjectionCenterOffset, 0, 0) * projCenter; 43.613 + 43.614 + EyeRenderParams[0].Init(StereoEye_Left, 43.615 + Viewport(FullView.x, FullView.y, FullView.w/2, FullView.h), 43.616 + +InterpupillaryDistance * 0.5f, // World view shift. 43.617 + projLeft, OrthoCenter * Matrix4f::Translation(OrthoPixelOffset, 0, 0), 43.618 + &Distortion); 43.619 + EyeRenderParams[1].Init(StereoEye_Right, 43.620 + Viewport(FullView.x + FullView.w/2, FullView.y, FullView.w/2, FullView.h), 43.621 + -InterpupillaryDistance * 0.5f, 43.622 + projRight, OrthoCenter * Matrix4f::Translation(-OrthoPixelOffset, 0, 0), 43.623 + &Distortion); 43.624 + } 43.625 + break; 43.626 + } 43.627 + 43.628 +} 43.629 + 43.630 + 43.631 +}}} // OVR::Util::Render 43.632 +
44.1 --- a/libovr/Src/Util/Util_Render_Stereo.h Sat Sep 14 17:51:03 2013 +0300 44.2 +++ b/libovr/Src/Util/Util_Render_Stereo.h Sun Sep 15 04:10:05 2013 +0300 44.3 @@ -1,1 +1,300 @@ 44.4 -/************************************************************************************ 44.5 44.6 PublicHeader: OVR.h 44.7 Filename : Util_Render_Stereo.h 44.8 Content : Sample stereo rendering configuration classes. 44.9 Created : October 22, 2012 44.10 Authors : Michael Antonov 44.11 44.12 Copyright : Copyright 2012 Oculus, Inc. All Rights reserved. 44.13 44.14 Use of this software is subject to the terms of the Oculus Inc license 44.15 agreement provided at the time of installation or download, or which 44.16 otherwise accompanies this software in either electronic or hard copy form. 44.17 44.18 *************************************************************************************/ 44.19 44.20 #ifndef OVR_Util_Render_Stereo_h 44.21 #define OVR_Util_Render_Stereo_h 44.22 44.23 #include "../OVR_Device.h" 44.24 44.25 namespace OVR { namespace Util { namespace Render { 44.26 44.27 44.28 //----------------------------------------------------------------------------------- 44.29 // ***** Stereo Enumerations 44.30 44.31 // StereoMode describes rendering modes that can be used by StereoConfig. 44.32 // These modes control whether stereo rendering is used or not (Stereo_None), 44.33 // and how it is implemented. 44.34 enum StereoMode 44.35 { 44.36 Stereo_None = 0, 44.37 Stereo_LeftRight_Multipass = 1 44.38 }; 44.39 44.40 44.41 // StereoEye specifies which eye we are rendering for; it is used to 44.42 // retrieve StereoEyeParams. 44.43 enum StereoEye 44.44 { 44.45 StereoEye_Center, 44.46 StereoEye_Left, 44.47 StereoEye_Right 44.48 }; 44.49 44.50 44.51 //----------------------------------------------------------------------------------- 44.52 // ***** Viewport 44.53 44.54 // Viewport describes a rectangular area used for rendering, in pixels. 44.55 struct Viewport 44.56 { 44.57 int x, y; 44.58 int w, h; 44.59 44.60 Viewport() {} 44.61 Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { } 44.62 44.63 bool operator == (const Viewport& vp) const 44.64 { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); } 44.65 bool operator != (const Viewport& vp) const 44.66 { return !operator == (vp); } 44.67 }; 44.68 44.69 44.70 //----------------------------------------------------------------------------------- 44.71 // ***** DistortionConfig 44.72 44.73 // DistortionConfig Provides controls for the distortion shader. 44.74 // - K[0] - K[3] are coefficients for the distortion function. 44.75 // - XCenterOffset is the offset of lens distortion center from the 44.76 // center of one-eye screen half. [-1, 1] Range. 44.77 // - Scale is a factor of how much larger will the input image be, 44.78 // with a factor of 1.0f being no scaling. An inverse of this 44.79 // value is applied to sampled UV coordinates (1/Scale). 44.80 // - ChromaticAberration is an array of parameters for controlling 44.81 // additional Red and Blue scaling in order to reduce chromatic aberration 44.82 // caused by the Rift lenses. 44.83 class DistortionConfig 44.84 { 44.85 public: 44.86 DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 44.87 : XCenterOffset(0), YCenterOffset(0), Scale(1.0f) 44.88 { 44.89 SetCoefficients(k0, k1, k2, k3); 44.90 SetChromaticAberration(); 44.91 } 44.92 44.93 void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 44.94 { K[0] = k0; K[1] = k1; K[2] = k2; K[3] = k3; } 44.95 44.96 void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f) 44.97 { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; } 44.98 44.99 44.100 // DistortionFn applies distortion equation to the argument. The returned 44.101 // value should match distortion equation used in shader. 44.102 float DistortionFn(float r) const 44.103 { 44.104 float rsq = r * r; 44.105 float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq); 44.106 return scale; 44.107 } 44.108 44.109 // DistortionFnInverse computes the inverse of the distortion function on an argument. 44.110 float DistortionFnInverse(float r); 44.111 44.112 float K[4]; 44.113 float XCenterOffset, YCenterOffset; 44.114 float Scale; 44.115 44.116 float ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion: 44.117 // Index [0] - Red channel constant coefficient. 44.118 // Index [1] - Red channel r^2 coefficient. 44.119 // Index [2] - Blue channel constant coefficient. 44.120 // Index [3] - Blue channel r^2 coefficient. 44.121 }; 44.122 44.123 44.124 //----------------------------------------------------------------------------------- 44.125 // ***** StereoEyeParams 44.126 44.127 // StereoEyeParams describes RenderDevice configuration needed to render 44.128 // the scene for one eye. 44.129 class StereoEyeParams 44.130 { 44.131 public: 44.132 StereoEye Eye; 44.133 Viewport VP; // Viewport that we are rendering to 44.134 const DistortionConfig* pDistortion; 44.135 44.136 Matrix4f ViewAdjust; // Translation to be applied to view matrix. 44.137 Matrix4f Projection; // Projection matrix used with this eye. 44.138 Matrix4f OrthoProjection; // Orthographic projection used with this eye. 44.139 44.140 void Init(StereoEye eye, const Viewport &vp, float vofs, 44.141 const Matrix4f& proj, const Matrix4f& orthoProj, 44.142 const DistortionConfig* distortion = 0) 44.143 { 44.144 Eye = eye; 44.145 VP = vp; 44.146 ViewAdjust = Matrix4f::Translation(Vector3f(vofs,0,0)); 44.147 Projection = proj; 44.148 OrthoProjection = orthoProj; 44.149 pDistortion = distortion; 44.150 } 44.151 }; 44.152 44.153 44.154 //----------------------------------------------------------------------------------- 44.155 // ***** StereoConfig 44.156 44.157 // StereoConfig maintains a scene stereo state and allow switching between different 44.158 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD 44.159 // variables such as screen size, eye-to-screen distance and distortion, and computes 44.160 // extra data such as FOV and distortion center offsets based on it. Rendering 44.161 // parameters are returned though StereoEyeParams for each eye. 44.162 // 44.163 // Beyond regular 3D projection, this class supports rendering a 2D orthographic 44.164 // surface for UI and text. The 2D surface will be defined as fitting within a 2D 44.165 // field of view (85 degrees by default) and used [-1,1] coordinate system with 44.166 // square pixels. The (0,0) coordinate corresponds to eye center location 44.167 // that is properly adjusted during rendering through SterepRenderParams::Adjust2D. 44.168 // Genreally speaking, text outside [-1,1] coordinate range will not be readable. 44.169 44.170 class StereoConfig 44.171 { 44.172 public: 44.173 44.174 StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass, 44.175 const Viewport& fullViewport = Viewport(0,0, 1280,800)); 44.176 44.177 44.178 // *** Modifiable State Access 44.179 44.180 // Sets a stereo rendering mode and updates internal cached 44.181 // state (matrices, per-eye view) based on it. 44.182 void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; } 44.183 StereoMode GetStereoMode() const { return Mode; } 44.184 44.185 // Sets HMD parameters; also initializes distortion coefficients. 44.186 void SetHMDInfo(const HMDInfo& hmd); 44.187 const HMDInfo& GetHMDInfo() const { return HMD; } 44.188 44.189 // Query physical eye-to-screen distance in meters, which combines screen-to-lens and 44.190 // and lens-to-eye pupil distances. Modifying this value adjusts FOV. 44.191 float GetEyeToScreenDistance() const { return HMD.EyeToScreenDistance; } 44.192 void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; } 44.193 44.194 // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm). 44.195 void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; } 44.196 float GetIPD() const { return InterpupillaryDistance; } 44.197 44.198 // Set full render target viewport; for HMD this includes both eyes. 44.199 void SetFullViewport(const Viewport& vp); 44.200 const Viewport& GetFullViewport() const { return FullView; } 44.201 44.202 // Aspect ratio defaults to ((w/h)*multiplier) computed per eye. 44.203 // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo. 44.204 void SetAspectMultiplier(float m) { AspectMultiplier = m; DirtyFlag = true; } 44.205 float GetAspectMultiplier() const { return AspectMultiplier; } 44.206 44.207 44.208 // For the distorted image to fill rendered viewport, input texture render target needs to be 44.209 // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point 44.210 // on of specified radius from a distortion center, more easily specified as a coordinate. 44.211 // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to, 44.212 // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location 44.213 // where source (pre-distortion) and target (post-distortion) image match each other. 44.214 // For the right eye, the interpretation of 'u' will be inverted. 44.215 void SetDistortionFitPointVP(float x, float y); 44.216 // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to, 44.217 // specified in pixeld for full left-eye texture. 44.218 void SetDistortionFitPointPixels(float x, float y); 44.219 44.220 // Changes all distortion settings. 44.221 // Note that setting HMDInfo also changes Distortion coefficients. 44.222 void SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; } 44.223 44.224 // Modify distortion coefficients; useful for adjustment tweaking. 44.225 void SetDistortionK(int i, float k) { Distortion.K[i] = k; DirtyFlag = true; } 44.226 float GetDistortionK(int i) const { return Distortion.K[i]; } 44.227 44.228 // Sets the fieldOfView that the 2D coordinate area stretches to. 44.229 void Set2DAreaFov(float fovRadians); 44.230 44.231 44.232 // *** Computed State 44.233 44.234 // Return current aspect ratio. 44.235 float GetAspect() { updateIfDirty(); return Aspect; } 44.236 44.237 // Return computed vertical FOV in radians/degrees. 44.238 float GetYFOVRadians() { updateIfDirty(); return YFov; } 44.239 float GetYFOVDegrees() { return RadToDegree(GetYFOVRadians()); } 44.240 44.241 // Query horizontal projection center offset as a distance away from the 44.242 // one-eye [-1,1] unit viewport. 44.243 // Positive return value should be used for left eye, negative for right eye. 44.244 float GetProjectionCenterOffset() { updateIfDirty(); return ProjectionCenterOffset; } 44.245 44.246 // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed. 44.247 const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; } 44.248 44.249 // Returns DistortionScale factor by which input texture size is increased to make 44.250 // post-distortion result distortion fit the viewport. 44.251 float GetDistortionScale() { updateIfDirty(); return Distortion.Scale; } 44.252 44.253 // Returns the size of a pixel within 2D coordinate system. 44.254 float Get2DUnitPixel() { updateIfDirty(); return (2.0f / (FovPixels * Distortion.Scale)); } 44.255 44.256 // Returns full set of Stereo rendering parameters for the specified eye. 44.257 const StereoEyeParams& GetEyeRenderParams(StereoEye eye); 44.258 44.259 private: 44.260 44.261 void updateIfDirty() { if (DirtyFlag) updateComputedState(); } 44.262 void updateComputedState(); 44.263 44.264 void updateDistortionOffsetAndScale(); 44.265 void updateProjectionOffset(); 44.266 void update2D(); 44.267 void updateEyeParams(); 44.268 44.269 44.270 // *** Modifiable State 44.271 44.272 StereoMode Mode; 44.273 float InterpupillaryDistance; 44.274 float AspectMultiplier; // Multiplied into aspect ratio to change it. 44.275 HMDInfo HMD; 44.276 DistortionConfig Distortion; 44.277 float DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units. 44.278 Viewport FullView; // Entire window viewport. 44.279 44.280 float Area2DFov; // FOV range mapping to [-1, 1] 2D area. 44.281 44.282 // *** Computed State 44.283 44.284 bool DirtyFlag; // Set when any if the modifiable state changed. 44.285 bool IPDOverride; // True after SetIPD was called. 44.286 float YFov; // Vertical FOV. 44.287 float Aspect; // Aspect ratio: (w/h)*AspectMultiplier. 44.288 float ProjectionCenterOffset; 44.289 StereoEyeParams EyeRenderParams[2]; 44.290 44.291 44.292 // ** 2D Rendering 44.293 44.294 // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D. 44.295 float FovPixels; 44.296 Matrix4f OrthoCenter; 44.297 float OrthoPixelOffset; 44.298 }; 44.299 44.300 44.301 }}} // OVR::Util::Render 44.302 44.303 #endif 44.304 \ No newline at end of file 44.305 +/************************************************************************************ 44.306 + 44.307 +PublicHeader: OVR.h 44.308 +Filename : Util_Render_Stereo.h 44.309 +Content : Sample stereo rendering configuration classes. 44.310 +Created : October 22, 2012 44.311 +Authors : Michael Antonov 44.312 + 44.313 +Copyright : Copyright 2012 Oculus, Inc. All Rights reserved. 44.314 + 44.315 +Use of this software is subject to the terms of the Oculus Inc license 44.316 +agreement provided at the time of installation or download, or which 44.317 +otherwise accompanies this software in either electronic or hard copy form. 44.318 + 44.319 +*************************************************************************************/ 44.320 + 44.321 +#ifndef OVR_Util_Render_Stereo_h 44.322 +#define OVR_Util_Render_Stereo_h 44.323 + 44.324 +#include "../OVR_Device.h" 44.325 + 44.326 +namespace OVR { namespace Util { namespace Render { 44.327 + 44.328 + 44.329 +//----------------------------------------------------------------------------------- 44.330 +// ***** Stereo Enumerations 44.331 + 44.332 +// StereoMode describes rendering modes that can be used by StereoConfig. 44.333 +// These modes control whether stereo rendering is used or not (Stereo_None), 44.334 +// and how it is implemented. 44.335 +enum StereoMode 44.336 +{ 44.337 + Stereo_None = 0, 44.338 + Stereo_LeftRight_Multipass = 1 44.339 +}; 44.340 + 44.341 + 44.342 +// StereoEye specifies which eye we are rendering for; it is used to 44.343 +// retrieve StereoEyeParams. 44.344 +enum StereoEye 44.345 +{ 44.346 + StereoEye_Center, 44.347 + StereoEye_Left, 44.348 + StereoEye_Right 44.349 +}; 44.350 + 44.351 + 44.352 +//----------------------------------------------------------------------------------- 44.353 +// ***** Viewport 44.354 + 44.355 +// Viewport describes a rectangular area used for rendering, in pixels. 44.356 +struct Viewport 44.357 +{ 44.358 + int x, y; 44.359 + int w, h; 44.360 + 44.361 + Viewport() {} 44.362 + Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { } 44.363 + 44.364 + bool operator == (const Viewport& vp) const 44.365 + { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); } 44.366 + bool operator != (const Viewport& vp) const 44.367 + { return !operator == (vp); } 44.368 +}; 44.369 + 44.370 + 44.371 +//----------------------------------------------------------------------------------- 44.372 +// ***** DistortionConfig 44.373 + 44.374 +// DistortionConfig Provides controls for the distortion shader. 44.375 +// - K[0] - K[3] are coefficients for the distortion function. 44.376 +// - XCenterOffset is the offset of lens distortion center from the 44.377 +// center of one-eye screen half. [-1, 1] Range. 44.378 +// - Scale is a factor of how much larger will the input image be, 44.379 +// with a factor of 1.0f being no scaling. An inverse of this 44.380 +// value is applied to sampled UV coordinates (1/Scale). 44.381 +// - ChromaticAberration is an array of parameters for controlling 44.382 +// additional Red and Blue scaling in order to reduce chromatic aberration 44.383 +// caused by the Rift lenses. 44.384 +class DistortionConfig 44.385 +{ 44.386 +public: 44.387 + DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 44.388 + : XCenterOffset(0), YCenterOffset(0), Scale(1.0f) 44.389 + { 44.390 + SetCoefficients(k0, k1, k2, k3); 44.391 + SetChromaticAberration(); 44.392 + } 44.393 + 44.394 + void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 44.395 + { K[0] = k0; K[1] = k1; K[2] = k2; K[3] = k3; } 44.396 + 44.397 + void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f) 44.398 + { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; } 44.399 + 44.400 + 44.401 + // DistortionFn applies distortion equation to the argument. The returned 44.402 + // value should match distortion equation used in shader. 44.403 + float DistortionFn(float r) const 44.404 + { 44.405 + float rsq = r * r; 44.406 + float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq); 44.407 + return scale; 44.408 + } 44.409 + 44.410 + // DistortionFnInverse computes the inverse of the distortion function on an argument. 44.411 + float DistortionFnInverse(float r); 44.412 + 44.413 + float K[4]; 44.414 + float XCenterOffset, YCenterOffset; 44.415 + float Scale; 44.416 + 44.417 + float ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion: 44.418 + // Index [0] - Red channel constant coefficient. 44.419 + // Index [1] - Red channel r^2 coefficient. 44.420 + // Index [2] - Blue channel constant coefficient. 44.421 + // Index [3] - Blue channel r^2 coefficient. 44.422 +}; 44.423 + 44.424 + 44.425 +//----------------------------------------------------------------------------------- 44.426 +// ***** StereoEyeParams 44.427 + 44.428 +// StereoEyeParams describes RenderDevice configuration needed to render 44.429 +// the scene for one eye. 44.430 +class StereoEyeParams 44.431 +{ 44.432 +public: 44.433 + StereoEye Eye; 44.434 + Viewport VP; // Viewport that we are rendering to 44.435 + const DistortionConfig* pDistortion; 44.436 + 44.437 + Matrix4f ViewAdjust; // Translation to be applied to view matrix. 44.438 + Matrix4f Projection; // Projection matrix used with this eye. 44.439 + Matrix4f OrthoProjection; // Orthographic projection used with this eye. 44.440 + 44.441 + void Init(StereoEye eye, const Viewport &vp, float vofs, 44.442 + const Matrix4f& proj, const Matrix4f& orthoProj, 44.443 + const DistortionConfig* distortion = 0) 44.444 + { 44.445 + Eye = eye; 44.446 + VP = vp; 44.447 + ViewAdjust = Matrix4f::Translation(Vector3f(vofs,0,0)); 44.448 + Projection = proj; 44.449 + OrthoProjection = orthoProj; 44.450 + pDistortion = distortion; 44.451 + } 44.452 +}; 44.453 + 44.454 + 44.455 +//----------------------------------------------------------------------------------- 44.456 +// ***** StereoConfig 44.457 + 44.458 +// StereoConfig maintains a scene stereo state and allow switching between different 44.459 +// stereo rendering modes. To support rendering, StereoConfig keeps track of HMD 44.460 +// variables such as screen size, eye-to-screen distance and distortion, and computes 44.461 +// extra data such as FOV and distortion center offsets based on it. Rendering 44.462 +// parameters are returned though StereoEyeParams for each eye. 44.463 +// 44.464 +// Beyond regular 3D projection, this class supports rendering a 2D orthographic 44.465 +// surface for UI and text. The 2D surface will be defined as fitting within a 2D 44.466 +// field of view (85 degrees by default) and used [-1,1] coordinate system with 44.467 +// square pixels. The (0,0) coordinate corresponds to eye center location 44.468 +// that is properly adjusted during rendering through SterepRenderParams::Adjust2D. 44.469 +// Genreally speaking, text outside [-1,1] coordinate range will not be readable. 44.470 + 44.471 +class StereoConfig 44.472 +{ 44.473 +public: 44.474 + 44.475 + StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass, 44.476 + const Viewport& fullViewport = Viewport(0,0, 1280,800)); 44.477 + 44.478 + 44.479 + // *** Modifiable State Access 44.480 + 44.481 + // Sets a stereo rendering mode and updates internal cached 44.482 + // state (matrices, per-eye view) based on it. 44.483 + void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; } 44.484 + StereoMode GetStereoMode() const { return Mode; } 44.485 + 44.486 + // Sets HMD parameters; also initializes distortion coefficients. 44.487 + void SetHMDInfo(const HMDInfo& hmd); 44.488 + const HMDInfo& GetHMDInfo() const { return HMD; } 44.489 + 44.490 + // Query physical eye-to-screen distance in meters, which combines screen-to-lens and 44.491 + // and lens-to-eye pupil distances. Modifying this value adjusts FOV. 44.492 + float GetEyeToScreenDistance() const { return HMD.EyeToScreenDistance; } 44.493 + void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; } 44.494 + 44.495 + // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm). 44.496 + void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; } 44.497 + float GetIPD() const { return InterpupillaryDistance; } 44.498 + 44.499 + // Set full render target viewport; for HMD this includes both eyes. 44.500 + void SetFullViewport(const Viewport& vp); 44.501 + const Viewport& GetFullViewport() const { return FullView; } 44.502 + 44.503 + // Aspect ratio defaults to ((w/h)*multiplier) computed per eye. 44.504 + // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo. 44.505 + void SetAspectMultiplier(float m) { AspectMultiplier = m; DirtyFlag = true; } 44.506 + float GetAspectMultiplier() const { return AspectMultiplier; } 44.507 + 44.508 + 44.509 + // For the distorted image to fill rendered viewport, input texture render target needs to be 44.510 + // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point 44.511 + // on of specified radius from a distortion center, more easily specified as a coordinate. 44.512 + // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to, 44.513 + // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location 44.514 + // where source (pre-distortion) and target (post-distortion) image match each other. 44.515 + // For the right eye, the interpretation of 'u' will be inverted. 44.516 + void SetDistortionFitPointVP(float x, float y); 44.517 + // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to, 44.518 + // specified in pixeld for full left-eye texture. 44.519 + void SetDistortionFitPointPixels(float x, float y); 44.520 + 44.521 + // Changes all distortion settings. 44.522 + // Note that setting HMDInfo also changes Distortion coefficients. 44.523 + void SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; } 44.524 + 44.525 + // Modify distortion coefficients; useful for adjustment tweaking. 44.526 + void SetDistortionK(int i, float k) { Distortion.K[i] = k; DirtyFlag = true; } 44.527 + float GetDistortionK(int i) const { return Distortion.K[i]; } 44.528 + 44.529 + // Sets the fieldOfView that the 2D coordinate area stretches to. 44.530 + void Set2DAreaFov(float fovRadians); 44.531 + 44.532 + 44.533 + // *** Computed State 44.534 + 44.535 + // Return current aspect ratio. 44.536 + float GetAspect() { updateIfDirty(); return Aspect; } 44.537 + 44.538 + // Return computed vertical FOV in radians/degrees. 44.539 + float GetYFOVRadians() { updateIfDirty(); return YFov; } 44.540 + float GetYFOVDegrees() { return RadToDegree(GetYFOVRadians()); } 44.541 + 44.542 + // Query horizontal projection center offset as a distance away from the 44.543 + // one-eye [-1,1] unit viewport. 44.544 + // Positive return value should be used for left eye, negative for right eye. 44.545 + float GetProjectionCenterOffset() { updateIfDirty(); return ProjectionCenterOffset; } 44.546 + 44.547 + // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed. 44.548 + const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; } 44.549 + 44.550 + // Returns DistortionScale factor by which input texture size is increased to make 44.551 + // post-distortion result distortion fit the viewport. 44.552 + float GetDistortionScale() { updateIfDirty(); return Distortion.Scale; } 44.553 + 44.554 + // Returns the size of a pixel within 2D coordinate system. 44.555 + float Get2DUnitPixel() { updateIfDirty(); return (2.0f / (FovPixels * Distortion.Scale)); } 44.556 + 44.557 + // Returns full set of Stereo rendering parameters for the specified eye. 44.558 + const StereoEyeParams& GetEyeRenderParams(StereoEye eye); 44.559 + 44.560 +private: 44.561 + 44.562 + void updateIfDirty() { if (DirtyFlag) updateComputedState(); } 44.563 + void updateComputedState(); 44.564 + 44.565 + void updateDistortionOffsetAndScale(); 44.566 + void updateProjectionOffset(); 44.567 + void update2D(); 44.568 + void updateEyeParams(); 44.569 + 44.570 + 44.571 + // *** Modifiable State 44.572 + 44.573 + StereoMode Mode; 44.574 + float InterpupillaryDistance; 44.575 + float AspectMultiplier; // Multiplied into aspect ratio to change it. 44.576 + HMDInfo HMD; 44.577 + DistortionConfig Distortion; 44.578 + float DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units. 44.579 + Viewport FullView; // Entire window viewport. 44.580 + 44.581 + float Area2DFov; // FOV range mapping to [-1, 1] 2D area. 44.582 + 44.583 + // *** Computed State 44.584 + 44.585 + bool DirtyFlag; // Set when any if the modifiable state changed. 44.586 + bool IPDOverride; // True after SetIPD was called. 44.587 + float YFov; // Vertical FOV. 44.588 + float Aspect; // Aspect ratio: (w/h)*AspectMultiplier. 44.589 + float ProjectionCenterOffset; 44.590 + StereoEyeParams EyeRenderParams[2]; 44.591 + 44.592 + 44.593 + // ** 2D Rendering 44.594 + 44.595 + // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D. 44.596 + float FovPixels; 44.597 + Matrix4f OrthoCenter; 44.598 + float OrthoPixelOffset; 44.599 +}; 44.600 + 44.601 + 44.602 +}}} // OVR::Util::Render 44.603 + 44.604 +#endif
45.1 --- a/libovr/Src/linux/OVR_ThreadsPthread.cpp Sat Sep 14 17:51:03 2013 +0300 45.2 +++ b/libovr/Src/linux/OVR_ThreadsPthread.cpp Sun Sep 15 04:10:05 2013 +0300 45.3 @@ -1,1 +1,795 @@ 45.4 - 45.5 #include "OVR_Threads.h" 45.6 #include "OVR_Hash.h" 45.7 45.8 #ifdef OVR_ENABLE_THREADS 45.9 45.10 #include "OVR_Timer.h" 45.11 #include "OVR_Log.h" 45.12 45.13 #include <pthread.h> 45.14 #include <time.h> 45.15 45.16 #ifdef OVR_OS_PS3 45.17 #include <sys/sys_time.h> 45.18 #include <sys/timer.h> 45.19 #include <sys/synchronization.h> 45.20 #define sleep(x) sys_timer_sleep(x) 45.21 #define usleep(x) sys_timer_usleep(x) 45.22 using std::timespec; 45.23 #else 45.24 #include <unistd.h> 45.25 #include <sys/time.h> 45.26 #include <errno.h> 45.27 #endif 45.28 45.29 namespace OVR { 45.30 45.31 // ***** Mutex implementation 45.32 45.33 45.34 // *** Internal Mutex implementation structure 45.35 45.36 class MutexImpl : public NewOverrideBase 45.37 { 45.38 // System mutex or semaphore 45.39 pthread_mutex_t SMutex; 45.40 bool Recursive; 45.41 unsigned LockCount; 45.42 pthread_t LockedBy; 45.43 45.44 friend class WaitConditionImpl; 45.45 45.46 public: 45.47 // Constructor/destructor 45.48 MutexImpl(Mutex* pmutex, bool recursive = 1); 45.49 ~MutexImpl(); 45.50 45.51 // Locking functions 45.52 void DoLock(); 45.53 bool TryLock(); 45.54 void Unlock(Mutex* pmutex); 45.55 // Returns 1 if the mutes is currently locked 45.56 bool IsLockedByAnotherThread(Mutex* pmutex); 45.57 bool IsSignaled() const; 45.58 }; 45.59 45.60 pthread_mutexattr_t Lock::RecursiveAttr; 45.61 bool Lock::RecursiveAttrInit = 0; 45.62 45.63 // *** Constructor/destructor 45.64 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) 45.65 { 45.66 Recursive = recursive; 45.67 LockCount = 0; 45.68 45.69 if (Recursive) 45.70 { 45.71 if (!Lock::RecursiveAttrInit) 45.72 { 45.73 pthread_mutexattr_init(&Lock::RecursiveAttr); 45.74 pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 45.75 Lock::RecursiveAttrInit = 1; 45.76 } 45.77 45.78 pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); 45.79 } 45.80 else 45.81 pthread_mutex_init(&SMutex, 0); 45.82 } 45.83 45.84 MutexImpl::~MutexImpl() 45.85 { 45.86 pthread_mutex_destroy(&SMutex); 45.87 } 45.88 45.89 45.90 // Lock and try lock 45.91 void MutexImpl::DoLock() 45.92 { 45.93 while (pthread_mutex_lock(&SMutex)); 45.94 LockCount++; 45.95 LockedBy = pthread_self(); 45.96 } 45.97 45.98 bool MutexImpl::TryLock() 45.99 { 45.100 if (!pthread_mutex_trylock(&SMutex)) 45.101 { 45.102 LockCount++; 45.103 LockedBy = pthread_self(); 45.104 return 1; 45.105 } 45.106 45.107 return 0; 45.108 } 45.109 45.110 void MutexImpl::Unlock(Mutex* pmutex) 45.111 { 45.112 OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); 45.113 45.114 unsigned lockCount; 45.115 LockCount--; 45.116 lockCount = LockCount; 45.117 45.118 pthread_mutex_unlock(&SMutex); 45.119 } 45.120 45.121 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 45.122 { 45.123 // There could be multiple interpretations of IsLocked with respect to current thread 45.124 if (LockCount == 0) 45.125 return 0; 45.126 if (pthread_self() != LockedBy) 45.127 return 1; 45.128 return 0; 45.129 } 45.130 45.131 bool MutexImpl::IsSignaled() const 45.132 { 45.133 // An mutex is signaled if it is not locked ANYWHERE 45.134 // Note that this is different from IsLockedByAnotherThread function, 45.135 // that takes current thread into account 45.136 return LockCount == 0; 45.137 } 45.138 45.139 45.140 // *** Actual Mutex class implementation 45.141 45.142 Mutex::Mutex(bool recursive) 45.143 { 45.144 // NOTE: RefCount mode already thread-safe for all waitables. 45.145 pImpl = new MutexImpl(this, recursive); 45.146 } 45.147 45.148 Mutex::~Mutex() 45.149 { 45.150 delete pImpl; 45.151 } 45.152 45.153 // Lock and try lock 45.154 void Mutex::DoLock() 45.155 { 45.156 pImpl->DoLock(); 45.157 } 45.158 bool Mutex::TryLock() 45.159 { 45.160 return pImpl->TryLock(); 45.161 } 45.162 void Mutex::Unlock() 45.163 { 45.164 pImpl->Unlock(this); 45.165 } 45.166 bool Mutex::IsLockedByAnotherThread() 45.167 { 45.168 return pImpl->IsLockedByAnotherThread(this); 45.169 } 45.170 45.171 45.172 45.173 //----------------------------------------------------------------------------------- 45.174 // ***** Event 45.175 45.176 bool Event::Wait(unsigned delay) 45.177 { 45.178 Mutex::Locker lock(&StateMutex); 45.179 45.180 // Do the correct amount of waiting 45.181 if (delay == OVR_WAIT_INFINITE) 45.182 { 45.183 while(!State) 45.184 StateWaitCondition.Wait(&StateMutex); 45.185 } 45.186 else if (delay) 45.187 { 45.188 if (!State) 45.189 StateWaitCondition.Wait(&StateMutex, delay); 45.190 } 45.191 45.192 bool state = State; 45.193 // Take care of temporary 'pulsing' of a state 45.194 if (Temporary) 45.195 { 45.196 Temporary = false; 45.197 State = false; 45.198 } 45.199 return state; 45.200 } 45.201 45.202 void Event::updateState(bool newState, bool newTemp, bool mustNotify) 45.203 { 45.204 Mutex::Locker lock(&StateMutex); 45.205 State = newState; 45.206 Temporary = newTemp; 45.207 if (mustNotify) 45.208 StateWaitCondition.NotifyAll(); 45.209 } 45.210 45.211 45.212 45.213 // ***** Wait Condition Implementation 45.214 45.215 // Internal implementation class 45.216 class WaitConditionImpl : public NewOverrideBase 45.217 { 45.218 pthread_mutex_t SMutex; 45.219 pthread_cond_t Condv; 45.220 45.221 public: 45.222 45.223 // Constructor/destructor 45.224 WaitConditionImpl(); 45.225 ~WaitConditionImpl(); 45.226 45.227 // Release mutex and wait for condition. The mutex is re-aqured after the wait. 45.228 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 45.229 45.230 // Notify a condition, releasing at one object waiting 45.231 void Notify(); 45.232 // Notify a condition, releasing all objects waiting 45.233 void NotifyAll(); 45.234 }; 45.235 45.236 45.237 WaitConditionImpl::WaitConditionImpl() 45.238 { 45.239 pthread_mutex_init(&SMutex, 0); 45.240 pthread_cond_init(&Condv, 0); 45.241 } 45.242 45.243 WaitConditionImpl::~WaitConditionImpl() 45.244 { 45.245 pthread_mutex_destroy(&SMutex); 45.246 pthread_cond_destroy(&Condv); 45.247 } 45.248 45.249 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 45.250 { 45.251 bool result = 1; 45.252 unsigned lockCount = pmutex->pImpl->LockCount; 45.253 45.254 // Mutex must have been locked 45.255 if (lockCount == 0) 45.256 return 0; 45.257 45.258 pthread_mutex_lock(&SMutex); 45.259 45.260 // Finally, release a mutex or semaphore 45.261 if (pmutex->pImpl->Recursive) 45.262 { 45.263 // Release the recursive mutex N times 45.264 pmutex->pImpl->LockCount = 0; 45.265 for(unsigned i=0; i<lockCount; i++) 45.266 pthread_mutex_unlock(&pmutex->pImpl->SMutex); 45.267 } 45.268 else 45.269 { 45.270 pmutex->pImpl->LockCount = 0; 45.271 pthread_mutex_unlock(&pmutex->pImpl->SMutex); 45.272 } 45.273 45.274 // Note that there is a gap here between mutex.Unlock() and Wait(). 45.275 // The other mutex protects this gap. 45.276 45.277 if (delay == OVR_WAIT_INFINITE) 45.278 pthread_cond_wait(&Condv,&SMutex); 45.279 else 45.280 { 45.281 timespec ts; 45.282 #ifdef OVR_OS_PS3 45.283 sys_time_sec_t s; 45.284 sys_time_nsec_t ns; 45.285 sys_time_get_current_time(&s, &ns); 45.286 45.287 ts.tv_sec = s + (delay / 1000); 45.288 ts.tv_nsec = ns + (delay % 1000) * 1000000; 45.289 45.290 #else 45.291 struct timeval tv; 45.292 gettimeofday(&tv, 0); 45.293 45.294 ts.tv_sec = tv.tv_sec + (delay / 1000); 45.295 ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000; 45.296 #endif 45.297 if (ts.tv_nsec > 999999999) 45.298 { 45.299 ts.tv_sec++; 45.300 ts.tv_nsec -= 1000000000; 45.301 } 45.302 int r = pthread_cond_timedwait(&Condv,&SMutex, &ts); 45.303 OVR_ASSERT(r == 0 || r == ETIMEDOUT); 45.304 if (r) 45.305 result = 0; 45.306 } 45.307 45.308 pthread_mutex_unlock(&SMutex); 45.309 45.310 // Re-aquire the mutex 45.311 for(unsigned i=0; i<lockCount; i++) 45.312 pmutex->DoLock(); 45.313 45.314 // Return the result 45.315 return result; 45.316 } 45.317 45.318 // Notify a condition, releasing the least object in a queue 45.319 void WaitConditionImpl::Notify() 45.320 { 45.321 pthread_mutex_lock(&SMutex); 45.322 pthread_cond_signal(&Condv); 45.323 pthread_mutex_unlock(&SMutex); 45.324 } 45.325 45.326 // Notify a condition, releasing all objects waiting 45.327 void WaitConditionImpl::NotifyAll() 45.328 { 45.329 pthread_mutex_lock(&SMutex); 45.330 pthread_cond_broadcast(&Condv); 45.331 pthread_mutex_unlock(&SMutex); 45.332 } 45.333 45.334 45.335 45.336 // *** Actual implementation of WaitCondition 45.337 45.338 WaitCondition::WaitCondition() 45.339 { 45.340 pImpl = new WaitConditionImpl; 45.341 } 45.342 WaitCondition::~WaitCondition() 45.343 { 45.344 delete pImpl; 45.345 } 45.346 45.347 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 45.348 { 45.349 return pImpl->Wait(pmutex, delay); 45.350 } 45.351 // Notification 45.352 void WaitCondition::Notify() 45.353 { 45.354 pImpl->Notify(); 45.355 } 45.356 void WaitCondition::NotifyAll() 45.357 { 45.358 pImpl->NotifyAll(); 45.359 } 45.360 45.361 45.362 // ***** Current thread 45.363 45.364 // Per-thread variable 45.365 /* 45.366 static __thread Thread* pCurrentThread = 0; 45.367 45.368 // Static function to return a pointer to the current thread 45.369 void Thread::InitCurrentThread(Thread *pthread) 45.370 { 45.371 pCurrentThread = pthread; 45.372 } 45.373 45.374 // Static function to return a pointer to the current thread 45.375 Thread* Thread::GetThread() 45.376 { 45.377 return pCurrentThread; 45.378 } 45.379 */ 45.380 45.381 45.382 // *** Thread constructors. 45.383 45.384 Thread::Thread(UPInt stackSize, int processor) 45.385 { 45.386 // NOTE: RefCount mode already thread-safe for all Waitable objects. 45.387 CreateParams params; 45.388 params.stackSize = stackSize; 45.389 params.processor = processor; 45.390 Init(params); 45.391 } 45.392 45.393 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 45.394 int processor, Thread::ThreadState initialState) 45.395 { 45.396 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 45.397 Init(params); 45.398 } 45.399 45.400 Thread::Thread(const CreateParams& params) 45.401 { 45.402 Init(params); 45.403 } 45.404 45.405 void Thread::Init(const CreateParams& params) 45.406 { 45.407 // Clear the variables 45.408 ThreadFlags = 0; 45.409 ThreadHandle = 0; 45.410 ExitCode = 0; 45.411 SuspendCount = 0; 45.412 StackSize = params.stackSize; 45.413 Processor = params.processor; 45.414 Priority = params.priority; 45.415 45.416 // Clear Function pointers 45.417 ThreadFunction = params.threadFunction; 45.418 UserHandle = params.userHandle; 45.419 if (params.initialState != NotRunning) 45.420 Start(params.initialState); 45.421 } 45.422 45.423 Thread::~Thread() 45.424 { 45.425 // Thread should not running while object is being destroyed, 45.426 // this would indicate ref-counting issue. 45.427 //OVR_ASSERT(IsRunning() == 0); 45.428 45.429 // Clean up thread. 45.430 ThreadHandle = 0; 45.431 } 45.432 45.433 45.434 45.435 // *** Overridable User functions. 45.436 45.437 // Default Run implementation 45.438 int Thread::Run() 45.439 { 45.440 // Call pointer to function, if available. 45.441 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 45.442 } 45.443 void Thread::OnExit() 45.444 { 45.445 } 45.446 45.447 45.448 // Finishes the thread and releases internal reference to it. 45.449 void Thread::FinishAndRelease() 45.450 { 45.451 // Note: thread must be US. 45.452 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 45.453 ThreadFlags |= OVR_THREAD_FINISHED; 45.454 45.455 // Release our reference; this is equivalent to 'delete this' 45.456 // from the point of view of our thread. 45.457 Release(); 45.458 } 45.459 45.460 45.461 45.462 // *** ThreadList - used to track all created threads 45.463 45.464 class ThreadList : public NewOverrideBase 45.465 { 45.466 //------------------------------------------------------------------------ 45.467 struct ThreadHashOp 45.468 { 45.469 size_t operator()(const Thread* ptr) 45.470 { 45.471 return (((size_t)ptr) >> 6) ^ (size_t)ptr; 45.472 } 45.473 }; 45.474 45.475 HashSet<Thread*, ThreadHashOp> ThreadSet; 45.476 Mutex ThreadMutex; 45.477 WaitCondition ThreadsEmpty; 45.478 // Track the root thread that created us. 45.479 pthread_t RootThreadId; 45.480 45.481 static ThreadList* volatile pRunningThreads; 45.482 45.483 void addThread(Thread *pthread) 45.484 { 45.485 Mutex::Locker lock(&ThreadMutex); 45.486 ThreadSet.Add(pthread); 45.487 } 45.488 45.489 void removeThread(Thread *pthread) 45.490 { 45.491 Mutex::Locker lock(&ThreadMutex); 45.492 ThreadSet.Remove(pthread); 45.493 if (ThreadSet.GetSize() == 0) 45.494 ThreadsEmpty.Notify(); 45.495 } 45.496 45.497 void finishAllThreads() 45.498 { 45.499 // Only original root thread can call this. 45.500 OVR_ASSERT(pthread_self() == RootThreadId); 45.501 45.502 Mutex::Locker lock(&ThreadMutex); 45.503 while (ThreadSet.GetSize() != 0) 45.504 ThreadsEmpty.Wait(&ThreadMutex); 45.505 } 45.506 45.507 public: 45.508 45.509 ThreadList() 45.510 { 45.511 RootThreadId = pthread_self(); 45.512 } 45.513 ~ThreadList() { } 45.514 45.515 45.516 static void AddRunningThread(Thread *pthread) 45.517 { 45.518 // Non-atomic creation ok since only the root thread 45.519 if (!pRunningThreads) 45.520 { 45.521 pRunningThreads = new ThreadList; 45.522 OVR_ASSERT(pRunningThreads); 45.523 } 45.524 pRunningThreads->addThread(pthread); 45.525 } 45.526 45.527 // NOTE: 'pthread' might be a dead pointer when this is 45.528 // called so it should not be accessed; it is only used 45.529 // for removal. 45.530 static void RemoveRunningThread(Thread *pthread) 45.531 { 45.532 OVR_ASSERT(pRunningThreads); 45.533 pRunningThreads->removeThread(pthread); 45.534 } 45.535 45.536 static void FinishAllThreads() 45.537 { 45.538 // This is ok because only root thread can wait for other thread finish. 45.539 if (pRunningThreads) 45.540 { 45.541 pRunningThreads->finishAllThreads(); 45.542 delete pRunningThreads; 45.543 pRunningThreads = 0; 45.544 } 45.545 } 45.546 }; 45.547 45.548 // By default, we have no thread list. 45.549 ThreadList* volatile ThreadList::pRunningThreads = 0; 45.550 45.551 45.552 // FinishAllThreads - exposed publicly in Thread. 45.553 void Thread::FinishAllThreads() 45.554 { 45.555 ThreadList::FinishAllThreads(); 45.556 } 45.557 45.558 // *** Run override 45.559 45.560 int Thread::PRun() 45.561 { 45.562 // Suspend us on start, if requested 45.563 if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 45.564 { 45.565 Suspend(); 45.566 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 45.567 } 45.568 45.569 // Call the virtual run function 45.570 ExitCode = Run(); 45.571 return ExitCode; 45.572 } 45.573 45.574 45.575 45.576 45.577 // *** User overridables 45.578 45.579 bool Thread::GetExitFlag() const 45.580 { 45.581 return (ThreadFlags & OVR_THREAD_EXIT) != 0; 45.582 } 45.583 45.584 void Thread::SetExitFlag(bool exitFlag) 45.585 { 45.586 // The below is atomic since ThreadFlags is AtomicInt. 45.587 if (exitFlag) 45.588 ThreadFlags |= OVR_THREAD_EXIT; 45.589 else 45.590 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 45.591 } 45.592 45.593 45.594 // Determines whether the thread was running and is now finished 45.595 bool Thread::IsFinished() const 45.596 { 45.597 return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 45.598 } 45.599 // Determines whether the thread is suspended 45.600 bool Thread::IsSuspended() const 45.601 { 45.602 return SuspendCount > 0; 45.603 } 45.604 // Returns current thread state 45.605 Thread::ThreadState Thread::GetThreadState() const 45.606 { 45.607 if (IsSuspended()) 45.608 return Suspended; 45.609 if (ThreadFlags & OVR_THREAD_STARTED) 45.610 return Running; 45.611 return NotRunning; 45.612 } 45.613 /* 45.614 static const char* mapsched_policy(int policy) 45.615 { 45.616 switch(policy) 45.617 { 45.618 case SCHED_OTHER: 45.619 return "SCHED_OTHER"; 45.620 case SCHED_RR: 45.621 return "SCHED_RR"; 45.622 case SCHED_FIFO: 45.623 return "SCHED_FIFO"; 45.624 45.625 } 45.626 return "UNKNOWN"; 45.627 } 45.628 int policy; 45.629 sched_param sparam; 45.630 pthread_getschedparam(pthread_self(), &policy, &sparam); 45.631 int max_prior = sched_get_priority_max(policy); 45.632 int min_prior = sched_get_priority_min(policy); 45.633 printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior); 45.634 #include <stdio.h> 45.635 */ 45.636 // ***** Thread management 45.637 45.638 // The actual first function called on thread start 45.639 void* Thread_PthreadStartFn(void* phandle) 45.640 { 45.641 Thread* pthread = (Thread*)phandle; 45.642 int result = pthread->PRun(); 45.643 // Signal the thread as done and release it atomically. 45.644 pthread->FinishAndRelease(); 45.645 // At this point Thread object might be dead; however we can still pass 45.646 // it to RemoveRunningThread since it is only used as a key there. 45.647 ThreadList::RemoveRunningThread(pthread); 45.648 return (void*) result; 45.649 } 45.650 45.651 int Thread::InitAttr = 0; 45.652 pthread_attr_t Thread::Attr; 45.653 45.654 /* static */ 45.655 int Thread::GetOSPriority(ThreadPriority p) 45.656 //static inline int MapToSystemPrority(Thread::ThreadPriority p) 45.657 { 45.658 #ifdef OVR_OS_PS3 45.659 switch(p) 45.660 { 45.661 case Thread::CriticalPriority: return 0; 45.662 case Thread::HighestPriority: return 300; 45.663 case Thread::AboveNormalPriority: return 600; 45.664 case Thread::NormalPriority: return 1000; 45.665 case Thread::BelowNormalPriority: return 1500; 45.666 case Thread::LowestPriority: return 2500; 45.667 case Thread::IdlePriority: return 3071; 45.668 } return 1000; 45.669 #else 45.670 OVR_UNUSED(p); 45.671 return -1; 45.672 #endif 45.673 } 45.674 45.675 bool Thread::Start(ThreadState initialState) 45.676 { 45.677 if (initialState == NotRunning) 45.678 return 0; 45.679 if (GetThreadState() != NotRunning) 45.680 { 45.681 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 45.682 return 0; 45.683 } 45.684 45.685 if (!InitAttr) 45.686 { 45.687 pthread_attr_init(&Attr); 45.688 pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED); 45.689 pthread_attr_setstacksize(&Attr, 128 * 1024); 45.690 sched_param sparam; 45.691 sparam.sched_priority = Thread::GetOSPriority(NormalPriority); 45.692 pthread_attr_setschedparam(&Attr, &sparam); 45.693 InitAttr = 1; 45.694 } 45.695 45.696 ExitCode = 0; 45.697 SuspendCount = 0; 45.698 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 45.699 45.700 // AddRef to us until the thread is finished 45.701 AddRef(); 45.702 ThreadList::AddRunningThread(this); 45.703 45.704 int result; 45.705 if (StackSize != 128 * 1024 || Priority != NormalPriority) 45.706 { 45.707 pthread_attr_t attr; 45.708 45.709 pthread_attr_init(&attr); 45.710 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 45.711 pthread_attr_setstacksize(&attr, StackSize); 45.712 sched_param sparam; 45.713 sparam.sched_priority = Thread::GetOSPriority(Priority); 45.714 pthread_attr_setschedparam(&attr, &sparam); 45.715 result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this); 45.716 pthread_attr_destroy(&attr); 45.717 } 45.718 else 45.719 result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this); 45.720 45.721 if (result) 45.722 { 45.723 ThreadFlags = 0; 45.724 Release(); 45.725 ThreadList::RemoveRunningThread(this); 45.726 return 0; 45.727 } 45.728 return 1; 45.729 } 45.730 45.731 45.732 // Suspend the thread until resumed 45.733 bool Thread::Suspend() 45.734 { 45.735 OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system")); 45.736 return 0; 45.737 } 45.738 45.739 // Resumes currently suspended thread 45.740 bool Thread::Resume() 45.741 { 45.742 return 0; 45.743 } 45.744 45.745 45.746 // Quits with an exit code 45.747 void Thread::Exit(int exitCode) 45.748 { 45.749 // Can only exist the current thread 45.750 // if (GetThread() != this) 45.751 // return; 45.752 45.753 // Call the virtual OnExit function 45.754 OnExit(); 45.755 45.756 // Signal this thread object as done and release it's references. 45.757 FinishAndRelease(); 45.758 ThreadList::RemoveRunningThread(this); 45.759 45.760 pthread_exit((void *) exitCode); 45.761 } 45.762 45.763 ThreadId GetCurrentThreadId() 45.764 { 45.765 return (void*)pthread_self(); 45.766 } 45.767 45.768 // *** Sleep functions 45.769 45.770 /* static */ 45.771 bool Thread::Sleep(unsigned secs) 45.772 { 45.773 sleep(secs); 45.774 return 1; 45.775 } 45.776 /* static */ 45.777 bool Thread::MSleep(unsigned msecs) 45.778 { 45.779 usleep(msecs*1000); 45.780 return 1; 45.781 } 45.782 45.783 /* static */ 45.784 int Thread::GetCPUCount() 45.785 { 45.786 return 1; 45.787 } 45.788 45.789 45.790 #ifdef OVR_OS_PS3 45.791 45.792 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE }; 45.793 45.794 #endif 45.795 45.796 } 45.797 45.798 #endif // OVR_ENABLE_THREADS 45.799 \ No newline at end of file 45.800 + 45.801 +#include "OVR_Threads.h" 45.802 +#include "OVR_Hash.h" 45.803 + 45.804 +#ifdef OVR_ENABLE_THREADS 45.805 + 45.806 +#include "OVR_Timer.h" 45.807 +#include "OVR_Log.h" 45.808 + 45.809 +#include <pthread.h> 45.810 +#include <time.h> 45.811 + 45.812 +#ifdef OVR_OS_PS3 45.813 +#include <sys/sys_time.h> 45.814 +#include <sys/timer.h> 45.815 +#include <sys/synchronization.h> 45.816 +#define sleep(x) sys_timer_sleep(x) 45.817 +#define usleep(x) sys_timer_usleep(x) 45.818 +using std::timespec; 45.819 +#else 45.820 +#include <unistd.h> 45.821 +#include <sys/time.h> 45.822 +#include <errno.h> 45.823 +#endif 45.824 + 45.825 +namespace OVR { 45.826 + 45.827 +// ***** Mutex implementation 45.828 + 45.829 + 45.830 +// *** Internal Mutex implementation structure 45.831 + 45.832 +class MutexImpl : public NewOverrideBase 45.833 +{ 45.834 + // System mutex or semaphore 45.835 + pthread_mutex_t SMutex; 45.836 + bool Recursive; 45.837 + unsigned LockCount; 45.838 + pthread_t LockedBy; 45.839 + 45.840 + friend class WaitConditionImpl; 45.841 + 45.842 +public: 45.843 + // Constructor/destructor 45.844 + MutexImpl(Mutex* pmutex, bool recursive = 1); 45.845 + ~MutexImpl(); 45.846 + 45.847 + // Locking functions 45.848 + void DoLock(); 45.849 + bool TryLock(); 45.850 + void Unlock(Mutex* pmutex); 45.851 + // Returns 1 if the mutes is currently locked 45.852 + bool IsLockedByAnotherThread(Mutex* pmutex); 45.853 + bool IsSignaled() const; 45.854 +}; 45.855 + 45.856 +pthread_mutexattr_t Lock::RecursiveAttr; 45.857 +bool Lock::RecursiveAttrInit = 0; 45.858 + 45.859 +// *** Constructor/destructor 45.860 +MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) 45.861 +{ 45.862 + Recursive = recursive; 45.863 + LockCount = 0; 45.864 + 45.865 + if (Recursive) 45.866 + { 45.867 + if (!Lock::RecursiveAttrInit) 45.868 + { 45.869 + pthread_mutexattr_init(&Lock::RecursiveAttr); 45.870 + pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 45.871 + Lock::RecursiveAttrInit = 1; 45.872 + } 45.873 + 45.874 + pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); 45.875 + } 45.876 + else 45.877 + pthread_mutex_init(&SMutex, 0); 45.878 +} 45.879 + 45.880 +MutexImpl::~MutexImpl() 45.881 +{ 45.882 + pthread_mutex_destroy(&SMutex); 45.883 +} 45.884 + 45.885 + 45.886 +// Lock and try lock 45.887 +void MutexImpl::DoLock() 45.888 +{ 45.889 + while (pthread_mutex_lock(&SMutex)); 45.890 + LockCount++; 45.891 + LockedBy = pthread_self(); 45.892 +} 45.893 + 45.894 +bool MutexImpl::TryLock() 45.895 +{ 45.896 + if (!pthread_mutex_trylock(&SMutex)) 45.897 + { 45.898 + LockCount++; 45.899 + LockedBy = pthread_self(); 45.900 + return 1; 45.901 + } 45.902 + 45.903 + return 0; 45.904 +} 45.905 + 45.906 +void MutexImpl::Unlock(Mutex* pmutex) 45.907 +{ 45.908 + OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); 45.909 + 45.910 + unsigned lockCount; 45.911 + LockCount--; 45.912 + lockCount = LockCount; 45.913 + 45.914 + pthread_mutex_unlock(&SMutex); 45.915 +} 45.916 + 45.917 +bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 45.918 +{ 45.919 + // There could be multiple interpretations of IsLocked with respect to current thread 45.920 + if (LockCount == 0) 45.921 + return 0; 45.922 + if (pthread_self() != LockedBy) 45.923 + return 1; 45.924 + return 0; 45.925 +} 45.926 + 45.927 +bool MutexImpl::IsSignaled() const 45.928 +{ 45.929 + // An mutex is signaled if it is not locked ANYWHERE 45.930 + // Note that this is different from IsLockedByAnotherThread function, 45.931 + // that takes current thread into account 45.932 + return LockCount == 0; 45.933 +} 45.934 + 45.935 + 45.936 +// *** Actual Mutex class implementation 45.937 + 45.938 +Mutex::Mutex(bool recursive) 45.939 +{ 45.940 + // NOTE: RefCount mode already thread-safe for all waitables. 45.941 + pImpl = new MutexImpl(this, recursive); 45.942 +} 45.943 + 45.944 +Mutex::~Mutex() 45.945 +{ 45.946 + delete pImpl; 45.947 +} 45.948 + 45.949 +// Lock and try lock 45.950 +void Mutex::DoLock() 45.951 +{ 45.952 + pImpl->DoLock(); 45.953 +} 45.954 +bool Mutex::TryLock() 45.955 +{ 45.956 + return pImpl->TryLock(); 45.957 +} 45.958 +void Mutex::Unlock() 45.959 +{ 45.960 + pImpl->Unlock(this); 45.961 +} 45.962 +bool Mutex::IsLockedByAnotherThread() 45.963 +{ 45.964 + return pImpl->IsLockedByAnotherThread(this); 45.965 +} 45.966 + 45.967 + 45.968 + 45.969 +//----------------------------------------------------------------------------------- 45.970 +// ***** Event 45.971 + 45.972 +bool Event::Wait(unsigned delay) 45.973 +{ 45.974 + Mutex::Locker lock(&StateMutex); 45.975 + 45.976 + // Do the correct amount of waiting 45.977 + if (delay == OVR_WAIT_INFINITE) 45.978 + { 45.979 + while(!State) 45.980 + StateWaitCondition.Wait(&StateMutex); 45.981 + } 45.982 + else if (delay) 45.983 + { 45.984 + if (!State) 45.985 + StateWaitCondition.Wait(&StateMutex, delay); 45.986 + } 45.987 + 45.988 + bool state = State; 45.989 + // Take care of temporary 'pulsing' of a state 45.990 + if (Temporary) 45.991 + { 45.992 + Temporary = false; 45.993 + State = false; 45.994 + } 45.995 + return state; 45.996 +} 45.997 + 45.998 +void Event::updateState(bool newState, bool newTemp, bool mustNotify) 45.999 +{ 45.1000 + Mutex::Locker lock(&StateMutex); 45.1001 + State = newState; 45.1002 + Temporary = newTemp; 45.1003 + if (mustNotify) 45.1004 + StateWaitCondition.NotifyAll(); 45.1005 +} 45.1006 + 45.1007 + 45.1008 + 45.1009 +// ***** Wait Condition Implementation 45.1010 + 45.1011 +// Internal implementation class 45.1012 +class WaitConditionImpl : public NewOverrideBase 45.1013 +{ 45.1014 + pthread_mutex_t SMutex; 45.1015 + pthread_cond_t Condv; 45.1016 + 45.1017 +public: 45.1018 + 45.1019 + // Constructor/destructor 45.1020 + WaitConditionImpl(); 45.1021 + ~WaitConditionImpl(); 45.1022 + 45.1023 + // Release mutex and wait for condition. The mutex is re-aqured after the wait. 45.1024 + bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 45.1025 + 45.1026 + // Notify a condition, releasing at one object waiting 45.1027 + void Notify(); 45.1028 + // Notify a condition, releasing all objects waiting 45.1029 + void NotifyAll(); 45.1030 +}; 45.1031 + 45.1032 + 45.1033 +WaitConditionImpl::WaitConditionImpl() 45.1034 +{ 45.1035 + pthread_mutex_init(&SMutex, 0); 45.1036 + pthread_cond_init(&Condv, 0); 45.1037 +} 45.1038 + 45.1039 +WaitConditionImpl::~WaitConditionImpl() 45.1040 +{ 45.1041 + pthread_mutex_destroy(&SMutex); 45.1042 + pthread_cond_destroy(&Condv); 45.1043 +} 45.1044 + 45.1045 +bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 45.1046 +{ 45.1047 + bool result = 1; 45.1048 + unsigned lockCount = pmutex->pImpl->LockCount; 45.1049 + 45.1050 + // Mutex must have been locked 45.1051 + if (lockCount == 0) 45.1052 + return 0; 45.1053 + 45.1054 + pthread_mutex_lock(&SMutex); 45.1055 + 45.1056 + // Finally, release a mutex or semaphore 45.1057 + if (pmutex->pImpl->Recursive) 45.1058 + { 45.1059 + // Release the recursive mutex N times 45.1060 + pmutex->pImpl->LockCount = 0; 45.1061 + for(unsigned i=0; i<lockCount; i++) 45.1062 + pthread_mutex_unlock(&pmutex->pImpl->SMutex); 45.1063 + } 45.1064 + else 45.1065 + { 45.1066 + pmutex->pImpl->LockCount = 0; 45.1067 + pthread_mutex_unlock(&pmutex->pImpl->SMutex); 45.1068 + } 45.1069 + 45.1070 + // Note that there is a gap here between mutex.Unlock() and Wait(). 45.1071 + // The other mutex protects this gap. 45.1072 + 45.1073 + if (delay == OVR_WAIT_INFINITE) 45.1074 + pthread_cond_wait(&Condv,&SMutex); 45.1075 + else 45.1076 + { 45.1077 + timespec ts; 45.1078 +#ifdef OVR_OS_PS3 45.1079 + sys_time_sec_t s; 45.1080 + sys_time_nsec_t ns; 45.1081 + sys_time_get_current_time(&s, &ns); 45.1082 + 45.1083 + ts.tv_sec = s + (delay / 1000); 45.1084 + ts.tv_nsec = ns + (delay % 1000) * 1000000; 45.1085 + 45.1086 +#else 45.1087 + struct timeval tv; 45.1088 + gettimeofday(&tv, 0); 45.1089 + 45.1090 + ts.tv_sec = tv.tv_sec + (delay / 1000); 45.1091 + ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000; 45.1092 +#endif 45.1093 + if (ts.tv_nsec > 999999999) 45.1094 + { 45.1095 + ts.tv_sec++; 45.1096 + ts.tv_nsec -= 1000000000; 45.1097 + } 45.1098 + int r = pthread_cond_timedwait(&Condv,&SMutex, &ts); 45.1099 + OVR_ASSERT(r == 0 || r == ETIMEDOUT); 45.1100 + if (r) 45.1101 + result = 0; 45.1102 + } 45.1103 + 45.1104 + pthread_mutex_unlock(&SMutex); 45.1105 + 45.1106 + // Re-aquire the mutex 45.1107 + for(unsigned i=0; i<lockCount; i++) 45.1108 + pmutex->DoLock(); 45.1109 + 45.1110 + // Return the result 45.1111 + return result; 45.1112 +} 45.1113 + 45.1114 +// Notify a condition, releasing the least object in a queue 45.1115 +void WaitConditionImpl::Notify() 45.1116 +{ 45.1117 + pthread_mutex_lock(&SMutex); 45.1118 + pthread_cond_signal(&Condv); 45.1119 + pthread_mutex_unlock(&SMutex); 45.1120 +} 45.1121 + 45.1122 +// Notify a condition, releasing all objects waiting 45.1123 +void WaitConditionImpl::NotifyAll() 45.1124 +{ 45.1125 + pthread_mutex_lock(&SMutex); 45.1126 + pthread_cond_broadcast(&Condv); 45.1127 + pthread_mutex_unlock(&SMutex); 45.1128 +} 45.1129 + 45.1130 + 45.1131 + 45.1132 +// *** Actual implementation of WaitCondition 45.1133 + 45.1134 +WaitCondition::WaitCondition() 45.1135 +{ 45.1136 + pImpl = new WaitConditionImpl; 45.1137 +} 45.1138 +WaitCondition::~WaitCondition() 45.1139 +{ 45.1140 + delete pImpl; 45.1141 +} 45.1142 + 45.1143 +bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 45.1144 +{ 45.1145 + return pImpl->Wait(pmutex, delay); 45.1146 +} 45.1147 +// Notification 45.1148 +void WaitCondition::Notify() 45.1149 +{ 45.1150 + pImpl->Notify(); 45.1151 +} 45.1152 +void WaitCondition::NotifyAll() 45.1153 +{ 45.1154 + pImpl->NotifyAll(); 45.1155 +} 45.1156 + 45.1157 + 45.1158 +// ***** Current thread 45.1159 + 45.1160 +// Per-thread variable 45.1161 +/* 45.1162 +static __thread Thread* pCurrentThread = 0; 45.1163 + 45.1164 +// Static function to return a pointer to the current thread 45.1165 +void Thread::InitCurrentThread(Thread *pthread) 45.1166 +{ 45.1167 + pCurrentThread = pthread; 45.1168 +} 45.1169 + 45.1170 +// Static function to return a pointer to the current thread 45.1171 +Thread* Thread::GetThread() 45.1172 +{ 45.1173 + return pCurrentThread; 45.1174 +} 45.1175 +*/ 45.1176 + 45.1177 + 45.1178 +// *** Thread constructors. 45.1179 + 45.1180 +Thread::Thread(UPInt stackSize, int processor) 45.1181 +{ 45.1182 + // NOTE: RefCount mode already thread-safe for all Waitable objects. 45.1183 + CreateParams params; 45.1184 + params.stackSize = stackSize; 45.1185 + params.processor = processor; 45.1186 + Init(params); 45.1187 +} 45.1188 + 45.1189 +Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 45.1190 + int processor, Thread::ThreadState initialState) 45.1191 +{ 45.1192 + CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 45.1193 + Init(params); 45.1194 +} 45.1195 + 45.1196 +Thread::Thread(const CreateParams& params) 45.1197 +{ 45.1198 + Init(params); 45.1199 +} 45.1200 + 45.1201 +void Thread::Init(const CreateParams& params) 45.1202 +{ 45.1203 + // Clear the variables 45.1204 + ThreadFlags = 0; 45.1205 + ThreadHandle = 0; 45.1206 + ExitCode = 0; 45.1207 + SuspendCount = 0; 45.1208 + StackSize = params.stackSize; 45.1209 + Processor = params.processor; 45.1210 + Priority = params.priority; 45.1211 + 45.1212 + // Clear Function pointers 45.1213 + ThreadFunction = params.threadFunction; 45.1214 + UserHandle = params.userHandle; 45.1215 + if (params.initialState != NotRunning) 45.1216 + Start(params.initialState); 45.1217 +} 45.1218 + 45.1219 +Thread::~Thread() 45.1220 +{ 45.1221 + // Thread should not running while object is being destroyed, 45.1222 + // this would indicate ref-counting issue. 45.1223 + //OVR_ASSERT(IsRunning() == 0); 45.1224 + 45.1225 + // Clean up thread. 45.1226 + ThreadHandle = 0; 45.1227 +} 45.1228 + 45.1229 + 45.1230 + 45.1231 +// *** Overridable User functions. 45.1232 + 45.1233 +// Default Run implementation 45.1234 +int Thread::Run() 45.1235 +{ 45.1236 + // Call pointer to function, if available. 45.1237 + return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 45.1238 +} 45.1239 +void Thread::OnExit() 45.1240 +{ 45.1241 +} 45.1242 + 45.1243 + 45.1244 +// Finishes the thread and releases internal reference to it. 45.1245 +void Thread::FinishAndRelease() 45.1246 +{ 45.1247 + // Note: thread must be US. 45.1248 + ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 45.1249 + ThreadFlags |= OVR_THREAD_FINISHED; 45.1250 + 45.1251 + // Release our reference; this is equivalent to 'delete this' 45.1252 + // from the point of view of our thread. 45.1253 + Release(); 45.1254 +} 45.1255 + 45.1256 + 45.1257 + 45.1258 +// *** ThreadList - used to track all created threads 45.1259 + 45.1260 +class ThreadList : public NewOverrideBase 45.1261 +{ 45.1262 + //------------------------------------------------------------------------ 45.1263 + struct ThreadHashOp 45.1264 + { 45.1265 + size_t operator()(const Thread* ptr) 45.1266 + { 45.1267 + return (((size_t)ptr) >> 6) ^ (size_t)ptr; 45.1268 + } 45.1269 + }; 45.1270 + 45.1271 + HashSet<Thread*, ThreadHashOp> ThreadSet; 45.1272 + Mutex ThreadMutex; 45.1273 + WaitCondition ThreadsEmpty; 45.1274 + // Track the root thread that created us. 45.1275 + pthread_t RootThreadId; 45.1276 + 45.1277 + static ThreadList* volatile pRunningThreads; 45.1278 + 45.1279 + void addThread(Thread *pthread) 45.1280 + { 45.1281 + Mutex::Locker lock(&ThreadMutex); 45.1282 + ThreadSet.Add(pthread); 45.1283 + } 45.1284 + 45.1285 + void removeThread(Thread *pthread) 45.1286 + { 45.1287 + Mutex::Locker lock(&ThreadMutex); 45.1288 + ThreadSet.Remove(pthread); 45.1289 + if (ThreadSet.GetSize() == 0) 45.1290 + ThreadsEmpty.Notify(); 45.1291 + } 45.1292 + 45.1293 + void finishAllThreads() 45.1294 + { 45.1295 + // Only original root thread can call this. 45.1296 + OVR_ASSERT(pthread_self() == RootThreadId); 45.1297 + 45.1298 + Mutex::Locker lock(&ThreadMutex); 45.1299 + while (ThreadSet.GetSize() != 0) 45.1300 + ThreadsEmpty.Wait(&ThreadMutex); 45.1301 + } 45.1302 + 45.1303 +public: 45.1304 + 45.1305 + ThreadList() 45.1306 + { 45.1307 + RootThreadId = pthread_self(); 45.1308 + } 45.1309 + ~ThreadList() { } 45.1310 + 45.1311 + 45.1312 + static void AddRunningThread(Thread *pthread) 45.1313 + { 45.1314 + // Non-atomic creation ok since only the root thread 45.1315 + if (!pRunningThreads) 45.1316 + { 45.1317 + pRunningThreads = new ThreadList; 45.1318 + OVR_ASSERT(pRunningThreads); 45.1319 + } 45.1320 + pRunningThreads->addThread(pthread); 45.1321 + } 45.1322 + 45.1323 + // NOTE: 'pthread' might be a dead pointer when this is 45.1324 + // called so it should not be accessed; it is only used 45.1325 + // for removal. 45.1326 + static void RemoveRunningThread(Thread *pthread) 45.1327 + { 45.1328 + OVR_ASSERT(pRunningThreads); 45.1329 + pRunningThreads->removeThread(pthread); 45.1330 + } 45.1331 + 45.1332 + static void FinishAllThreads() 45.1333 + { 45.1334 + // This is ok because only root thread can wait for other thread finish. 45.1335 + if (pRunningThreads) 45.1336 + { 45.1337 + pRunningThreads->finishAllThreads(); 45.1338 + delete pRunningThreads; 45.1339 + pRunningThreads = 0; 45.1340 + } 45.1341 + } 45.1342 +}; 45.1343 + 45.1344 +// By default, we have no thread list. 45.1345 +ThreadList* volatile ThreadList::pRunningThreads = 0; 45.1346 + 45.1347 + 45.1348 +// FinishAllThreads - exposed publicly in Thread. 45.1349 +void Thread::FinishAllThreads() 45.1350 +{ 45.1351 + ThreadList::FinishAllThreads(); 45.1352 +} 45.1353 + 45.1354 +// *** Run override 45.1355 + 45.1356 +int Thread::PRun() 45.1357 +{ 45.1358 + // Suspend us on start, if requested 45.1359 + if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 45.1360 + { 45.1361 + Suspend(); 45.1362 + ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 45.1363 + } 45.1364 + 45.1365 + // Call the virtual run function 45.1366 + ExitCode = Run(); 45.1367 + return ExitCode; 45.1368 +} 45.1369 + 45.1370 + 45.1371 + 45.1372 + 45.1373 +// *** User overridables 45.1374 + 45.1375 +bool Thread::GetExitFlag() const 45.1376 +{ 45.1377 + return (ThreadFlags & OVR_THREAD_EXIT) != 0; 45.1378 +} 45.1379 + 45.1380 +void Thread::SetExitFlag(bool exitFlag) 45.1381 +{ 45.1382 + // The below is atomic since ThreadFlags is AtomicInt. 45.1383 + if (exitFlag) 45.1384 + ThreadFlags |= OVR_THREAD_EXIT; 45.1385 + else 45.1386 + ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 45.1387 +} 45.1388 + 45.1389 + 45.1390 +// Determines whether the thread was running and is now finished 45.1391 +bool Thread::IsFinished() const 45.1392 +{ 45.1393 + return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 45.1394 +} 45.1395 +// Determines whether the thread is suspended 45.1396 +bool Thread::IsSuspended() const 45.1397 +{ 45.1398 + return SuspendCount > 0; 45.1399 +} 45.1400 +// Returns current thread state 45.1401 +Thread::ThreadState Thread::GetThreadState() const 45.1402 +{ 45.1403 + if (IsSuspended()) 45.1404 + return Suspended; 45.1405 + if (ThreadFlags & OVR_THREAD_STARTED) 45.1406 + return Running; 45.1407 + return NotRunning; 45.1408 +} 45.1409 +/* 45.1410 +static const char* mapsched_policy(int policy) 45.1411 +{ 45.1412 + switch(policy) 45.1413 + { 45.1414 + case SCHED_OTHER: 45.1415 + return "SCHED_OTHER"; 45.1416 + case SCHED_RR: 45.1417 + return "SCHED_RR"; 45.1418 + case SCHED_FIFO: 45.1419 + return "SCHED_FIFO"; 45.1420 + 45.1421 + } 45.1422 + return "UNKNOWN"; 45.1423 +} 45.1424 + int policy; 45.1425 + sched_param sparam; 45.1426 + pthread_getschedparam(pthread_self(), &policy, &sparam); 45.1427 + int max_prior = sched_get_priority_max(policy); 45.1428 + int min_prior = sched_get_priority_min(policy); 45.1429 + printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior); 45.1430 +#include <stdio.h> 45.1431 +*/ 45.1432 +// ***** Thread management 45.1433 + 45.1434 +// The actual first function called on thread start 45.1435 +void* Thread_PthreadStartFn(void* phandle) 45.1436 +{ 45.1437 + Thread* pthread = (Thread*)phandle; 45.1438 + int result = pthread->PRun(); 45.1439 + // Signal the thread as done and release it atomically. 45.1440 + pthread->FinishAndRelease(); 45.1441 + // At this point Thread object might be dead; however we can still pass 45.1442 + // it to RemoveRunningThread since it is only used as a key there. 45.1443 + ThreadList::RemoveRunningThread(pthread); 45.1444 + return (void*) result; 45.1445 +} 45.1446 + 45.1447 +int Thread::InitAttr = 0; 45.1448 +pthread_attr_t Thread::Attr; 45.1449 + 45.1450 +/* static */ 45.1451 +int Thread::GetOSPriority(ThreadPriority p) 45.1452 +//static inline int MapToSystemPrority(Thread::ThreadPriority p) 45.1453 +{ 45.1454 +#ifdef OVR_OS_PS3 45.1455 + switch(p) 45.1456 + { 45.1457 + case Thread::CriticalPriority: return 0; 45.1458 + case Thread::HighestPriority: return 300; 45.1459 + case Thread::AboveNormalPriority: return 600; 45.1460 + case Thread::NormalPriority: return 1000; 45.1461 + case Thread::BelowNormalPriority: return 1500; 45.1462 + case Thread::LowestPriority: return 2500; 45.1463 + case Thread::IdlePriority: return 3071; 45.1464 + } return 1000; 45.1465 +#else 45.1466 + OVR_UNUSED(p); 45.1467 + return -1; 45.1468 +#endif 45.1469 +} 45.1470 + 45.1471 +bool Thread::Start(ThreadState initialState) 45.1472 +{ 45.1473 + if (initialState == NotRunning) 45.1474 + return 0; 45.1475 + if (GetThreadState() != NotRunning) 45.1476 + { 45.1477 + OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 45.1478 + return 0; 45.1479 + } 45.1480 + 45.1481 + if (!InitAttr) 45.1482 + { 45.1483 + pthread_attr_init(&Attr); 45.1484 + pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED); 45.1485 + pthread_attr_setstacksize(&Attr, 128 * 1024); 45.1486 + sched_param sparam; 45.1487 + sparam.sched_priority = Thread::GetOSPriority(NormalPriority); 45.1488 + pthread_attr_setschedparam(&Attr, &sparam); 45.1489 + InitAttr = 1; 45.1490 + } 45.1491 + 45.1492 + ExitCode = 0; 45.1493 + SuspendCount = 0; 45.1494 + ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 45.1495 + 45.1496 + // AddRef to us until the thread is finished 45.1497 + AddRef(); 45.1498 + ThreadList::AddRunningThread(this); 45.1499 + 45.1500 + int result; 45.1501 + if (StackSize != 128 * 1024 || Priority != NormalPriority) 45.1502 + { 45.1503 + pthread_attr_t attr; 45.1504 + 45.1505 + pthread_attr_init(&attr); 45.1506 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 45.1507 + pthread_attr_setstacksize(&attr, StackSize); 45.1508 + sched_param sparam; 45.1509 + sparam.sched_priority = Thread::GetOSPriority(Priority); 45.1510 + pthread_attr_setschedparam(&attr, &sparam); 45.1511 + result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this); 45.1512 + pthread_attr_destroy(&attr); 45.1513 + } 45.1514 + else 45.1515 + result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this); 45.1516 + 45.1517 + if (result) 45.1518 + { 45.1519 + ThreadFlags = 0; 45.1520 + Release(); 45.1521 + ThreadList::RemoveRunningThread(this); 45.1522 + return 0; 45.1523 + } 45.1524 + return 1; 45.1525 +} 45.1526 + 45.1527 + 45.1528 +// Suspend the thread until resumed 45.1529 +bool Thread::Suspend() 45.1530 +{ 45.1531 + OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system")); 45.1532 + return 0; 45.1533 +} 45.1534 + 45.1535 +// Resumes currently suspended thread 45.1536 +bool Thread::Resume() 45.1537 +{ 45.1538 + return 0; 45.1539 +} 45.1540 + 45.1541 + 45.1542 +// Quits with an exit code 45.1543 +void Thread::Exit(int exitCode) 45.1544 +{ 45.1545 + // Can only exist the current thread 45.1546 + // if (GetThread() != this) 45.1547 + // return; 45.1548 + 45.1549 + // Call the virtual OnExit function 45.1550 + OnExit(); 45.1551 + 45.1552 + // Signal this thread object as done and release it's references. 45.1553 + FinishAndRelease(); 45.1554 + ThreadList::RemoveRunningThread(this); 45.1555 + 45.1556 + pthread_exit((void *) exitCode); 45.1557 +} 45.1558 + 45.1559 +ThreadId GetCurrentThreadId() 45.1560 +{ 45.1561 + return (void*)pthread_self(); 45.1562 +} 45.1563 + 45.1564 +// *** Sleep functions 45.1565 + 45.1566 +/* static */ 45.1567 +bool Thread::Sleep(unsigned secs) 45.1568 +{ 45.1569 + sleep(secs); 45.1570 + return 1; 45.1571 +} 45.1572 +/* static */ 45.1573 +bool Thread::MSleep(unsigned msecs) 45.1574 +{ 45.1575 + usleep(msecs*1000); 45.1576 + return 1; 45.1577 +} 45.1578 + 45.1579 +/* static */ 45.1580 +int Thread::GetCPUCount() 45.1581 +{ 45.1582 + return 1; 45.1583 +} 45.1584 + 45.1585 + 45.1586 +#ifdef OVR_OS_PS3 45.1587 + 45.1588 +sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE }; 45.1589 + 45.1590 +#endif 45.1591 + 45.1592 +} 45.1593 + 45.1594 +#endif // OVR_ENABLE_THREADS
46.1 --- a/libovr/Src/osx/OVR_ThreadsPthread.cpp Sat Sep 14 17:51:03 2013 +0300 46.2 +++ b/libovr/Src/osx/OVR_ThreadsPthread.cpp Sun Sep 15 04:10:05 2013 +0300 46.3 @@ -1,1 +1,795 @@ 46.4 - 46.5 #include "OVR_Threads.h" 46.6 #include "OVR_Hash.h" 46.7 46.8 #ifdef OVR_ENABLE_THREADS 46.9 46.10 #include "OVR_Timer.h" 46.11 #include "OVR_Log.h" 46.12 46.13 #include <pthread.h> 46.14 #include <time.h> 46.15 46.16 #ifdef OVR_OS_PS3 46.17 #include <sys/sys_time.h> 46.18 #include <sys/timer.h> 46.19 #include <sys/synchronization.h> 46.20 #define sleep(x) sys_timer_sleep(x) 46.21 #define usleep(x) sys_timer_usleep(x) 46.22 using std::timespec; 46.23 #else 46.24 #include <unistd.h> 46.25 #include <sys/time.h> 46.26 #include <errno.h> 46.27 #endif 46.28 46.29 namespace OVR { 46.30 46.31 // ***** Mutex implementation 46.32 46.33 46.34 // *** Internal Mutex implementation structure 46.35 46.36 class MutexImpl : public NewOverrideBase 46.37 { 46.38 // System mutex or semaphore 46.39 pthread_mutex_t SMutex; 46.40 bool Recursive; 46.41 unsigned LockCount; 46.42 pthread_t LockedBy; 46.43 46.44 friend class WaitConditionImpl; 46.45 46.46 public: 46.47 // Constructor/destructor 46.48 MutexImpl(Mutex* pmutex, bool recursive = 1); 46.49 ~MutexImpl(); 46.50 46.51 // Locking functions 46.52 void DoLock(); 46.53 bool TryLock(); 46.54 void Unlock(Mutex* pmutex); 46.55 // Returns 1 if the mutes is currently locked 46.56 bool IsLockedByAnotherThread(Mutex* pmutex); 46.57 bool IsSignaled() const; 46.58 }; 46.59 46.60 pthread_mutexattr_t Lock::RecursiveAttr; 46.61 bool Lock::RecursiveAttrInit = 0; 46.62 46.63 // *** Constructor/destructor 46.64 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) 46.65 { 46.66 Recursive = recursive; 46.67 LockCount = 0; 46.68 46.69 if (Recursive) 46.70 { 46.71 if (!Lock::RecursiveAttrInit) 46.72 { 46.73 pthread_mutexattr_init(&Lock::RecursiveAttr); 46.74 pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 46.75 Lock::RecursiveAttrInit = 1; 46.76 } 46.77 46.78 pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); 46.79 } 46.80 else 46.81 pthread_mutex_init(&SMutex, 0); 46.82 } 46.83 46.84 MutexImpl::~MutexImpl() 46.85 { 46.86 pthread_mutex_destroy(&SMutex); 46.87 } 46.88 46.89 46.90 // Lock and try lock 46.91 void MutexImpl::DoLock() 46.92 { 46.93 while (pthread_mutex_lock(&SMutex)); 46.94 LockCount++; 46.95 LockedBy = pthread_self(); 46.96 } 46.97 46.98 bool MutexImpl::TryLock() 46.99 { 46.100 if (!pthread_mutex_trylock(&SMutex)) 46.101 { 46.102 LockCount++; 46.103 LockedBy = pthread_self(); 46.104 return 1; 46.105 } 46.106 46.107 return 0; 46.108 } 46.109 46.110 void MutexImpl::Unlock(Mutex* pmutex) 46.111 { 46.112 OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); 46.113 46.114 unsigned lockCount; 46.115 LockCount--; 46.116 lockCount = LockCount; 46.117 46.118 pthread_mutex_unlock(&SMutex); 46.119 } 46.120 46.121 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 46.122 { 46.123 // There could be multiple interpretations of IsLocked with respect to current thread 46.124 if (LockCount == 0) 46.125 return 0; 46.126 if (pthread_self() != LockedBy) 46.127 return 1; 46.128 return 0; 46.129 } 46.130 46.131 bool MutexImpl::IsSignaled() const 46.132 { 46.133 // An mutex is signaled if it is not locked ANYWHERE 46.134 // Note that this is different from IsLockedByAnotherThread function, 46.135 // that takes current thread into account 46.136 return LockCount == 0; 46.137 } 46.138 46.139 46.140 // *** Actual Mutex class implementation 46.141 46.142 Mutex::Mutex(bool recursive) 46.143 { 46.144 // NOTE: RefCount mode already thread-safe for all waitables. 46.145 pImpl = new MutexImpl(this, recursive); 46.146 } 46.147 46.148 Mutex::~Mutex() 46.149 { 46.150 delete pImpl; 46.151 } 46.152 46.153 // Lock and try lock 46.154 void Mutex::DoLock() 46.155 { 46.156 pImpl->DoLock(); 46.157 } 46.158 bool Mutex::TryLock() 46.159 { 46.160 return pImpl->TryLock(); 46.161 } 46.162 void Mutex::Unlock() 46.163 { 46.164 pImpl->Unlock(this); 46.165 } 46.166 bool Mutex::IsLockedByAnotherThread() 46.167 { 46.168 return pImpl->IsLockedByAnotherThread(this); 46.169 } 46.170 46.171 46.172 46.173 //----------------------------------------------------------------------------------- 46.174 // ***** Event 46.175 46.176 bool Event::Wait(unsigned delay) 46.177 { 46.178 Mutex::Locker lock(&StateMutex); 46.179 46.180 // Do the correct amount of waiting 46.181 if (delay == OVR_WAIT_INFINITE) 46.182 { 46.183 while(!State) 46.184 StateWaitCondition.Wait(&StateMutex); 46.185 } 46.186 else if (delay) 46.187 { 46.188 if (!State) 46.189 StateWaitCondition.Wait(&StateMutex, delay); 46.190 } 46.191 46.192 bool state = State; 46.193 // Take care of temporary 'pulsing' of a state 46.194 if (Temporary) 46.195 { 46.196 Temporary = false; 46.197 State = false; 46.198 } 46.199 return state; 46.200 } 46.201 46.202 void Event::updateState(bool newState, bool newTemp, bool mustNotify) 46.203 { 46.204 Mutex::Locker lock(&StateMutex); 46.205 State = newState; 46.206 Temporary = newTemp; 46.207 if (mustNotify) 46.208 StateWaitCondition.NotifyAll(); 46.209 } 46.210 46.211 46.212 46.213 // ***** Wait Condition Implementation 46.214 46.215 // Internal implementation class 46.216 class WaitConditionImpl : public NewOverrideBase 46.217 { 46.218 pthread_mutex_t SMutex; 46.219 pthread_cond_t Condv; 46.220 46.221 public: 46.222 46.223 // Constructor/destructor 46.224 WaitConditionImpl(); 46.225 ~WaitConditionImpl(); 46.226 46.227 // Release mutex and wait for condition. The mutex is re-aqured after the wait. 46.228 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 46.229 46.230 // Notify a condition, releasing at one object waiting 46.231 void Notify(); 46.232 // Notify a condition, releasing all objects waiting 46.233 void NotifyAll(); 46.234 }; 46.235 46.236 46.237 WaitConditionImpl::WaitConditionImpl() 46.238 { 46.239 pthread_mutex_init(&SMutex, 0); 46.240 pthread_cond_init(&Condv, 0); 46.241 } 46.242 46.243 WaitConditionImpl::~WaitConditionImpl() 46.244 { 46.245 pthread_mutex_destroy(&SMutex); 46.246 pthread_cond_destroy(&Condv); 46.247 } 46.248 46.249 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 46.250 { 46.251 bool result = 1; 46.252 unsigned lockCount = pmutex->pImpl->LockCount; 46.253 46.254 // Mutex must have been locked 46.255 if (lockCount == 0) 46.256 return 0; 46.257 46.258 pthread_mutex_lock(&SMutex); 46.259 46.260 // Finally, release a mutex or semaphore 46.261 if (pmutex->pImpl->Recursive) 46.262 { 46.263 // Release the recursive mutex N times 46.264 pmutex->pImpl->LockCount = 0; 46.265 for(unsigned i=0; i<lockCount; i++) 46.266 pthread_mutex_unlock(&pmutex->pImpl->SMutex); 46.267 } 46.268 else 46.269 { 46.270 pmutex->pImpl->LockCount = 0; 46.271 pthread_mutex_unlock(&pmutex->pImpl->SMutex); 46.272 } 46.273 46.274 // Note that there is a gap here between mutex.Unlock() and Wait(). 46.275 // The other mutex protects this gap. 46.276 46.277 if (delay == OVR_WAIT_INFINITE) 46.278 pthread_cond_wait(&Condv,&SMutex); 46.279 else 46.280 { 46.281 timespec ts; 46.282 #ifdef OVR_OS_PS3 46.283 sys_time_sec_t s; 46.284 sys_time_nsec_t ns; 46.285 sys_time_get_current_time(&s, &ns); 46.286 46.287 ts.tv_sec = s + (delay / 1000); 46.288 ts.tv_nsec = ns + (delay % 1000) * 1000000; 46.289 46.290 #else 46.291 struct timeval tv; 46.292 gettimeofday(&tv, 0); 46.293 46.294 ts.tv_sec = tv.tv_sec + (delay / 1000); 46.295 ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000; 46.296 #endif 46.297 if (ts.tv_nsec > 999999999) 46.298 { 46.299 ts.tv_sec++; 46.300 ts.tv_nsec -= 1000000000; 46.301 } 46.302 int r = pthread_cond_timedwait(&Condv,&SMutex, &ts); 46.303 OVR_ASSERT(r == 0 || r == ETIMEDOUT); 46.304 if (r) 46.305 result = 0; 46.306 } 46.307 46.308 pthread_mutex_unlock(&SMutex); 46.309 46.310 // Re-aquire the mutex 46.311 for(unsigned i=0; i<lockCount; i++) 46.312 pmutex->DoLock(); 46.313 46.314 // Return the result 46.315 return result; 46.316 } 46.317 46.318 // Notify a condition, releasing the least object in a queue 46.319 void WaitConditionImpl::Notify() 46.320 { 46.321 pthread_mutex_lock(&SMutex); 46.322 pthread_cond_signal(&Condv); 46.323 pthread_mutex_unlock(&SMutex); 46.324 } 46.325 46.326 // Notify a condition, releasing all objects waiting 46.327 void WaitConditionImpl::NotifyAll() 46.328 { 46.329 pthread_mutex_lock(&SMutex); 46.330 pthread_cond_broadcast(&Condv); 46.331 pthread_mutex_unlock(&SMutex); 46.332 } 46.333 46.334 46.335 46.336 // *** Actual implementation of WaitCondition 46.337 46.338 WaitCondition::WaitCondition() 46.339 { 46.340 pImpl = new WaitConditionImpl; 46.341 } 46.342 WaitCondition::~WaitCondition() 46.343 { 46.344 delete pImpl; 46.345 } 46.346 46.347 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 46.348 { 46.349 return pImpl->Wait(pmutex, delay); 46.350 } 46.351 // Notification 46.352 void WaitCondition::Notify() 46.353 { 46.354 pImpl->Notify(); 46.355 } 46.356 void WaitCondition::NotifyAll() 46.357 { 46.358 pImpl->NotifyAll(); 46.359 } 46.360 46.361 46.362 // ***** Current thread 46.363 46.364 // Per-thread variable 46.365 /* 46.366 static __thread Thread* pCurrentThread = 0; 46.367 46.368 // Static function to return a pointer to the current thread 46.369 void Thread::InitCurrentThread(Thread *pthread) 46.370 { 46.371 pCurrentThread = pthread; 46.372 } 46.373 46.374 // Static function to return a pointer to the current thread 46.375 Thread* Thread::GetThread() 46.376 { 46.377 return pCurrentThread; 46.378 } 46.379 */ 46.380 46.381 46.382 // *** Thread constructors. 46.383 46.384 Thread::Thread(UPInt stackSize, int processor) 46.385 { 46.386 // NOTE: RefCount mode already thread-safe for all Waitable objects. 46.387 CreateParams params; 46.388 params.stackSize = stackSize; 46.389 params.processor = processor; 46.390 Init(params); 46.391 } 46.392 46.393 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 46.394 int processor, Thread::ThreadState initialState) 46.395 { 46.396 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 46.397 Init(params); 46.398 } 46.399 46.400 Thread::Thread(const CreateParams& params) 46.401 { 46.402 Init(params); 46.403 } 46.404 46.405 void Thread::Init(const CreateParams& params) 46.406 { 46.407 // Clear the variables 46.408 ThreadFlags = 0; 46.409 ThreadHandle = 0; 46.410 ExitCode = 0; 46.411 SuspendCount = 0; 46.412 StackSize = params.stackSize; 46.413 Processor = params.processor; 46.414 Priority = params.priority; 46.415 46.416 // Clear Function pointers 46.417 ThreadFunction = params.threadFunction; 46.418 UserHandle = params.userHandle; 46.419 if (params.initialState != NotRunning) 46.420 Start(params.initialState); 46.421 } 46.422 46.423 Thread::~Thread() 46.424 { 46.425 // Thread should not running while object is being destroyed, 46.426 // this would indicate ref-counting issue. 46.427 //OVR_ASSERT(IsRunning() == 0); 46.428 46.429 // Clean up thread. 46.430 ThreadHandle = 0; 46.431 } 46.432 46.433 46.434 46.435 // *** Overridable User functions. 46.436 46.437 // Default Run implementation 46.438 int Thread::Run() 46.439 { 46.440 // Call pointer to function, if available. 46.441 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 46.442 } 46.443 void Thread::OnExit() 46.444 { 46.445 } 46.446 46.447 46.448 // Finishes the thread and releases internal reference to it. 46.449 void Thread::FinishAndRelease() 46.450 { 46.451 // Note: thread must be US. 46.452 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 46.453 ThreadFlags |= OVR_THREAD_FINISHED; 46.454 46.455 // Release our reference; this is equivalent to 'delete this' 46.456 // from the point of view of our thread. 46.457 Release(); 46.458 } 46.459 46.460 46.461 46.462 // *** ThreadList - used to track all created threads 46.463 46.464 class ThreadList : public NewOverrideBase 46.465 { 46.466 //------------------------------------------------------------------------ 46.467 struct ThreadHashOp 46.468 { 46.469 size_t operator()(const Thread* ptr) 46.470 { 46.471 return (((size_t)ptr) >> 6) ^ (size_t)ptr; 46.472 } 46.473 }; 46.474 46.475 HashSet<Thread*, ThreadHashOp> ThreadSet; 46.476 Mutex ThreadMutex; 46.477 WaitCondition ThreadsEmpty; 46.478 // Track the root thread that created us. 46.479 pthread_t RootThreadId; 46.480 46.481 static ThreadList* volatile pRunningThreads; 46.482 46.483 void addThread(Thread *pthread) 46.484 { 46.485 Mutex::Locker lock(&ThreadMutex); 46.486 ThreadSet.Add(pthread); 46.487 } 46.488 46.489 void removeThread(Thread *pthread) 46.490 { 46.491 Mutex::Locker lock(&ThreadMutex); 46.492 ThreadSet.Remove(pthread); 46.493 if (ThreadSet.GetSize() == 0) 46.494 ThreadsEmpty.Notify(); 46.495 } 46.496 46.497 void finishAllThreads() 46.498 { 46.499 // Only original root thread can call this. 46.500 OVR_ASSERT(pthread_self() == RootThreadId); 46.501 46.502 Mutex::Locker lock(&ThreadMutex); 46.503 while (ThreadSet.GetSize() != 0) 46.504 ThreadsEmpty.Wait(&ThreadMutex); 46.505 } 46.506 46.507 public: 46.508 46.509 ThreadList() 46.510 { 46.511 RootThreadId = pthread_self(); 46.512 } 46.513 ~ThreadList() { } 46.514 46.515 46.516 static void AddRunningThread(Thread *pthread) 46.517 { 46.518 // Non-atomic creation ok since only the root thread 46.519 if (!pRunningThreads) 46.520 { 46.521 pRunningThreads = new ThreadList; 46.522 OVR_ASSERT(pRunningThreads); 46.523 } 46.524 pRunningThreads->addThread(pthread); 46.525 } 46.526 46.527 // NOTE: 'pthread' might be a dead pointer when this is 46.528 // called so it should not be accessed; it is only used 46.529 // for removal. 46.530 static void RemoveRunningThread(Thread *pthread) 46.531 { 46.532 OVR_ASSERT(pRunningThreads); 46.533 pRunningThreads->removeThread(pthread); 46.534 } 46.535 46.536 static void FinishAllThreads() 46.537 { 46.538 // This is ok because only root thread can wait for other thread finish. 46.539 if (pRunningThreads) 46.540 { 46.541 pRunningThreads->finishAllThreads(); 46.542 delete pRunningThreads; 46.543 pRunningThreads = 0; 46.544 } 46.545 } 46.546 }; 46.547 46.548 // By default, we have no thread list. 46.549 ThreadList* volatile ThreadList::pRunningThreads = 0; 46.550 46.551 46.552 // FinishAllThreads - exposed publicly in Thread. 46.553 void Thread::FinishAllThreads() 46.554 { 46.555 ThreadList::FinishAllThreads(); 46.556 } 46.557 46.558 // *** Run override 46.559 46.560 int Thread::PRun() 46.561 { 46.562 // Suspend us on start, if requested 46.563 if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 46.564 { 46.565 Suspend(); 46.566 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 46.567 } 46.568 46.569 // Call the virtual run function 46.570 ExitCode = Run(); 46.571 return ExitCode; 46.572 } 46.573 46.574 46.575 46.576 46.577 // *** User overridables 46.578 46.579 bool Thread::GetExitFlag() const 46.580 { 46.581 return (ThreadFlags & OVR_THREAD_EXIT) != 0; 46.582 } 46.583 46.584 void Thread::SetExitFlag(bool exitFlag) 46.585 { 46.586 // The below is atomic since ThreadFlags is AtomicInt. 46.587 if (exitFlag) 46.588 ThreadFlags |= OVR_THREAD_EXIT; 46.589 else 46.590 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 46.591 } 46.592 46.593 46.594 // Determines whether the thread was running and is now finished 46.595 bool Thread::IsFinished() const 46.596 { 46.597 return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 46.598 } 46.599 // Determines whether the thread is suspended 46.600 bool Thread::IsSuspended() const 46.601 { 46.602 return SuspendCount > 0; 46.603 } 46.604 // Returns current thread state 46.605 Thread::ThreadState Thread::GetThreadState() const 46.606 { 46.607 if (IsSuspended()) 46.608 return Suspended; 46.609 if (ThreadFlags & OVR_THREAD_STARTED) 46.610 return Running; 46.611 return NotRunning; 46.612 } 46.613 /* 46.614 static const char* mapsched_policy(int policy) 46.615 { 46.616 switch(policy) 46.617 { 46.618 case SCHED_OTHER: 46.619 return "SCHED_OTHER"; 46.620 case SCHED_RR: 46.621 return "SCHED_RR"; 46.622 case SCHED_FIFO: 46.623 return "SCHED_FIFO"; 46.624 46.625 } 46.626 return "UNKNOWN"; 46.627 } 46.628 int policy; 46.629 sched_param sparam; 46.630 pthread_getschedparam(pthread_self(), &policy, &sparam); 46.631 int max_prior = sched_get_priority_max(policy); 46.632 int min_prior = sched_get_priority_min(policy); 46.633 printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior); 46.634 #include <stdio.h> 46.635 */ 46.636 // ***** Thread management 46.637 46.638 // The actual first function called on thread start 46.639 void* Thread_PthreadStartFn(void* phandle) 46.640 { 46.641 Thread* pthread = (Thread*)phandle; 46.642 int result = pthread->PRun(); 46.643 // Signal the thread as done and release it atomically. 46.644 pthread->FinishAndRelease(); 46.645 // At this point Thread object might be dead; however we can still pass 46.646 // it to RemoveRunningThread since it is only used as a key there. 46.647 ThreadList::RemoveRunningThread(pthread); 46.648 return (void*) result; 46.649 } 46.650 46.651 int Thread::InitAttr = 0; 46.652 pthread_attr_t Thread::Attr; 46.653 46.654 /* static */ 46.655 int Thread::GetOSPriority(ThreadPriority p) 46.656 //static inline int MapToSystemPrority(Thread::ThreadPriority p) 46.657 { 46.658 #ifdef OVR_OS_PS3 46.659 switch(p) 46.660 { 46.661 case Thread::CriticalPriority: return 0; 46.662 case Thread::HighestPriority: return 300; 46.663 case Thread::AboveNormalPriority: return 600; 46.664 case Thread::NormalPriority: return 1000; 46.665 case Thread::BelowNormalPriority: return 1500; 46.666 case Thread::LowestPriority: return 2500; 46.667 case Thread::IdlePriority: return 3071; 46.668 } return 1000; 46.669 #else 46.670 OVR_UNUSED(p); 46.671 return -1; 46.672 #endif 46.673 } 46.674 46.675 bool Thread::Start(ThreadState initialState) 46.676 { 46.677 if (initialState == NotRunning) 46.678 return 0; 46.679 if (GetThreadState() != NotRunning) 46.680 { 46.681 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 46.682 return 0; 46.683 } 46.684 46.685 if (!InitAttr) 46.686 { 46.687 pthread_attr_init(&Attr); 46.688 pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED); 46.689 pthread_attr_setstacksize(&Attr, 128 * 1024); 46.690 sched_param sparam; 46.691 sparam.sched_priority = Thread::GetOSPriority(NormalPriority); 46.692 pthread_attr_setschedparam(&Attr, &sparam); 46.693 InitAttr = 1; 46.694 } 46.695 46.696 ExitCode = 0; 46.697 SuspendCount = 0; 46.698 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 46.699 46.700 // AddRef to us until the thread is finished 46.701 AddRef(); 46.702 ThreadList::AddRunningThread(this); 46.703 46.704 int result; 46.705 if (StackSize != 128 * 1024 || Priority != NormalPriority) 46.706 { 46.707 pthread_attr_t attr; 46.708 46.709 pthread_attr_init(&attr); 46.710 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 46.711 pthread_attr_setstacksize(&attr, StackSize); 46.712 sched_param sparam; 46.713 sparam.sched_priority = Thread::GetOSPriority(Priority); 46.714 pthread_attr_setschedparam(&attr, &sparam); 46.715 result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this); 46.716 pthread_attr_destroy(&attr); 46.717 } 46.718 else 46.719 result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this); 46.720 46.721 if (result) 46.722 { 46.723 ThreadFlags = 0; 46.724 Release(); 46.725 ThreadList::RemoveRunningThread(this); 46.726 return 0; 46.727 } 46.728 return 1; 46.729 } 46.730 46.731 46.732 // Suspend the thread until resumed 46.733 bool Thread::Suspend() 46.734 { 46.735 OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system")); 46.736 return 0; 46.737 } 46.738 46.739 // Resumes currently suspended thread 46.740 bool Thread::Resume() 46.741 { 46.742 return 0; 46.743 } 46.744 46.745 46.746 // Quits with an exit code 46.747 void Thread::Exit(int exitCode) 46.748 { 46.749 // Can only exist the current thread 46.750 // if (GetThread() != this) 46.751 // return; 46.752 46.753 // Call the virtual OnExit function 46.754 OnExit(); 46.755 46.756 // Signal this thread object as done and release it's references. 46.757 FinishAndRelease(); 46.758 ThreadList::RemoveRunningThread(this); 46.759 46.760 pthread_exit((void *) exitCode); 46.761 } 46.762 46.763 ThreadId GetCurrentThreadId() 46.764 { 46.765 return (void*)pthread_self(); 46.766 } 46.767 46.768 // *** Sleep functions 46.769 46.770 /* static */ 46.771 bool Thread::Sleep(unsigned secs) 46.772 { 46.773 sleep(secs); 46.774 return 1; 46.775 } 46.776 /* static */ 46.777 bool Thread::MSleep(unsigned msecs) 46.778 { 46.779 usleep(msecs*1000); 46.780 return 1; 46.781 } 46.782 46.783 /* static */ 46.784 int Thread::GetCPUCount() 46.785 { 46.786 return 1; 46.787 } 46.788 46.789 46.790 #ifdef OVR_OS_PS3 46.791 46.792 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE }; 46.793 46.794 #endif 46.795 46.796 } 46.797 46.798 #endif // OVR_ENABLE_THREADS 46.799 \ No newline at end of file 46.800 + 46.801 +#include "OVR_Threads.h" 46.802 +#include "OVR_Hash.h" 46.803 + 46.804 +#ifdef OVR_ENABLE_THREADS 46.805 + 46.806 +#include "OVR_Timer.h" 46.807 +#include "OVR_Log.h" 46.808 + 46.809 +#include <pthread.h> 46.810 +#include <time.h> 46.811 + 46.812 +#ifdef OVR_OS_PS3 46.813 +#include <sys/sys_time.h> 46.814 +#include <sys/timer.h> 46.815 +#include <sys/synchronization.h> 46.816 +#define sleep(x) sys_timer_sleep(x) 46.817 +#define usleep(x) sys_timer_usleep(x) 46.818 +using std::timespec; 46.819 +#else 46.820 +#include <unistd.h> 46.821 +#include <sys/time.h> 46.822 +#include <errno.h> 46.823 +#endif 46.824 + 46.825 +namespace OVR { 46.826 + 46.827 +// ***** Mutex implementation 46.828 + 46.829 + 46.830 +// *** Internal Mutex implementation structure 46.831 + 46.832 +class MutexImpl : public NewOverrideBase 46.833 +{ 46.834 + // System mutex or semaphore 46.835 + pthread_mutex_t SMutex; 46.836 + bool Recursive; 46.837 + unsigned LockCount; 46.838 + pthread_t LockedBy; 46.839 + 46.840 + friend class WaitConditionImpl; 46.841 + 46.842 +public: 46.843 + // Constructor/destructor 46.844 + MutexImpl(Mutex* pmutex, bool recursive = 1); 46.845 + ~MutexImpl(); 46.846 + 46.847 + // Locking functions 46.848 + void DoLock(); 46.849 + bool TryLock(); 46.850 + void Unlock(Mutex* pmutex); 46.851 + // Returns 1 if the mutes is currently locked 46.852 + bool IsLockedByAnotherThread(Mutex* pmutex); 46.853 + bool IsSignaled() const; 46.854 +}; 46.855 + 46.856 +pthread_mutexattr_t Lock::RecursiveAttr; 46.857 +bool Lock::RecursiveAttrInit = 0; 46.858 + 46.859 +// *** Constructor/destructor 46.860 +MutexImpl::MutexImpl(Mutex* pmutex, bool recursive) 46.861 +{ 46.862 + Recursive = recursive; 46.863 + LockCount = 0; 46.864 + 46.865 + if (Recursive) 46.866 + { 46.867 + if (!Lock::RecursiveAttrInit) 46.868 + { 46.869 + pthread_mutexattr_init(&Lock::RecursiveAttr); 46.870 + pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE); 46.871 + Lock::RecursiveAttrInit = 1; 46.872 + } 46.873 + 46.874 + pthread_mutex_init(&SMutex, &Lock::RecursiveAttr); 46.875 + } 46.876 + else 46.877 + pthread_mutex_init(&SMutex, 0); 46.878 +} 46.879 + 46.880 +MutexImpl::~MutexImpl() 46.881 +{ 46.882 + pthread_mutex_destroy(&SMutex); 46.883 +} 46.884 + 46.885 + 46.886 +// Lock and try lock 46.887 +void MutexImpl::DoLock() 46.888 +{ 46.889 + while (pthread_mutex_lock(&SMutex)); 46.890 + LockCount++; 46.891 + LockedBy = pthread_self(); 46.892 +} 46.893 + 46.894 +bool MutexImpl::TryLock() 46.895 +{ 46.896 + if (!pthread_mutex_trylock(&SMutex)) 46.897 + { 46.898 + LockCount++; 46.899 + LockedBy = pthread_self(); 46.900 + return 1; 46.901 + } 46.902 + 46.903 + return 0; 46.904 +} 46.905 + 46.906 +void MutexImpl::Unlock(Mutex* pmutex) 46.907 +{ 46.908 + OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0); 46.909 + 46.910 + unsigned lockCount; 46.911 + LockCount--; 46.912 + lockCount = LockCount; 46.913 + 46.914 + pthread_mutex_unlock(&SMutex); 46.915 +} 46.916 + 46.917 +bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 46.918 +{ 46.919 + // There could be multiple interpretations of IsLocked with respect to current thread 46.920 + if (LockCount == 0) 46.921 + return 0; 46.922 + if (pthread_self() != LockedBy) 46.923 + return 1; 46.924 + return 0; 46.925 +} 46.926 + 46.927 +bool MutexImpl::IsSignaled() const 46.928 +{ 46.929 + // An mutex is signaled if it is not locked ANYWHERE 46.930 + // Note that this is different from IsLockedByAnotherThread function, 46.931 + // that takes current thread into account 46.932 + return LockCount == 0; 46.933 +} 46.934 + 46.935 + 46.936 +// *** Actual Mutex class implementation 46.937 + 46.938 +Mutex::Mutex(bool recursive) 46.939 +{ 46.940 + // NOTE: RefCount mode already thread-safe for all waitables. 46.941 + pImpl = new MutexImpl(this, recursive); 46.942 +} 46.943 + 46.944 +Mutex::~Mutex() 46.945 +{ 46.946 + delete pImpl; 46.947 +} 46.948 + 46.949 +// Lock and try lock 46.950 +void Mutex::DoLock() 46.951 +{ 46.952 + pImpl->DoLock(); 46.953 +} 46.954 +bool Mutex::TryLock() 46.955 +{ 46.956 + return pImpl->TryLock(); 46.957 +} 46.958 +void Mutex::Unlock() 46.959 +{ 46.960 + pImpl->Unlock(this); 46.961 +} 46.962 +bool Mutex::IsLockedByAnotherThread() 46.963 +{ 46.964 + return pImpl->IsLockedByAnotherThread(this); 46.965 +} 46.966 + 46.967 + 46.968 + 46.969 +//----------------------------------------------------------------------------------- 46.970 +// ***** Event 46.971 + 46.972 +bool Event::Wait(unsigned delay) 46.973 +{ 46.974 + Mutex::Locker lock(&StateMutex); 46.975 + 46.976 + // Do the correct amount of waiting 46.977 + if (delay == OVR_WAIT_INFINITE) 46.978 + { 46.979 + while(!State) 46.980 + StateWaitCondition.Wait(&StateMutex); 46.981 + } 46.982 + else if (delay) 46.983 + { 46.984 + if (!State) 46.985 + StateWaitCondition.Wait(&StateMutex, delay); 46.986 + } 46.987 + 46.988 + bool state = State; 46.989 + // Take care of temporary 'pulsing' of a state 46.990 + if (Temporary) 46.991 + { 46.992 + Temporary = false; 46.993 + State = false; 46.994 + } 46.995 + return state; 46.996 +} 46.997 + 46.998 +void Event::updateState(bool newState, bool newTemp, bool mustNotify) 46.999 +{ 46.1000 + Mutex::Locker lock(&StateMutex); 46.1001 + State = newState; 46.1002 + Temporary = newTemp; 46.1003 + if (mustNotify) 46.1004 + StateWaitCondition.NotifyAll(); 46.1005 +} 46.1006 + 46.1007 + 46.1008 + 46.1009 +// ***** Wait Condition Implementation 46.1010 + 46.1011 +// Internal implementation class 46.1012 +class WaitConditionImpl : public NewOverrideBase 46.1013 +{ 46.1014 + pthread_mutex_t SMutex; 46.1015 + pthread_cond_t Condv; 46.1016 + 46.1017 +public: 46.1018 + 46.1019 + // Constructor/destructor 46.1020 + WaitConditionImpl(); 46.1021 + ~WaitConditionImpl(); 46.1022 + 46.1023 + // Release mutex and wait for condition. The mutex is re-aqured after the wait. 46.1024 + bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 46.1025 + 46.1026 + // Notify a condition, releasing at one object waiting 46.1027 + void Notify(); 46.1028 + // Notify a condition, releasing all objects waiting 46.1029 + void NotifyAll(); 46.1030 +}; 46.1031 + 46.1032 + 46.1033 +WaitConditionImpl::WaitConditionImpl() 46.1034 +{ 46.1035 + pthread_mutex_init(&SMutex, 0); 46.1036 + pthread_cond_init(&Condv, 0); 46.1037 +} 46.1038 + 46.1039 +WaitConditionImpl::~WaitConditionImpl() 46.1040 +{ 46.1041 + pthread_mutex_destroy(&SMutex); 46.1042 + pthread_cond_destroy(&Condv); 46.1043 +} 46.1044 + 46.1045 +bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 46.1046 +{ 46.1047 + bool result = 1; 46.1048 + unsigned lockCount = pmutex->pImpl->LockCount; 46.1049 + 46.1050 + // Mutex must have been locked 46.1051 + if (lockCount == 0) 46.1052 + return 0; 46.1053 + 46.1054 + pthread_mutex_lock(&SMutex); 46.1055 + 46.1056 + // Finally, release a mutex or semaphore 46.1057 + if (pmutex->pImpl->Recursive) 46.1058 + { 46.1059 + // Release the recursive mutex N times 46.1060 + pmutex->pImpl->LockCount = 0; 46.1061 + for(unsigned i=0; i<lockCount; i++) 46.1062 + pthread_mutex_unlock(&pmutex->pImpl->SMutex); 46.1063 + } 46.1064 + else 46.1065 + { 46.1066 + pmutex->pImpl->LockCount = 0; 46.1067 + pthread_mutex_unlock(&pmutex->pImpl->SMutex); 46.1068 + } 46.1069 + 46.1070 + // Note that there is a gap here between mutex.Unlock() and Wait(). 46.1071 + // The other mutex protects this gap. 46.1072 + 46.1073 + if (delay == OVR_WAIT_INFINITE) 46.1074 + pthread_cond_wait(&Condv,&SMutex); 46.1075 + else 46.1076 + { 46.1077 + timespec ts; 46.1078 +#ifdef OVR_OS_PS3 46.1079 + sys_time_sec_t s; 46.1080 + sys_time_nsec_t ns; 46.1081 + sys_time_get_current_time(&s, &ns); 46.1082 + 46.1083 + ts.tv_sec = s + (delay / 1000); 46.1084 + ts.tv_nsec = ns + (delay % 1000) * 1000000; 46.1085 + 46.1086 +#else 46.1087 + struct timeval tv; 46.1088 + gettimeofday(&tv, 0); 46.1089 + 46.1090 + ts.tv_sec = tv.tv_sec + (delay / 1000); 46.1091 + ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000; 46.1092 +#endif 46.1093 + if (ts.tv_nsec > 999999999) 46.1094 + { 46.1095 + ts.tv_sec++; 46.1096 + ts.tv_nsec -= 1000000000; 46.1097 + } 46.1098 + int r = pthread_cond_timedwait(&Condv,&SMutex, &ts); 46.1099 + OVR_ASSERT(r == 0 || r == ETIMEDOUT); 46.1100 + if (r) 46.1101 + result = 0; 46.1102 + } 46.1103 + 46.1104 + pthread_mutex_unlock(&SMutex); 46.1105 + 46.1106 + // Re-aquire the mutex 46.1107 + for(unsigned i=0; i<lockCount; i++) 46.1108 + pmutex->DoLock(); 46.1109 + 46.1110 + // Return the result 46.1111 + return result; 46.1112 +} 46.1113 + 46.1114 +// Notify a condition, releasing the least object in a queue 46.1115 +void WaitConditionImpl::Notify() 46.1116 +{ 46.1117 + pthread_mutex_lock(&SMutex); 46.1118 + pthread_cond_signal(&Condv); 46.1119 + pthread_mutex_unlock(&SMutex); 46.1120 +} 46.1121 + 46.1122 +// Notify a condition, releasing all objects waiting 46.1123 +void WaitConditionImpl::NotifyAll() 46.1124 +{ 46.1125 + pthread_mutex_lock(&SMutex); 46.1126 + pthread_cond_broadcast(&Condv); 46.1127 + pthread_mutex_unlock(&SMutex); 46.1128 +} 46.1129 + 46.1130 + 46.1131 + 46.1132 +// *** Actual implementation of WaitCondition 46.1133 + 46.1134 +WaitCondition::WaitCondition() 46.1135 +{ 46.1136 + pImpl = new WaitConditionImpl; 46.1137 +} 46.1138 +WaitCondition::~WaitCondition() 46.1139 +{ 46.1140 + delete pImpl; 46.1141 +} 46.1142 + 46.1143 +bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 46.1144 +{ 46.1145 + return pImpl->Wait(pmutex, delay); 46.1146 +} 46.1147 +// Notification 46.1148 +void WaitCondition::Notify() 46.1149 +{ 46.1150 + pImpl->Notify(); 46.1151 +} 46.1152 +void WaitCondition::NotifyAll() 46.1153 +{ 46.1154 + pImpl->NotifyAll(); 46.1155 +} 46.1156 + 46.1157 + 46.1158 +// ***** Current thread 46.1159 + 46.1160 +// Per-thread variable 46.1161 +/* 46.1162 +static __thread Thread* pCurrentThread = 0; 46.1163 + 46.1164 +// Static function to return a pointer to the current thread 46.1165 +void Thread::InitCurrentThread(Thread *pthread) 46.1166 +{ 46.1167 + pCurrentThread = pthread; 46.1168 +} 46.1169 + 46.1170 +// Static function to return a pointer to the current thread 46.1171 +Thread* Thread::GetThread() 46.1172 +{ 46.1173 + return pCurrentThread; 46.1174 +} 46.1175 +*/ 46.1176 + 46.1177 + 46.1178 +// *** Thread constructors. 46.1179 + 46.1180 +Thread::Thread(UPInt stackSize, int processor) 46.1181 +{ 46.1182 + // NOTE: RefCount mode already thread-safe for all Waitable objects. 46.1183 + CreateParams params; 46.1184 + params.stackSize = stackSize; 46.1185 + params.processor = processor; 46.1186 + Init(params); 46.1187 +} 46.1188 + 46.1189 +Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 46.1190 + int processor, Thread::ThreadState initialState) 46.1191 +{ 46.1192 + CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 46.1193 + Init(params); 46.1194 +} 46.1195 + 46.1196 +Thread::Thread(const CreateParams& params) 46.1197 +{ 46.1198 + Init(params); 46.1199 +} 46.1200 + 46.1201 +void Thread::Init(const CreateParams& params) 46.1202 +{ 46.1203 + // Clear the variables 46.1204 + ThreadFlags = 0; 46.1205 + ThreadHandle = 0; 46.1206 + ExitCode = 0; 46.1207 + SuspendCount = 0; 46.1208 + StackSize = params.stackSize; 46.1209 + Processor = params.processor; 46.1210 + Priority = params.priority; 46.1211 + 46.1212 + // Clear Function pointers 46.1213 + ThreadFunction = params.threadFunction; 46.1214 + UserHandle = params.userHandle; 46.1215 + if (params.initialState != NotRunning) 46.1216 + Start(params.initialState); 46.1217 +} 46.1218 + 46.1219 +Thread::~Thread() 46.1220 +{ 46.1221 + // Thread should not running while object is being destroyed, 46.1222 + // this would indicate ref-counting issue. 46.1223 + //OVR_ASSERT(IsRunning() == 0); 46.1224 + 46.1225 + // Clean up thread. 46.1226 + ThreadHandle = 0; 46.1227 +} 46.1228 + 46.1229 + 46.1230 + 46.1231 +// *** Overridable User functions. 46.1232 + 46.1233 +// Default Run implementation 46.1234 +int Thread::Run() 46.1235 +{ 46.1236 + // Call pointer to function, if available. 46.1237 + return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 46.1238 +} 46.1239 +void Thread::OnExit() 46.1240 +{ 46.1241 +} 46.1242 + 46.1243 + 46.1244 +// Finishes the thread and releases internal reference to it. 46.1245 +void Thread::FinishAndRelease() 46.1246 +{ 46.1247 + // Note: thread must be US. 46.1248 + ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 46.1249 + ThreadFlags |= OVR_THREAD_FINISHED; 46.1250 + 46.1251 + // Release our reference; this is equivalent to 'delete this' 46.1252 + // from the point of view of our thread. 46.1253 + Release(); 46.1254 +} 46.1255 + 46.1256 + 46.1257 + 46.1258 +// *** ThreadList - used to track all created threads 46.1259 + 46.1260 +class ThreadList : public NewOverrideBase 46.1261 +{ 46.1262 + //------------------------------------------------------------------------ 46.1263 + struct ThreadHashOp 46.1264 + { 46.1265 + size_t operator()(const Thread* ptr) 46.1266 + { 46.1267 + return (((size_t)ptr) >> 6) ^ (size_t)ptr; 46.1268 + } 46.1269 + }; 46.1270 + 46.1271 + HashSet<Thread*, ThreadHashOp> ThreadSet; 46.1272 + Mutex ThreadMutex; 46.1273 + WaitCondition ThreadsEmpty; 46.1274 + // Track the root thread that created us. 46.1275 + pthread_t RootThreadId; 46.1276 + 46.1277 + static ThreadList* volatile pRunningThreads; 46.1278 + 46.1279 + void addThread(Thread *pthread) 46.1280 + { 46.1281 + Mutex::Locker lock(&ThreadMutex); 46.1282 + ThreadSet.Add(pthread); 46.1283 + } 46.1284 + 46.1285 + void removeThread(Thread *pthread) 46.1286 + { 46.1287 + Mutex::Locker lock(&ThreadMutex); 46.1288 + ThreadSet.Remove(pthread); 46.1289 + if (ThreadSet.GetSize() == 0) 46.1290 + ThreadsEmpty.Notify(); 46.1291 + } 46.1292 + 46.1293 + void finishAllThreads() 46.1294 + { 46.1295 + // Only original root thread can call this. 46.1296 + OVR_ASSERT(pthread_self() == RootThreadId); 46.1297 + 46.1298 + Mutex::Locker lock(&ThreadMutex); 46.1299 + while (ThreadSet.GetSize() != 0) 46.1300 + ThreadsEmpty.Wait(&ThreadMutex); 46.1301 + } 46.1302 + 46.1303 +public: 46.1304 + 46.1305 + ThreadList() 46.1306 + { 46.1307 + RootThreadId = pthread_self(); 46.1308 + } 46.1309 + ~ThreadList() { } 46.1310 + 46.1311 + 46.1312 + static void AddRunningThread(Thread *pthread) 46.1313 + { 46.1314 + // Non-atomic creation ok since only the root thread 46.1315 + if (!pRunningThreads) 46.1316 + { 46.1317 + pRunningThreads = new ThreadList; 46.1318 + OVR_ASSERT(pRunningThreads); 46.1319 + } 46.1320 + pRunningThreads->addThread(pthread); 46.1321 + } 46.1322 + 46.1323 + // NOTE: 'pthread' might be a dead pointer when this is 46.1324 + // called so it should not be accessed; it is only used 46.1325 + // for removal. 46.1326 + static void RemoveRunningThread(Thread *pthread) 46.1327 + { 46.1328 + OVR_ASSERT(pRunningThreads); 46.1329 + pRunningThreads->removeThread(pthread); 46.1330 + } 46.1331 + 46.1332 + static void FinishAllThreads() 46.1333 + { 46.1334 + // This is ok because only root thread can wait for other thread finish. 46.1335 + if (pRunningThreads) 46.1336 + { 46.1337 + pRunningThreads->finishAllThreads(); 46.1338 + delete pRunningThreads; 46.1339 + pRunningThreads = 0; 46.1340 + } 46.1341 + } 46.1342 +}; 46.1343 + 46.1344 +// By default, we have no thread list. 46.1345 +ThreadList* volatile ThreadList::pRunningThreads = 0; 46.1346 + 46.1347 + 46.1348 +// FinishAllThreads - exposed publicly in Thread. 46.1349 +void Thread::FinishAllThreads() 46.1350 +{ 46.1351 + ThreadList::FinishAllThreads(); 46.1352 +} 46.1353 + 46.1354 +// *** Run override 46.1355 + 46.1356 +int Thread::PRun() 46.1357 +{ 46.1358 + // Suspend us on start, if requested 46.1359 + if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 46.1360 + { 46.1361 + Suspend(); 46.1362 + ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 46.1363 + } 46.1364 + 46.1365 + // Call the virtual run function 46.1366 + ExitCode = Run(); 46.1367 + return ExitCode; 46.1368 +} 46.1369 + 46.1370 + 46.1371 + 46.1372 + 46.1373 +// *** User overridables 46.1374 + 46.1375 +bool Thread::GetExitFlag() const 46.1376 +{ 46.1377 + return (ThreadFlags & OVR_THREAD_EXIT) != 0; 46.1378 +} 46.1379 + 46.1380 +void Thread::SetExitFlag(bool exitFlag) 46.1381 +{ 46.1382 + // The below is atomic since ThreadFlags is AtomicInt. 46.1383 + if (exitFlag) 46.1384 + ThreadFlags |= OVR_THREAD_EXIT; 46.1385 + else 46.1386 + ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 46.1387 +} 46.1388 + 46.1389 + 46.1390 +// Determines whether the thread was running and is now finished 46.1391 +bool Thread::IsFinished() const 46.1392 +{ 46.1393 + return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 46.1394 +} 46.1395 +// Determines whether the thread is suspended 46.1396 +bool Thread::IsSuspended() const 46.1397 +{ 46.1398 + return SuspendCount > 0; 46.1399 +} 46.1400 +// Returns current thread state 46.1401 +Thread::ThreadState Thread::GetThreadState() const 46.1402 +{ 46.1403 + if (IsSuspended()) 46.1404 + return Suspended; 46.1405 + if (ThreadFlags & OVR_THREAD_STARTED) 46.1406 + return Running; 46.1407 + return NotRunning; 46.1408 +} 46.1409 +/* 46.1410 +static const char* mapsched_policy(int policy) 46.1411 +{ 46.1412 + switch(policy) 46.1413 + { 46.1414 + case SCHED_OTHER: 46.1415 + return "SCHED_OTHER"; 46.1416 + case SCHED_RR: 46.1417 + return "SCHED_RR"; 46.1418 + case SCHED_FIFO: 46.1419 + return "SCHED_FIFO"; 46.1420 + 46.1421 + } 46.1422 + return "UNKNOWN"; 46.1423 +} 46.1424 + int policy; 46.1425 + sched_param sparam; 46.1426 + pthread_getschedparam(pthread_self(), &policy, &sparam); 46.1427 + int max_prior = sched_get_priority_max(policy); 46.1428 + int min_prior = sched_get_priority_min(policy); 46.1429 + printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior); 46.1430 +#include <stdio.h> 46.1431 +*/ 46.1432 +// ***** Thread management 46.1433 + 46.1434 +// The actual first function called on thread start 46.1435 +void* Thread_PthreadStartFn(void* phandle) 46.1436 +{ 46.1437 + Thread* pthread = (Thread*)phandle; 46.1438 + int result = pthread->PRun(); 46.1439 + // Signal the thread as done and release it atomically. 46.1440 + pthread->FinishAndRelease(); 46.1441 + // At this point Thread object might be dead; however we can still pass 46.1442 + // it to RemoveRunningThread since it is only used as a key there. 46.1443 + ThreadList::RemoveRunningThread(pthread); 46.1444 + return (void*) result; 46.1445 +} 46.1446 + 46.1447 +int Thread::InitAttr = 0; 46.1448 +pthread_attr_t Thread::Attr; 46.1449 + 46.1450 +/* static */ 46.1451 +int Thread::GetOSPriority(ThreadPriority p) 46.1452 +//static inline int MapToSystemPrority(Thread::ThreadPriority p) 46.1453 +{ 46.1454 +#ifdef OVR_OS_PS3 46.1455 + switch(p) 46.1456 + { 46.1457 + case Thread::CriticalPriority: return 0; 46.1458 + case Thread::HighestPriority: return 300; 46.1459 + case Thread::AboveNormalPriority: return 600; 46.1460 + case Thread::NormalPriority: return 1000; 46.1461 + case Thread::BelowNormalPriority: return 1500; 46.1462 + case Thread::LowestPriority: return 2500; 46.1463 + case Thread::IdlePriority: return 3071; 46.1464 + } return 1000; 46.1465 +#else 46.1466 + OVR_UNUSED(p); 46.1467 + return -1; 46.1468 +#endif 46.1469 +} 46.1470 + 46.1471 +bool Thread::Start(ThreadState initialState) 46.1472 +{ 46.1473 + if (initialState == NotRunning) 46.1474 + return 0; 46.1475 + if (GetThreadState() != NotRunning) 46.1476 + { 46.1477 + OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 46.1478 + return 0; 46.1479 + } 46.1480 + 46.1481 + if (!InitAttr) 46.1482 + { 46.1483 + pthread_attr_init(&Attr); 46.1484 + pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED); 46.1485 + pthread_attr_setstacksize(&Attr, 128 * 1024); 46.1486 + sched_param sparam; 46.1487 + sparam.sched_priority = Thread::GetOSPriority(NormalPriority); 46.1488 + pthread_attr_setschedparam(&Attr, &sparam); 46.1489 + InitAttr = 1; 46.1490 + } 46.1491 + 46.1492 + ExitCode = 0; 46.1493 + SuspendCount = 0; 46.1494 + ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 46.1495 + 46.1496 + // AddRef to us until the thread is finished 46.1497 + AddRef(); 46.1498 + ThreadList::AddRunningThread(this); 46.1499 + 46.1500 + int result; 46.1501 + if (StackSize != 128 * 1024 || Priority != NormalPriority) 46.1502 + { 46.1503 + pthread_attr_t attr; 46.1504 + 46.1505 + pthread_attr_init(&attr); 46.1506 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 46.1507 + pthread_attr_setstacksize(&attr, StackSize); 46.1508 + sched_param sparam; 46.1509 + sparam.sched_priority = Thread::GetOSPriority(Priority); 46.1510 + pthread_attr_setschedparam(&attr, &sparam); 46.1511 + result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this); 46.1512 + pthread_attr_destroy(&attr); 46.1513 + } 46.1514 + else 46.1515 + result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this); 46.1516 + 46.1517 + if (result) 46.1518 + { 46.1519 + ThreadFlags = 0; 46.1520 + Release(); 46.1521 + ThreadList::RemoveRunningThread(this); 46.1522 + return 0; 46.1523 + } 46.1524 + return 1; 46.1525 +} 46.1526 + 46.1527 + 46.1528 +// Suspend the thread until resumed 46.1529 +bool Thread::Suspend() 46.1530 +{ 46.1531 + OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system")); 46.1532 + return 0; 46.1533 +} 46.1534 + 46.1535 +// Resumes currently suspended thread 46.1536 +bool Thread::Resume() 46.1537 +{ 46.1538 + return 0; 46.1539 +} 46.1540 + 46.1541 + 46.1542 +// Quits with an exit code 46.1543 +void Thread::Exit(int exitCode) 46.1544 +{ 46.1545 + // Can only exist the current thread 46.1546 + // if (GetThread() != this) 46.1547 + // return; 46.1548 + 46.1549 + // Call the virtual OnExit function 46.1550 + OnExit(); 46.1551 + 46.1552 + // Signal this thread object as done and release it's references. 46.1553 + FinishAndRelease(); 46.1554 + ThreadList::RemoveRunningThread(this); 46.1555 + 46.1556 + pthread_exit((void *) exitCode); 46.1557 +} 46.1558 + 46.1559 +ThreadId GetCurrentThreadId() 46.1560 +{ 46.1561 + return (void*)pthread_self(); 46.1562 +} 46.1563 + 46.1564 +// *** Sleep functions 46.1565 + 46.1566 +/* static */ 46.1567 +bool Thread::Sleep(unsigned secs) 46.1568 +{ 46.1569 + sleep(secs); 46.1570 + return 1; 46.1571 +} 46.1572 +/* static */ 46.1573 +bool Thread::MSleep(unsigned msecs) 46.1574 +{ 46.1575 + usleep(msecs*1000); 46.1576 + return 1; 46.1577 +} 46.1578 + 46.1579 +/* static */ 46.1580 +int Thread::GetCPUCount() 46.1581 +{ 46.1582 + return 1; 46.1583 +} 46.1584 + 46.1585 + 46.1586 +#ifdef OVR_OS_PS3 46.1587 + 46.1588 +sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE }; 46.1589 + 46.1590 +#endif 46.1591 + 46.1592 +} 46.1593 + 46.1594 +#endif // OVR_ENABLE_THREADS
47.1 --- a/libovr/Src/win32/OVR_ThreadsWinAPI.cpp Sat Sep 14 17:51:03 2013 +0300 47.2 +++ b/libovr/Src/win32/OVR_ThreadsWinAPI.cpp Sun Sep 15 04:10:05 2013 +0300 47.3 @@ -1,1 +1,994 @@ 47.4 -/************************************************************************************ 47.5 47.6 Filename : OVR_ThreadsWinAPI.cpp 47.7 Platform : WinAPI 47.8 Content : Windows specific thread-related (safe) functionality 47.9 Created : September 19, 2012 47.10 Notes : 47.11 47.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 47.13 47.14 Use of this software is subject to the terms of the Oculus license 47.15 agreement provided at the time of installation or download, or which 47.16 otherwise accompanies this software in either electronic or hard copy form. 47.17 47.18 ************************************************************************************/ 47.19 47.20 #include "OVR_Threads.h" 47.21 #include "OVR_Hash.h" 47.22 #include "OVR_Log.h" 47.23 47.24 #ifdef OVR_ENABLE_THREADS 47.25 47.26 // For _beginthreadex / _endtheadex 47.27 #include <process.h> 47.28 47.29 namespace OVR { 47.30 47.31 47.32 //----------------------------------------------------------------------------------- 47.33 // *** Internal Mutex implementation class 47.34 47.35 class MutexImpl : public NewOverrideBase 47.36 { 47.37 // System mutex or semaphore 47.38 HANDLE hMutexOrSemaphore; 47.39 bool Recursive; 47.40 volatile unsigned LockCount; 47.41 47.42 friend class WaitConditionImpl; 47.43 47.44 public: 47.45 // Constructor/destructor 47.46 MutexImpl(bool recursive = 1); 47.47 ~MutexImpl(); 47.48 47.49 // Locking functions 47.50 void DoLock(); 47.51 bool TryLock(); 47.52 void Unlock(Mutex* pmutex); 47.53 // Returns 1 if the mutes is currently locked 47.54 bool IsLockedByAnotherThread(Mutex* pmutex); 47.55 }; 47.56 47.57 // *** Constructor/destructor 47.58 MutexImpl::MutexImpl(bool recursive) 47.59 { 47.60 Recursive = recursive; 47.61 LockCount = 0; 47.62 hMutexOrSemaphore = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL); 47.63 } 47.64 MutexImpl::~MutexImpl() 47.65 { 47.66 CloseHandle(hMutexOrSemaphore); 47.67 } 47.68 47.69 47.70 // Lock and try lock 47.71 void MutexImpl::DoLock() 47.72 { 47.73 if (::WaitForSingleObject(hMutexOrSemaphore, INFINITE) != WAIT_OBJECT_0) 47.74 return; 47.75 LockCount++; 47.76 } 47.77 47.78 bool MutexImpl::TryLock() 47.79 { 47.80 DWORD ret; 47.81 if ((ret=::WaitForSingleObject(hMutexOrSemaphore, 0)) != WAIT_OBJECT_0) 47.82 return 0; 47.83 LockCount++; 47.84 return 1; 47.85 } 47.86 47.87 void MutexImpl::Unlock(Mutex* pmutex) 47.88 { 47.89 OVR_UNUSED(pmutex); 47.90 47.91 unsigned lockCount; 47.92 LockCount--; 47.93 lockCount = LockCount; 47.94 47.95 // Release mutex 47.96 if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) : 47.97 ReleaseSemaphore(hMutexOrSemaphore, 1, NULL)) != 0) 47.98 { 47.99 // This used to call Wait handlers if lockCount == 0. 47.100 } 47.101 } 47.102 47.103 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 47.104 { 47.105 // There could be multiple interpretations of IsLocked with respect to current thread 47.106 if (LockCount == 0) 47.107 return 0; 47.108 if (!TryLock()) 47.109 return 1; 47.110 Unlock(pmutex); 47.111 return 0; 47.112 } 47.113 47.114 /* 47.115 bool MutexImpl::IsSignaled() const 47.116 { 47.117 // An mutex is signaled if it is not locked ANYWHERE 47.118 // Note that this is different from IsLockedByAnotherThread function, 47.119 // that takes current thread into account 47.120 return LockCount == 0; 47.121 } 47.122 */ 47.123 47.124 47.125 // *** Actual Mutex class implementation 47.126 47.127 Mutex::Mutex(bool recursive) 47.128 { 47.129 pImpl = new MutexImpl(recursive); 47.130 } 47.131 Mutex::~Mutex() 47.132 { 47.133 delete pImpl; 47.134 } 47.135 47.136 // Lock and try lock 47.137 void Mutex::DoLock() 47.138 { 47.139 pImpl->DoLock(); 47.140 } 47.141 bool Mutex::TryLock() 47.142 { 47.143 return pImpl->TryLock(); 47.144 } 47.145 void Mutex::Unlock() 47.146 { 47.147 pImpl->Unlock(this); 47.148 } 47.149 bool Mutex::IsLockedByAnotherThread() 47.150 { 47.151 return pImpl->IsLockedByAnotherThread(this); 47.152 } 47.153 47.154 //----------------------------------------------------------------------------------- 47.155 // ***** Event 47.156 47.157 bool Event::Wait(unsigned delay) 47.158 { 47.159 Mutex::Locker lock(&StateMutex); 47.160 47.161 // Do the correct amount of waiting 47.162 if (delay == OVR_WAIT_INFINITE) 47.163 { 47.164 while(!State) 47.165 StateWaitCondition.Wait(&StateMutex); 47.166 } 47.167 else if (delay) 47.168 { 47.169 if (!State) 47.170 StateWaitCondition.Wait(&StateMutex, delay); 47.171 } 47.172 47.173 bool state = State; 47.174 // Take care of temporary 'pulsing' of a state 47.175 if (Temporary) 47.176 { 47.177 Temporary = false; 47.178 State = false; 47.179 } 47.180 return state; 47.181 } 47.182 47.183 void Event::updateState(bool newState, bool newTemp, bool mustNotify) 47.184 { 47.185 Mutex::Locker lock(&StateMutex); 47.186 State = newState; 47.187 Temporary = newTemp; 47.188 if (mustNotify) 47.189 StateWaitCondition.NotifyAll(); 47.190 } 47.191 47.192 47.193 //----------------------------------------------------------------------------------- 47.194 // ***** Win32 Wait Condition Implementation 47.195 47.196 // Internal implementation class 47.197 class WaitConditionImpl : public NewOverrideBase 47.198 { 47.199 // Event pool entries for extra events 47.200 struct EventPoolEntry : public NewOverrideBase 47.201 { 47.202 HANDLE hEvent; 47.203 EventPoolEntry *pNext; 47.204 EventPoolEntry *pPrev; 47.205 }; 47.206 47.207 Lock WaitQueueLoc; 47.208 // Stores free events that can be used later 47.209 EventPoolEntry * pFreeEventList; 47.210 47.211 // A queue of waiting objects to be signaled 47.212 EventPoolEntry* pQueueHead; 47.213 EventPoolEntry* pQueueTail; 47.214 47.215 // Allocation functions for free events 47.216 EventPoolEntry* GetNewEvent(); 47.217 void ReleaseEvent(EventPoolEntry* pevent); 47.218 47.219 // Queue operations 47.220 void QueuePush(EventPoolEntry* pentry); 47.221 EventPoolEntry* QueuePop(); 47.222 void QueueFindAndRemove(EventPoolEntry* pentry); 47.223 47.224 public: 47.225 47.226 // Constructor/destructor 47.227 WaitConditionImpl(); 47.228 ~WaitConditionImpl(); 47.229 47.230 // Release mutex and wait for condition. The mutex is re-acqured after the wait. 47.231 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 47.232 47.233 // Notify a condition, releasing at one object waiting 47.234 void Notify(); 47.235 // Notify a condition, releasing all objects waiting 47.236 void NotifyAll(); 47.237 }; 47.238 47.239 47.240 47.241 WaitConditionImpl::WaitConditionImpl() 47.242 { 47.243 pFreeEventList = 0; 47.244 pQueueHead = 47.245 pQueueTail = 0; 47.246 } 47.247 47.248 WaitConditionImpl::~WaitConditionImpl() 47.249 { 47.250 // Free all the resources 47.251 EventPoolEntry* p = pFreeEventList; 47.252 EventPoolEntry* pentry; 47.253 47.254 while(p) 47.255 { 47.256 // Move to next 47.257 pentry = p; 47.258 p = p->pNext; 47.259 // Delete old 47.260 ::CloseHandle(pentry->hEvent); 47.261 delete pentry; 47.262 } 47.263 // Shouldn't we also consider the queue? 47.264 47.265 // To be safe 47.266 pFreeEventList = 0; 47.267 pQueueHead = 47.268 pQueueTail = 0; 47.269 } 47.270 47.271 47.272 // Allocation functions for free events 47.273 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent() 47.274 { 47.275 EventPoolEntry* pentry; 47.276 47.277 // If there are any free nodes, use them 47.278 if (pFreeEventList) 47.279 { 47.280 pentry = pFreeEventList; 47.281 pFreeEventList = pFreeEventList->pNext; 47.282 } 47.283 else 47.284 { 47.285 // Allocate a new node 47.286 pentry = new EventPoolEntry; 47.287 pentry->pNext = 0; 47.288 pentry->pPrev = 0; 47.289 // Non-signaled manual event 47.290 pentry->hEvent = ::CreateEvent(NULL, TRUE, 0, NULL); 47.291 } 47.292 47.293 return pentry; 47.294 } 47.295 47.296 void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent) 47.297 { 47.298 // Mark event as non-signaled 47.299 ::ResetEvent(pevent->hEvent); 47.300 // And add it to free pool 47.301 pevent->pNext = pFreeEventList; 47.302 pevent->pPrev = 0; 47.303 pFreeEventList = pevent; 47.304 } 47.305 47.306 // Queue operations 47.307 void WaitConditionImpl::QueuePush(EventPoolEntry* pentry) 47.308 { 47.309 // Items already exist? Just add to tail 47.310 if (pQueueTail) 47.311 { 47.312 pentry->pPrev = pQueueTail; 47.313 pQueueTail->pNext = pentry; 47.314 pentry->pNext = 0; 47.315 pQueueTail = pentry; 47.316 } 47.317 else 47.318 { 47.319 // No items in queue 47.320 pentry->pNext = 47.321 pentry->pPrev = 0; 47.322 pQueueHead = 47.323 pQueueTail = pentry; 47.324 } 47.325 } 47.326 47.327 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::QueuePop() 47.328 { 47.329 EventPoolEntry* pentry = pQueueHead; 47.330 47.331 // No items, null pointer 47.332 if (pentry) 47.333 { 47.334 // More items after this one? just grab the first item 47.335 if (pQueueHead->pNext) 47.336 { 47.337 pQueueHead = pentry->pNext; 47.338 pQueueHead->pPrev = 0; 47.339 } 47.340 else 47.341 { 47.342 // Last item left 47.343 pQueueTail = 47.344 pQueueHead = 0; 47.345 } 47.346 } 47.347 return pentry; 47.348 } 47.349 47.350 void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry) 47.351 { 47.352 // Do an exhaustive search looking for an entry 47.353 EventPoolEntry* p = pQueueHead; 47.354 47.355 while(p) 47.356 { 47.357 // Entry found? Remove. 47.358 if (p == pentry) 47.359 { 47.360 47.361 // Remove the node form the list 47.362 // Prev link 47.363 if (pentry->pPrev) 47.364 pentry->pPrev->pNext = pentry->pNext; 47.365 else 47.366 pQueueHead = pentry->pNext; 47.367 // Next link 47.368 if (pentry->pNext) 47.369 pentry->pNext->pPrev = pentry->pPrev; 47.370 else 47.371 pQueueTail = pentry->pPrev; 47.372 // Done 47.373 return; 47.374 } 47.375 47.376 // Move to next item 47.377 p = p->pNext; 47.378 } 47.379 } 47.380 47.381 47.382 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 47.383 { 47.384 bool result = 0; 47.385 unsigned i; 47.386 unsigned lockCount = pmutex->pImpl->LockCount; 47.387 EventPoolEntry* pentry; 47.388 47.389 // Mutex must have been locked 47.390 if (lockCount == 0) 47.391 return 0; 47.392 47.393 // Add an object to the wait queue 47.394 WaitQueueLoc.DoLock(); 47.395 QueuePush(pentry = GetNewEvent()); 47.396 WaitQueueLoc.Unlock(); 47.397 47.398 // Finally, release a mutex or semaphore 47.399 if (pmutex->pImpl->Recursive) 47.400 { 47.401 // Release the recursive mutex N times 47.402 pmutex->pImpl->LockCount = 0; 47.403 for(i=0; i<lockCount; i++) 47.404 ::ReleaseMutex(pmutex->pImpl->hMutexOrSemaphore); 47.405 } 47.406 else 47.407 { 47.408 pmutex->pImpl->LockCount = 0; 47.409 ::ReleaseSemaphore(pmutex->pImpl->hMutexOrSemaphore, 1, NULL); 47.410 } 47.411 47.412 // Note that there is a gap here between mutex.Unlock() and Wait(). However, 47.413 // if notify() comes in at this point in the other thread it will set our 47.414 // corresponding event so wait will just fall through, as expected. 47.415 47.416 // Block and wait on the event 47.417 DWORD waitResult = ::WaitForSingleObject(pentry->hEvent, 47.418 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay); 47.419 /* 47.420 repeat_wait: 47.421 DWORD waitResult = 47.422 47.423 ::MsgWaitForMultipleObjects(1, &pentry->hEvent, FALSE, 47.424 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay, 47.425 QS_ALLINPUT); 47.426 */ 47.427 47.428 WaitQueueLoc.DoLock(); 47.429 switch(waitResult) 47.430 { 47.431 case WAIT_ABANDONED: 47.432 case WAIT_OBJECT_0: 47.433 result = 1; 47.434 // Wait was successful, therefore the event entry should already be removed 47.435 // So just add entry back to a free list 47.436 ReleaseEvent(pentry); 47.437 break; 47.438 /* 47.439 case WAIT_OBJECT_0 + 1: 47.440 // Messages in WINDOWS queue 47.441 { 47.442 MSG msg; 47.443 PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); 47.444 WaitQueueLoc.Unlock(); 47.445 goto repeat_wait; 47.446 } 47.447 break; */ 47.448 default: 47.449 // Timeout, our entry should still be in a queue 47.450 QueueFindAndRemove(pentry); 47.451 ReleaseEvent(pentry); 47.452 } 47.453 WaitQueueLoc.Unlock(); 47.454 47.455 // Re-aquire the mutex 47.456 for(i=0; i<lockCount; i++) 47.457 pmutex->DoLock(); 47.458 47.459 // Return the result 47.460 return result; 47.461 } 47.462 47.463 // Notify a condition, releasing the least object in a queue 47.464 void WaitConditionImpl::Notify() 47.465 { 47.466 Lock::Locker lock(&WaitQueueLoc); 47.467 47.468 // Pop last entry & signal it 47.469 EventPoolEntry* pentry = QueuePop(); 47.470 if (pentry) 47.471 ::SetEvent(pentry->hEvent); 47.472 } 47.473 47.474 // Notify a condition, releasing all objects waiting 47.475 void WaitConditionImpl::NotifyAll() 47.476 { 47.477 Lock::Locker lock(&WaitQueueLoc); 47.478 47.479 // Pop and signal all events 47.480 // NOTE : There is no need to release the events, it's the waiters job to do so 47.481 EventPoolEntry* pentry = QueuePop(); 47.482 while (pentry) 47.483 { 47.484 ::SetEvent(pentry->hEvent); 47.485 pentry = QueuePop(); 47.486 } 47.487 } 47.488 47.489 47.490 47.491 // *** Actual implementation of WaitCondition 47.492 47.493 WaitCondition::WaitCondition() 47.494 { 47.495 pImpl = new WaitConditionImpl; 47.496 } 47.497 WaitCondition::~WaitCondition() 47.498 { 47.499 delete pImpl; 47.500 } 47.501 47.502 // Wait without a mutex 47.503 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 47.504 { 47.505 return pImpl->Wait(pmutex, delay); 47.506 } 47.507 // Notification 47.508 void WaitCondition::Notify() 47.509 { 47.510 pImpl->Notify(); 47.511 } 47.512 void WaitCondition::NotifyAll() 47.513 { 47.514 pImpl->NotifyAll(); 47.515 } 47.516 47.517 47.518 47.519 //----------------------------------------------------------------------------------- 47.520 // ***** Thread Class 47.521 47.522 // Per-thread variable 47.523 // MA: Don't use TLS for now - portability issues with DLLs, etc. 47.524 /* 47.525 #if !defined(OVR_CC_MSVC) || (OVR_CC_MSVC < 1300) 47.526 __declspec(thread) Thread* pCurrentThread = 0; 47.527 #else 47.528 #pragma data_seg(".tls$") 47.529 __declspec(thread) Thread* pCurrentThread = 0; 47.530 #pragma data_seg(".rwdata") 47.531 #endif 47.532 */ 47.533 47.534 // *** Thread constructors. 47.535 47.536 Thread::Thread(UPInt stackSize, int processor) 47.537 { 47.538 CreateParams params; 47.539 params.stackSize = stackSize; 47.540 params.processor = processor; 47.541 Init(params); 47.542 } 47.543 47.544 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 47.545 int processor, Thread::ThreadState initialState) 47.546 { 47.547 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 47.548 Init(params); 47.549 } 47.550 47.551 Thread::Thread(const CreateParams& params) 47.552 { 47.553 Init(params); 47.554 } 47.555 void Thread::Init(const CreateParams& params) 47.556 { 47.557 // Clear the variables 47.558 ThreadFlags = 0; 47.559 ThreadHandle = 0; 47.560 IdValue = 0; 47.561 ExitCode = 0; 47.562 SuspendCount = 0; 47.563 StackSize = params.stackSize; 47.564 Processor = params.processor; 47.565 Priority = params.priority; 47.566 47.567 // Clear Function pointers 47.568 ThreadFunction = params.threadFunction; 47.569 UserHandle = params.userHandle; 47.570 if (params.initialState != NotRunning) 47.571 Start(params.initialState); 47.572 47.573 } 47.574 47.575 Thread::~Thread() 47.576 { 47.577 // Thread should not running while object is being destroyed, 47.578 // this would indicate ref-counting issue. 47.579 //OVR_ASSERT(IsRunning() == 0); 47.580 47.581 // Clean up thread. 47.582 CleanupSystemThread(); 47.583 ThreadHandle = 0; 47.584 } 47.585 47.586 47.587 // *** Overridable User functions. 47.588 47.589 // Default Run implementation 47.590 int Thread::Run() 47.591 { 47.592 // Call pointer to function, if available. 47.593 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 47.594 } 47.595 void Thread::OnExit() 47.596 { 47.597 } 47.598 47.599 // Finishes the thread and releases internal reference to it. 47.600 void Thread::FinishAndRelease() 47.601 { 47.602 // Note: thread must be US. 47.603 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 47.604 ThreadFlags |= OVR_THREAD_FINISHED; 47.605 47.606 // Release our reference; this is equivalent to 'delete this' 47.607 // from the point of view of our thread. 47.608 Release(); 47.609 } 47.610 47.611 47.612 // *** ThreadList - used to tack all created threads 47.613 47.614 class ThreadList : public NewOverrideBase 47.615 { 47.616 //------------------------------------------------------------------------ 47.617 struct ThreadHashOp 47.618 { 47.619 UPInt operator()(const Thread* ptr) 47.620 { 47.621 return (((UPInt)ptr) >> 6) ^ (UPInt)ptr; 47.622 } 47.623 }; 47.624 47.625 HashSet<Thread*, ThreadHashOp> ThreadSet; 47.626 Mutex ThreadMutex; 47.627 WaitCondition ThreadsEmpty; 47.628 // Track the root thread that created us. 47.629 ThreadId RootThreadId; 47.630 47.631 static ThreadList* volatile pRunningThreads; 47.632 47.633 void addThread(Thread *pthread) 47.634 { 47.635 Mutex::Locker lock(&ThreadMutex); 47.636 ThreadSet.Add(pthread); 47.637 } 47.638 47.639 void removeThread(Thread *pthread) 47.640 { 47.641 Mutex::Locker lock(&ThreadMutex); 47.642 ThreadSet.Remove(pthread); 47.643 if (ThreadSet.GetSize() == 0) 47.644 ThreadsEmpty.Notify(); 47.645 } 47.646 47.647 void finishAllThreads() 47.648 { 47.649 // Only original root thread can call this. 47.650 OVR_ASSERT(GetCurrentThreadId() == RootThreadId); 47.651 47.652 Mutex::Locker lock(&ThreadMutex); 47.653 while (ThreadSet.GetSize() != 0) 47.654 ThreadsEmpty.Wait(&ThreadMutex); 47.655 } 47.656 47.657 public: 47.658 47.659 ThreadList() 47.660 { 47.661 RootThreadId = GetCurrentThreadId(); 47.662 } 47.663 ~ThreadList() { } 47.664 47.665 47.666 static void AddRunningThread(Thread *pthread) 47.667 { 47.668 // Non-atomic creation ok since only the root thread 47.669 if (!pRunningThreads) 47.670 { 47.671 pRunningThreads = new ThreadList; 47.672 OVR_ASSERT(pRunningThreads); 47.673 } 47.674 pRunningThreads->addThread(pthread); 47.675 } 47.676 47.677 // NOTE: 'pthread' might be a dead pointer when this is 47.678 // called so it should not be accessed; it is only used 47.679 // for removal. 47.680 static void RemoveRunningThread(Thread *pthread) 47.681 { 47.682 OVR_ASSERT(pRunningThreads); 47.683 pRunningThreads->removeThread(pthread); 47.684 } 47.685 47.686 static void FinishAllThreads() 47.687 { 47.688 // This is ok because only root thread can wait for other thread finish. 47.689 if (pRunningThreads) 47.690 { 47.691 pRunningThreads->finishAllThreads(); 47.692 delete pRunningThreads; 47.693 pRunningThreads = 0; 47.694 } 47.695 } 47.696 }; 47.697 47.698 // By default, we have no thread list. 47.699 ThreadList* volatile ThreadList::pRunningThreads = 0; 47.700 47.701 47.702 // FinishAllThreads - exposed publicly in Thread. 47.703 void Thread::FinishAllThreads() 47.704 { 47.705 ThreadList::FinishAllThreads(); 47.706 } 47.707 47.708 47.709 // *** Run override 47.710 47.711 int Thread::PRun() 47.712 { 47.713 // Suspend us on start, if requested 47.714 if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 47.715 { 47.716 Suspend(); 47.717 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 47.718 } 47.719 47.720 // Call the virtual run function 47.721 ExitCode = Run(); 47.722 return ExitCode; 47.723 } 47.724 47.725 47.726 47.727 /* MA: Don't use TLS for now. 47.728 47.729 // Static function to return a pointer to the current thread 47.730 void Thread::InitCurrentThread(Thread *pthread) 47.731 { 47.732 pCurrentThread = pthread; 47.733 } 47.734 47.735 // Static function to return a pointer to the current thread 47.736 Thread* Thread::GetThread() 47.737 { 47.738 return pCurrentThread; 47.739 } 47.740 */ 47.741 47.742 47.743 // *** User overridables 47.744 47.745 bool Thread::GetExitFlag() const 47.746 { 47.747 return (ThreadFlags & OVR_THREAD_EXIT) != 0; 47.748 } 47.749 47.750 void Thread::SetExitFlag(bool exitFlag) 47.751 { 47.752 // The below is atomic since ThreadFlags is AtomicInt. 47.753 if (exitFlag) 47.754 ThreadFlags |= OVR_THREAD_EXIT; 47.755 else 47.756 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 47.757 } 47.758 47.759 47.760 // Determines whether the thread was running and is now finished 47.761 bool Thread::IsFinished() const 47.762 { 47.763 return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 47.764 } 47.765 // Determines whether the thread is suspended 47.766 bool Thread::IsSuspended() const 47.767 { 47.768 return SuspendCount > 0; 47.769 } 47.770 // Returns current thread state 47.771 Thread::ThreadState Thread::GetThreadState() const 47.772 { 47.773 if (IsSuspended()) 47.774 return Suspended; 47.775 if (ThreadFlags & OVR_THREAD_STARTED) 47.776 return Running; 47.777 return NotRunning; 47.778 } 47.779 47.780 47.781 47.782 // ***** Thread management 47.783 /* static */ 47.784 int Thread::GetOSPriority(ThreadPriority p) 47.785 { 47.786 switch(p) 47.787 { 47.788 case Thread::CriticalPriority: return THREAD_PRIORITY_TIME_CRITICAL; 47.789 case Thread::HighestPriority: return THREAD_PRIORITY_HIGHEST; 47.790 case Thread::AboveNormalPriority: return THREAD_PRIORITY_ABOVE_NORMAL; 47.791 case Thread::NormalPriority: return THREAD_PRIORITY_NORMAL; 47.792 case Thread::BelowNormalPriority: return THREAD_PRIORITY_BELOW_NORMAL; 47.793 case Thread::LowestPriority: return THREAD_PRIORITY_LOWEST; 47.794 case Thread::IdlePriority: return THREAD_PRIORITY_IDLE; 47.795 } 47.796 return THREAD_PRIORITY_NORMAL; 47.797 } 47.798 47.799 // The actual first function called on thread start 47.800 unsigned WINAPI Thread_Win32StartFn(void * phandle) 47.801 { 47.802 Thread * pthread = (Thread*)phandle; 47.803 if (pthread->Processor != -1) 47.804 { 47.805 DWORD_PTR ret = SetThreadAffinityMask(GetCurrentThread(), (DWORD)pthread->Processor); 47.806 if (ret == 0) 47.807 OVR_DEBUG_LOG(("Could not set hardware processor for the thread")); 47.808 } 47.809 BOOL ret = ::SetThreadPriority(GetCurrentThread(), Thread::GetOSPriority(pthread->Priority)); 47.810 if (ret == 0) 47.811 OVR_DEBUG_LOG(("Could not set thread priority")); 47.812 OVR_UNUSED(ret); 47.813 47.814 // Ensure that ThreadId is assigned once thread is running, in case 47.815 // beginthread hasn't filled it in yet. 47.816 pthread->IdValue = (ThreadId)::GetCurrentThreadId(); 47.817 47.818 DWORD result = pthread->PRun(); 47.819 // Signal the thread as done and release it atomically. 47.820 pthread->FinishAndRelease(); 47.821 // At this point Thread object might be dead; however we can still pass 47.822 // it to RemoveRunningThread since it is only used as a key there. 47.823 ThreadList::RemoveRunningThread(pthread); 47.824 return (unsigned) result; 47.825 } 47.826 47.827 bool Thread::Start(ThreadState initialState) 47.828 { 47.829 if (initialState == NotRunning) 47.830 return 0; 47.831 if (GetThreadState() != NotRunning) 47.832 { 47.833 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 47.834 return 0; 47.835 } 47.836 47.837 // Free old thread handle before creating the new one 47.838 CleanupSystemThread(); 47.839 47.840 // AddRef to us until the thread is finished. 47.841 AddRef(); 47.842 ThreadList::AddRunningThread(this); 47.843 47.844 ExitCode = 0; 47.845 SuspendCount = 0; 47.846 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 47.847 ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize, 47.848 Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); 47.849 47.850 // Failed? Fail the function 47.851 if (ThreadHandle == 0) 47.852 { 47.853 ThreadFlags = 0; 47.854 Release(); 47.855 ThreadList::RemoveRunningThread(this); 47.856 return 0; 47.857 } 47.858 return 1; 47.859 } 47.860 47.861 47.862 // Suspend the thread until resumed 47.863 bool Thread::Suspend() 47.864 { 47.865 // Can't suspend a thread that wasn't started 47.866 if (!(ThreadFlags & OVR_THREAD_STARTED)) 47.867 return 0; 47.868 47.869 if (::SuspendThread(ThreadHandle) != 0xFFFFFFFF) 47.870 { 47.871 SuspendCount++; 47.872 return 1; 47.873 } 47.874 return 0; 47.875 } 47.876 47.877 // Resumes currently suspended thread 47.878 bool Thread::Resume() 47.879 { 47.880 // Can't suspend a thread that wasn't started 47.881 if (!(ThreadFlags & OVR_THREAD_STARTED)) 47.882 return 0; 47.883 47.884 // Decrement count, and resume thread if it is 0 47.885 SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1); 47.886 if (oldCount >= 1) 47.887 { 47.888 if (oldCount == 1) 47.889 { 47.890 if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF) 47.891 return 1; 47.892 } 47.893 else 47.894 { 47.895 return 1; 47.896 } 47.897 } 47.898 return 0; 47.899 } 47.900 47.901 47.902 // Quits with an exit code 47.903 void Thread::Exit(int exitCode) 47.904 { 47.905 // Can only exist the current thread. 47.906 // MA: Don't use TLS for now. 47.907 //if (GetThread() != this) 47.908 // return; 47.909 47.910 // Call the virtual OnExit function. 47.911 OnExit(); 47.912 47.913 // Signal this thread object as done and release it's references. 47.914 FinishAndRelease(); 47.915 ThreadList::RemoveRunningThread(this); 47.916 47.917 // Call the exit function. 47.918 _endthreadex((unsigned)exitCode); 47.919 } 47.920 47.921 47.922 void Thread::CleanupSystemThread() 47.923 { 47.924 if (ThreadHandle != 0) 47.925 { 47.926 ::CloseHandle(ThreadHandle); 47.927 ThreadHandle = 0; 47.928 } 47.929 } 47.930 47.931 // *** Sleep functions 47.932 // static 47.933 bool Thread::Sleep(unsigned secs) 47.934 { 47.935 ::Sleep(secs*1000); 47.936 return 1; 47.937 } 47.938 47.939 // static 47.940 bool Thread::MSleep(unsigned msecs) 47.941 { 47.942 ::Sleep(msecs); 47.943 return 1; 47.944 } 47.945 47.946 void Thread::SetThreadName( const char* name ) 47.947 { 47.948 #if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING) 47.949 // Looks ugly, but it is the recommended way to name a thread. 47.950 typedef struct tagTHREADNAME_INFO { 47.951 DWORD dwType; // Must be 0x1000 47.952 LPCSTR szName; // Pointer to name (in user address space) 47.953 DWORD dwThreadID; // Thread ID (-1 for caller thread) 47.954 DWORD dwFlags; // Reserved for future use; must be zero 47.955 } THREADNAME_INFO; 47.956 47.957 THREADNAME_INFO info; 47.958 47.959 info.dwType = 0x1000; 47.960 info.szName = name; 47.961 info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId()); 47.962 info.dwFlags = 0; 47.963 47.964 __try 47.965 { 47.966 #ifdef _WIN64 47.967 RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info ); 47.968 #else 47.969 RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info ); 47.970 #endif 47.971 } 47.972 __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER ) 47.973 { 47.974 } 47.975 #endif // OVR_BUILD_SHIPPING 47.976 } 47.977 47.978 // static 47.979 int Thread::GetCPUCount() 47.980 { 47.981 SYSTEM_INFO sysInfo; 47.982 GetSystemInfo(&sysInfo); 47.983 return (int) sysInfo.dwNumberOfProcessors; 47.984 } 47.985 47.986 // Returns the unique Id of a thread it is called on, intended for 47.987 // comparison purposes. 47.988 ThreadId GetCurrentThreadId() 47.989 { 47.990 return (ThreadId)::GetCurrentThreadId(); 47.991 } 47.992 47.993 } // OVR 47.994 47.995 #endif 47.996 47.997 47.998 \ No newline at end of file 47.999 +/************************************************************************************ 47.1000 + 47.1001 +Filename : OVR_ThreadsWinAPI.cpp 47.1002 +Platform : WinAPI 47.1003 +Content : Windows specific thread-related (safe) functionality 47.1004 +Created : September 19, 2012 47.1005 +Notes : 47.1006 + 47.1007 +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 47.1008 + 47.1009 +Use of this software is subject to the terms of the Oculus license 47.1010 +agreement provided at the time of installation or download, or which 47.1011 +otherwise accompanies this software in either electronic or hard copy form. 47.1012 + 47.1013 +************************************************************************************/ 47.1014 + 47.1015 +#include "OVR_Threads.h" 47.1016 +#include "OVR_Hash.h" 47.1017 +#include "OVR_Log.h" 47.1018 + 47.1019 +#ifdef OVR_ENABLE_THREADS 47.1020 + 47.1021 +// For _beginthreadex / _endtheadex 47.1022 +#include <process.h> 47.1023 + 47.1024 +namespace OVR { 47.1025 + 47.1026 + 47.1027 +//----------------------------------------------------------------------------------- 47.1028 +// *** Internal Mutex implementation class 47.1029 + 47.1030 +class MutexImpl : public NewOverrideBase 47.1031 +{ 47.1032 + // System mutex or semaphore 47.1033 + HANDLE hMutexOrSemaphore; 47.1034 + bool Recursive; 47.1035 + volatile unsigned LockCount; 47.1036 + 47.1037 + friend class WaitConditionImpl; 47.1038 + 47.1039 +public: 47.1040 + // Constructor/destructor 47.1041 + MutexImpl(bool recursive = 1); 47.1042 + ~MutexImpl(); 47.1043 + 47.1044 + // Locking functions 47.1045 + void DoLock(); 47.1046 + bool TryLock(); 47.1047 + void Unlock(Mutex* pmutex); 47.1048 + // Returns 1 if the mutes is currently locked 47.1049 + bool IsLockedByAnotherThread(Mutex* pmutex); 47.1050 +}; 47.1051 + 47.1052 +// *** Constructor/destructor 47.1053 +MutexImpl::MutexImpl(bool recursive) 47.1054 +{ 47.1055 + Recursive = recursive; 47.1056 + LockCount = 0; 47.1057 + hMutexOrSemaphore = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL); 47.1058 +} 47.1059 +MutexImpl::~MutexImpl() 47.1060 +{ 47.1061 + CloseHandle(hMutexOrSemaphore); 47.1062 +} 47.1063 + 47.1064 + 47.1065 +// Lock and try lock 47.1066 +void MutexImpl::DoLock() 47.1067 +{ 47.1068 + if (::WaitForSingleObject(hMutexOrSemaphore, INFINITE) != WAIT_OBJECT_0) 47.1069 + return; 47.1070 + LockCount++; 47.1071 +} 47.1072 + 47.1073 +bool MutexImpl::TryLock() 47.1074 +{ 47.1075 + DWORD ret; 47.1076 + if ((ret=::WaitForSingleObject(hMutexOrSemaphore, 0)) != WAIT_OBJECT_0) 47.1077 + return 0; 47.1078 + LockCount++; 47.1079 + return 1; 47.1080 +} 47.1081 + 47.1082 +void MutexImpl::Unlock(Mutex* pmutex) 47.1083 +{ 47.1084 + OVR_UNUSED(pmutex); 47.1085 + 47.1086 + unsigned lockCount; 47.1087 + LockCount--; 47.1088 + lockCount = LockCount; 47.1089 + 47.1090 + // Release mutex 47.1091 + if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) : 47.1092 + ReleaseSemaphore(hMutexOrSemaphore, 1, NULL)) != 0) 47.1093 + { 47.1094 + // This used to call Wait handlers if lockCount == 0. 47.1095 + } 47.1096 +} 47.1097 + 47.1098 +bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex) 47.1099 +{ 47.1100 + // There could be multiple interpretations of IsLocked with respect to current thread 47.1101 + if (LockCount == 0) 47.1102 + return 0; 47.1103 + if (!TryLock()) 47.1104 + return 1; 47.1105 + Unlock(pmutex); 47.1106 + return 0; 47.1107 +} 47.1108 + 47.1109 +/* 47.1110 +bool MutexImpl::IsSignaled() const 47.1111 +{ 47.1112 + // An mutex is signaled if it is not locked ANYWHERE 47.1113 + // Note that this is different from IsLockedByAnotherThread function, 47.1114 + // that takes current thread into account 47.1115 + return LockCount == 0; 47.1116 +} 47.1117 +*/ 47.1118 + 47.1119 + 47.1120 +// *** Actual Mutex class implementation 47.1121 + 47.1122 +Mutex::Mutex(bool recursive) 47.1123 +{ 47.1124 + pImpl = new MutexImpl(recursive); 47.1125 +} 47.1126 +Mutex::~Mutex() 47.1127 +{ 47.1128 + delete pImpl; 47.1129 +} 47.1130 + 47.1131 +// Lock and try lock 47.1132 +void Mutex::DoLock() 47.1133 +{ 47.1134 + pImpl->DoLock(); 47.1135 +} 47.1136 +bool Mutex::TryLock() 47.1137 +{ 47.1138 + return pImpl->TryLock(); 47.1139 +} 47.1140 +void Mutex::Unlock() 47.1141 +{ 47.1142 + pImpl->Unlock(this); 47.1143 +} 47.1144 +bool Mutex::IsLockedByAnotherThread() 47.1145 +{ 47.1146 + return pImpl->IsLockedByAnotherThread(this); 47.1147 +} 47.1148 + 47.1149 +//----------------------------------------------------------------------------------- 47.1150 +// ***** Event 47.1151 + 47.1152 +bool Event::Wait(unsigned delay) 47.1153 +{ 47.1154 + Mutex::Locker lock(&StateMutex); 47.1155 + 47.1156 + // Do the correct amount of waiting 47.1157 + if (delay == OVR_WAIT_INFINITE) 47.1158 + { 47.1159 + while(!State) 47.1160 + StateWaitCondition.Wait(&StateMutex); 47.1161 + } 47.1162 + else if (delay) 47.1163 + { 47.1164 + if (!State) 47.1165 + StateWaitCondition.Wait(&StateMutex, delay); 47.1166 + } 47.1167 + 47.1168 + bool state = State; 47.1169 + // Take care of temporary 'pulsing' of a state 47.1170 + if (Temporary) 47.1171 + { 47.1172 + Temporary = false; 47.1173 + State = false; 47.1174 + } 47.1175 + return state; 47.1176 +} 47.1177 + 47.1178 +void Event::updateState(bool newState, bool newTemp, bool mustNotify) 47.1179 +{ 47.1180 + Mutex::Locker lock(&StateMutex); 47.1181 + State = newState; 47.1182 + Temporary = newTemp; 47.1183 + if (mustNotify) 47.1184 + StateWaitCondition.NotifyAll(); 47.1185 +} 47.1186 + 47.1187 + 47.1188 +//----------------------------------------------------------------------------------- 47.1189 +// ***** Win32 Wait Condition Implementation 47.1190 + 47.1191 +// Internal implementation class 47.1192 +class WaitConditionImpl : public NewOverrideBase 47.1193 +{ 47.1194 + // Event pool entries for extra events 47.1195 + struct EventPoolEntry : public NewOverrideBase 47.1196 + { 47.1197 + HANDLE hEvent; 47.1198 + EventPoolEntry *pNext; 47.1199 + EventPoolEntry *pPrev; 47.1200 + }; 47.1201 + 47.1202 + Lock WaitQueueLoc; 47.1203 + // Stores free events that can be used later 47.1204 + EventPoolEntry * pFreeEventList; 47.1205 + 47.1206 + // A queue of waiting objects to be signaled 47.1207 + EventPoolEntry* pQueueHead; 47.1208 + EventPoolEntry* pQueueTail; 47.1209 + 47.1210 + // Allocation functions for free events 47.1211 + EventPoolEntry* GetNewEvent(); 47.1212 + void ReleaseEvent(EventPoolEntry* pevent); 47.1213 + 47.1214 + // Queue operations 47.1215 + void QueuePush(EventPoolEntry* pentry); 47.1216 + EventPoolEntry* QueuePop(); 47.1217 + void QueueFindAndRemove(EventPoolEntry* pentry); 47.1218 + 47.1219 +public: 47.1220 + 47.1221 + // Constructor/destructor 47.1222 + WaitConditionImpl(); 47.1223 + ~WaitConditionImpl(); 47.1224 + 47.1225 + // Release mutex and wait for condition. The mutex is re-acqured after the wait. 47.1226 + bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE); 47.1227 + 47.1228 + // Notify a condition, releasing at one object waiting 47.1229 + void Notify(); 47.1230 + // Notify a condition, releasing all objects waiting 47.1231 + void NotifyAll(); 47.1232 +}; 47.1233 + 47.1234 + 47.1235 + 47.1236 +WaitConditionImpl::WaitConditionImpl() 47.1237 +{ 47.1238 + pFreeEventList = 0; 47.1239 + pQueueHead = 47.1240 + pQueueTail = 0; 47.1241 +} 47.1242 + 47.1243 +WaitConditionImpl::~WaitConditionImpl() 47.1244 +{ 47.1245 + // Free all the resources 47.1246 + EventPoolEntry* p = pFreeEventList; 47.1247 + EventPoolEntry* pentry; 47.1248 + 47.1249 + while(p) 47.1250 + { 47.1251 + // Move to next 47.1252 + pentry = p; 47.1253 + p = p->pNext; 47.1254 + // Delete old 47.1255 + ::CloseHandle(pentry->hEvent); 47.1256 + delete pentry; 47.1257 + } 47.1258 + // Shouldn't we also consider the queue? 47.1259 + 47.1260 + // To be safe 47.1261 + pFreeEventList = 0; 47.1262 + pQueueHead = 47.1263 + pQueueTail = 0; 47.1264 +} 47.1265 + 47.1266 + 47.1267 +// Allocation functions for free events 47.1268 +WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent() 47.1269 +{ 47.1270 + EventPoolEntry* pentry; 47.1271 + 47.1272 + // If there are any free nodes, use them 47.1273 + if (pFreeEventList) 47.1274 + { 47.1275 + pentry = pFreeEventList; 47.1276 + pFreeEventList = pFreeEventList->pNext; 47.1277 + } 47.1278 + else 47.1279 + { 47.1280 + // Allocate a new node 47.1281 + pentry = new EventPoolEntry; 47.1282 + pentry->pNext = 0; 47.1283 + pentry->pPrev = 0; 47.1284 + // Non-signaled manual event 47.1285 + pentry->hEvent = ::CreateEvent(NULL, TRUE, 0, NULL); 47.1286 + } 47.1287 + 47.1288 + return pentry; 47.1289 +} 47.1290 + 47.1291 +void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent) 47.1292 +{ 47.1293 + // Mark event as non-signaled 47.1294 + ::ResetEvent(pevent->hEvent); 47.1295 + // And add it to free pool 47.1296 + pevent->pNext = pFreeEventList; 47.1297 + pevent->pPrev = 0; 47.1298 + pFreeEventList = pevent; 47.1299 +} 47.1300 + 47.1301 +// Queue operations 47.1302 +void WaitConditionImpl::QueuePush(EventPoolEntry* pentry) 47.1303 +{ 47.1304 + // Items already exist? Just add to tail 47.1305 + if (pQueueTail) 47.1306 + { 47.1307 + pentry->pPrev = pQueueTail; 47.1308 + pQueueTail->pNext = pentry; 47.1309 + pentry->pNext = 0; 47.1310 + pQueueTail = pentry; 47.1311 + } 47.1312 + else 47.1313 + { 47.1314 + // No items in queue 47.1315 + pentry->pNext = 47.1316 + pentry->pPrev = 0; 47.1317 + pQueueHead = 47.1318 + pQueueTail = pentry; 47.1319 + } 47.1320 +} 47.1321 + 47.1322 +WaitConditionImpl::EventPoolEntry* WaitConditionImpl::QueuePop() 47.1323 +{ 47.1324 + EventPoolEntry* pentry = pQueueHead; 47.1325 + 47.1326 + // No items, null pointer 47.1327 + if (pentry) 47.1328 + { 47.1329 + // More items after this one? just grab the first item 47.1330 + if (pQueueHead->pNext) 47.1331 + { 47.1332 + pQueueHead = pentry->pNext; 47.1333 + pQueueHead->pPrev = 0; 47.1334 + } 47.1335 + else 47.1336 + { 47.1337 + // Last item left 47.1338 + pQueueTail = 47.1339 + pQueueHead = 0; 47.1340 + } 47.1341 + } 47.1342 + return pentry; 47.1343 +} 47.1344 + 47.1345 +void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry) 47.1346 +{ 47.1347 + // Do an exhaustive search looking for an entry 47.1348 + EventPoolEntry* p = pQueueHead; 47.1349 + 47.1350 + while(p) 47.1351 + { 47.1352 + // Entry found? Remove. 47.1353 + if (p == pentry) 47.1354 + { 47.1355 + 47.1356 + // Remove the node form the list 47.1357 + // Prev link 47.1358 + if (pentry->pPrev) 47.1359 + pentry->pPrev->pNext = pentry->pNext; 47.1360 + else 47.1361 + pQueueHead = pentry->pNext; 47.1362 + // Next link 47.1363 + if (pentry->pNext) 47.1364 + pentry->pNext->pPrev = pentry->pPrev; 47.1365 + else 47.1366 + pQueueTail = pentry->pPrev; 47.1367 + // Done 47.1368 + return; 47.1369 + } 47.1370 + 47.1371 + // Move to next item 47.1372 + p = p->pNext; 47.1373 + } 47.1374 +} 47.1375 + 47.1376 + 47.1377 +bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay) 47.1378 +{ 47.1379 + bool result = 0; 47.1380 + unsigned i; 47.1381 + unsigned lockCount = pmutex->pImpl->LockCount; 47.1382 + EventPoolEntry* pentry; 47.1383 + 47.1384 + // Mutex must have been locked 47.1385 + if (lockCount == 0) 47.1386 + return 0; 47.1387 + 47.1388 + // Add an object to the wait queue 47.1389 + WaitQueueLoc.DoLock(); 47.1390 + QueuePush(pentry = GetNewEvent()); 47.1391 + WaitQueueLoc.Unlock(); 47.1392 + 47.1393 + // Finally, release a mutex or semaphore 47.1394 + if (pmutex->pImpl->Recursive) 47.1395 + { 47.1396 + // Release the recursive mutex N times 47.1397 + pmutex->pImpl->LockCount = 0; 47.1398 + for(i=0; i<lockCount; i++) 47.1399 + ::ReleaseMutex(pmutex->pImpl->hMutexOrSemaphore); 47.1400 + } 47.1401 + else 47.1402 + { 47.1403 + pmutex->pImpl->LockCount = 0; 47.1404 + ::ReleaseSemaphore(pmutex->pImpl->hMutexOrSemaphore, 1, NULL); 47.1405 + } 47.1406 + 47.1407 + // Note that there is a gap here between mutex.Unlock() and Wait(). However, 47.1408 + // if notify() comes in at this point in the other thread it will set our 47.1409 + // corresponding event so wait will just fall through, as expected. 47.1410 + 47.1411 + // Block and wait on the event 47.1412 + DWORD waitResult = ::WaitForSingleObject(pentry->hEvent, 47.1413 + (delay == OVR_WAIT_INFINITE) ? INFINITE : delay); 47.1414 + /* 47.1415 +repeat_wait: 47.1416 + DWORD waitResult = 47.1417 + 47.1418 + ::MsgWaitForMultipleObjects(1, &pentry->hEvent, FALSE, 47.1419 + (delay == OVR_WAIT_INFINITE) ? INFINITE : delay, 47.1420 + QS_ALLINPUT); 47.1421 + */ 47.1422 + 47.1423 + WaitQueueLoc.DoLock(); 47.1424 + switch(waitResult) 47.1425 + { 47.1426 + case WAIT_ABANDONED: 47.1427 + case WAIT_OBJECT_0: 47.1428 + result = 1; 47.1429 + // Wait was successful, therefore the event entry should already be removed 47.1430 + // So just add entry back to a free list 47.1431 + ReleaseEvent(pentry); 47.1432 + break; 47.1433 + /* 47.1434 + case WAIT_OBJECT_0 + 1: 47.1435 + // Messages in WINDOWS queue 47.1436 + { 47.1437 + MSG msg; 47.1438 + PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); 47.1439 + WaitQueueLoc.Unlock(); 47.1440 + goto repeat_wait; 47.1441 + } 47.1442 + break; */ 47.1443 + default: 47.1444 + // Timeout, our entry should still be in a queue 47.1445 + QueueFindAndRemove(pentry); 47.1446 + ReleaseEvent(pentry); 47.1447 + } 47.1448 + WaitQueueLoc.Unlock(); 47.1449 + 47.1450 + // Re-aquire the mutex 47.1451 + for(i=0; i<lockCount; i++) 47.1452 + pmutex->DoLock(); 47.1453 + 47.1454 + // Return the result 47.1455 + return result; 47.1456 +} 47.1457 + 47.1458 +// Notify a condition, releasing the least object in a queue 47.1459 +void WaitConditionImpl::Notify() 47.1460 +{ 47.1461 + Lock::Locker lock(&WaitQueueLoc); 47.1462 + 47.1463 + // Pop last entry & signal it 47.1464 + EventPoolEntry* pentry = QueuePop(); 47.1465 + if (pentry) 47.1466 + ::SetEvent(pentry->hEvent); 47.1467 +} 47.1468 + 47.1469 +// Notify a condition, releasing all objects waiting 47.1470 +void WaitConditionImpl::NotifyAll() 47.1471 +{ 47.1472 + Lock::Locker lock(&WaitQueueLoc); 47.1473 + 47.1474 + // Pop and signal all events 47.1475 + // NOTE : There is no need to release the events, it's the waiters job to do so 47.1476 + EventPoolEntry* pentry = QueuePop(); 47.1477 + while (pentry) 47.1478 + { 47.1479 + ::SetEvent(pentry->hEvent); 47.1480 + pentry = QueuePop(); 47.1481 + } 47.1482 +} 47.1483 + 47.1484 + 47.1485 + 47.1486 +// *** Actual implementation of WaitCondition 47.1487 + 47.1488 +WaitCondition::WaitCondition() 47.1489 +{ 47.1490 + pImpl = new WaitConditionImpl; 47.1491 +} 47.1492 +WaitCondition::~WaitCondition() 47.1493 +{ 47.1494 + delete pImpl; 47.1495 +} 47.1496 + 47.1497 +// Wait without a mutex 47.1498 +bool WaitCondition::Wait(Mutex *pmutex, unsigned delay) 47.1499 +{ 47.1500 + return pImpl->Wait(pmutex, delay); 47.1501 +} 47.1502 +// Notification 47.1503 +void WaitCondition::Notify() 47.1504 +{ 47.1505 + pImpl->Notify(); 47.1506 +} 47.1507 +void WaitCondition::NotifyAll() 47.1508 +{ 47.1509 + pImpl->NotifyAll(); 47.1510 +} 47.1511 + 47.1512 + 47.1513 + 47.1514 +//----------------------------------------------------------------------------------- 47.1515 +// ***** Thread Class 47.1516 + 47.1517 +// Per-thread variable 47.1518 +// MA: Don't use TLS for now - portability issues with DLLs, etc. 47.1519 +/* 47.1520 +#if !defined(OVR_CC_MSVC) || (OVR_CC_MSVC < 1300) 47.1521 +__declspec(thread) Thread* pCurrentThread = 0; 47.1522 +#else 47.1523 +#pragma data_seg(".tls$") 47.1524 +__declspec(thread) Thread* pCurrentThread = 0; 47.1525 +#pragma data_seg(".rwdata") 47.1526 +#endif 47.1527 +*/ 47.1528 + 47.1529 +// *** Thread constructors. 47.1530 + 47.1531 +Thread::Thread(UPInt stackSize, int processor) 47.1532 +{ 47.1533 + CreateParams params; 47.1534 + params.stackSize = stackSize; 47.1535 + params.processor = processor; 47.1536 + Init(params); 47.1537 +} 47.1538 + 47.1539 +Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize, 47.1540 + int processor, Thread::ThreadState initialState) 47.1541 +{ 47.1542 + CreateParams params(threadFunction, userHandle, stackSize, processor, initialState); 47.1543 + Init(params); 47.1544 +} 47.1545 + 47.1546 +Thread::Thread(const CreateParams& params) 47.1547 +{ 47.1548 + Init(params); 47.1549 +} 47.1550 +void Thread::Init(const CreateParams& params) 47.1551 +{ 47.1552 + // Clear the variables 47.1553 + ThreadFlags = 0; 47.1554 + ThreadHandle = 0; 47.1555 + IdValue = 0; 47.1556 + ExitCode = 0; 47.1557 + SuspendCount = 0; 47.1558 + StackSize = params.stackSize; 47.1559 + Processor = params.processor; 47.1560 + Priority = params.priority; 47.1561 + 47.1562 + // Clear Function pointers 47.1563 + ThreadFunction = params.threadFunction; 47.1564 + UserHandle = params.userHandle; 47.1565 + if (params.initialState != NotRunning) 47.1566 + Start(params.initialState); 47.1567 + 47.1568 +} 47.1569 + 47.1570 +Thread::~Thread() 47.1571 +{ 47.1572 + // Thread should not running while object is being destroyed, 47.1573 + // this would indicate ref-counting issue. 47.1574 + //OVR_ASSERT(IsRunning() == 0); 47.1575 + 47.1576 + // Clean up thread. 47.1577 + CleanupSystemThread(); 47.1578 + ThreadHandle = 0; 47.1579 +} 47.1580 + 47.1581 + 47.1582 +// *** Overridable User functions. 47.1583 + 47.1584 +// Default Run implementation 47.1585 +int Thread::Run() 47.1586 +{ 47.1587 + // Call pointer to function, if available. 47.1588 + return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0; 47.1589 +} 47.1590 +void Thread::OnExit() 47.1591 +{ 47.1592 +} 47.1593 + 47.1594 +// Finishes the thread and releases internal reference to it. 47.1595 +void Thread::FinishAndRelease() 47.1596 +{ 47.1597 + // Note: thread must be US. 47.1598 + ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED); 47.1599 + ThreadFlags |= OVR_THREAD_FINISHED; 47.1600 + 47.1601 + // Release our reference; this is equivalent to 'delete this' 47.1602 + // from the point of view of our thread. 47.1603 + Release(); 47.1604 +} 47.1605 + 47.1606 + 47.1607 +// *** ThreadList - used to tack all created threads 47.1608 + 47.1609 +class ThreadList : public NewOverrideBase 47.1610 +{ 47.1611 + //------------------------------------------------------------------------ 47.1612 + struct ThreadHashOp 47.1613 + { 47.1614 + UPInt operator()(const Thread* ptr) 47.1615 + { 47.1616 + return (((UPInt)ptr) >> 6) ^ (UPInt)ptr; 47.1617 + } 47.1618 + }; 47.1619 + 47.1620 + HashSet<Thread*, ThreadHashOp> ThreadSet; 47.1621 + Mutex ThreadMutex; 47.1622 + WaitCondition ThreadsEmpty; 47.1623 + // Track the root thread that created us. 47.1624 + ThreadId RootThreadId; 47.1625 + 47.1626 + static ThreadList* volatile pRunningThreads; 47.1627 + 47.1628 + void addThread(Thread *pthread) 47.1629 + { 47.1630 + Mutex::Locker lock(&ThreadMutex); 47.1631 + ThreadSet.Add(pthread); 47.1632 + } 47.1633 + 47.1634 + void removeThread(Thread *pthread) 47.1635 + { 47.1636 + Mutex::Locker lock(&ThreadMutex); 47.1637 + ThreadSet.Remove(pthread); 47.1638 + if (ThreadSet.GetSize() == 0) 47.1639 + ThreadsEmpty.Notify(); 47.1640 + } 47.1641 + 47.1642 + void finishAllThreads() 47.1643 + { 47.1644 + // Only original root thread can call this. 47.1645 + OVR_ASSERT(GetCurrentThreadId() == RootThreadId); 47.1646 + 47.1647 + Mutex::Locker lock(&ThreadMutex); 47.1648 + while (ThreadSet.GetSize() != 0) 47.1649 + ThreadsEmpty.Wait(&ThreadMutex); 47.1650 + } 47.1651 + 47.1652 +public: 47.1653 + 47.1654 + ThreadList() 47.1655 + { 47.1656 + RootThreadId = GetCurrentThreadId(); 47.1657 + } 47.1658 + ~ThreadList() { } 47.1659 + 47.1660 + 47.1661 + static void AddRunningThread(Thread *pthread) 47.1662 + { 47.1663 + // Non-atomic creation ok since only the root thread 47.1664 + if (!pRunningThreads) 47.1665 + { 47.1666 + pRunningThreads = new ThreadList; 47.1667 + OVR_ASSERT(pRunningThreads); 47.1668 + } 47.1669 + pRunningThreads->addThread(pthread); 47.1670 + } 47.1671 + 47.1672 + // NOTE: 'pthread' might be a dead pointer when this is 47.1673 + // called so it should not be accessed; it is only used 47.1674 + // for removal. 47.1675 + static void RemoveRunningThread(Thread *pthread) 47.1676 + { 47.1677 + OVR_ASSERT(pRunningThreads); 47.1678 + pRunningThreads->removeThread(pthread); 47.1679 + } 47.1680 + 47.1681 + static void FinishAllThreads() 47.1682 + { 47.1683 + // This is ok because only root thread can wait for other thread finish. 47.1684 + if (pRunningThreads) 47.1685 + { 47.1686 + pRunningThreads->finishAllThreads(); 47.1687 + delete pRunningThreads; 47.1688 + pRunningThreads = 0; 47.1689 + } 47.1690 + } 47.1691 +}; 47.1692 + 47.1693 +// By default, we have no thread list. 47.1694 +ThreadList* volatile ThreadList::pRunningThreads = 0; 47.1695 + 47.1696 + 47.1697 +// FinishAllThreads - exposed publicly in Thread. 47.1698 +void Thread::FinishAllThreads() 47.1699 +{ 47.1700 + ThreadList::FinishAllThreads(); 47.1701 +} 47.1702 + 47.1703 + 47.1704 +// *** Run override 47.1705 + 47.1706 +int Thread::PRun() 47.1707 +{ 47.1708 + // Suspend us on start, if requested 47.1709 + if (ThreadFlags & OVR_THREAD_START_SUSPENDED) 47.1710 + { 47.1711 + Suspend(); 47.1712 + ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED; 47.1713 + } 47.1714 + 47.1715 + // Call the virtual run function 47.1716 + ExitCode = Run(); 47.1717 + return ExitCode; 47.1718 +} 47.1719 + 47.1720 + 47.1721 + 47.1722 +/* MA: Don't use TLS for now. 47.1723 + 47.1724 +// Static function to return a pointer to the current thread 47.1725 +void Thread::InitCurrentThread(Thread *pthread) 47.1726 +{ 47.1727 + pCurrentThread = pthread; 47.1728 +} 47.1729 + 47.1730 +// Static function to return a pointer to the current thread 47.1731 +Thread* Thread::GetThread() 47.1732 +{ 47.1733 + return pCurrentThread; 47.1734 +} 47.1735 +*/ 47.1736 + 47.1737 + 47.1738 +// *** User overridables 47.1739 + 47.1740 +bool Thread::GetExitFlag() const 47.1741 +{ 47.1742 + return (ThreadFlags & OVR_THREAD_EXIT) != 0; 47.1743 +} 47.1744 + 47.1745 +void Thread::SetExitFlag(bool exitFlag) 47.1746 +{ 47.1747 + // The below is atomic since ThreadFlags is AtomicInt. 47.1748 + if (exitFlag) 47.1749 + ThreadFlags |= OVR_THREAD_EXIT; 47.1750 + else 47.1751 + ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT; 47.1752 +} 47.1753 + 47.1754 + 47.1755 +// Determines whether the thread was running and is now finished 47.1756 +bool Thread::IsFinished() const 47.1757 +{ 47.1758 + return (ThreadFlags & OVR_THREAD_FINISHED) != 0; 47.1759 +} 47.1760 +// Determines whether the thread is suspended 47.1761 +bool Thread::IsSuspended() const 47.1762 +{ 47.1763 + return SuspendCount > 0; 47.1764 +} 47.1765 +// Returns current thread state 47.1766 +Thread::ThreadState Thread::GetThreadState() const 47.1767 +{ 47.1768 + if (IsSuspended()) 47.1769 + return Suspended; 47.1770 + if (ThreadFlags & OVR_THREAD_STARTED) 47.1771 + return Running; 47.1772 + return NotRunning; 47.1773 +} 47.1774 + 47.1775 + 47.1776 + 47.1777 +// ***** Thread management 47.1778 +/* static */ 47.1779 +int Thread::GetOSPriority(ThreadPriority p) 47.1780 +{ 47.1781 + switch(p) 47.1782 + { 47.1783 + case Thread::CriticalPriority: return THREAD_PRIORITY_TIME_CRITICAL; 47.1784 + case Thread::HighestPriority: return THREAD_PRIORITY_HIGHEST; 47.1785 + case Thread::AboveNormalPriority: return THREAD_PRIORITY_ABOVE_NORMAL; 47.1786 + case Thread::NormalPriority: return THREAD_PRIORITY_NORMAL; 47.1787 + case Thread::BelowNormalPriority: return THREAD_PRIORITY_BELOW_NORMAL; 47.1788 + case Thread::LowestPriority: return THREAD_PRIORITY_LOWEST; 47.1789 + case Thread::IdlePriority: return THREAD_PRIORITY_IDLE; 47.1790 + } 47.1791 + return THREAD_PRIORITY_NORMAL; 47.1792 +} 47.1793 + 47.1794 +// The actual first function called on thread start 47.1795 +unsigned WINAPI Thread_Win32StartFn(void * phandle) 47.1796 +{ 47.1797 + Thread * pthread = (Thread*)phandle; 47.1798 + if (pthread->Processor != -1) 47.1799 + { 47.1800 + DWORD_PTR ret = SetThreadAffinityMask(GetCurrentThread(), (DWORD)pthread->Processor); 47.1801 + if (ret == 0) 47.1802 + OVR_DEBUG_LOG(("Could not set hardware processor for the thread")); 47.1803 + } 47.1804 + BOOL ret = ::SetThreadPriority(GetCurrentThread(), Thread::GetOSPriority(pthread->Priority)); 47.1805 + if (ret == 0) 47.1806 + OVR_DEBUG_LOG(("Could not set thread priority")); 47.1807 + OVR_UNUSED(ret); 47.1808 + 47.1809 + // Ensure that ThreadId is assigned once thread is running, in case 47.1810 + // beginthread hasn't filled it in yet. 47.1811 + pthread->IdValue = (ThreadId)::GetCurrentThreadId(); 47.1812 + 47.1813 + DWORD result = pthread->PRun(); 47.1814 + // Signal the thread as done and release it atomically. 47.1815 + pthread->FinishAndRelease(); 47.1816 + // At this point Thread object might be dead; however we can still pass 47.1817 + // it to RemoveRunningThread since it is only used as a key there. 47.1818 + ThreadList::RemoveRunningThread(pthread); 47.1819 + return (unsigned) result; 47.1820 +} 47.1821 + 47.1822 +bool Thread::Start(ThreadState initialState) 47.1823 +{ 47.1824 + if (initialState == NotRunning) 47.1825 + return 0; 47.1826 + if (GetThreadState() != NotRunning) 47.1827 + { 47.1828 + OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this)); 47.1829 + return 0; 47.1830 + } 47.1831 + 47.1832 + // Free old thread handle before creating the new one 47.1833 + CleanupSystemThread(); 47.1834 + 47.1835 + // AddRef to us until the thread is finished. 47.1836 + AddRef(); 47.1837 + ThreadList::AddRunningThread(this); 47.1838 + 47.1839 + ExitCode = 0; 47.1840 + SuspendCount = 0; 47.1841 + ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; 47.1842 + ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize, 47.1843 + Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); 47.1844 + 47.1845 + // Failed? Fail the function 47.1846 + if (ThreadHandle == 0) 47.1847 + { 47.1848 + ThreadFlags = 0; 47.1849 + Release(); 47.1850 + ThreadList::RemoveRunningThread(this); 47.1851 + return 0; 47.1852 + } 47.1853 + return 1; 47.1854 +} 47.1855 + 47.1856 + 47.1857 +// Suspend the thread until resumed 47.1858 +bool Thread::Suspend() 47.1859 +{ 47.1860 + // Can't suspend a thread that wasn't started 47.1861 + if (!(ThreadFlags & OVR_THREAD_STARTED)) 47.1862 + return 0; 47.1863 + 47.1864 + if (::SuspendThread(ThreadHandle) != 0xFFFFFFFF) 47.1865 + { 47.1866 + SuspendCount++; 47.1867 + return 1; 47.1868 + } 47.1869 + return 0; 47.1870 +} 47.1871 + 47.1872 +// Resumes currently suspended thread 47.1873 +bool Thread::Resume() 47.1874 +{ 47.1875 + // Can't suspend a thread that wasn't started 47.1876 + if (!(ThreadFlags & OVR_THREAD_STARTED)) 47.1877 + return 0; 47.1878 + 47.1879 + // Decrement count, and resume thread if it is 0 47.1880 + SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1); 47.1881 + if (oldCount >= 1) 47.1882 + { 47.1883 + if (oldCount == 1) 47.1884 + { 47.1885 + if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF) 47.1886 + return 1; 47.1887 + } 47.1888 + else 47.1889 + { 47.1890 + return 1; 47.1891 + } 47.1892 + } 47.1893 + return 0; 47.1894 +} 47.1895 + 47.1896 + 47.1897 +// Quits with an exit code 47.1898 +void Thread::Exit(int exitCode) 47.1899 +{ 47.1900 + // Can only exist the current thread. 47.1901 + // MA: Don't use TLS for now. 47.1902 + //if (GetThread() != this) 47.1903 + // return; 47.1904 + 47.1905 + // Call the virtual OnExit function. 47.1906 + OnExit(); 47.1907 + 47.1908 + // Signal this thread object as done and release it's references. 47.1909 + FinishAndRelease(); 47.1910 + ThreadList::RemoveRunningThread(this); 47.1911 + 47.1912 + // Call the exit function. 47.1913 + _endthreadex((unsigned)exitCode); 47.1914 +} 47.1915 + 47.1916 + 47.1917 +void Thread::CleanupSystemThread() 47.1918 +{ 47.1919 + if (ThreadHandle != 0) 47.1920 + { 47.1921 + ::CloseHandle(ThreadHandle); 47.1922 + ThreadHandle = 0; 47.1923 + } 47.1924 +} 47.1925 + 47.1926 +// *** Sleep functions 47.1927 +// static 47.1928 +bool Thread::Sleep(unsigned secs) 47.1929 +{ 47.1930 + ::Sleep(secs*1000); 47.1931 + return 1; 47.1932 +} 47.1933 + 47.1934 +// static 47.1935 +bool Thread::MSleep(unsigned msecs) 47.1936 +{ 47.1937 + ::Sleep(msecs); 47.1938 + return 1; 47.1939 +} 47.1940 + 47.1941 +void Thread::SetThreadName( const char* name ) 47.1942 +{ 47.1943 +#if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING) 47.1944 + // Looks ugly, but it is the recommended way to name a thread. 47.1945 + typedef struct tagTHREADNAME_INFO { 47.1946 + DWORD dwType; // Must be 0x1000 47.1947 + LPCSTR szName; // Pointer to name (in user address space) 47.1948 + DWORD dwThreadID; // Thread ID (-1 for caller thread) 47.1949 + DWORD dwFlags; // Reserved for future use; must be zero 47.1950 + } THREADNAME_INFO; 47.1951 + 47.1952 + THREADNAME_INFO info; 47.1953 + 47.1954 + info.dwType = 0x1000; 47.1955 + info.szName = name; 47.1956 + info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId()); 47.1957 + info.dwFlags = 0; 47.1958 + 47.1959 + __try 47.1960 + { 47.1961 +#ifdef _WIN64 47.1962 + RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info ); 47.1963 +#else 47.1964 + RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info ); 47.1965 +#endif 47.1966 + } 47.1967 + __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER ) 47.1968 + { 47.1969 + } 47.1970 +#endif // OVR_BUILD_SHIPPING 47.1971 +} 47.1972 + 47.1973 +// static 47.1974 +int Thread::GetCPUCount() 47.1975 +{ 47.1976 + SYSTEM_INFO sysInfo; 47.1977 + GetSystemInfo(&sysInfo); 47.1978 + return (int) sysInfo.dwNumberOfProcessors; 47.1979 +} 47.1980 + 47.1981 +// Returns the unique Id of a thread it is called on, intended for 47.1982 +// comparison purposes. 47.1983 +ThreadId GetCurrentThreadId() 47.1984 +{ 47.1985 + return (ThreadId)::GetCurrentThreadId(); 47.1986 +} 47.1987 + 47.1988 +} // OVR 47.1989 + 47.1990 +#endif 47.1991 + 47.1992 +
48.1 --- a/src/main.cc Sat Sep 14 17:51:03 2013 +0300 48.2 +++ b/src/main.cc Sun Sep 15 04:10:05 2013 +0300 48.3 @@ -26,13 +26,13 @@ 48.4 48.5 int main(int argc, char **argv) 48.6 { 48.7 + glutInitWindowSize(1280, 800); 48.8 glutInit(&argc, argv); 48.9 48.10 if(!parse_args(argc, argv)) { 48.11 return 1; 48.12 } 48.13 48.14 - glutInitWindowSize(1280, 800); 48.15 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 48.16 glutCreateWindow("oculus test 01"); 48.17 48.18 @@ -63,7 +63,7 @@ 48.19 glEnable(GL_LIGHTING); 48.20 48.21 if(vr_init(VR_INIT_OCULUS) == -1) { 48.22 - return false; 48.23 + //return false; 48.24 } 48.25 return true; 48.26 } 48.27 @@ -75,6 +75,15 @@ 48.28 48.29 static void disp() 48.30 { 48.31 + // test rift sensor 48.32 + float quat[4], euler[3]; 48.33 + 48.34 + vr_get_rotation(quat); 48.35 + vr_get_rotation_euler(euler); 48.36 + 48.37 + printf("q(%.3f + %.3fi + %.3fj %.3fk)", quat[3], quat[0], quat[1], quat[2]); 48.38 + printf(" - euler(%.3f %.3f %.3f)\n", euler[0], euler[1], euler[2]); 48.39 + 48.40 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 48.41 48.42 glMatrixMode(GL_PROJECTION);
49.1 --- a/src/vr.cc Sat Sep 14 17:51:03 2013 +0300 49.2 +++ b/src/vr.cc Sun Sep 15 04:10:05 2013 +0300 49.3 @@ -4,7 +4,7 @@ 49.4 49.5 static bool init_ovr(); 49.6 49.7 -VRData vr_data; 49.8 +VRContext vr_ctx; 49.9 49.10 extern "C" int vr_init(enum vr_init_mode mode) 49.11 { 49.12 @@ -16,28 +16,26 @@ 49.13 49.14 extern "C" void vr_shutdown(void) 49.15 { 49.16 - System::Destroy(); 49.17 + //System::Destroy(); 49.18 } 49.19 49.20 - 49.21 - 49.22 static bool init_ovr() 49.23 { 49.24 // initialize Oculus SDK 49.25 System::Init(); 49.26 - if(!(vr_data.ovr_devman = DeviceManager::Create())) { 49.27 + if(!(vr_ctx.ovr_devman = DeviceManager::Create())) { 49.28 fprintf(stderr, "failed to create OVR device manager\n"); 49.29 return false; 49.30 } 49.31 49.32 // create the display device 49.33 - if(!(vr_data.ovr_hmd_dev = vr_data.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) { 49.34 + if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) { 49.35 fprintf(stderr, "no oculus rift devices found\n"); 49.36 return false; 49.37 } 49.38 49.39 HMDInfo info; 49.40 - if(vr_data.ovr_hmd_dev->GetDeviceInfo(&info)) { 49.41 + if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) { 49.42 printf("oculus device info:\n"); 49.43 printf(" name: %s\n", info.DisplayDeviceName); 49.44 printf(" ipd: %f\n", info.InterpupillaryDistance); 49.45 @@ -46,16 +44,102 @@ 49.46 } 49.47 49.48 // get the sensor device 49.49 - if(!(vr_data.ovr_sensor_dev = vr_data.ovr_hmd_dev->GetSensor())) { 49.50 + if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) { 49.51 fprintf(stderr, "failed to get oculus sensor device\n"); 49.52 return false; 49.53 } 49.54 49.55 SensorInfo sinfo; 49.56 - if(vr_data.ovr_sensor_dev->GetDeviceInfo(&sinfo)) { 49.57 + if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) { 49.58 printf("oculus sensor device info:\n"); 49.59 printf(" name: %s\n", sinfo.ProductName); 49.60 } 49.61 49.62 + vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev); 49.63 + 49.64 + // calculate and store viewing parameters 49.65 + float vhalfsz = info.VScreenSize * 0.5; 49.66 + vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance); 49.67 + 49.68 + vr_ctx.info.width = info.HResolution; 49.69 + vr_ctx.info.height = info.VResolution; 49.70 + vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height; 49.71 + 49.72 + vr_ctx.info.ipd = info.InterpupillaryDistance; 49.73 + for(int i=0; i<4; i++) { 49.74 + vr_ctx.info.distort[i] = info.DistortionK[i]; 49.75 + } 49.76 + 49.77 return true; 49.78 } 49.79 + 49.80 +extern "C" int vr_get_width(void) 49.81 +{ 49.82 + return vr_ctx.info.width; 49.83 +} 49.84 + 49.85 +extern "C" int vr_get_height(void) 49.86 +{ 49.87 + return vr_ctx.info.height; 49.88 +} 49.89 + 49.90 +extern "C" float vr_get_fov(void) 49.91 +{ 49.92 + return vr_ctx.info.fov; 49.93 +} 49.94 + 49.95 +extern "C" float vr_get_aspect(void) 49.96 +{ 49.97 + return vr_ctx.info.aspect; 49.98 +} 49.99 + 49.100 +extern "C" void vr_set_eyedist(float ipd) 49.101 +{ 49.102 + vr_ctx.info.ipd = ipd; 49.103 +} 49.104 + 49.105 +extern "C" float vr_get_eyedist(void) 49.106 +{ 49.107 + return vr_ctx.info.ipd; 49.108 +} 49.109 + 49.110 +extern "C" void vr_set_distort(const float *coef) 49.111 +{ 49.112 + memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort); 49.113 +} 49.114 + 49.115 +extern "C" void vr_get_distort(float *coef) 49.116 +{ 49.117 + memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort); 49.118 +} 49.119 + 49.120 +extern "C" void vr_set_prediction_sec(float dt) 49.121 +{ 49.122 + vr_ctx.ovr_sfusion.SetPrediction(dt); 49.123 +} 49.124 + 49.125 +extern "C" float vr_get_prediction_sec(void) 49.126 +{ 49.127 + return vr_ctx.ovr_sfusion.GetPredictionDelta(); 49.128 +} 49.129 + 49.130 +extern "C" void vr_get_translation(float *offs) 49.131 +{ 49.132 + // current oculus devkit doesn't do translation 49.133 + offs[0] = offs[1] = offs[2] = 0.0f; 49.134 +} 49.135 + 49.136 +extern "C" void vr_get_rotation(float *quat) 49.137 +{ 49.138 + Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation(); 49.139 + quat[0] = oq.x; 49.140 + quat[1] = oq.y; 49.141 + quat[2] = oq.z; 49.142 + quat[3] = oq.w; 49.143 +} 49.144 + 49.145 +extern "C" void vr_get_rotation_euler(float *euler) 49.146 +{ 49.147 + Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation(); 49.148 + oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2); 49.149 +}
50.1 --- a/src/vr.h Sat Sep 14 17:51:03 2013 +0300 50.2 +++ b/src/vr.h Sun Sep 15 04:10:05 2013 +0300 50.3 @@ -22,10 +22,7 @@ 50.4 int vr_init(enum vr_init_mode mode); 50.5 void vr_shutdown(void); 50.6 50.7 -void vr_set_fov(float fov); 50.8 float vr_get_fov(void); 50.9 - 50.10 -void vr_set_aspect(float aspect); 50.11 float vr_get_aspect(void); 50.12 50.13 void vr_set_eyedist(float ipd); 50.14 @@ -37,6 +34,9 @@ 50.15 void vr_set_distort(const float *coef); 50.16 void vr_get_distort(float *coef); 50.17 50.18 +void vr_set_prediction_sec(float dt); 50.19 +float vr_get_prediction_sec(void); 50.20 + 50.21 void vr_get_view_matrix(float *res, int eye); 50.22 void vr_get_proj_matrix(float *res, int eye); 50.23
51.1 --- a/src/vr_impl.h Sat Sep 14 17:51:03 2013 +0300 51.2 +++ b/src/vr_impl.h Sun Sep 15 04:10:05 2013 +0300 51.3 @@ -5,17 +5,23 @@ 51.4 51.5 using namespace OVR; 51.6 51.7 -struct VRData { 51.8 +struct VRContext { 51.9 DeviceManager *ovr_devman; 51.10 HMDDevice *ovr_hmd_dev; 51.11 SensorDevice *ovr_sensor_dev; 51.12 + SensorFusion ovr_sfusion; 51.13 51.14 - float fov; 51.15 - float aspect; 51.16 - float ipd; 51.17 - float distort[4]; 51.18 + struct { 51.19 + // the full width and height of the display (both eyes) 51.20 + int width, height; 51.21 + float fov; 51.22 + // the full aspect ratio of the display (both eyes) 51.23 + float aspect; 51.24 + float ipd; 51.25 + float distort[4]; 51.26 + } info; 51.27 }; 51.28 51.29 -extern VRData vr_data; 51.30 +extern VRContext vr_ctx; 51.31 51.32 #endif // VR_IMPL_H_