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(