fbxarray.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_ARRAY_H_
00014 #define _FBXSDK_CORE_BASE_ARRAY_H_
00015 
00016 #include <fbxsdk/fbxsdk_def.h>
00017 
00018 #include <fbxsdk/fbxsdk_nsbegin.h>
00019 
00023 template <class T> class FbxArray
00024 {
00025 public:
00027     FbxArray() : mSize(0), mCapacity(0), mArray(NULL){}
00028 
00030     FbxArray(const FbxArray& pArray) : mSize(0), mCapacity(0), mArray(NULL){ *this = pArray; }
00031 
00034     ~FbxArray(){ Clear(); }
00035 
00041     inline int InsertAt(const int pIndex, const T pElement)
00042     {
00043         FBX_ASSERT_RETURN_VALUE(pIndex >= 0, -1);
00044         int lIndex = FbxMin(pIndex, mSize);
00045         if( mSize >= mCapacity )
00046         {
00047             int lNewCapacity = FbxMax(mCapacity * 2, 1);    //Double capacity
00048             T* lArray = Allocate(lNewCapacity);
00049             FBX_ASSERT_RETURN_VALUE(lArray, -1);
00050             mArray = lArray;
00051             mCapacity = lNewCapacity;
00052         }
00053 
00054         if( lIndex < mSize )    //Move elements to leave a space open to insert the new element
00055         {
00056             memmove(&mArray[lIndex + 1], &mArray[lIndex], (mSize - lIndex) * sizeof(T));
00057         }
00058 
00059         memcpy(&mArray[lIndex], &pElement, sizeof(T));
00060         mSize++;
00061 
00062         return lIndex;
00063     }
00064 
00068     inline int Add(const T pElement)
00069     {
00070         return InsertAt(mSize, pElement);
00071     }
00072 
00076     inline int AddUnique(const T pElement)
00077     {
00078         int lIndex = Find(pElement);
00079         return ( lIndex == -1 ) ? Add(pElement) : lIndex;
00080     }
00081 
00085     inline int Size() const { return mSize; }
00086 
00090     inline int Capacity() const { return mCapacity; }
00091 
00096     inline T& operator[](int pIndex) const
00097     {
00098     #ifdef _DEBUG
00099         FBX_ASSERT_MSG(pIndex >= 0, "Index is out of range!");
00100         if( pIndex >= mSize )
00101         {
00102             if( pIndex < mCapacity )
00103             {
00104                 FBX_ASSERT_NOW("Index is out of range, but not outside of capacity! Call SetAt() to use reserved memory.");
00105             }
00106             else FBX_ASSERT_NOW("Index is out of range!");
00107         }
00108     #endif
00109         return (T&)mArray[pIndex];
00110     }
00111 
00116     inline T GetAt(const int pIndex) const
00117     {
00118         return operator[](pIndex);
00119     }
00120 
00124     inline T GetFirst() const
00125     {
00126         return GetAt(0);
00127     }
00128 
00132     inline T GetLast() const
00133     {
00134         return GetAt(mSize-1);
00135     }
00136 
00141     inline int Find(const T pElement, const int pStartIndex=0) const
00142     {
00143         FBX_ASSERT_RETURN_VALUE(pStartIndex >= 0, -1);
00144         for( int i = pStartIndex; i < mSize; ++i )
00145         {
00146             if( GetAt(i) == pElement ) return i;
00147         }
00148         return -1;
00149     }
00150 
00155     inline int FindReverse(const T pElement, const int pStartIndex=FBXSDK_INT_MAX) const
00156     {
00157         for( int i = FbxMin(pStartIndex, mSize-1); i >= 0; --i )
00158         {
00159             if( GetAt(i) == pElement ) return i;
00160         }
00161         return -1;
00162     }
00163 
00168     inline bool Reserve(const int pCapacity)
00169     {
00170         FBX_ASSERT_RETURN_VALUE(pCapacity > 0, false);
00171         if( pCapacity > mCapacity )
00172         {
00173             T* lArray = Allocate(pCapacity);
00174             FBX_ASSERT_RETURN_VALUE(lArray, false);
00175             mArray = lArray;
00176             mCapacity = pCapacity;
00177 
00178             //Initialize new memory to zero
00179             memset(&mArray[mSize], 0, (mCapacity - mSize) * sizeof(T));
00180         }
00181         return true;
00182     }
00183 
00189     inline void SetAt(const int pIndex, const T pElement)
00190     {
00191         if( pIndex >= mSize )
00192         {
00193             FBX_ASSERT_RETURN(pIndex < mCapacity);
00194             mSize = pIndex + 1;
00195         }
00196         memcpy(&mArray[pIndex], &pElement, sizeof(T));
00197     }
00198 
00202     inline void SetFirst(const T pElement)
00203     {
00204         SetAt(0, pElement);
00205     }
00206 
00210     inline void SetLast(const T pElement)
00211     {
00212         SetAt(mSize-1, pElement);
00213     }
00214 
00219     inline T RemoveAt(const int pIndex)
00220     {
00221         T lElement = GetAt(pIndex);
00222         if( pIndex + 1 < mSize )
00223         {
00224             memmove(&mArray[pIndex], &mArray[pIndex + 1], (mSize - pIndex - 1) * sizeof(T));
00225         }
00226         mSize--;
00227         return lElement;
00228     }
00229 
00233     inline T RemoveFirst()
00234     {
00235         return RemoveAt(0);
00236     }
00237 
00241     inline T RemoveLast()
00242     {
00243         return RemoveAt(mSize-1);
00244     }
00245 
00249     inline bool RemoveIt(const T pElement)
00250     {
00251         int Index = Find(pElement);
00252         if( Index >= 0 )
00253         {
00254             RemoveAt(Index);
00255             return true;
00256         }
00257         return false;
00258     }
00259 
00264     inline bool Resize(const int pSize)
00265     {
00266         if( pSize == 0 )
00267         {
00268             Clear();
00269             return true;
00270         }
00271 
00272         FBX_ASSERT_RETURN_VALUE(pSize > 0, false);
00273         if( pSize != mCapacity )
00274         {
00275             T* lArray = Allocate(pSize);
00276             FBX_ASSERT_RETURN_VALUE(lArray, false);
00277             mArray = lArray;
00278         }
00279 
00280         if( pSize > mCapacity ) //Initialize new memory to zero
00281         {
00282             memset(&mArray[mSize], 0, (pSize - mSize) * sizeof(T));
00283         }
00284 
00285         mSize = pSize;
00286         mCapacity = pSize;
00287 
00288         return true;
00289     }
00290 
00294     inline bool Grow(const int pSize)
00295     {
00296         return Resize(mSize + pSize);
00297     }
00298 
00301     inline void Clear()
00302     {
00303         if( mArray != NULL )
00304         {
00305             mSize = 0;
00306             mCapacity = 0;
00307             FbxFree(mArray);
00308             mArray = NULL;
00309         }
00310     }
00311 
00313     inline T* GetArray() const { return mArray ? (T*)mArray : NULL; }
00314 
00316     inline operator T* (){ return (T*)mArray; }
00317 
00320     inline void AddArray(const FbxArray<T>& pOther)
00321     {
00322         if( Grow(pOther.mSize) )
00323         {
00324             memcpy(&mArray[mSize - pOther.mSize], pOther.mArray, pOther.mSize * sizeof(T));
00325         }
00326     }
00327 
00330     inline void AddArrayNoDuplicate(const FbxArray<T>& pOther)
00331     {
00332         for( int i = 0, c = pOther.mSize; i < c; ++i )
00333         {
00334             AddUnique(pOther[i]);
00335         }
00336     }
00337 
00340     inline void RemoveArray(const FbxArray<T>& pOther)
00341     {
00342         for( int i = 0, c = pOther.mSize; i < c; ++i )
00343         {
00344             RemoveIt(pOther[i]);
00345         }
00346     }
00347 
00350     inline FbxArray<T>& operator=(const FbxArray<T>& pOther)
00351     {
00352         if( this != &pOther )
00353         {
00354             if( Resize(pOther.mSize) )
00355             {
00356                 memcpy(mArray, pOther.mArray, pOther.mSize * sizeof(T));
00357             }
00358         }
00359         return *this;
00360     }
00361 
00362 /*****************************************************************************************************************************
00363 ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
00364 *****************************************************************************************************************************/
00365 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00366     inline int GetCount() const { return mSize; }
00367     FBX_DEPRECATED inline void Empty(){ Clear(); }
00368     FBX_DEPRECATED inline int FindAfter(int pAfterIndex, T pItem) const { return Find(pItem, pAfterIndex+1); }
00369     FBX_DEPRECATED inline int FindBefore(int pBeforeIndex, T pItem) const { return FindReverse(pItem, pBeforeIndex-1); }
00370     FBX_DEPRECATED inline void AddMultiple(int pItemCount){ Grow(pItemCount); }
00371 
00372 private:
00373     inline T* Allocate(const int pCapacity)
00374     {
00375         return (T*)FbxRealloc(mArray, pCapacity * sizeof(T));
00376     }
00377 
00378     int     mSize;
00379     int     mCapacity;
00380     T*  mArray;
00381 
00382 #if defined(FBXSDK_COMPILER_MSC)
00383     //Previously class FbxArray is for pointers. Somehow, it's used to store other types. Here's a compile-time checking for known incompatible classes.
00384     //If it happens you find new incompatible ones, declare them with macro FBXSDK_INCOMPATIBLE_WITH_ARRAY. Also see file fbxstring.h.
00385     FBX_ASSERT_STATIC(FBXSDK_IS_SIMPLE_TYPE(T) || __is_enum(T) || (__has_trivial_constructor(T)&&__has_trivial_destructor(T)) || !FBXSDK_IS_INCOMPATIBLE_WITH_ARRAY(T));
00386 #endif
00387 
00388 #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
00389 };
00390 
00392 template <class T> inline void FbxArrayFree(FbxArray<T>& pArray)
00393 {
00394     for( int i = 0, c = pArray.Size(); i < c; ++i )
00395     {
00396         FbxFree(pArray[i]);
00397     }
00398     pArray.Clear();
00399 }
00400 
00402 template <class T> inline void FbxArrayDelete(FbxArray<T>& pArray)
00403 {
00404     for( int i = 0, c = pArray.Size(); i < c; ++i )
00405     {
00406         FbxDelete(pArray[i]);
00407     }
00408     pArray.Clear();
00409 }
00410 
00412 template <class T> inline void FbxArrayDestroy(FbxArray<T>& pArray)
00413 {
00414     for( int i = 0, c = pArray.Size(); i < c; ++i )
00415     {
00416         (pArray[i])->Destroy();
00417     }
00418     pArray.Clear();
00419 }
00420 
00422 template <class T> FBXSDK_INCOMPATIBLE_WITH_ARRAY_TEMPLATE(FbxArray<T>);
00423 
00424 #include <fbxsdk/fbxsdk_nsend.h>
00425 
00426 #endif /* _FBXSDK_CORE_BASE_ARRAY_H_ */