/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ #ifndef SE_INCL_STATICARRAY_CPP #define SE_INCL_STATICARRAY_CPP #ifdef PRAGMA_ONCE #pragma once #endif #define FOREACHINSTATICARRAY(array, type, iter) \ for(CStaticArrayIterator<type> iter(array); !iter.IsPastEnd(); iter.MoveToNext() ) #include <Engine/Base/Console.h> #include <Engine/Templates/StaticArray.h> /* * Default constructor. */ template<class Type> inline CStaticArray<Type>::CStaticArray(void) { sa_Count=0; sa_Array=NULL; } /* * Destructor. */ template<class Type> inline CStaticArray<Type>::~CStaticArray(void) { // if some objects were allocated if (sa_Count!=0) { // destroy them Delete(); } }; /* Random access operator. */ template<class Type> inline void CStaticArray<Type>::operator=(const CStaticArray<Type> &arOriginal) { CopyArray(arOriginal); } template<class Type> /* Destroy all objects, and reset the array to initial (empty) state. */ inline void CStaticArray<Type>::Clear(void) { if (sa_Count!=0) Delete(); } /* * Create a given number of objects. */ template<class Type> inline void CStaticArray<Type>::New(INDEX iCount) { ASSERT(this!=NULL && iCount>=0); // if no new members are needed in fact if (iCount==0) { // do nothing return; } //ASSERT(sa_Count==0 && sa_Array==NULL); #ifndef NDEBUG if(!(sa_Count==0 && sa_Array==NULL)) { if(sa_Array == NULL) { CPrintF("CStaticArray array not set!\n"); } else { CPrintF("CStaticArray new(%d) called while already holding %d elements!\n", iCount, sa_Count); } } #endif sa_Count = iCount; sa_Array = new Type[iCount+1]; //(+1 for cache-prefetch opt) }; /* Expand stack size but keep old objects. */ template<class Type> inline void CStaticArray<Type>::Expand(INDEX iNewCount) { ASSERT(this!=NULL && iNewCount>sa_Count); // if not already allocated if (sa_Count==0) { // just allocate New(iNewCount); return; // if already allocated } else { ASSERT(sa_Count!=0 && sa_Array!=NULL); // allocate new array with more space Type *ptNewArray = new Type[iNewCount+1]; //(+1 for cache-prefetch opt) // copy old objects for (INDEX iOld=0; iOld<sa_Count; iOld++) { ptNewArray[iOld] = sa_Array[iOld]; } // free old array delete[] sa_Array; // remember the new array sa_Count = iNewCount; sa_Array = ptNewArray; } } /* * Destroy all objects. */ template<class Type> inline void CStaticArray<Type>::Delete(void) { ASSERT(this!=NULL); ASSERT(sa_Count!=0 && sa_Array!=NULL); delete[] sa_Array; sa_Count = 0; sa_Array = NULL; } /* * Random access operator. */ template<class Type> inline Type &CStaticArray<Type>::operator[](INDEX i) { ASSERT(this!=NULL); ASSERT(i>=0 && i<sa_Count); // check bounds return sa_Array[i]; } template<class Type> inline const Type &CStaticArray<Type>::operator[](INDEX i) const { ASSERT(this!=NULL); ASSERT(i>=0 && i<sa_Count); // check bounds return sa_Array[i]; } /* * Get number of elements in array. */ template<class Type> INDEX CStaticArray<Type>::Count(void) const { ASSERT(this!=NULL); return sa_Count; } /* * Get index of a member from it's pointer */ template<class Type> INDEX CStaticArray<Type>::Index(Type *ptMember) { ASSERT(this!=NULL); INDEX i = ptMember-sa_Array; ASSERT(i>=0 && i<sa_Count); return i; } /* * Assignment operator. */ template<class Type> /* Copy all elements of another array into this one. */ void CStaticArray<Type>::CopyArray(const CStaticArray<Type> &arOriginal) { ASSERT(this!=NULL); ASSERT(&arOriginal!=NULL); ASSERT(this!=&arOriginal); // clear previous contents Clear(); // get count of elements in original array INDEX ctOriginal = arOriginal.Count(); // if the other array has no elements if (ctOriginal ==0) { return; } // create that much elements New(ctOriginal); // copy them all for (INDEX iNew=0; iNew<ctOriginal; iNew++) { sa_Array[iNew] = arOriginal[iNew]; } } /* Move all elements of another array into this one. */ template<class Type> void CStaticArray<Type>::MoveArray(CStaticArray<Type> &arOther) { ASSERT(this!=NULL); ASSERT(&arOther!=NULL); ASSERT(this!=&arOther); // clear previous contents Clear(); // if the other array has no elements if (arOther.Count()==0) { // no assignment return; } // move data from the other array into this one and clear the other one sa_Count = arOther.sa_Count; sa_Array = arOther.sa_Array; arOther.sa_Count = 0; arOther.sa_Array = NULL; } ///////////////////////////////////////////////////////////////////// // CStaticArrayIterator /* * Template class for iterating static array. */ template<class Type> class CStaticArrayIterator { private: INDEX sai_Index; // index of current element CStaticArray<Type> &sai_Array; // reference to array public: /* Constructor for given array. */ inline CStaticArrayIterator(CStaticArray<Type> &sa); /* Destructor. */ inline ~CStaticArrayIterator(void); /* Move to next object. */ inline void MoveToNext(void); /* Check if finished. */ inline BOOL IsPastEnd(void); /* Get current element. */ Type &Current(void) { return sai_Array[sai_Index]; } Type &operator*(void) { return sai_Array[sai_Index]; } operator Type *(void) { return &sai_Array[sai_Index]; } Type *operator->(void) { return &sai_Array[sai_Index]; } }; /* * Constructor for given array. */ template<class Type> inline CStaticArrayIterator<Type>::CStaticArrayIterator(CStaticArray<Type> &sa) : sai_Array(sa) { sai_Index = 0; } /* * Destructor. */ template<class Type> inline CStaticArrayIterator<Type>::~CStaticArrayIterator(void) { sai_Index = -1; } /* * Move to next object. */ template<class Type> inline void CStaticArrayIterator<Type>::MoveToNext(void) { ASSERT(this!=NULL); sai_Index++; } /* * Check if finished. */ template<class Type> inline BOOL CStaticArrayIterator<Type>::IsPastEnd(void) { ASSERT(this!=NULL); return sai_Index>=sai_Array.sa_Count; } #endif /* include-once check. */