mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-25 11:45:53 +01:00
261 lines
6.0 KiB
C++
261 lines
6.0 KiB
C++
|
/* 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. */
|
||
|
|