#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 // TARRAY(int) - none/none #define TARRAYREF(TYPE) TArrayDynamic, TDesNDes, CNullClass> // TARRAYREF(CStr) - constructor/destructor #define TARRAYPTR(TYPE) TArrayDynamic, TDesNDEL, CNullClass> // TARRAYREF(CStr*) - new/delete #define TARRAYPTR2(TYPE) TArrayDynamic, TDesNDEL2, CNullClass> // // TARRAYREF(char*) - malloc/free #define TARRAYSIMPLE(TYPE) TArraySimple // 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 inline void SwapValue(TYPE& a, TYPE& b) { a ^= b; b ^= a; a ^= b; } template 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 struct TCon1None { // constructor: do NOTHING static void Construct(TYPE* pData) { ASSERT(pData); } }; template struct TCon1Con { // constructor: call the constructor... static void Construct(TYPE* pData) { ASSERT(pData); new (pData) TYPE; } }; template struct TCon1AZ { // constructor: assign zero. static void Construct(TYPE* pData) { ASSERT(pData); *pData = 0; } }; template struct TCon1FZ { // constructor: fill with zero static void Construct(TYPE* pData) { ASSERT(pData); memset(pData, 0, sizeof(TYPE)); } }; template struct TConNNone { // constructor: do NOTHING static void Construct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); } }; template struct TConNCon : public TCon1Con { // constructor: call the constructor static void Construct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); while(nCount-- > 0) { TCon1Con::Construct(pData++); } } }; template struct TConNAZ : public TCon1AZ { // constructor: assign zero static void Construct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); while(nCount-- > 0) { TCon1AZ::Construct(pData++); } } }; template 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 struct TDes1None { // destructor: do NOTHING static void Destruct(TYPE* pData) { ASSERT(pData); } }; template struct TDes1Des { // destructor: call the destructor static void Destruct(TYPE* pData) { ASSERT(pData); pData-> ~TYPE(); } }; template struct TDes1AZ { // destructor: assign zero static void Destruct(TYPE* pData) { ASSERT(pData); *pData = 0; } }; template struct TDes1FZ { // destructor: fill with zero static void Destruct(TYPE* pData) { ASSERT(pData); memset(pData, 0, sizeof(TYPE)); } }; template struct TDesNNone { // destructor: do NOTHING static void Destruct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); } }; template struct TDesNDes : public TDes1Des { // destructor: call the destructor static void Destruct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); while(nCount-- > 0) { TDes1Des::Destruct(pData++); } } }; template struct TDesNAZ : public TDes1AZ { // destructor: assign zero static void Destruct(TYPE* pData, int nCount) { ASSERT((nCount >= 0) && (pData || (nCount == 0))); while(nCount-- > 0) { TDes1AZ::Destruct(pData++); } } }; template 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 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 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 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& 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& 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& that) const { return IsEqual(that); } BOOL operator != (const TArray& 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& that) { // append array... int nSize = that.m_nSize; if (nSize > 0) { memcpy(&Add(nSize), that.m_pData, nSize * sizeof(TYPE)); } } void Assign(const TArray& that) { // append array... int nSize = that.m_nSize; SetSize(nSize); if (nSize > 0) { memcpy(m_pData, that.m_pData, nSize * sizeof(TYPE)); } } TArray& operator = (const TArray& that) { Assign(that); return *this; } void operator *= (const TArray& 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& 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& 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& 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 TArrayDynamic : public TArray { /* 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::Reset(); } BOOL IsEqual(const TArrayDynamic& 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& that) const { return IsEqual(that); } BOOL operator != (const TArrayDynamic& 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::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::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::Del(nIndex, nCount); } int DelFind(TYPE data) { int nIndex = Find(data); if (0 <= nIndex) { Del(nIndex); } return nIndex; } void Append(const TArrayDynamic& 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& 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& operator = (const TArrayDynamic& that) { Assign(that); return *this; } }; template class TArraySimple : public TArrayDynamic, TDesNNone, BaseClass> { public: BOOL IsEqual(const TArraySimple& that) const { return TArray::IsEqual(that); } BOOL operator == (const TArraySimple& that) const { return TArray::IsEqual(that); } BOOL operator != (const TArraySimple& that) const { return !TArray::IsEqual(that); } void Append(const TArraySimple& that) { // append array... int nSize = that.m_nSize; if (nSize > 0) { memcpy(&TArray::Add(nSize), that.m_pData, nSize * sizeof(TYPE)); } } void Assign(const TArraySimple& that) { // append array... int nSize = that.m_nSize; TArray::SetSize(nSize); if (nSize > 0) { memcpy(m_pData, that.m_pData, nSize * sizeof(TYPE)); } } TArraySimple& operator = (const TArraySimple& that) { Assign(that); return *this; } }; #endif // !defined(__ARRAY__)