- Main Page
- Classes
- Files
- Directories

- File List
- File Members

# fbxdynamicarray.h

Go to the documentation of this file.

    00001 /****************************************************************************************
    00002
    00003    Copyright (C) 2013 Autodesk, Inc.
    00004    All rights reserved.
    00005
    00006    Use of this software is subject to the terms of the Autodesk license agreement
    00007    provided at the time of installation or download, or which otherwise accompanies
    00008    this software in either electronic or hard copy form.
    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             // We don't use mAllocator.PreAllocate, because we want our array
    00103             // to be continuous in memory.
    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             // grow by 50%
    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; // in case pValue is in array
    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             // not enough room
    00163             // grow by 50%
    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); // copy prefix
    00175             Fill(lNewArray + pIndex, pValue, pNCopies); // copy values
    00176             MoveArray(lNewArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex); // copy suffix
    00177
    00178             mAllocator.FreeMemory(mArray);
    00179             mArray = lNewArray;
    00180             mValueCount += pNCopies;
    00181             mArrayCapacity = lNewSize;
    00182         }
    00183         else
    00184         {
    00185             // copy suffix backwards
    00186             MoveArrayBackwards(mArray + pIndex + pNCopies, mArray + pIndex, mValueCount - pIndex);
    00187             Fill(mArray + pIndex, pValue, pNCopies); // copy values
    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 ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
    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]);    //in-place new won't allocate memory, so it is safe
    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]);    //in-place new won't allocate memory, so it is safe
    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]);    //in-place new won't allocate memory, so it is safe
    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]);  //in-place new won't allocate memory, so it is safe
    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); //in-place new won't allocate memory, so it is safe
    00313         }
    00314     }
    00315
    00316     ValueType*      mArray;
    00317     size_t          mArrayCapacity;
    00318     size_t          mValueCount;
    00319     AllocatorType   mAllocator;
    00320 #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
    00321 };
    00322
    00323 #include <fbxsdk/fbxsdk_nsend.h>
    00324
    00325 #endif /* _FBXSDK_CORE_BASE_DYNAMICARRAY_H_ */