Files
firestorm/Gameleap/code/mw4/Code/MW4Application/ARRAY.INL
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

907 lines
22 KiB
C++

#if !defined(__ARRAY__)
#define __ARRAY__
//{{NO_DEPENDENCIES}}
//
// Array Templates
//
#pragma warning(disable: 4786)
#ifndef NULL_CLASS_DEFINED
#define NULL_CLASS_DEFINED
class CNullClass {};
#endif
#define TARRAY(TYPE) TArray<TYPE, CNullClass> // TARRAY(int) - none/none
#define TARRAYREF(TYPE) TArrayDynamic<TYPE, TConNCon<TYPE>, TDesNDes<TYPE>, CNullClass> // TARRAYREF(CStr) - constructor/destructor
#define TARRAYPTR(TYPE) TArrayDynamic<TYPE, TConNFZ<TYPE>, TDesNDEL<TYPE>, CNullClass> // TARRAYREF(CStr*) - new/delete
#define TARRAYPTR2(TYPE) TArrayDynamic<TYPE, TConNFZ<TYPE>, TDesNDEL2<TYPE>, CNullClass> // // TARRAYREF(char*) - malloc/free
#define TARRAYSIMPLE(TYPE) TArraySimple<TYPE, CNullClass> // TARRAYSIMPLE(int), TARRAYZERO(float)
// above class definition
#define DECLARE_TARRAYREF_EX(CClass) inline void* _cdecl operator new(size_t nSize, CClass* pData) { return (void*)pData; } inline void _cdecl operator delete(void* p, CClass* pData) { }
#define DECLARE_TARRAYREF(CClass) class CClass; DECLARE_TARRAYREF_EX(CClass);
#define DECLARE_TARRAYREF_CLASS_EX(CClass, BaseClass) DECLARE_TARRAYREF(CClass) class CClass : public BaseClass { public: CClass() {} ~CClass() {} };
#define DECLARE_TARRAYREF_CLASS(Class,TYPE) DECLARE_TARRAYREF_CLASS_EX(Class, TARRAYREF(TYPE))
// in class definition
#define DECLARE_STATIC_CONSTRUCTION(CClass) inline void new##CClass() { new (this) CClass; } inline void delete##CClass() { this-> ~CClass(); }
template <class TYPE> inline void SwapValue(TYPE& a, TYPE& b)
{
a ^= b;
b ^= a;
a ^= b;
}
template <class TYPE> inline void SwapPointer(TYPE*& a, TYPE*& b)
{
TYPE* p;
p = a;
a = b;
b = p;
}
/*
All the structures starting with TCon are the Template-Constructor.
TCon1XXXX means the constructor for 1 element.
TConNXXXX means the constructor for arbitrary number of elements.
All the structures starting with TDes are the Template-Destructor.
*/
template <class TYPE>
struct TCon1None
{
// constructor: do NOTHING
static void Construct(TYPE* pData)
{
ASSERT(pData);
}
};
template <class TYPE>
struct TCon1Con
{
// constructor: call the constructor...
static void Construct(TYPE* pData)
{
ASSERT(pData);
new (pData) TYPE;
}
};
template <class TYPE>
struct TCon1AZ
{
// constructor: assign zero.
static void Construct(TYPE* pData)
{
ASSERT(pData);
*pData = 0;
}
};
template <class TYPE>
struct TCon1FZ
{
// constructor: fill with zero
static void Construct(TYPE* pData)
{
ASSERT(pData);
memset(pData, 0, sizeof(TYPE));
}
};
template <class TYPE>
struct TConNNone
{
// constructor: do NOTHING
static void Construct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
}
};
template <class TYPE>
struct TConNCon : public TCon1Con<TYPE>
{
// constructor: call the constructor
static void Construct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TCon1Con<TYPE>::Construct(pData++);
}
}
};
template <class TYPE>
struct TConNAZ : public TCon1AZ<TYPE>
{
// constructor: assign zero
static void Construct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TCon1AZ<TYPE>::Construct(pData++);
}
}
};
template <class TYPE>
struct TConNFZ
{
// constructor: fill with zero
static void Construct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
if (nCount > 0) {
memset(pData, 0, sizeof(TYPE) * nCount);
}
}
};
template <class TYPE>
struct TDes1None
{
// destructor: do NOTHING
static void Destruct(TYPE* pData)
{
ASSERT(pData);
}
};
template <class TYPE>
struct TDes1Des
{
// destructor: call the destructor
static void Destruct(TYPE* pData)
{
ASSERT(pData);
pData-> ~TYPE();
}
};
template <class TYPE>
struct TDes1AZ
{
// destructor: assign zero
static void Destruct(TYPE* pData)
{
ASSERT(pData);
*pData = 0;
}
};
template <class TYPE>
struct TDes1FZ
{
// destructor: fill with zero
static void Destruct(TYPE* pData)
{
ASSERT(pData);
memset(pData, 0, sizeof(TYPE));
}
};
template <class TYPE>
struct TDesNNone
{
// destructor: do NOTHING
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
}
};
template <class TYPE>
struct TDesNDes : public TDes1Des<TYPE>
{
// destructor: call the destructor
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TDes1Des<TYPE>::Destruct(pData++);
}
}
};
template <class TYPE>
struct TDesNAZ : public TDes1AZ<TYPE>
{
// destructor: assign zero
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TDes1AZ<TYPE>::Destruct(pData++);
}
}
};
template <class TYPE>
struct TDesNFZ
{
// destructor: fill with zero
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
if (nCount > 0) {
memset(pData, 0, sizeof(TYPE) * nCount);
}
}
};
template <class TYPE>
struct TDesNDEL
{
// destructor: fill with zero
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TYPE t = *pData++;
if (t)
delete t;
}
}
};
template <class TYPE>
struct TDesNDEL2
{
// destructor: fill with zero
static void Destruct(TYPE* pData, int nCount)
{
ASSERT((nCount >= 0) && (pData || (nCount == 0)));
while(nCount-- > 0) {
TYPE t = *pData++;
if (t)
delete [] t;
}
}
};
template <class TYPE, class BaseClass>
class TArray : public BaseClass
{
/*
This class is the classical array implementation.
*/
public:
typedef TYPE Type;
public: // This may should be protected or private, but...
TYPE* m_pData; // Data Type Pointer - classic data array pointer
int m_nSize; // Exact Array Size - size of array being used
protected:
int m_nGrowBy; // Number used to determine the allocate unit.
private:
int m_nSizeMax; // Allocated Array Size - It could be modified by SetGrowBy()... - size of array allocated (memory allocation)
public: // Construction & Desturction
TArray()
{
// as is...
m_pData = NULL;
m_nSize = m_nSizeMax = 0;
m_nGrowBy = 100;
}
~TArray()
{
// as is...
Reset();
}
void RemoveAll()
{
// remove all the elements, and free all the memory used.
// but no destruction of object-itself.
// IMPORTANT: don't call this method, when constructor/destructor should be called.
if (m_pData) {
ASSERT(m_nSizeMax > 0);
free(m_pData);
m_pData = NULL;
m_nSize = m_nSizeMax = 0;
} else {
ASSERT((m_nSize == 0) && (m_nSizeMax == 0));
}
}
void Reset()
{
// same with RemoveAll
RemoveAll();
}
void Swap(TArray<TYPE, BaseClass>& that)
{
SwapPointer(m_pData, that.m_pData);
SwapValue(m_nSize, that.m_nSize);
SwapValue(m_nGrowBy, that.m_nGrowBy);
SwapValue(m_nSizeMax, that.m_nSizeMax);
}
BOOL IsEqual(const TArray<TYPE, BaseClass>& that) const
{
int nSize = m_nSize;
if (nSize == that.m_nSize) {
if (nSize > 0) {
if (memcmp(m_pData, that.m_pData, nSize * sizeof(TYPE)) == 0) {
return TRUE;
}
} else {
return TRUE;
}
}
return FALSE;
}
BOOL operator == (const TArray<TYPE, BaseClass>& that) const
{
return IsEqual(that);
}
BOOL operator != (const TArray<TYPE, BaseClass>& that) const
{
return !IsEqual(that);
}
void SetAllValue(const TYPE one)
{
int i, nSize = m_nSize;
TYPE* pDest = m_pData;
for(i = 0; i < nSize; i++) {
*pDest = one;
pDest++;
}
}
void SetAll(const TYPE& one)
{
int i, nSize = m_nSize;
TYPE* pDest = m_pData;
for(i = 0; i < nSize; i++) {
*pDest = one;
pDest++;
}
}
int SetGrowBy(int nGrowBy)
{
ASSERT(nGrowBy >= 0);
// swap m_nGrowBy with nGrowBy, and return nGrowBy(old value)...
SwapValue(m_nGrowBy, nGrowBy);
return nGrowBy;
}
int GetSize() const
{
// as is...
return m_nSize;
}
void SetSize(int nSize)
{
ASSERT(nSize >= 0);
int nDiff = nSize - m_nSize;
if (nDiff != 0) {
if (nDiff < 0) {
// shrink
Del(m_nSize + nDiff, -nDiff);
} else {
// grow
Add(nDiff);
}
}
}
void ResetSize(int nSize)
{
Reset();
SetSize(nSize);
}
TYPE At(int nIndex) const // return data
{
// used to retrive values(as like char, int, long...)
// usually this method used retrieve small(accuping 1 or 2 CPU register) objects
ASSERT((0 <= nIndex) && (nIndex < m_nSize));
return m_pData[nIndex];
}
TYPE& GetAt(int nIndex) const // return reference to data
{
// used to retrive structures(as like POINT, RECT, MSG...)
// usually this method used retrieve large(accuping 2 or more CPU registers) objects
ASSERT(0 <= nIndex); // (nIndex < m_nSize) - used as pointer?
return m_pData[nIndex];
}
TYPE& operator [] (int nIndex) const // return reference to data
{
// same with "TYPE& GetAt(int nIndex) const"
ASSERT(0 <= nIndex); // (nIndex < m_nSize) - used as pointer?
return m_pData[nIndex];
}
int Find(TYPE data) const
{
int i, nSize = m_nSize;
TYPE* pData = m_pData;
for(i = 0; i < nSize; i++) {
if (*pData == data)
return i;
pData++;
}
return -1;
}
TYPE& Add(int nRoom = 1) // return reference to the first slot added
{
// add nRoom element(s), and return its starting memory reference...
ASSERT(nRoom > 0);
TYPE* pData = m_pData;
nRoom += m_nSize;
if (nRoom > m_nSizeMax) { // insufficient slot. grow array
int nSizeMax = nRoom + m_nGrowBy;
if (pData) {
pData = (TYPE*)realloc(pData, sizeof(TYPE) * nSizeMax);
} else {
pData = (TYPE*)malloc(sizeof(TYPE) * nSizeMax);
}
#if 0
if (!pData)
return *(TYPE*)NULL;
#endif
m_pData = pData;
m_nSizeMax = nSizeMax;
}
pData = &m_pData[m_nSize]; // point to the first slot added
m_nSize = nRoom;
return *pData;
}
TYPE& Ins(int nIndex, int nRoom = 1) // return reference to the first slot inserted
{
// insert nRoom element(s) before nIndex, and return its starting memory reference...
ASSERT(nRoom > 0);
ASSERT((0 <= nIndex) && (nIndex <= m_nSize));
int nSize = m_nSize - nIndex; // number of array to move
TYPE* pData = &Add(nRoom);
if (nSize) {
int nCount = nSize * sizeof(TYPE);
TYPE* pDataSrc = (TYPE*)((char*)pData - nCount);
memmove(&pDataSrc[nRoom], pDataSrc, nCount);
return *pDataSrc;
}
return *pData;
}
void FreeExtra()
{
// used to free extra memories(make m_nSizeMax same with m_nSize)...
if (m_pData) {
if (m_nSize) {
// realloc to smaller size: always successive.
m_pData = (TYPE*)realloc(m_pData, sizeof(TYPE) * m_nSize);
} else {
free(m_pData);
m_pData = NULL;
}
m_nSizeMax = m_nSize;
} else {
ASSERT(m_nSize == 0); // (m_nSizeMax == 0)
}
}
void Del(int nIndex, int nCount = 1)
{
// delete nCount element(s) where nIndex...
ASSERT(nCount > 0);
ASSERT((0 <= nIndex) && (nIndex <= m_nSize));
int nSize = m_nSize;
if (nIndex < nSize) {
ASSERT(nIndex + nCount <= nSize);
TYPE* pDataDst = &m_pData[nIndex];
nIndex += nCount;
int nMove = nSize - nIndex;
if (nMove) {
memcpy(pDataDst, &pDataDst[nCount], nMove * sizeof(TYPE));
}
m_nSize = nSize - nCount;
} else {
TRACE("TArray::Del() : deletion at the out of bound\n");
ASSERT(nIndex == nSize);
}
}
int DelFind(TYPE data)
{
int nIndex = Find(data);
if (0 <= nIndex) {
Del(nIndex);
}
return nIndex;
}
void Append(const TArray<TYPE, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
if (nSize > 0) {
memcpy(&Add(nSize), that.m_pData, nSize * sizeof(TYPE));
}
}
void Assign(const TArray<TYPE, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
SetSize(nSize);
if (nSize > 0) {
memcpy(m_pData, that.m_pData, nSize * sizeof(TYPE));
}
}
TArray<TYPE, BaseClass>& operator = (const TArray<TYPE, BaseClass>& that)
{
Assign(that);
return *this;
}
void operator *= (const TArray<TYPE, BaseClass>& that)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
ASSERT(nSize == that.GetSize());
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
const TYPE* pSrc = that.m_pData;
while(pStart < pEnd) {
*pStart *= *pSrc;
pSrc++;
pStart++;
}
}
void operator /= (const TArray<TYPE, BaseClass>& that)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
ASSERT(nSize == that.GetSize());
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
const TYPE* pSrc = that.m_pData;
while(pStart < pEnd) {
*pStart /= *pSrc;
pSrc++;
pStart++;
}
}
void operator += (const TArray<TYPE, BaseClass>& that)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
ASSERT(nSize == that.GetSize());
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
const TYPE* pSrc = that.m_pData;
while(pStart < pEnd) {
*pStart += *pSrc;
pSrc++;
pStart++;
}
}
void operator -= (const TArray<TYPE, BaseClass>& that)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
ASSERT(nSize == that.GetSize());
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
const TYPE* pSrc = that.m_pData;
while(pStart < pEnd) {
*pStart -= *pSrc;
pSrc++;
pStart++;
}
}
void operator *= (TYPE tValue)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
while(pStart < pEnd) {
*pStart *= tValue;
pStart++;
}
}
void operator /= (TYPE tValue)
{
ASSERT(tValue != 0);
int nSize = m_nSize;
ASSERT(nSize > 0);
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
while(pStart < pEnd) {
*pStart /= tValue;
pStart++;
}
}
void operator += (TYPE tValue)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
while(pStart < pEnd) {
*pStart += tValue;
pStart++;
}
}
void operator -= (TYPE tValue)
{
int nSize = m_nSize;
ASSERT(nSize > 0);
TYPE* pStart = m_pData;
TYPE* pEnd = &pStart[nSize];
while(pStart < pEnd) {
*pStart -= tValue;
pStart++;
}
}
};
template <class TYPE, class CON, class DES, class BaseClass>
class TArrayDynamic : public TArray<TYPE, BaseClass>
{
/*
This class is used to call constructor or destructor when enlarged or reduced.
CON: constructor template(TConNNone, TConNCon, TConNAZ, TConNFZ)
DES: destructor template(TDesNNone, TDesNCon, TDesNAZ, TDesNFZ)
*/
public:
~TArrayDynamic()
{
Reset();
}
void ConstructAll()
{
CON::Construct(m_pData, m_nSize);
}
void DestructAll()
{
DES::Destruct(m_pData, m_nSize);
}
void Reset()
{
// call the specified destructor(see DES)
DES::Destruct(m_pData, m_nSize);
TArray<TYPE, BaseClass>::Reset();
}
BOOL IsEqual(const TArrayDynamic<TYPE, CON, DES, BaseClass>& that) const
{
int nSize = m_nSize;
if (nSize == that.m_nSize) {
if (nSize > 0) {
const TYPE* pDest = m_pData;
const TYPE* pSrc = that.m_pData;
for(int i = 0; i < nSize; i++) {
if (!(*pDest == *pSrc)) {
return FALSE;
}
pDest++;
pSrc++;
}
}
return TRUE;
}
return FALSE;
}
BOOL operator == (const TArrayDynamic<TYPE, CON, DES, BaseClass>& that) const
{
return IsEqual(that);
}
BOOL operator != (const TArrayDynamic<TYPE, CON, DES, BaseClass>& that) const
{
return !IsEqual(that);
}
void SetSize(int nSize)
{
ASSERT(nSize >= 0);
int nDiff = nSize - m_nSize;
if (nDiff != 0) {
if (nDiff < 0) {
// shrink
Del(m_nSize + nDiff, -nDiff);
} else {
// grow
Add(nDiff);
}
}
}
void ResetSize(int nSize)
{
Reset();
SetSize(nSize);
}
TYPE& Add(int nRoom = 1)
{
ASSERT(nRoom >= 0);
TYPE* pData;
if (nRoom) {
pData = &TArray<TYPE, BaseClass>::Add(nRoom);
CON::Construct(pData, nRoom);
} else {
pData = NULL;
}
return *pData;
}
TYPE& Ins(int nIndex, int nRoom = 1)
{
ASSERT((0 <= nIndex) && (nIndex <= m_nSize) && (nRoom >= 0));
TYPE* pData;
if (nRoom) {
pData = &TArray<TYPE, BaseClass>::Ins(nIndex, nRoom);
CON::Construct(pData, nRoom);
} else {
pData = NULL;
}
return *pData;
}
void Del(int nIndex, int nCount = 1)
{
ASSERT(nCount > 0);
ASSERT((0 <= nIndex) && (nIndex < m_nSize));
TYPE* pData = &m_pData[nIndex];
DES::Destruct(pData, nCount);
TArray<TYPE, BaseClass>::Del(nIndex, nCount);
}
int DelFind(TYPE data)
{
int nIndex = Find(data);
if (0 <= nIndex) {
Del(nIndex);
}
return nIndex;
}
void Append(const TArrayDynamic<TYPE, CON, DES, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
TYPE* pDest = &Add(nSize);
const TYPE* pSrc = that.m_pData;
for(int i = 0; i < nSize; i++) {
*pDest = *pSrc;
pDest++;
pSrc++;
}
}
void Assign(const TArrayDynamic<TYPE, CON, DES, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
SetSize(nSize);
TYPE* pDest = m_pData;
const TYPE* pSrc = that.m_pData;
for(int i = 0; i < nSize; i++) {
*pDest = *pSrc;
pDest++;
pSrc++;
}
}
TArrayDynamic<TYPE, CON, DES, BaseClass>& operator = (const TArrayDynamic<TYPE, CON, DES, BaseClass>& that)
{
Assign(that);
return *this;
}
};
template <class TYPE, class BaseClass>
class TArraySimple : public TArrayDynamic<TYPE, TConNFZ<TYPE>, TDesNNone<TYPE>, BaseClass>
{
public:
BOOL IsEqual(const TArraySimple<TYPE, BaseClass>& that) const
{
return TArray<TYPE, BaseClass>::IsEqual(that);
}
BOOL operator == (const TArraySimple<TYPE, BaseClass>& that) const
{
return TArray<TYPE, BaseClass>::IsEqual(that);
}
BOOL operator != (const TArraySimple<TYPE, BaseClass>& that) const
{
return !TArray<TYPE, BaseClass>::IsEqual(that);
}
void Append(const TArraySimple<TYPE, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
if (nSize > 0) {
memcpy(&TArray<TYPE, BaseClass>::Add(nSize), that.m_pData, nSize * sizeof(TYPE));
}
}
void Assign(const TArraySimple<TYPE, BaseClass>& that)
{
// append array...
int nSize = that.m_nSize;
TArray<TYPE, BaseClass>::SetSize(nSize);
if (nSize > 0) {
memcpy(m_pData, that.m_pData, nSize * sizeof(TYPE));
}
}
TArraySimple<TYPE, BaseClass>& operator = (const TArraySimple<TYPE, BaseClass>& that)
{
Assign(that);
return *this;
}
};
#endif // !defined(__ARRAY__)