/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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/Templates/StaticArray.h> /* Random access operator. */ template<class Type> inline void CStaticArray<Type>::operator=(const CStaticArray<Type> &arOriginal) { CopyArray(arOriginal); } /* * 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); 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; } } /* * Random access operator. */ // rcg10162001 wtf...I had to move this into the class definition itself. // I think it's an optimization bug; I didn't have this problem when I // didn't give GCC the "-O2" option. #if 0 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; } #endif /* * 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. */