Serious-Engine/Sources/Engine/Templates/AllocationArray.cpp

216 lines
5.6 KiB
C++
Raw Normal View History

2016-03-12 01:20:51 +01:00
/* 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. */
2016-03-11 14:57:17 +01:00
#ifndef SE_INCL_ALLOCATIONARRAY_CPP
#define SE_INCL_ALLOCATIONARRAY_CPP
#ifdef PRAGMA_ONCE
#pragma once
#endif
#include <Engine/Templates/StaticStackArray.h>
#include <Engine/Templates/StaticStackArray.cpp>
#include <Engine/Templates/StaticArray.cpp>
extern BOOL _bAllocationArrayParanoiaCheck;
/*
* Default constructor.
*/
template<class Type>
inline CAllocationArray<Type>::CAllocationArray(void) :
CStaticArray<Type>(),
aa_aiFreeElements()
{
aa_ctAllocationStep = 256;
}
/*
* Destructor.
*/
template<class Type>
inline CAllocationArray<Type>::~CAllocationArray(void) {
};
/* Destroy all objects, and reset the array to initial (empty) state. */
template<class Type>
inline void CAllocationArray<Type>::Clear(void) {
// delete the objects themselves
CStaticArray<Type>::Clear();
// clear array of free indices
aa_aiFreeElements.Clear();
}
/*
* Set how many elements to allocate when stack overflows.
*/
template<class Type>
inline void CAllocationArray<Type>::SetAllocationStep(INDEX ctStep)
{
ASSERT(ctStep>0);
aa_ctAllocationStep = ctStep;
};
/*
* Create a given number of objects.
*/
template<class Type>
inline void CAllocationArray<Type>::New(INDEX iCount) {
// never call this!
ASSERT(FALSE);
};
/*
* Destroy all objects.
*/
template<class Type>
inline void CAllocationArray<Type>::Delete(void) {
// never call this!
ASSERT(FALSE);
}
/* Alocate a new object. */
template<class Type>
inline INDEX CAllocationArray<Type>::Allocate(void)
{
// if there are no more free indices
if (aa_aiFreeElements.Count()==0) {
// remember old size
INDEX ctOldSize = CStaticArray<Type>::Count();
// expand the array by the allocation step
Expand(ctOldSize+aa_ctAllocationStep);
// create new free indices
INDEX *piNewFree = aa_aiFreeElements.Push(aa_ctAllocationStep);
// fill them up
for(INDEX iNew=0; iNew<aa_ctAllocationStep; iNew++) {
piNewFree[iNew] = ctOldSize+iNew;
}
}
// pop one free index from the top of stack, and use that one
return aa_aiFreeElements.Pop();
}
/* Free object with given index. */
template<class Type>
inline void CAllocationArray<Type>::Free(INDEX iToFree)
{
#ifndef NDEBUG
// must be within pool limits
ASSERT(iToFree>=0 && iToFree<CStaticArray<Type>::Count());
// must not be free
if (_bAllocationArrayParanoiaCheck) {
ASSERT(IsAllocated(iToFree));
}
#endif
// push its index on top of the free stack
aa_aiFreeElements.Push() = iToFree;
}
/* Free all objects, but keep pool space. */
template<class Type>
inline void CAllocationArray<Type>::FreeAll(void)
{
// clear the free array
aa_aiFreeElements.PopAll();
// push as much free elements as there is pool space
INDEX ctSize = CStaticArray<Type>::Count();
INDEX *piNewFree = aa_aiFreeElements.Push(ctSize);
// fill them up
for(INDEX iNew=0; iNew<ctSize; iNew++) {
piNewFree[iNew] = iNew;
}
}
// check if an index is allocated (slow!)
template<class Type>
inline BOOL CAllocationArray<Type>::IsAllocated(INDEX i)
{
// must be within pool limits
ASSERT(i>=0 && i<CStaticArray<Type>::Count());
// for each free index
INDEX ctFree = aa_aiFreeElements.Count();
for(INDEX iFree=0; iFree<ctFree; iFree++) {
// if it is that one
if (aa_aiFreeElements[iFree]==i) {
// it is not allocated
return FALSE;
}
}
// if not found as free, it is allocated
return TRUE;
}
/* Random access operator. */
template<class Type>
inline Type &CAllocationArray<Type>::operator[](INDEX iObject)
{
#ifndef NDEBUG
ASSERT(this!=NULL);
// must be within pool limits
ASSERT(iObject>=0 && iObject<CStaticArray<Type>::Count());
// must not be free
if (_bAllocationArrayParanoiaCheck) {
ASSERT(IsAllocated(iObject));
}
#endif
return CStaticArray<Type>::operator[](iObject);
}
template<class Type>
inline const Type &CAllocationArray<Type>::operator[](INDEX iObject) const
{
#ifndef NDEBUG
ASSERT(this!=NULL);
// must be within pool limits
ASSERT(iObject>=0 && iObject<CStaticArray<Type>::Count());
// must not be free
if (_bAllocationArrayParanoiaCheck) {
ASSERT(IsAllocated(iObject));
}
#endif
return CStaticArray<Type>::operator[](iObject);
}
/* Get number of allocated objects in array. */
template<class Type>
INDEX CAllocationArray<Type>::Count(void) const
{
ASSERT(this!=NULL);
// it is pool size without the count of free elements
return CStaticArray<Type>::Count()-aa_aiFreeElements.Count();
}
/* Get index of a object from it's pointer. */
template<class Type>
INDEX CAllocationArray<Type>::Index(Type *ptObject)
{
ASSERT(this!=NULL);
INDEX i = CStaticArray<Type>::Index(ptMember);
ASSERT(IsAllocated(i));
return i;
}
/* Assignment operator. */
template<class Type>
CAllocationArray<Type> &CAllocationArray<Type>::operator=(
const CAllocationArray<Type> &aaOriginal)
{
ASSERT(this!=NULL);
(CStaticArray<Type>&)(*this) = (CStaticArray<Type>&)aaOriginal;
aa_aiFreeElements = aaOriginal.aa_aiFreeElements;
aa_ctAllocationStep = aaOriginal.aa_ctAllocationStep;
}
#endif /* include-once check. */