/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_TARRAY_H #define CRYINCLUDE_CRYCOMMON_TARRAY_H #pragma once #include <ILog.h> #include <ICryPak.h> //impl of fxopen #include <Cry_Math.h> #include <AzCore/IO/FileIO.h> #include <STLGlobalAllocator.h> #ifndef CLAMP #define CLAMP(X, mn, mx) ((X) < (mn) ? (mn) : ((X) < (mx) ? (X) : (mx))) #endif #ifndef SATURATE #define SATURATE(X) clamp_tpl(X, 0.f, 1.f) #endif #ifndef SATURATEB #define SATURATEB(X) CLAMP(X, 0, 255) #endif #ifndef LERP #define LERP(A, B, Alpha) ((A) + (Alpha) * ((B)-(A))) #endif // Safe memory freeing #ifndef SAFE_DELETE #define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } \ } #endif #ifndef SAFE_DELETE_ARRAY #define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = NULL; } \ } #endif #ifndef SAFE_RELEASE #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } \ } #endif #ifndef SAFE_RELEASE_FORCE #define SAFE_RELEASE_FORCE(p) { if (p) { (p)->ReleaseForce(); (p) = NULL; } \ } #endif // General array class. // Can refer to a general (unowned) region of memory (m_nAllocatedCount = 0). // Can allocate, grow, and shrink an array. // Does not deep copy. template<class T> class TArray { protected: T* m_pElements; unsigned int m_nCount; unsigned int m_nAllocatedCount; public: typedef T value_type; // Empty array. TArray() { ClearArr(); } // Create a new array, delete it on destruction. TArray(int Count) { m_nCount = Count; m_nAllocatedCount = Count; m_pElements = NULL; Realloc(0); } TArray(int Use, int Max) { m_nCount = Use; m_nAllocatedCount = Max; m_pElements = NULL; Realloc(0); } // Reference pre-existing memory. Does not delete it. TArray(T* Elems, int Count) { m_pElements = Elems; m_nCount = Count; m_nAllocatedCount = 0; } ~TArray() { Free(); } void Free() { m_nCount = 0; if (m_nAllocatedCount) { AZ::AllocatorInstance<CryLegacySTLAllocator>::Get().DeAllocate(m_pElements); } m_nAllocatedCount = 0; m_pElements = NULL; } void Create (int Count) { m_pElements = NULL; m_nCount = Count; m_nAllocatedCount = Count; Realloc(0); Clear(); } void Copy (const TArray<T>& src) { m_pElements = NULL; m_nCount = m_nAllocatedCount = src.Num(); Realloc(0); PREFAST_ASSUME(m_pElements); // realloc asserts if it fails - so this is safe memcpy(m_pElements, src.m_pElements, src.Num() * sizeof(T)); } void Copy (const T* src, unsigned int numElems) { int nOffs = m_nCount; Grow(numElems); memcpy(&m_pElements[nOffs], src, numElems * sizeof(T)); } void Align4Copy (const T* src, unsigned int& numElems) { int nOffs = m_nCount; Grow((numElems + 3) & ~3); memcpy(&m_pElements[nOffs], src, numElems * sizeof(T)); if (numElems & 3) { int nSet = 4 - (numElems & 3); memset(&m_pElements[nOffs + numElems], 0, nSet); numElems += nSet; } } void Realloc(int nOldAllocatedCount) { if (!m_nAllocatedCount) { m_pElements = NULL; } else { m_pElements = static_cast<decltype(m_pElements)>(AZ::AllocatorInstance<CryLegacySTLAllocator>::Get().ReAllocate(m_pElements, m_nAllocatedCount * sizeof(T), alignof(T))); assert (m_pElements); } } void Remove(unsigned int Index, unsigned int Count = 1) { if (Count) { memmove(m_pElements + Index, m_pElements + (Index + Count), sizeof(T) * (m_nCount - Index - Count)); m_nCount -= Count; } } void Shrink() { if (m_nCount == 0 || m_nAllocatedCount == 0) { return; } assert(m_nAllocatedCount >= m_nCount); if (m_nAllocatedCount != m_nCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = m_nCount; Realloc(nOldAllocatedCount); } } void _Remove(unsigned int Index, unsigned int Count) { assert (Index >= 0); assert (Index <= m_nCount); assert ((Index + Count) <= m_nCount); Remove(Index, Count); } unsigned int Num(void) const { return m_nCount; } unsigned int Capacity(void) const { return m_nAllocatedCount; } unsigned int MemSize(void) const { return m_nCount * sizeof(T); } void SetNum(unsigned int n) { m_nCount = m_nAllocatedCount = n; } void SetUse(unsigned int n) { m_nCount = n; } void Alloc(unsigned int n) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = n; Realloc(nOldAllocatedCount); } void Reserve(unsigned int n) { int nOldAllocatedCount = m_nAllocatedCount; SetNum(n); Realloc(nOldAllocatedCount); Clear(); } void ReserveNoClear(unsigned int n) { int nOldAllocatedCount = m_nAllocatedCount; SetNum(n); Realloc(nOldAllocatedCount); } void Expand(unsigned int n) { if (n > m_nAllocatedCount) { ReserveNew(n); } } void ReserveNew(unsigned int n) { int num = m_nCount; if (n > m_nAllocatedCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = n * 2; Realloc(nOldAllocatedCount); } m_nCount = n; memset(&m_pElements[num], 0, sizeof(T) * (m_nCount - num)); } T* Grow(unsigned int n) { int nStart = m_nCount; m_nCount += n; if (m_nCount > m_nAllocatedCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = m_nCount * 2; Realloc(nOldAllocatedCount); } return &m_pElements[nStart]; } T* GrowReset(unsigned int n) { int num = m_nAllocatedCount; T* Obj = AddIndex(n); if (num != m_nAllocatedCount) { memset(&m_pElements[num], 0, sizeof(T) * (m_nAllocatedCount - num)); } return Obj; } unsigned int* GetNumAddr(void) { return &m_nCount; } T** GetDataAddr(void) { return &m_pElements; } T* Data(void) const { return m_pElements; } T& Get(unsigned int id) const { return m_pElements[id]; } void Assign(TArray& fa) { m_pElements = fa.m_pElements; m_nCount = fa.m_nCount; m_nAllocatedCount = fa.m_nAllocatedCount; } /*const TArray operator=(TArray fa) const { TArray<T> t = TArray(fa.m_nCount,fa.m_nAllocatedCount); for ( int i=0; i<fa.Num(); i++ ) { t.AddElem(fa[i]); } return t; }*/ const T& operator[](unsigned int i) const { assert(i < m_nCount); return m_pElements[i]; } T& operator[](unsigned int i) { assert(i < m_nCount); return m_pElements[i]; } T& operator * () { assert(m_nCount > 0); return *m_pElements; } TArray<T> operator()(unsigned int Start) { assert(Start < m_nCount); return TArray<T>(m_pElements + Start, m_nCount - Start); } TArray<T> operator()(unsigned int Start, unsigned int Count) { assert(Start < m_nCount); assert(Start + Count <= m_nCount); return TArray<T>(m_pElements + Start, Count); } // For simple types only TArray(const TArray<T>& cTA) { m_pElements = NULL; m_nCount = m_nAllocatedCount = cTA.Num(); Realloc(0); if (m_pElements) { memcpy(m_pElements, &cTA[0], m_nCount * sizeof(T)); } /*for (unsigned int i=0; i<cTA.Num(); i++ ) { AddElem(cTA[i]); }*/ } inline TArray& operator = (const TArray& cTA) { Free(); new(this)TArray(cTA); return *this; } void ClearArr(void) { m_nCount = 0; m_nAllocatedCount = 0; m_pElements = NULL; } void Clear(void) { memset(m_pElements, 0, m_nCount * sizeof(T)); } void AddString(const char* szStr) { assert(szStr); int nLen = strlen(szStr) + 1; T* pDst = Grow(nLen); memcpy(pDst, szStr, nLen); } void Set(unsigned int m) { memset(m_pElements, m, m_nCount * sizeof(T)); } ILINE T* AddIndex(unsigned int inc) { unsigned int nIndex = m_nCount; unsigned int nNewCount = m_nCount + inc; if (nNewCount > m_nAllocatedCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = nNewCount + (nNewCount >> 1) + 10; Realloc(nOldAllocatedCount); } m_nCount = nNewCount; return &m_pElements[nIndex]; } T& Insert(unsigned int nIndex, unsigned int inc = 1) { m_nCount += inc; if (m_nCount > m_nAllocatedCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = m_nCount + (m_nCount >> 1) + 32; Realloc(nOldAllocatedCount); } memmove(&m_pElements[nIndex + inc], &m_pElements[nIndex], (m_nCount - inc - nIndex) * sizeof(T)); return m_pElements[nIndex]; } void AddIndexNoCache(unsigned int inc) { m_nCount += inc; if (m_nCount > m_nAllocatedCount) { int nOldAllocatedCount = m_nAllocatedCount; m_nAllocatedCount = m_nCount; Realloc(nOldAllocatedCount); } } void Add(const T& elem){AddElem(elem); } void AddElem(const T& elem) { unsigned int m = m_nCount; AddIndex(1); m_pElements[m] = elem; } void AddElemNoCache(const T& elem) { unsigned int m = m_nCount; AddIndexNoCache(1); m_pElements[m] = elem; } int Find(const T& p) { for (unsigned int i = 0; i < m_nCount; i++) { if (p == (*this)[i]) { return i; } } return -1; } void Delete(unsigned int n){DelElem(n); } void DelElem(unsigned int n) { // memset(&m_pElements[n],0,sizeof(T)); _Remove(n, 1); } // 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(); } void resize(unsigned int nSize) { reserve(nSize); m_nCount = nSize; } void reserve(unsigned int nSize) { if (nSize > m_nAllocatedCount) { Alloc(nSize); } } 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); } void pop_back () {m_nCount--; } void erase (T* pElem) { int n = int(pElem - m_pElements); assert(n >= 0 && n < m_nCount); _Remove(n, 1); } T* begin() {return m_pElements; } T* end() {return m_pElements + m_nCount; } T last() {return m_pElements[m_nCount - 1]; } const T* begin() const {return m_pElements; } const T* end() const {return m_pElements + m_nCount; } int GetMemoryUsage() const { return (int)(m_nAllocatedCount * sizeof(T)); } }; template <class T> inline void Exchange(T& X, T& Y) { const T Tmp = X; X = Y; Y = Tmp; } #endif // CRYINCLUDE_CRYCOMMON_TARRAY_H