oculus1

changeset 3:b069a5c27388

added a couple more stuff, fixed all the LibOVR line endings
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Sep 2013 04:10:05 +0300
parents 59fc487ba58e
children bb81990dc7c8
files libovr/Src/Kernel/OVR_Alg.cpp libovr/Src/Kernel/OVR_Alg.h libovr/Src/Kernel/OVR_Allocator.cpp libovr/Src/Kernel/OVR_Allocator.h libovr/Src/Kernel/OVR_Array.h libovr/Src/Kernel/OVR_Atomic.cpp libovr/Src/Kernel/OVR_Atomic.h libovr/Src/Kernel/OVR_Color.h libovr/Src/Kernel/OVR_ContainerAllocator.h libovr/Src/Kernel/OVR_File.cpp libovr/Src/Kernel/OVR_File.h libovr/Src/Kernel/OVR_FileFILE.cpp libovr/Src/Kernel/OVR_Hash.h libovr/Src/Kernel/OVR_KeyCodes.h libovr/Src/Kernel/OVR_List.h libovr/Src/Kernel/OVR_Log.cpp libovr/Src/Kernel/OVR_Log.h libovr/Src/Kernel/OVR_Math.cpp libovr/Src/Kernel/OVR_Math.h libovr/Src/Kernel/OVR_RefCount.cpp libovr/Src/Kernel/OVR_RefCount.h libovr/Src/Kernel/OVR_Std.cpp libovr/Src/Kernel/OVR_Std.h libovr/Src/Kernel/OVR_String.cpp libovr/Src/Kernel/OVR_String.h libovr/Src/Kernel/OVR_StringHash.h libovr/Src/Kernel/OVR_String_FormatUtil.cpp libovr/Src/Kernel/OVR_String_PathUtil.cpp libovr/Src/Kernel/OVR_SysFile.cpp libovr/Src/Kernel/OVR_SysFile.h libovr/Src/Kernel/OVR_System.cpp libovr/Src/Kernel/OVR_System.h libovr/Src/Kernel/OVR_Threads.h libovr/Src/Kernel/OVR_Timer.cpp libovr/Src/Kernel/OVR_Timer.h libovr/Src/Kernel/OVR_Types.h libovr/Src/Kernel/OVR_UTF8Util.cpp libovr/Src/Kernel/OVR_UTF8Util.h libovr/Src/Util/Util_LatencyTest.cpp libovr/Src/Util/Util_LatencyTest.h libovr/Src/Util/Util_MagCalibration.cpp libovr/Src/Util/Util_MagCalibration.h libovr/Src/Util/Util_Render_Stereo.cpp libovr/Src/Util/Util_Render_Stereo.h libovr/Src/linux/OVR_ThreadsPthread.cpp libovr/Src/osx/OVR_ThreadsPthread.cpp libovr/Src/win32/OVR_ThreadsWinAPI.cpp src/main.cc src/vr.cc src/vr.h src/vr_impl.h
diffstat 51 files changed, 19047 insertions(+), 67 deletions(-) [+]
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(