Serious-Engine/Sources/Engine/Templates/StaticArray.cpp
2016-03-11 18:20:51 -06:00

274 lines
6.5 KiB
C++

/* 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/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. */