fbxsdk/core/base/fbxarray.h Source File
 
 
 
fbxsdk/core/base/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 
00033         FbxArray(int pCapacity) : mSize(0), mCapacity(0), mArray(NULL){ if( pCapacity > 0 ) Reserve(pCapacity); }
00034 
00037         ~FbxArray(){ Clear(); }
00038 
00044         inline int InsertAt(const int pIndex, const T pElement)
00045         {
00046                 FBX_ASSERT_RETURN_VALUE(pIndex >= 0, -1);
00047                 int lIndex = FbxMin(pIndex, mSize);
00048                 if( mSize >= mCapacity )
00049                 {
00050                         int lNewCapacity = FbxMax(mCapacity * 2, 1);    //Double capacity
00051                         T* lArray = Allocate(lNewCapacity);
00052                         FBX_ASSERT_RETURN_VALUE(lArray, -1);
00053                         mArray = lArray;
00054                         mCapacity = lNewCapacity;
00055                 }
00056 
00057                 if( lIndex < mSize )    //Move elements to leave a space open to insert the new element
00058                 {
00059                         memmove(&mArray[lIndex + 1], &mArray[lIndex], (mSize - lIndex) * sizeof(T));
00060                 }
00061 
00062                 memcpy(&mArray[lIndex], &pElement, sizeof(T));
00063                 mSize++;
00064 
00065                 return lIndex;
00066         }
00067 
00071         inline int Add(const T pElement)
00072         {
00073                 return InsertAt(mSize, pElement);
00074         }
00075 
00079         inline int AddUnique(const T pElement)
00080         {
00081                 int lIndex = Find(pElement);
00082                 return ( lIndex == -1 ) ? Add(pElement) : lIndex;
00083         }
00084 
00088         inline int Size() const { return mSize; }
00089 
00093         inline int Capacity() const { return mCapacity; }
00094 
00099         inline T& operator[](int pIndex) const
00100         {
00101         #ifdef _DEBUG
00102                 FBX_ASSERT_MSG(pIndex >= 0, "Index is out of range!");
00103                 if( pIndex >= mSize )
00104                 {
00105                         if( pIndex < mCapacity )
00106                         {
00107                                 FBX_ASSERT_NOW("Index is out of range, but not outside of capacity! Call SetAt() to use reserved memory.");
00108                         }
00109                         else FBX_ASSERT_NOW("Index is out of range!");
00110                 }
00111         #endif
00112                 return (T&)mArray[pIndex];
00113         }
00114 
00119         inline T GetAt(const int pIndex) const
00120         {
00121                 return operator[](pIndex);
00122         }
00123 
00127         inline T GetFirst() const
00128         {
00129                 return GetAt(0);
00130         }
00131 
00135         inline T GetLast() const
00136         {
00137                 return GetAt(mSize-1);
00138         }
00139 
00144         inline int Find(const T pElement, const int pStartIndex=0) const
00145         {
00146                 FBX_ASSERT_RETURN_VALUE(pStartIndex >= 0, -1);
00147                 for( int i = pStartIndex; i < mSize; ++i )
00148                 {
00149                         if( GetAt(i) == pElement ) return i;
00150                 }
00151                 return -1;
00152         }
00153 
00158         inline int FindReverse(const T pElement, const int pStartIndex=FBXSDK_INT_MAX) const
00159         {
00160                 for( int i = FbxMin(pStartIndex, mSize-1); i >= 0; --i )
00161                 {
00162                         if( GetAt(i) == pElement ) return i;
00163                 }
00164                 return -1;
00165         }
00166 
00171         inline bool Reserve(const int pCapacity)
00172         {
00173                 FBX_ASSERT_RETURN_VALUE(pCapacity > 0, false);
00174                 if( pCapacity > mCapacity )
00175                 {
00176                         T* lArray = Allocate(pCapacity);
00177                         FBX_ASSERT_RETURN_VALUE(lArray, false);
00178                         mArray = lArray;
00179                         mCapacity = pCapacity;
00180 
00181                         //Initialize new memory to zero
00182                         memset(&mArray[mSize], 0, (mCapacity - mSize) * sizeof(T));
00183                 }
00184                 return true;
00185         }
00186 
00192         inline void SetAt(const int pIndex, const T pElement)
00193         {
00194                 if( pIndex >= mSize )
00195                 {
00196                         FBX_ASSERT_RETURN(pIndex < mCapacity);
00197                         mSize = pIndex + 1;
00198                 }
00199                 memcpy(&mArray[pIndex], &pElement, sizeof(T));
00200         }
00201 
00205         inline void SetFirst(const T pElement)
00206         {
00207                 SetAt(0, pElement);
00208         }
00209 
00213         inline void SetLast(const T pElement)
00214         {
00215                 SetAt(mSize-1, pElement);
00216         }
00217 
00222         inline T RemoveAt(const int pIndex)
00223         {
00224                 T lElement = GetAt(pIndex);
00225                 if( pIndex + 1 < mSize )
00226                 {
00227                         memmove(&mArray[pIndex], &mArray[pIndex + 1], (mSize - pIndex - 1) * sizeof(T));
00228                 }
00229                 mSize--;
00230                 return lElement;
00231         }
00232 
00236         inline T RemoveFirst()
00237         {
00238                 return RemoveAt(0);
00239         }
00240 
00244         inline T RemoveLast()
00245         {
00246                 return RemoveAt(mSize-1);
00247         }
00248 
00252         inline bool RemoveIt(const T pElement)
00253         {
00254                 int Index = Find(pElement);
00255                 if( Index >= 0 )
00256                 {
00257                         RemoveAt(Index);
00258                         return true;
00259                 }
00260                 return false;
00261         }
00262 
00267         inline bool Resize(const int pSize)
00268         {
00269                 if( pSize == 0 )
00270                 {
00271                         Clear();
00272                         return true;
00273                 }
00274 
00275                 FBX_ASSERT_RETURN_VALUE(pSize > 0, false);
00276                 if( pSize != mCapacity )
00277                 {
00278                         T* lArray = Allocate(pSize);
00279                         FBX_ASSERT_RETURN_VALUE(lArray, false);
00280                         mArray = lArray;
00281                 }
00282 
00283                 if( pSize > mCapacity ) //Initialize new memory to zero
00284                 {
00285                         memset(&mArray[mSize], 0, (pSize - mSize) * sizeof(T));
00286                 }
00287 
00288                 mSize = pSize;
00289                 mCapacity = pSize;
00290 
00291                 return true;
00292         }
00293 
00297         inline bool Grow(const int pSize)
00298         {
00299                 return Resize(mSize + pSize);
00300         }
00301 
00304         inline void Clear()
00305         {
00306                 if( mArray != NULL )
00307                 {
00308                         mSize = 0;
00309                         mCapacity = 0;
00310                         FbxFree(mArray);
00311                         mArray = NULL;
00312                 }
00313         }
00314 
00316         inline T* GetArray() const { return mArray ? (T*)mArray : NULL; }
00317 
00319         inline operator T* (){ return (T*)mArray; }
00320 
00323         inline void AddArray(const FbxArray<T>& pOther)
00324         {
00325                 if( Grow(pOther.mSize) )
00326                 {
00327                         memcpy(&mArray[mSize - pOther.mSize], pOther.mArray, pOther.mSize * sizeof(T));
00328                 }
00329         }
00330 
00333         inline void AddArrayNoDuplicate(const FbxArray<T>& pOther)
00334         {
00335                 for( int i = 0, c = pOther.mSize; i < c; ++i )
00336                 {
00337                         AddUnique(pOther[i]);
00338                 }
00339         }
00340 
00343         inline void RemoveArray(const FbxArray<T>& pOther)
00344         {
00345                 for( int i = 0, c = pOther.mSize; i < c; ++i )
00346                 {
00347                         RemoveIt(pOther[i]);
00348                 }
00349         }
00350 
00353         inline FbxArray<T>& operator=(const FbxArray<T>& pOther)
00354         {
00355                 if( this != &pOther )
00356                 {
00357                         if( Resize(pOther.mSize) )
00358                         {
00359                                 memcpy(mArray, pOther.mArray, pOther.mSize * sizeof(T));
00360                         }
00361                 }
00362                 return *this;
00363         }
00364 
00365 /*****************************************************************************************************************************
00366 ** WARNING! Anything beyond these lines is for internal use, may not be documented and is subject to change without notice! **
00367 *****************************************************************************************************************************/
00368 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00369         inline int GetCount() const { return mSize; }
00370         FBX_DEPRECATED inline void Empty(){ Clear(); }
00371         FBX_DEPRECATED inline int FindAfter(int pAfterIndex, T pItem) const { return Find(pItem, pAfterIndex+1); }
00372         FBX_DEPRECATED inline int FindBefore(int pBeforeIndex, T pItem) const { return FindReverse(pItem, pBeforeIndex-1); }
00373         FBX_DEPRECATED inline void AddMultiple(int pItemCount){ Grow(pItemCount); }
00374 
00375 private:
00376         inline T* Allocate(const int pCapacity)
00377         {
00378                 return (T*)FbxRealloc(mArray, pCapacity * sizeof(T));
00379         }
00380 
00381         int             mSize;
00382         int             mCapacity;
00383         T*      mArray;
00384 
00385 #if defined(FBXSDK_COMPILER_MSC)
00386     //Previously class FbxArray is for pointers. Somehow, it's used to store other types. Here's a compile-time checking for known incompatible classes.
00387     //If it happens you find new incompatible ones, declare them with macro FBXSDK_INCOMPATIBLE_WITH_ARRAY. Also see file fbxstring.h.
00388     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));
00389 #endif
00390 
00391 #endif /* !DOXYGEN_SHOULD_SKIP_THIS *****************************************************************************************/
00392 };
00393 
00395 template <class T> inline void FbxArrayFree(FbxArray<T>& pArray)
00396 {
00397         for( int i = 0, c = pArray.Size(); i < c; ++i )
00398         {
00399                 FbxFree(pArray[i]);
00400         }
00401         pArray.Clear();
00402 }
00403 
00405 template <class T> inline void FbxArrayDelete(FbxArray<T>& pArray)
00406 {
00407         for( int i = 0, c = pArray.Size(); i < c; ++i )
00408         {
00409                 FbxDelete(pArray[i]);
00410         }
00411         pArray.Clear();
00412 }
00413 
00415 template <class T> inline void FbxArrayDestroy(FbxArray<T>& pArray)
00416 {
00417         for( int i = 0, c = pArray.Size(); i < c; ++i )
00418         {
00419                 (pArray[i])->Destroy();
00420         }
00421         pArray.Clear();
00422 }
00423 
00425 template <class T> FBXSDK_INCOMPATIBLE_WITH_ARRAY_TEMPLATE(FbxArray<T>);
00426 
00427 #include <fbxsdk/fbxsdk_nsend.h>
00428 
00429 #endif /* _FBXSDK_CORE_BASE_ARRAY_H_ */