123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886 |
- #ifndef _AKARRAY_H
- #define _AKARRAY_H
- #include <AK/Tools/Common/AkObject.h>
- #include <AK/Tools/Common/AkAssert.h>
- #include <AK/Tools/Common/AkPlatformFuncs.h>
- #include <utility>
- template <AkMemID T_MEMID>
- struct AkArrayAllocatorNoAlign
- {
- static AkForceInline void * Alloc( size_t in_uSize )
- {
- return AkAlloc(T_MEMID, in_uSize);
- }
- static AkForceInline void * ReAlloc( void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize )
- {
- return AkRealloc(T_MEMID, in_pCurrent, in_uNewSize);
- }
- static AkForceInline void Free( void * in_pAddress )
- {
- AkFree(T_MEMID, in_pAddress);
- }
- static AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorNoAlign<T_MEMID> in_srcAlloc, void * in_pSrc )
- {
- io_pDest = in_pSrc;
- }
- };
- template <AkMemID T_MEMID>
- struct AkArrayAllocatorAlignedSimd
- {
- AkForceInline void * Alloc( size_t in_uSize )
- {
- return AkMalign(T_MEMID, in_uSize, AK_SIMD_ALIGNMENT);
- }
- AkForceInline void * ReAlloc(void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
- {
- return AkReallocAligned(T_MEMID, in_pCurrent, in_uNewSize, AK_SIMD_ALIGNMENT);
- }
- AkForceInline void Free( void * in_pAddress )
- {
- AkFree(T_MEMID, in_pAddress);
- }
- AkForceInline void TransferMem(void *& io_pDest, AkArrayAllocatorAlignedSimd<T_MEMID> in_srcAlloc, void * in_pSrc )
- {
- io_pDest = in_pSrc;
- }
- };
- template< AkUInt32 uBufferSizeBytes, AkUInt8 uAlignmentSize = 1, AkMemID T_MEMID = AkMemID_Object>
- struct AkHybridAllocator
- {
- static const AkUInt32 _uBufferSizeBytes = uBufferSizeBytes;
- AkForceInline void * Alloc(size_t in_uSize)
- {
- if (in_uSize <= uBufferSizeBytes)
- return (void *)&m_buffer;
- return AkMalign(T_MEMID, in_uSize, uAlignmentSize);
- }
- AkForceInline void * ReAlloc(void * in_pCurrent, size_t in_uOldSize, size_t in_uNewSize)
- {
- if (in_uNewSize <= uBufferSizeBytes)
- return (void *)&m_buffer;
- if (&m_buffer != in_pCurrent)
- return AkReallocAligned(T_MEMID, in_pCurrent, in_uNewSize, uAlignmentSize);
- void* pAddress = AkMalign(T_MEMID, in_uNewSize, uAlignmentSize);
- if (!pAddress)
- return NULL;
- AKPLATFORM::AkMemCpy(pAddress, m_buffer, (AkUInt32)in_uOldSize);
- return pAddress;
- }
- AkForceInline void Free(void * in_pAddress)
- {
- if (&m_buffer != in_pAddress)
- AkFree(T_MEMID, in_pAddress);
- }
- AkForceInline void TransferMem(void *& io_pDest, AkHybridAllocator<uBufferSizeBytes, uAlignmentSize, T_MEMID>& in_srcAlloc, void * in_pSrc)
- {
- if (&in_srcAlloc.m_buffer == in_pSrc)
- {
- AKPLATFORM::AkMemCpy(m_buffer, in_srcAlloc.m_buffer, uBufferSizeBytes);
- io_pDest = m_buffer;
- }
- else
- {
- io_pDest = in_pSrc;
- }
- }
-
- AK_ALIGN(char m_buffer[uBufferSizeBytes], uAlignmentSize);
- };
- template <class T, AkUInt32 uCount = 1, AkMemID MemID = AkMemID_Object>
- using AkSmallArrayAllocator = AkHybridAllocator<sizeof(T)* uCount, alignof(T), MemID>;
- template <class T>
- struct AkAssignmentMovePolicy
- {
-
-
- static AkForceInline void Move( T& in_Dest, T& in_Src )
- {
- in_Dest = in_Src;
- }
-
-
-
- static AkForceInline bool IsTrivial()
- {
- return true;
- }
- };
- struct AkStdMovePolicy
- {
- template <class T>
- static AkForceInline void Move(T&& io_Dest, T&& io_Src)
- {
- io_Dest = std::move(io_Src);
- }
- static AkForceInline bool IsTrivial()
- {
- return false;
- }
- };
- struct AkTrivialStdMovePolicy
- {
- template <class T>
- static AkForceInline void Move(T&& io_Dest, T&& io_Src)
- {
- io_Dest = std::move(io_Src);
- }
- static AkForceInline bool IsTrivial()
- {
- return true;
- }
- };
- template <class T>
- struct AkTransferMovePolicy
- {
- static AkForceInline void Move( T& in_Dest, T& in_Src )
- {
- in_Dest.Transfer(in_Src);
- }
- static AkForceInline bool IsTrivial()
- {
- return false;
- }
- };
- typedef AkArrayAllocatorNoAlign<AkMemID_Object> ArrayPoolDefault;
- typedef AkArrayAllocatorNoAlign<AkMemID_Processing> ArrayPoolLEngineDefault;
- typedef AkArrayAllocatorNoAlign<AkMemID_Profiler> ArrayPoolProfiler;
- typedef AkArrayAllocatorAlignedSimd<AkMemID_Processing> ArrayPoolLEngineDefaultAlignedSimd;
- struct AkGrowByPolicy_Legacy
- {
- static AkUInt32 GrowBy( AkUInt32 ) { return 1; }
- };
- struct AkGrowByPolicy_NoGrow
- {
- static AkUInt32 GrowBy( AkUInt32 ) { return 0; }
- };
- template <AkUInt32 uCount>
- struct AkGrowByPolicy_Hybrid
- {
- static AkUInt32 GrowBy(AkUInt32 in_CurrentArraySize)
- {
- if (in_CurrentArraySize < uCount)
- return uCount - in_CurrentArraySize;
- else
- {
- return in_CurrentArraySize + (in_CurrentArraySize >> 1);
- }
- }
- };
- struct AkGrowByPolicy_Proportional
- {
- static AkUInt32 GrowBy( AkUInt32 in_CurrentArraySize )
- {
- if ( in_CurrentArraySize == 0 )
- return 1;
- else
- return in_CurrentArraySize + ( in_CurrentArraySize >> 1 );
- }
- };
- #define AkGrowByPolicy_DEFAULT AkGrowByPolicy_Proportional
- template <class T, class ARG_T, class TAlloc = ArrayPoolDefault, class TGrowBy = AkGrowByPolicy_DEFAULT, class TMovePolicy = AkAssignmentMovePolicy<T> > class AkArray : public TAlloc
- {
- public:
-
- AkArray()
- : m_pItems( 0 )
- , m_uLength( 0 )
- , m_ulReserved( 0 )
- {
- }
-
- ~AkArray()
- {
- AKASSERT( m_pItems == 0 );
- AKASSERT( m_uLength == 0 );
- AKASSERT( m_ulReserved == 0 );
- }
- #ifndef SWIG
-
- struct Iterator
- {
- T* pItem;
-
- Iterator operator+(AkUInt32 inc) const
- {
- AKASSERT( pItem );
- Iterator returnedIt;
- returnedIt.pItem = pItem + inc;
- return returnedIt;
- }
-
- AkUInt32 operator-(Iterator const& rhs) const
- {
- AKASSERT((pItem && rhs.pItem)||(!pItem && !rhs.pItem));
- return (AkUInt32)(pItem - rhs.pItem);
- }
-
- Iterator& operator++()
- {
- AKASSERT( pItem );
- ++pItem;
- return *this;
- }
-
- Iterator& operator--()
- {
- AKASSERT( pItem );
- --pItem;
- return *this;
- }
-
- T& operator*()
- {
- AKASSERT( pItem );
- return *pItem;
- }
- T* operator->() const
- {
- AKASSERT( pItem );
- return pItem;
- }
-
- bool operator ==( const Iterator& in_rOp ) const
- {
- return ( pItem == in_rOp.pItem );
- }
-
- bool operator !=( const Iterator& in_rOp ) const
- {
- return ( pItem != in_rOp.pItem );
- }
- };
- #endif
-
- Iterator Begin() const
- {
- Iterator returnedIt;
- returnedIt.pItem = m_pItems;
- return returnedIt;
- }
-
- Iterator End() const
- {
- Iterator returnedIt;
- returnedIt.pItem = m_pItems + m_uLength;
- return returnedIt;
- }
-
- Iterator FindEx( ARG_T in_Item ) const
- {
- Iterator it = Begin();
- for ( Iterator itEnd = End(); it != itEnd; ++it )
- {
- if ( *it == in_Item )
- break;
- }
- return it;
- }
-
-
- Iterator BinarySearch( ARG_T in_Item ) const
- {
- AkUInt32 uNumToSearch = Length();
- T* pBase = m_pItems;
- T* pPivot;
- while ( uNumToSearch > 0 )
- {
- pPivot = pBase + ( uNumToSearch >> 1 );
- if ( in_Item == *pPivot )
- {
- Iterator result;
- result.pItem = pPivot;
- return result;
- }
- if ( in_Item > *pPivot )
- {
- pBase = pPivot + 1;
- uNumToSearch--;
- }
- uNumToSearch >>= 1;
- }
- return End();
- }
-
- Iterator Erase( Iterator& in_rIter )
- {
- AKASSERT( m_pItems != 0 );
- if (TMovePolicy::IsTrivial())
- {
- T* pItem = in_rIter.pItem;
- T* pLastItem = m_pItems + (m_uLength - 1);
-
- pItem->~T();
-
- if (pItem < pLastItem)
- {
- AKPLATFORM::AkMemMove(
- pItem,
- pItem + 1,
- (AkUInt32)(pLastItem - pItem) * sizeof(T)
- );
- }
- }
- else
- {
-
- T* pItemLast = m_pItems + m_uLength - 1;
- for (T* pItem = in_rIter.pItem; pItem < pItemLast; pItem++)
- TMovePolicy::Move(pItem[0], pItem[1]);
-
- pItemLast->~T();
- }
- m_uLength--;
- return in_rIter;
- }
-
- void Erase( unsigned int in_uIndex )
- {
- AKASSERT( m_pItems != 0 );
- if (TMovePolicy::IsTrivial())
- {
- T* pItem = m_pItems + in_uIndex;
-
- pItem->~T();
-
- if (in_uIndex + 1 < m_uLength)
- {
- AKPLATFORM::AkMemMove(
- pItem,
- pItem + 1,
- (m_uLength - in_uIndex - 1) * sizeof(T)
- );
- }
- }
- else
- {
-
- T* pItemLast = m_pItems + m_uLength - 1;
- for (T* pItem = m_pItems + in_uIndex; pItem < pItemLast; pItem++)
- TMovePolicy::Move(pItem[0], pItem[1]);
-
- pItemLast->~T();
- }
- m_uLength--;
- }
-
-
- Iterator EraseSwap( Iterator& in_rIter )
- {
- AKASSERT( m_pItems != 0 && Length() > 0 );
- if (in_rIter.pItem < (m_pItems + m_uLength - 1))
- {
-
- TMovePolicy::Move( *in_rIter.pItem, Last( ) );
- }
-
- AKASSERT( Length( ) > 0 );
- Last( ).~T();
- m_uLength--;
- return in_rIter;
- }
-
-
- void EraseSwap(unsigned int in_uIndex)
- {
- Iterator Iterator;
- Iterator.pItem = m_pItems + in_uIndex;
- EraseSwap(Iterator);
- }
- bool IsGrowingAllowed() const
- {
- return TGrowBy::GrowBy( 1 ) != 0;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- inline AKRESULT Reserve(AkUInt32 in_ulReserve)
- {
- if (in_ulReserve <= m_ulReserved)
- return AK_Success;
- if (m_ulReserved && !IsGrowingAllowed())
- {
- AKASSERT(!"AkArray calling Reserve() with AkGrowByPolicy_NoGrow is only allowed when reserved size is zero");
- return AK_InvalidParameter;
- }
- return GrowArray(in_ulReserve - m_ulReserved) ? AK_Success : AK_InsufficientMemory;
- }
-
-
-
- inline AKRESULT ReserveExtra(AkUInt32 in_ulReserve)
- {
- return Reserve(Length() + in_ulReserve);
- }
- AkUInt32 Reserved() const { return m_ulReserved; }
-
- void Term()
- {
- if ( m_pItems )
- {
- RemoveAll();
- TAlloc::Free( m_pItems );
- m_pItems = 0;
- m_ulReserved = 0;
- }
- }
-
- AkForceInline AkUInt32 Length() const
- {
- return m_uLength;
- }
-
- AkForceInline T * Data() const
- {
- return m_pItems;
- }
-
- AkForceInline bool IsEmpty() const
- {
- return m_uLength == 0;
- }
-
-
- AkForceInline T* Exists(ARG_T in_Item) const
- {
- Iterator it = FindEx( in_Item );
- return ( it != End() ) ? it.pItem : 0;
- }
-
-
- AkForceInline T * AddLast()
- {
- size_t cItems = Length();
- #if defined(_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4127 )
- #endif
- if ( ( cItems >= m_ulReserved ) && IsGrowingAllowed() )
- {
- if ( !GrowArray() )
- return 0;
- }
- #if defined(_MSC_VER)
- #pragma warning( pop )
- #endif
-
- if( cItems < m_ulReserved )
- {
- T * pEnd = m_pItems + m_uLength++;
- AkPlacementNew( pEnd ) T;
- return pEnd;
- }
- return 0;
- }
-
- AkForceInline T * AddLast(ARG_T in_rItem)
- {
- T * pItem = AddLast();
- if ( pItem )
- *pItem = in_rItem;
- return pItem;
- }
-
- T& Last()
- {
- AKASSERT( m_uLength );
- return *( m_pItems + m_uLength - 1 );
- }
-
- void RemoveLast()
- {
- AKASSERT( m_uLength );
- ( m_pItems + m_uLength - 1 )->~T();
- m_uLength--;
- }
-
- AKRESULT Remove(ARG_T in_rItem)
- {
- Iterator it = FindEx( in_rItem );
- if ( it != End() )
- {
- Erase( it );
- return AK_Success;
- }
- return AK_Fail;
- }
-
-
- AKRESULT RemoveSwap(ARG_T in_rItem)
- {
- Iterator it = FindEx( in_rItem );
- if ( it != End() )
- {
- EraseSwap( it );
- return AK_Success;
- }
- return AK_Fail;
- }
-
- void RemoveAll()
- {
- for ( Iterator it = Begin(), itEnd = End(); it != itEnd; ++it )
- (*it).~T();
- m_uLength = 0;
- }
-
- AkForceInline T& operator[](unsigned int uiIndex) const
- {
- AKASSERT( m_pItems );
- AKASSERT( uiIndex < Length() );
- return m_pItems[uiIndex];
- }
-
-
-
- Iterator Insert(Iterator& in_rIter)
- {
- AKASSERT(!in_rIter.pItem || m_pItems);
- AkUInt32 index = (in_rIter.pItem && m_pItems) ? (AkUInt32)(in_rIter.pItem - m_pItems) : 0;
- if (index <= Length())
- {
- if (T* ptr = Insert(index))
- {
- Iterator it;
- it.pItem = ptr;
- return it;
- }
- }
- return End();
- }
-
-
- T * Insert(unsigned int in_uIndex)
- {
- AKASSERT( in_uIndex <= Length() );
- size_t cItems = Length();
- #if defined(_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4127 )
- #endif
- if ( ( cItems >= m_ulReserved ) && IsGrowingAllowed() )
- {
- if ( !GrowArray() )
- return 0;
- }
- #if defined(_MSC_VER)
- #pragma warning( pop )
- #endif
-
- if (cItems < m_ulReserved)
- {
- if (TMovePolicy::IsTrivial())
- {
- T* pItem = m_pItems + in_uIndex;
-
- if (in_uIndex < m_uLength)
- {
- AKPLATFORM::AkMemMove(
- pItem + 1,
- pItem,
- (m_uLength - in_uIndex) * sizeof(T)
- );
- }
-
- AkPlacementNew(pItem) T;
- m_uLength++;
- }
- else
- {
- T* pItemLast = m_pItems + m_uLength++;
- AkPlacementNew(pItemLast) T;
-
- for (T* pItem = pItemLast; pItem > (m_pItems + in_uIndex); --pItem)
- TMovePolicy::Move(pItem[0], pItem[-1]);
-
- (m_pItems + in_uIndex)->~T();
- AkPlacementNew(m_pItems + in_uIndex) T;
- }
- return m_pItems + in_uIndex;
- }
- return 0;
- }
- bool GrowArray()
- {
-
- return GrowArray( TGrowBy::GrowBy( m_ulReserved ) );
- }
-
- bool GrowArray( AkUInt32 in_uGrowBy )
- {
- AKASSERT( in_uGrowBy );
- AkUInt32 ulNewReserve = m_ulReserved + in_uGrowBy;
- T * pNewItems = NULL;
- size_t cItems = Length();
-
- if (m_pItems && TMovePolicy::IsTrivial())
- {
- pNewItems = (T *)TAlloc::ReAlloc(m_pItems, sizeof(T) * cItems, sizeof(T) * ulNewReserve);
- if (!pNewItems)
- return false;
- }
- else
- {
- pNewItems = (T *)TAlloc::Alloc(sizeof(T) * ulNewReserve);
- if (!pNewItems)
- return false;
-
- if (m_pItems && m_pItems != pNewItems )
- {
- for (size_t i = 0; i < cItems; ++i)
- {
- AkPlacementNew(pNewItems + i) T;
- TMovePolicy::Move(pNewItems[i], m_pItems[i]);
- m_pItems[i].~T();
- }
- TAlloc::Free(m_pItems);
- }
- }
- m_pItems = pNewItems;
- m_ulReserved = ulNewReserve;
- return true;
- }
-
- bool Resize(AkUInt32 in_uiSize)
- {
- AkUInt32 cItems = Length();
- if (in_uiSize < cItems)
- {
- for (AkUInt32 i = in_uiSize; i < cItems; i++)
- {
- m_pItems[i].~T();
- }
-
- m_uLength = in_uiSize;
- return true;
- }
- if ( in_uiSize > m_ulReserved )
- {
- if ( !GrowArray(in_uiSize - m_ulReserved) )
- return false;
- }
-
- for(size_t i = cItems; i < in_uiSize; i++)
- {
- AkPlacementNew( m_pItems + i ) T;
- }
- m_uLength = in_uiSize;
- return true;
- }
- void Transfer(AkArray<T,ARG_T,TAlloc,TGrowBy,TMovePolicy>& in_rSource)
- {
- Term();
- TAlloc::TransferMem( (void*&)m_pItems, in_rSource, (void*)in_rSource.m_pItems );
- m_uLength = in_rSource.m_uLength;
- m_ulReserved = in_rSource.m_ulReserved;
- in_rSource.m_pItems = NULL;
- in_rSource.m_uLength = 0;
- in_rSource.m_ulReserved = 0;
- }
- AKRESULT Copy(const AkArray<T, ARG_T, TAlloc, TGrowBy, TMovePolicy>& in_rSource)
- {
- RemoveAll();
- if (Resize(in_rSource.Length()))
- {
- for (AkUInt32 i = 0; i < in_rSource.Length(); ++i)
- m_pItems[i] = in_rSource.m_pItems[i];
- return AK_Success;
- }
- return AK_Fail;
- }
- protected:
- T * m_pItems;
- AkUInt32 m_uLength;
- AkUInt32 m_ulReserved;
- };
- #endif
|