Serious-Engine/Sources/Engine/Templates/AllocationArray.cpp
Ryan C. Gordon 24cb244d43 First attempt to hand-merge Ryan's Linux and Mac OS X port.
This was a _ton_ of changes, made 15 years ago, so there are probably some
problems to work out still.

Among others: Engine/Base/Stream.* was mostly abandoned and will need to be
re-ported.

Still, this is a pretty good start, and probably holds a world record for
lines of changes or something.  :)
2016-03-28 23:46:13 -04:00

209 lines
5.2 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#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
this->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. */
// 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 &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);
}
#endif // 0
/* 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(this->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. */