#ifndef __TARRAY_H__ #define __TARRAY_H__ #include "platform.h" #if defined(LINUX) #include "ILog.h" #else #include #endif #ifndef CLAMP #define CLAMP(X, mn, mx) (XRelease(); (p)=NULL; } } #endif #ifndef SAFE_RELEASE_FORCE #define SAFE_RELEASE_FORCE(p) { if(p) { (p)->Release(1); (p)=NULL; } } #endif // this is an allocator that's allocates 16-byte-aligned blocks, // using the normal mem manager. The overhead of allocation is always 16 byte more, // to keep the original address in the DWORD before the aligned address // NOTE: since this is like a garbage collector (the items are not guaranteed to be // freed immediately), the destructors won't be called // for simplicity, constructors won't be called either // // DOES NOT construct / destruct objects, so use with care! template class TAllocator16 { public: typedef size_t size_type; typedef T *pointer; TAllocator16 () #if defined(_DEBUG) && defined(_INC_CRTDBG) && !defined(WIN64) : m_szParentObject("TAllocator16"), m_nParentIndex (1) #endif { } TAllocator16 (const char* szParentObject, int nParentIndex) #if defined(_DEBUG) && defined(_INC_CRTDBG) && !defined(WIN64) : m_szParentObject(szParentObject), m_nParentIndex (nParentIndex) #endif { } // allocates the aligned memory for the given number of objects; // puts the pointer to the actually allocated block before the aligned memory block pointer allocate (size_type _Count) { pointer p; #if defined(_DEBUG) && defined(_INC_CRTDBG) && !defined(WIN64) p = (pointer)_malloc_dbg (0x10+_Count * sizeof(T), _NORMAL_BLOCK, m_szParentObject, m_nParentIndex); #else p = (pointer)malloc (0x10+_Count*sizeof(T)); #endif pointer pResult = (pointer)(((UINT_PTR)p+0x10)&~0xF); // save the offset to the actual allocated address behind the useable aligned address reinterpret_cast(pResult)[-1] = (char*)p - (char*)pResult; return pResult; } pointer allocate_construct (size_type _Count) { pointer p = allocate(_Count); return p; } void deallocate_destroy(pointer _Ptr) { if (!_Ptr) return; int nOffset = ((int*)_Ptr)[-1]; assert (nOffset >= -16 && nOffset <= -4); #if defined(_DEBUG) && defined(_INC_CRTDBG) && !defined(WIN64) _free_dbg (((char*)_Ptr)+nOffset, _NORMAL_BLOCK); #else free (((char*)_Ptr)+nOffset); #endif } protected: #if defined(_DEBUG) && defined(_INC_CRTDBG) && !defined(WIN64) // the parent object (on behalf of which to call the new operator) const char* m_szParentObject; // the file name int m_nParentIndex; // the file line number #endif }; /*---------------------------------------------------------------------------- Sorting template. ----------------------------------------------------------------------------*/ // // Sort elements. The sort is unstable, meaning that the ordering of equal // items is not necessarily preserved. // template struct TSortStack { T* Min; T* Max; }; template void Sort( T* First, int Num ) { if( Num<2 ) return; TSortStack RecursionStack[32]={{First,First+Num-1}}, Current, Inner; for( TSortStack* StackTop=RecursionStack; StackTop>=RecursionStack; --StackTop ) { Current = *StackTop; Loop: INT Count = Current.Max - Current.Min + 1; if( Count <= 8 ) { // Use simple bubble-sort. while( Current.Max > Current.Min ) { T *Max, *Item; for( Max=Current.Min, Item=Current.Min+1; Item<=Current.Max; Item++ ) if( Compare(*Item, *Max) > 0 ) Max = Item; Exchange( *Max, *Current.Max-- ); } } else { // Grab middle element so sort doesn't exhibit worst-cast behaviour with presorted lists. Exchange( Current.Min[Count/2], Current.Min[0] ); // Divide list into two halves, one with items <=Current.Min, the other with items >Current.Max. Inner.Min = Current.Min; Inner.Max = Current.Max+1; for( ; ; ) { while( ++Inner.Min<=Current.Max && Compare(*Inner.Min, *Current.Min) <= 0 ); while( --Inner.Max> Current.Min && Compare(*Inner.Max, *Current.Min) >= 0 ); if( Inner.Min>Inner.Max ) break; Exchange( *Inner.Min, *Inner.Max ); } Exchange( *Current.Min, *Inner.Max ); // Save big half and recurse with small half. if( Inner.Max-1-Current.Min >= Current.Max-Inner.Min ) { if( Current.Min+1 < Inner.Max ) { StackTop->Min = Current.Min; StackTop->Max = Inner.Max - 1; StackTop++; } if( Current.Max>Inner.Min ) { Current.Min = Inner.Min; goto Loop; } } else { if( Current.Max>Inner.Min ) { StackTop->Min = Inner .Min; StackTop->Max = Current.Max; StackTop++; } if( Current.Min+1 class TArray { protected: T* m_pElements; int m_nCount; int m_nAllocatedCount; public: typedef T value_type; TArray(void) { m_pElements = NULL, m_nCount = m_nAllocatedCount = 0; } TArray(int Count) { m_pElements = NULL; m_nCount = Count; m_nAllocatedCount = Count; Realloc(); } TArray(int Use, int Max) { m_nCount = Use; m_nAllocatedCount = Max; Realloc(); } ~TArray(void) { Free(); } void Reset(){Free();} void Free() { if (m_pElements) { free(m_pElements); m_pElements = NULL; } m_nCount = m_nAllocatedCount = 0; } void Create (int Count) { m_pElements = NULL; m_nCount = Count; m_nAllocatedCount = Count; Realloc(); Clear(); } void Copy (const TArray& src) { m_pElements = NULL; m_nCount = m_nAllocatedCount = src.Num(); Realloc(); memcpy(m_pElements, src.m_pElements, src.Num()*sizeof(T)); } void Copy (const T *src, int numElems) { for (int i=0; i=m_nCount); if( m_nAllocatedCount != m_nCount ) { m_nAllocatedCount = m_nCount; Realloc(); } } void _Remove(int Index,int Count) { assert ( Index>=0 ); assert ( Index<=m_nCount ); assert ( (Index+Count)<=m_nCount ); Remove(Index, Count); } int Num(void) const { return m_nCount; } int GetSize(void) const { return m_nAllocatedCount; } void SetNum(int n) { m_nCount = m_nAllocatedCount = n; } void SetUse(int n) { m_nCount = n; } void Alloc(int n) { m_nAllocatedCount = n; Realloc(); } void Reserve(int n) { SetNum(n); Realloc(); Clear(); } void Expand(int n) { if (n > m_nAllocatedCount) ReserveNew(n); } void ReserveNew(int n) { int num = m_nCount; SetNum(n); Realloc(); memset(&m_pElements[num], 0, sizeof(T)*(m_nCount-num)); } void Grow(int n) { n += m_nCount; SetNum(n); Realloc(); } void GrowReset(int n) { int num = m_nAllocatedCount; AddIndex(n); if (num != m_nAllocatedCount) memset(&m_pElements[num], 0, sizeof(T)*(m_nAllocatedCount-num)); } int *GetNumAddr(void) { return &m_nCount; } T** GetDataAddr(void) { return &m_pElements; } T* Data(void) const { return m_pElements; } T& Get(int id) const { return m_pElements[id]; } TArray& operator=(TArray& fa) { m_pElements = fa.m_pElements; m_nCount = fa.m_nCount; m_nAllocatedCount = fa.m_nAllocatedCount; return *this; } /*const TArray operator=(TArray fa) const { TArray t = TArray(fa.m_nCount,fa.m_nAllocatedCount); for ( int i=0; i& cTA) { m_pElements = NULL; m_nCount = m_nAllocatedCount = cTA.Num(); Realloc(); m_nCount = 0; for ( int i=0; i m_nAllocatedCount ) { #ifdef PS2 m_nAllocatedCount = m_nCount + (m_nCount>>1) + 128; #else m_nAllocatedCount = m_nCount + (m_nCount>>1) + 32; #endif Realloc(); } } void AddIndexNoCache(int inc) { m_nCount += inc; if ( m_nCount > m_nAllocatedCount ) { m_nAllocatedCount = m_nCount; Realloc(); } } void Add(const T & elem){AddElem(elem);} void AddElem(const T elem) { int m = m_nCount; AddIndex(1); m_pElements[m] = elem; } void AddElemNoCache(const T elem) { int m = m_nCount; AddIndexNoCache(1); m_pElements[m] = elem; } int Find(const T & p) { for(int i=0; idistance > p2->distance) return 1; else if(p1->distance < p2->distance) return -1; return 0; } static int Cmp_Ptrs2(const void* v1, const void* v2) { T* p1 = (T*)v1; T* p2 = (T*)v2; if(p1->distance > p2->distance) return -1; else if(p1->distance < p2->distance) return 1; return 0; } void SortByDistanceMember(bool front_to_back = true) { if(front_to_back) qsort(&m_pElements[0], m_nCount, sizeof(T), Cmp_Ptrs1); else qsort(&m_pElements[0], m_nCount, sizeof(T), Cmp_Ptrs2); } */ // Save/Load void SaveToBuffer(const unsigned char * pBuffer, int & nPos) { // copy size of element int nSize = sizeof(T); if(pBuffer) memcpy((void*)&pBuffer[nPos],&nSize,4); nPos+=4; // copy count if(pBuffer) memcpy((void*)&pBuffer[nPos],&m_nCount,4); nPos+=4; // copy data if(m_nCount) { if(pBuffer) memcpy((void*)&pBuffer[nPos], m_pElements, sizeof(T)*m_nCount); nPos += sizeof(T)*m_nCount; } } void LoadFromBuffer(const unsigned char * pBuffer, int & nPos) { Reset(); // copy size of element int nElemSize = 0; memcpy(&nElemSize,(void*)&pBuffer[nPos],4); assert(nElemSize == sizeof(T)); nPos+=4; // copy count int nNewCount=0; memcpy((void*)&nNewCount,&pBuffer[nPos],4); assert(nNewCount>=0 && nNewCount<1000000); nPos+=4; // copy data if(nNewCount) { Reserve(nNewCount); memcpy((void*)m_pElements, &pBuffer[nPos], sizeof(T)*nNewCount); nPos += sizeof(T)*nNewCount; } } // Standard compliance interface // // This is for those who don't want to learn the non standard and // thus not very convenient interface of TArray, but are unlucky // enough not to be able to avoid using it. void clear(){Free();} unsigned size()const {return m_nCount;} unsigned capacity() const {return m_nAllocatedCount;} bool empty()const {return size() == 0;} void push_back (const T& rSample) {Add(rSample);} T* begin() {return m_pElements;} T* end() {return m_pElements + m_nCount;} const T* begin()const {return m_pElements;} const T* end()const {return m_pElements + m_nCount;} int GetMemoryUsage() { return (int)(m_nAllocatedCount*sizeof(T)); } }; template inline void Exchange(T& X, T& Y) { const T Tmp = X; X = Y; Y = Tmp; } #endif // __TARRAY_H__