00001
00004 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KDYNAMICARRAY_H
00005 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KDYNAMICARRAY_H
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
00040
00041 #include <fbxfilesdk/fbxfilesdk_def.h>
00042
00043 #include <fbxfilesdk/components/kbaselib/klib/kcontainerallocators.h>
00044 #include <fbxfilesdk/components/kbaselib/klib/kdebug.h>
00045
00046 #include <new>
00047
00048 #include <fbxfilesdk/fbxfilesdk_nsbegin.h>
00049
00054 template <typename VALUE_TYPE, typename ALLOCATOR = KBaseAllocator>
00055 class KDynamicArray
00056 {
00057 public:
00059 typedef VALUE_TYPE ValueType;
00061 typedef ALLOCATOR AllocatorType;
00062
00064 KDynamicArray()
00065 : mArray(NULL)
00066 , mArrayCapacity(0)
00067 , mValueCount(0)
00068 , mAllocator(sizeof(ValueType))
00069 {
00070 }
00071
00075 KDynamicArray(size_t const pInitialSize)
00076 : mArray(NULL)
00077 , mArrayCapacity(0)
00078 , mValueCount(0)
00079 , mAllocator(sizeof(ValueType))
00080 {
00081 Reserve(pInitialSize);
00082 }
00083
00089 KDynamicArray(KDynamicArray const& pArray)
00090 : mArray(NULL)
00091 , mArrayCapacity(0)
00092 , mValueCount(0)
00093 , mAllocator(sizeof(ValueType))
00094 {
00095 Reserve(pArray.mArrayCapacity);
00096 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00097 mValueCount = pArray.mValueCount;
00098 }
00099
00101 ~KDynamicArray()
00102 {
00103 size_t i;
00104 for (i = 0; i < mValueCount; i++)
00105 {
00106 mArray[i].~VALUE_TYPE();
00107 }
00108
00109 mAllocator.FreeMemory(mArray);
00110 }
00111
00113 size_t GetCapacity() const
00114 {
00115 return mArrayCapacity;
00116 }
00117
00119 size_t GetSize() const
00120 {
00121 return mValueCount;
00122 }
00123
00128 void Reserve(size_t const pCount)
00129 {
00130 if (pCount > mArrayCapacity)
00131 {
00132
00133
00134 void* lBuffer = mAllocator.AllocateRecords(pCount);
00135 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00136
00137 MoveArray(lNewArray, mArray, mValueCount);
00138
00139 mAllocator.FreeMemory(mArray);
00140 mArray = lNewArray;
00141 mArrayCapacity = pCount;
00142 }
00143 }
00144
00149 void PushBack(ValueType const& pValue, size_t const pNCopies = 1)
00150 {
00151 if (mValueCount + pNCopies > mArrayCapacity)
00152 {
00153
00154 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00155
00156 if (mValueCount + pNCopies > lNewSize)
00157 {
00158 lNewSize = mValueCount + pNCopies;
00159 }
00160
00161 Reserve(lNewSize);
00162 }
00163
00164 K_ASSERT(mValueCount + pNCopies <= mArrayCapacity);
00165
00166 Fill(mArray + mValueCount, pValue, pNCopies);
00167
00168 mValueCount += pNCopies;
00169 }
00170
00176 void Insert(size_t const pIndex, ValueType const& pValue, size_t const pNCopies = 1)
00177 {
00178 K_ASSERT(pIndex >= 0);
00179 K_ASSERT(pIndex <= mValueCount);
00180
00181 ValueType lValue = pValue;
00182
00183 if (pNCopies == 0)
00184 {
00185 }
00186 else if (pIndex >= mValueCount)
00187 {
00188 PushBack(pValue, pNCopies);
00189 }
00190 else if (mValueCount + pNCopies > mArrayCapacity)
00191 {
00192
00193
00194 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00195
00196 if (mValueCount + pNCopies > lNewSize)
00197 {
00198 lNewSize = mValueCount + pNCopies;
00199 }
00200
00201 void* lBuffer = mAllocator.AllocateRecords(lNewSize);
00202 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00203
00204 MoveArray(lNewArray, mArray, pIndex);
00205 Fill(lNewArray + pIndex, pValue, pNCopies);
00206 MoveArray(lNewArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00207
00208 mAllocator.FreeMemory(mArray);
00209 mArray = lNewArray;
00210 mValueCount += pNCopies;
00211 mArrayCapacity = lNewSize;
00212 }
00213 else
00214 {
00215
00216 MoveArrayBackwards(mArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00217 Fill(mArray + pIndex, pValue, pNCopies);
00218 mValueCount += pNCopies;
00219 }
00220 }
00221
00225 void PopBack(size_t pNElements = 1)
00226 {
00227 K_ASSERT(pNElements <= mValueCount);
00228
00229 size_t i;
00230 for (i = mValueCount - pNElements; i < mValueCount; i++)
00231 {
00232 mArray[i].~VALUE_TYPE();
00233 }
00234
00235 mValueCount -= pNElements;
00236 }
00237
00242 void Remove(size_t const pIndex, size_t pNElements = 1)
00243 {
00244 K_ASSERT(pIndex >= 0);
00245 K_ASSERT(pIndex <= mValueCount);
00246 K_ASSERT(pIndex + pNElements <= mValueCount);
00247
00248 if (pIndex + pNElements >= mValueCount)
00249 {
00250 PopBack(pNElements);
00251 }
00252 else
00253 {
00254 size_t i;
00255 for (i = pIndex; i < pIndex + pNElements; i++)
00256 {
00257 mArray[i].~VALUE_TYPE();
00258 }
00259
00260 MoveOverlappingArray(mArray + pIndex, mArray + pIndex + pNElements, mValueCount - pNElements);
00261
00262 mValueCount -= pNElements;
00263 }
00264 }
00265
00269 ValueType& operator[](size_t const pIndex)
00270 {
00271 return *(mArray + pIndex);
00272 }
00273
00277 ValueType const& operator[](size_t const pIndex) const
00278 {
00279 return *(mArray + pIndex);
00280 }
00281
00287 KDynamicArray& operator=(KDynamicArray const& pArray)
00288 {
00289 Reserve(pArray.mArrayCapacity);
00290 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00291 mValueCount = pArray.mValueCount;
00292
00293 return *this;
00294 }
00295
00297
00298
00299
00300
00301
00302
00304
00305 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00306
00307 private:
00308 static void CopyArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00309 {
00310 for( int i = 0; i < int(pCount); i++ )
00311 {
00312 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00313 #pragma push_macro("new")
00314 #undef new
00315 #endif
00316
00317 new(&(pDest[i])) ValueType(pSrc[i]);
00318
00319 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00320 #pragma pop_macro("new")
00321 #endif
00322 }
00323 }
00324
00325 static void MoveArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00326 {
00327 for( int i = 0; i < int(pCount); i++ )
00328 {
00329 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00330 #pragma push_macro("new")
00331 #undef new
00332 #endif
00333
00334 new(&(pDest[i])) ValueType(pSrc[i]);
00335
00336 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00337 #pragma pop_macro("new")
00338 #endif
00339 }
00340
00341 for( int i = 0; i < int(pCount); i++ )
00342 {
00343 pSrc[i].~VALUE_TYPE();
00344 }
00345 }
00346
00347 static void MoveOverlappingArray(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00348 {
00349 for( int i = 0; i < int(pCount); i++ )
00350 {
00351 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00352 #pragma push_macro("new")
00353 #undef new
00354 #endif
00355
00356 new(&(pDest[i])) ValueType(pSrc[i]);
00357
00358 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00359 #pragma pop_macro("new")
00360 #endif
00361
00362 pSrc[i].~VALUE_TYPE();
00363 }
00364 }
00365
00366 static void MoveArrayBackwards(ValueType* pDest, ValueType const* pSrc, size_t pCount)
00367 {
00368 for( int i = 0; i < int(pCount); ++i )
00369 {
00370 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00371 #pragma push_macro("new")
00372 #undef new
00373 #endif
00374
00375 new(&(pDest[pCount-1-i])) ValueType(pSrc[pCount-1-i]);
00376
00377 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00378 #pragma pop_macro("new")
00379 #endif
00380
00381 pSrc[pCount-1-i].~VALUE_TYPE();
00382 }
00383 }
00384
00385 static void Fill(ValueType* pDest, ValueType const& pValue, size_t pCount)
00386 {
00387 for( int i = 0; i < int(pCount); i++ )
00388 {
00389 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32) )
00390 #pragma push_macro("new")
00391 #undef new
00392 #endif
00393
00394 new(&(pDest[i])) ValueType(pValue);
00395
00396 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00397 #pragma pop_macro("new")
00398 #endif
00399 }
00400 }
00401
00402
00403 ValueType* mArray;
00404 size_t mArrayCapacity;
00405 size_t mValueCount;
00406
00407 AllocatorType mAllocator;
00408
00409 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
00410
00411 };
00412
00413 #include <fbxfilesdk/fbxfilesdk_nsend.h>
00414
00415 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KDYNAMICARRAY_H
00416