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.
907 lines
22 KiB
C++
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__)
|