00001 #ifndef _FBXSDK_KDYNAMICARRAY_H_
00002 #define _FBXSDK_KDYNAMICARRAY_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <kbaselib_h.h>
00040
00041 #include <klib/kcontainerallocators.h>
00042 #include <klib/kdebug.h>
00043
00044 #include <new>
00045
00046 #include <kbaselib_nsbegin.h>
00047
00048 template <typename VALUE_TYPE, typename ALLOCATOR = KBaseAllocator>
00049 class KDynamicArray
00050 {
00051 public:
00052 typedef VALUE_TYPE ValueType;
00053 typedef ALLOCATOR AllocatorType;
00054
00055 KDynamicArray()
00056 : mArray(NULL)
00057 , mArrayCapacity(0)
00058 , mValueCount(0)
00059 , mAllocator(sizeof(ValueType))
00060 {
00061 }
00062
00063 KDynamicArray(size_t const pInitialSize)
00064 : mArray(NULL)
00065 , mArrayCapacity(0)
00066 , mValueCount(0)
00067 , mAllocator(sizeof(ValueType))
00068 {
00069 Reserve(pInitialSize);
00070 }
00071
00072 KDynamicArray(KDynamicArray const& pArray)
00073 : mArray(NULL)
00074 , mArrayCapacity(0)
00075 , mValueCount(0)
00076 , mAllocator(sizeof(ValueType))
00077 {
00078 Reserve(pArray.mArrayCapacity);
00079 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00080 mValueCount = pArray.mValueCount;
00081 }
00082
00083 ~KDynamicArray()
00084 {
00085 size_t i;
00086 for (i = 0; i < mValueCount; i++)
00087 {
00088 mArray[i].~VALUE_TYPE();
00089 }
00090
00091 mAllocator.FreeMemory(mArray);
00092 }
00093
00094 size_t GetCapacity() const
00095 {
00096 return mArrayCapacity;
00097 }
00098
00099 size_t GetSize() const
00100 {
00101 return mValueCount;
00102 }
00103
00104 void Reserve(size_t const pCount)
00105 {
00106 if (pCount > mArrayCapacity)
00107 {
00108
00109
00110 void* lBuffer = mAllocator.AllocateRecords(pCount);
00111 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00112
00113 MoveArray(lNewArray, mArray, mValueCount);
00114
00115 mAllocator.FreeMemory(mArray);
00116 mArray = lNewArray;
00117 mArrayCapacity = pCount;
00118 }
00119 }
00120
00121 void PushBack(ValueType const& pValue, size_t const pNCopies = 1)
00122 {
00123 if (mValueCount + pNCopies > mArrayCapacity)
00124 {
00125
00126 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00127
00128 if (mValueCount + pNCopies > lNewSize)
00129 {
00130 lNewSize = mValueCount + pNCopies;
00131 }
00132
00133 Reserve(lNewSize);
00134 }
00135
00136 K_ASSERT(mValueCount + pNCopies <= mArrayCapacity);
00137
00138 Fill(mArray + mValueCount, pValue, pNCopies);
00139
00140 mValueCount += pNCopies;
00141 }
00142
00143 void Insert(size_t const pIndex, ValueType const& pValue, size_t const pNCopies = 1)
00144 {
00145 K_ASSERT(pIndex >= 0);
00146 K_ASSERT(pIndex <= mValueCount);
00147
00148 ValueType lValue = pValue;
00149
00150 if (pNCopies == 0)
00151 {
00152 }
00153 else if (pIndex >= mValueCount)
00154 {
00155 PushBack(pValue, pNCopies);
00156 }
00157 else if (mValueCount + pNCopies > mArrayCapacity)
00158 {
00159
00160
00161 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00162
00163 if (mValueCount + pNCopies > lNewSize)
00164 {
00165 lNewSize = mValueCount + pNCopies;
00166 }
00167
00168 void* lBuffer = mAllocator.AllocateRecords(lNewSize);
00169 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00170
00171 MoveArray(lNewArray, mArray, pIndex);
00172 Fill(lNewArray + pIndex, pValue, pNCopies);
00173 MoveArray(lNewArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00174
00175 mAllocator.FreeMemory(mArray);
00176 mArray = lNewArray;
00177 mValueCount += pNCopies;
00178 mArrayCapacity = lNewSize;
00179 }
00180 else
00181 {
00182
00183 MoveArrayBackwards(mArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00184 Fill(mArray + pIndex, pValue, pNCopies);
00185 mValueCount += pNCopies;
00186 }
00187 }
00188
00189 void PopBack(size_t pNElements = 1)
00190 {
00191 K_ASSERT(pNElements <= mValueCount);
00192
00193 size_t i;
00194 for (i = mValueCount - pNElements; i < mValueCount; i++)
00195 {
00196 mArray[i].~VALUE_TYPE();
00197 }
00198
00199 mValueCount -= pNElements;
00200 }
00201
00202 void Remove(size_t const pIndex, size_t pNElements = 1)
00203 {
00204 K_ASSERT(pIndex >= 0);
00205 K_ASSERT(pIndex <= mValueCount);
00206 K_ASSERT(pIndex + pNElements <= mValueCount);
00207
00208 if (pIndex + pNElements >= mValueCount)
00209 {
00210 PopBack(pNElements);
00211 }
00212 else
00213 {
00214 size_t i;
00215 for (i = pIndex; i < pIndex + pNElements; i++)
00216 {
00217 mArray[i].~VALUE_TYPE();
00218 }
00219
00220 MoveOverlappingArray(mArray + pIndex, mArray + pIndex + pNElements, mValueCount - pNElements);
00221
00222 mValueCount -= pNElements;
00223 }
00224 }
00225
00226 ValueType& operator[](size_t const pIndex)
00227 {
00228 return *(mArray + pIndex);
00229 }
00230
00231 ValueType const& operator[](size_t const pIndex) const
00232 {
00233 return *(mArray + pIndex);
00234 }
00235
00236 KDynamicArray& operator=(KDynamicArray const& pArray)
00237 {
00238 Reserve(pArray.mArrayCapacity);
00239 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00240 mValueCount = pArray.mValueCount;
00241
00242 return *this;
00243 }
00244
00245 private:
00246 static void CopyArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00247 {
00248 int i;
00249 for (i = 0; i < pCount; i++)
00250 {
00251 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00252 #pragma push_macro("new")
00253 #undef new
00254 #endif
00255 new(&(pDest[i])) ValueType(pSrc[i]);
00256 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00257 #pragma pop_macro("new")
00258 #endif
00259 }
00260 }
00261
00262 static void MoveArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00263 {
00264 int i;
00265 for (i = 0; i < pCount; i++)
00266 {
00267 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00268 #pragma push_macro("new")
00269 #undef new
00270 #endif
00271 new(&(pDest[i])) ValueType(pSrc[i]);
00272 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00273 #pragma pop_macro("new")
00274 #endif
00275 }
00276
00277 for (i = 0; i < pCount; i++)
00278 {
00279 pSrc[i].~VALUE_TYPE();
00280 }
00281 }
00282
00283 static void MoveOverlappingArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00284 {
00285 int i;
00286 for (i = 0; i < pCount; i++)
00287 {
00288 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00289 #pragma push_macro("new")
00290 #undef new
00291 #endif
00292 new(&(pDest[i])) ValueType(pSrc[i]);
00293 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00294 #pragma pop_macro("new")
00295 #endif
00296
00297 pSrc[i].~VALUE_TYPE();
00298 }
00299 }
00300
00301 static void MoveArrayBackwards(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00302 {
00303 size_t i;
00304 for (i = pCount - 1; i >= 0; i--)
00305 {
00306 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00307 #pragma push_macro("new")
00308 #undef new
00309 #endif
00310 new(&(pDest[i])) ValueType(pSrc[i]);
00311 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00312 #pragma pop_macro("new")
00313 #endif
00314
00315 pSrc[i].~VALUE_TYPE();
00316 }
00317 }
00318
00319 static void Fill(ValueType* pDest, ValueType const& pValue, size_t pCount)
00320 {
00321 size_t i;
00322 for (i = 0; i < pCount; i++)
00323 {
00324 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00325 #pragma push_macro("new")
00326 #undef new
00327 #endif
00328 new(&(pDest[i])) ValueType(pValue);
00329 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00330 #pragma pop_macro("new")
00331 #endif
00332 }
00333 }
00334
00335
00336 ValueType* mArray;
00337 size_t mArrayCapacity;
00338 size_t mValueCount;
00339
00340 AllocatorType mAllocator;
00341 };
00342
00343 #include <kbaselib_nsend.h>
00344
00345 #endif