00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00013 #ifndef _FBXSDK_CORE_BASE_DYNAMICARRAY_H_
00014 #define _FBXSDK_CORE_BASE_DYNAMICARRAY_H_
00015
00016 #include <fbxsdk/fbxsdk_def.h>
00017
00018 #include <fbxsdk/core/base/fbxcontainerallocators.h>
00019
00020 #include <fbxsdk/fbxsdk_nsbegin.h>
00021
00026 template <typename VALUE_TYPE, typename ALLOCATOR = FbxBaseAllocator> class FbxDynamicArray
00027 {
00028 public:
00030 typedef VALUE_TYPE ValueType;
00032 typedef ALLOCATOR AllocatorType;
00033
00035 FbxDynamicArray()
00036 : mArray(NULL)
00037 , mArrayCapacity(0)
00038 , mValueCount(0)
00039 , mAllocator(sizeof(ValueType))
00040 {
00041 }
00042
00046 FbxDynamicArray(const size_t pInitialSize)
00047 : mArray(NULL)
00048 , mArrayCapacity(0)
00049 , mValueCount(0)
00050 , mAllocator(sizeof(ValueType))
00051 {
00052 Reserve(pInitialSize);
00053 }
00054
00060 FbxDynamicArray(const FbxDynamicArray& pArray)
00061 : mArray(NULL)
00062 , mArrayCapacity(0)
00063 , mValueCount(0)
00064 , mAllocator(sizeof(ValueType))
00065 {
00066 Reserve(pArray.mArrayCapacity);
00067 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00068 mValueCount = pArray.mValueCount;
00069 }
00070
00072 ~FbxDynamicArray()
00073 {
00074 for (size_t i = 0; i < mValueCount; i++)
00075 {
00076 mArray[i].~VALUE_TYPE();
00077 }
00078
00079 mAllocator.FreeMemory(mArray);
00080 }
00081
00083 size_t GetCapacity() const
00084 {
00085 return mArrayCapacity;
00086 }
00087
00089 size_t GetSize() const
00090 {
00091 return mValueCount;
00092 }
00093
00098 void Reserve(const size_t pCount)
00099 {
00100 if (pCount > mArrayCapacity)
00101 {
00102
00103
00104 void* lBuffer = mAllocator.AllocateRecords(pCount);
00105 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00106
00107 MoveArray(lNewArray, mArray, mValueCount);
00108
00109 mAllocator.FreeMemory(mArray);
00110 mArray = lNewArray;
00111 mArrayCapacity = pCount;
00112 }
00113 }
00114
00119 void PushBack(const ValueType& pValue, const size_t pNCopies = 1)
00120 {
00121 if (mValueCount + pNCopies > mArrayCapacity)
00122 {
00123
00124 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00125
00126 if (mValueCount + pNCopies > lNewSize)
00127 {
00128 lNewSize = mValueCount + pNCopies;
00129 }
00130
00131 Reserve(lNewSize);
00132 }
00133
00134 FBX_ASSERT(mValueCount + pNCopies <= mArrayCapacity);
00135
00136 Fill(mArray + mValueCount, pValue, pNCopies);
00137
00138 mValueCount += pNCopies;
00139 }
00140
00146 void Insert(const size_t pIndex, const ValueType& pValue, const size_t pNCopies = 1)
00147 {
00148 FBX_ASSERT(pIndex >= 0);
00149 FBX_ASSERT(pIndex <= mValueCount);
00150
00151 ValueType lValue = pValue;
00152
00153 if (pNCopies == 0)
00154 {
00155 }
00156 else if (pIndex >= mValueCount)
00157 {
00158 PushBack(pValue, pNCopies);
00159 }
00160 else if (mValueCount + pNCopies > mArrayCapacity)
00161 {
00162
00163
00164 size_t lNewSize = mArrayCapacity + mArrayCapacity / 2;
00165
00166 if (mValueCount + pNCopies > lNewSize)
00167 {
00168 lNewSize = mValueCount + pNCopies;
00169 }
00170
00171 void* lBuffer = mAllocator.AllocateRecords(lNewSize);
00172 ValueType* lNewArray = reinterpret_cast<ValueType*>(lBuffer);
00173
00174 MoveArray(lNewArray, mArray, pIndex);
00175 Fill(lNewArray + pIndex, pValue, pNCopies);
00176 MoveArray(lNewArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00177
00178 mAllocator.FreeMemory(mArray);
00179 mArray = lNewArray;
00180 mValueCount += pNCopies;
00181 mArrayCapacity = lNewSize;
00182 }
00183 else
00184 {
00185
00186 MoveArrayBackwards(mArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
00187 Fill(mArray + pIndex, pValue, pNCopies);
00188 mValueCount += pNCopies;
00189 }
00190 }
00191
00195 void PopBack(size_t pNElements = 1)
00196 {
00197 FBX_ASSERT(pNElements <= mValueCount);
00198
00199 for (size_t i = mValueCount - pNElements; i < mValueCount; i++)
00200 {
00201 mArray[i].~VALUE_TYPE();
00202 }
00203
00204 mValueCount -= pNElements;
00205 }
00206
00211 void Remove(const size_t pIndex, size_t pNElements = 1)
00212 {
00213 FBX_ASSERT(pIndex >= 0);
00214 FBX_ASSERT(pIndex <= mValueCount);
00215 FBX_ASSERT(pIndex + pNElements <= mValueCount);
00216
00217 if (pIndex + pNElements >= mValueCount)
00218 {
00219 PopBack(pNElements);
00220 }
00221 else
00222 {
00223 for (size_t i = pIndex; i < pIndex + pNElements; i++)
00224 {
00225 mArray[i].~VALUE_TYPE();
00226 }
00227
00228 MoveOverlappingArray(mArray + pIndex, mArray + pIndex + pNElements, mValueCount - pNElements);
00229
00230 mValueCount -= pNElements;
00231 }
00232 }
00233
00237 ValueType& operator[](const size_t pIndex)
00238 {
00239 return *(mArray + pIndex);
00240 }
00241
00245 ValueType const& operator[](const size_t pIndex) const
00246 {
00247 return *(mArray + pIndex);
00248 }
00249
00255 FbxDynamicArray& operator=(const FbxDynamicArray& pArray)
00256 {
00257 Reserve(pArray.mArrayCapacity);
00258 CopyArray(mArray, pArray.mArray, pArray.mValueCount);
00259 mValueCount = pArray.mValueCount;
00260
00261 return *this;
00262 }
00263
00264
00265
00266
00267 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00268 private:
00269 static void CopyArray(ValueType* pDest, const ValueType* pSrc, size_t pCount)
00270 {
00271 for( int i = 0; i < int(pCount); i++ )
00272 {
00273 new(&(pDest[i])) ValueType(pSrc[i]);
00274 }
00275 }
00276
00277 static void MoveArray(ValueType* pDest, const ValueType* pSrc, size_t pCount)
00278 {
00279 for( int i = 0; i < int(pCount); i++ )
00280 {
00281 new(&(pDest[i])) ValueType(pSrc[i]);
00282 }
00283
00284 for( int i = 0; i < int(pCount); i++ )
00285 {
00286 pSrc[i].~VALUE_TYPE();
00287 }
00288 }
00289
00290 static void MoveOverlappingArray(ValueType* pDest, const ValueType* pSrc, size_t pCount)
00291 {
00292 for( int i = 0; i < int(pCount); i++ )
00293 {
00294 new(&(pDest[i])) ValueType(pSrc[i]);
00295 pSrc[i].~VALUE_TYPE();
00296 }
00297 }
00298
00299 static void MoveArrayBackwards(ValueType* pDest, const ValueType* pSrc, size_t pCount)
00300 {
00301 for( int i = 0; i < int(pCount); ++i )
00302 {
00303 new(&(pDest[pCount-1-i])) ValueType(pSrc[pCount-1-i]);
00304 pSrc[pCount-1-i].~VALUE_TYPE();
00305 }
00306 }
00307
00308 static void Fill(ValueType* pDest, const ValueType& pValue, size_t pCount)
00309 {
00310 for( int i = 0; i < int(pCount); i++ )
00311 {
00312 new(&(pDest[i])) ValueType(pValue);
00313 }
00314 }
00315
00316 ValueType* mArray;
00317 size_t mArrayCapacity;
00318 size_t mValueCount;
00319 AllocatorType mAllocator;
00320 #endif
00321 };
00322
00323 #include <fbxsdk/fbxsdk_nsend.h>
00324
00325 #endif