You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
9.8 KiB
C

1 month ago
//////////////////////////////////////////////////////////////////////////////
//<2F>ļ<EFBFBD> TObjectArray.h
//<2F><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>:
/////////////////////////////////////////////////////////////////////////////
#pragma once
namespace NSet
{
#ifndef _WIN64
typedef long DF_LONG; //<2F><><EFBFBD><EFBFBD>32λ<32><CEBB><EFBFBD><EFBFBD>
#else
typedef __int64 DF_LONG; //<2F><><EFBFBD><EFBFBD>64λ<34><CEBB><EFBFBD><EFBFBD>
#endif
template <class T> class TObjectArray
{
public:
// Construction
TObjectArray();
~TObjectArray();
// Attributes
DF_LONG GetSize() const;
DF_LONG GetCount() const;
bool IsEmpty() const;
DF_LONG GetUpperBound() const;
void SetSize(DF_LONG nNewSize, DF_LONG nGrowBy = -1);
// Operations
// Clean up
void FreeExtra();
void RemoveAll();
void DepthErase();
// Accessing elements
const T* GetAt(DF_LONG nIndex) const;
T* GetAt(DF_LONG nIndex);
void SetAt(DF_LONG nIndex, T* newElement);
const T*& ElementAt(DF_LONG nIndex) const;
T*& ElementAt(DF_LONG nIndex);
// Direct Access to the element data (may return NULL)
const T** GetData() const;
T** GetData();
// Potentially growing the array
void SetAtGrow(DF_LONG nIndex, T* newElement);
DF_LONG Add(T* newElement);
DF_LONG Append(const TObjectArray<T>& src);
void Copy(const TObjectArray<T>& src);
// overloaded operator helpers
const T* operator[](DF_LONG nIndex) const;
T*& operator[](DF_LONG nIndex);
// Operations that move elements around
void InsertAt(DF_LONG nIndex, T* newElement, DF_LONG nCount = 1);
void RemoveAt(DF_LONG nIndex, DF_LONG nCount = 1);
void InsertAt(DF_LONG nStartIndex, TObjectArray<T>* pNewArray);
// Implementation
protected:
T** m_pData; // the actual array of data
DF_LONG m_nSize; // # of elements (upperBound - 1)
DF_LONG m_nMaxSize; // max allocated
DF_LONG m_nGrowBy; // grow amount
protected:
// local typedefs for class templates
typedef void* BASE_TYPE;
typedef void* BASE_ARG_TYPE;
};
//<2F><>ʵ<EFBFBD><CAB5>
template<class T>
TObjectArray<T>::TObjectArray()
{
m_pData = NULL;
m_nSize = m_nMaxSize = m_nGrowBy = 0;
}
template<class T>
TObjectArray<T>::~TObjectArray()
{
RemoveAll();
}
template<class T>
DF_LONG TObjectArray<T>::GetSize() const
{
return m_nSize;
}
template<class T>
DF_LONG TObjectArray<T>::GetCount() const
{
return m_nSize;
}
template<class T>
bool TObjectArray<T>::IsEmpty() const
{
return m_nSize == 0;
}
template<class T>
DF_LONG TObjectArray<T>::GetUpperBound() const
{
return m_nSize-1;
}
template<class T>
void TObjectArray<T>::RemoveAll()
{
SetSize(0, -1);
}
template<class T>
void TObjectArray<T>::DepthErase()
{
for(DF_LONG i=0; i<m_nSize; i++)
{
delete m_pData[i];
}
RemoveAll();
}
template<class T>
T* TObjectArray<T>::GetAt(DF_LONG nIndex)
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if(nIndex >= 0 && nIndex < m_nSize)
return m_pData[nIndex];
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
template<class T>
const T* TObjectArray<T>::GetAt(DF_LONG nIndex) const
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if(nIndex >= 0 && nIndex < m_nSize)
return m_pData[nIndex];
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
template<class T>
void TObjectArray<T>::SetAt(DF_LONG nIndex, T* newElement)
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if(nIndex >= 0 && nIndex < m_nSize)
m_pData[nIndex] = newElement;
else
{
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
}
template<class T>
const T*& TObjectArray<T>::ElementAt(DF_LONG nIndex) const
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if(nIndex >= 0 && nIndex < m_nSize)
return m_pData[nIndex];
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
template<class T>
T*& TObjectArray<T>::ElementAt(DF_LONG nIndex)
{
ASSERT(nIndex >= 0 && nIndex < m_nSize);
if(nIndex >= 0 && nIndex < m_nSize)
return m_pData[nIndex];
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
template<class T>
const T** TObjectArray<T>::GetData() const
{
return (const T**)m_pData;
}
template<class T>
T** TObjectArray<T>::GetData()
{
return (T**)m_pData;
}
template<class T>
DF_LONG TObjectArray<T>::Add(T* newElement)
{
DF_LONG nIndex = m_nSize;
SetAtGrow(nIndex, newElement);
return nIndex;
}
template<class T>
const T* TObjectArray<T>::operator[](DF_LONG nIndex) const
{
return GetAt(nIndex);
}
template<class T>
T*& TObjectArray<T>::operator[](DF_LONG nIndex)
{
return ElementAt(nIndex);
}
template<class T>
void TObjectArray<T>::SetSize(DF_LONG nNewSize, DF_LONG nGrowBy)
{
ASSERT(nNewSize >= 0);
#ifndef _GDF_QT
if(nNewSize < 0 )
AfxThrowInvalidArgException();
#endif
if (nGrowBy >= 0)
m_nGrowBy = nGrowBy; // set new size
if (nNewSize == 0)
{
// shrink to nothing
if (m_pData != NULL)
{
delete[]m_pData;
m_pData = NULL;
}
m_nSize = m_nMaxSize = 0;
}
else if (m_pData == NULL)
{
// create buffer big enough to hold number of requested elements or
// m_nGrowBy elements, whichever is larger.
DF_LONG nAllocSize = __max(nNewSize, m_nGrowBy);
m_pData = new T*[nAllocSize];
memset(m_pData, 0, (DF_LONG)nAllocSize);
m_nSize = nNewSize;
m_nMaxSize = nAllocSize;
}
else if (nNewSize <= m_nMaxSize)
{
// it fits
if (nNewSize > m_nSize)
{
// initialize the new elements
memset((m_pData + m_nSize), 0, (DF_LONG)(nNewSize-m_nSize));
}
m_nSize = nNewSize;
}
else
{
// otherwise, grow array
nGrowBy = m_nGrowBy;
if (nGrowBy == 0)
{
// heuristically determine growth when nGrowBy == 0
// (this avoids heap fragmentation in many situations)
nGrowBy = m_nSize / 8;
nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
}
DF_LONG nNewMax;
if (nNewSize < m_nMaxSize + nGrowBy)
nNewMax = m_nMaxSize + nGrowBy; // granularity
else
nNewMax = nNewSize; // no slush
ASSERT(nNewMax >= m_nMaxSize); // no wrap around
#ifndef _GDF_QT
if(nNewMax < m_nMaxSize)
AfxThrowInvalidArgException();
#endif
T** pNewData = new T*[nNewMax];
// copy new data from old
for(DF_LONG i=0; i<m_nSize; i++)
{
pNewData[i] = m_pData[i];
}
// construct remaining elements
ASSERT(nNewSize > m_nSize);
memset((pNewData + m_nSize), 0, (DF_LONG)(nNewSize-m_nSize));
// get rid of old stuff (note: no destructors called)
delete[] m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
m_nMaxSize = nNewMax;
}
}
template<class T>
DF_LONG TObjectArray<T>::Append(const TObjectArray& src)
{
ASSERT(this != &src); // cannot append to itself
if(this == &src)
{
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
DF_LONG nOldSize = m_nSize;
SetSize(m_nSize + src.m_nSize);
for(DF_LONG i=0; i<src.m_nSize; i++)
{
m_pData[nOldSize + i] = src.m_pData[i];
}
return nOldSize;
}
template<class T>
void TObjectArray<T>::Copy(const TObjectArray& src)
{
ASSERT(this != &src); // cannot append to itself
if(this != &src)
{
SetSize(src.m_nSize);
for(DF_LONG i=0; i<src.m_nSize; i++)
{
m_pData[i] = src.m_pData[i];
}
}
}
template<class T>
void TObjectArray<T>::FreeExtra()
{
if (m_nSize != m_nMaxSize)
{
// shrink to desired size
T** pNewData = NULL;
if (m_nSize != 0)
{
pNewData = new T*[m_nSize];
// copy new data from old
for(DF_LONG i=0; i<m_nSize; i++)
{
pNewData[i] = m_pData[i];
}
}
// get rid of old stuff (note: no destructors called)
delete[] m_pData;
m_pData = pNewData;
m_nMaxSize = m_nSize;
}
}
template<class T>
void TObjectArray<T>::SetAtGrow(DF_LONG nIndex, T* newElement)
{
ASSERT(nIndex >= 0);
#ifndef _GDF_QT
if(nIndex < 0)
AfxThrowInvalidArgException();
#endif
if (nIndex >= m_nSize)
{
SetSize(nIndex+1, -1);
}
m_pData[nIndex] = newElement;
}
template<class T>
void TObjectArray<T>::InsertAt(DF_LONG nIndex, T* newElement, DF_LONG nCount /*=1*/)
{
ASSERT(nIndex >= 0); // will expand to meet need
ASSERT(nCount > 0); // zero or negative size not allowed
if(nIndex < 0 || nCount <= 0)
{
return;
}
if (nIndex >= m_nSize)
{
// adding after the end of the array
SetSize(nIndex + nCount, -1); // grow so nIndex is valid
}
else
{
// inserting in the middle of the array
DF_LONG nOldSize = m_nSize;
SetSize(m_nSize + nCount, -1); // grow it to new size
// re-init slots we copied from
for( DF_LONG i=(nOldSize-nIndex-1); i>-1; i-- )
{
m_pData[ nIndex + nCount + i ] = m_pData[ nIndex + i ];
}
memset((m_pData + nIndex), 0, (DF_LONG)(nCount));
}
// insert new value in the gap
ASSERT(nIndex + nCount <= m_nSize);
while (nCount--)
m_pData[nIndex++] = newElement;
}
template<class T>
void TObjectArray<T>::RemoveAt(DF_LONG nIndex, DF_LONG nCount)
{
ASSERT(nIndex >= 0);
ASSERT(nCount >= 0);
DF_LONG nUpperBound = nIndex + nCount;
ASSERT(nUpperBound <= m_nSize && nUpperBound >= nIndex && nUpperBound >= nCount);
if(nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))
{
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
// just remove a range
DF_LONG nMoveCount = m_nSize - (nUpperBound);
if (nMoveCount)
{
for(DF_LONG i=0; i<nMoveCount; i++)
{
m_pData[nIndex + i] = m_pData[nUpperBound + i];
}
}
m_nSize -= nCount;
}
template<class T>
void TObjectArray<T>::InsertAt(DF_LONG nStartIndex, TObjectArray* pNewArray)
{
ASSERT(pNewArray != NULL);
ASSERT_VALID(pNewArray);
ASSERT(nStartIndex >= 0);
if(pNewArray == NULL || nStartIndex < 0)
{
#ifndef _GDF_QT
AfxThrowInvalidArgException();
#endif
}
if (pNewArray->GetSize() > 0)
{
InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
for (DF_LONG i = 0; i < pNewArray->GetSize(); i++)
{
SetAt(nStartIndex + i, pNewArray->GetAt(i));
}
}
}
#undef DF_LONG //ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
};//namespace
using namespace NSet;