////////////////////////////////////////////////////////////////////////////// //文件 TObjectArray.h //主要功能: ///////////////////////////////////////////////////////////////////////////// #pragma once namespace NSet { #ifndef _WIN64 typedef long DF_LONG; //定义32位整型 #else typedef __int64 DF_LONG; //定义64位整型 #endif template 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& src); void Copy(const TObjectArray& 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* 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; }; //类实现 template TObjectArray::TObjectArray() { m_pData = NULL; m_nSize = m_nMaxSize = m_nGrowBy = 0; } template TObjectArray::~TObjectArray() { RemoveAll(); } template DF_LONG TObjectArray::GetSize() const { return m_nSize; } template DF_LONG TObjectArray::GetCount() const { return m_nSize; } template bool TObjectArray::IsEmpty() const { return m_nSize == 0; } template DF_LONG TObjectArray::GetUpperBound() const { return m_nSize-1; } template void TObjectArray::RemoveAll() { SetSize(0, -1); } template void TObjectArray::DepthErase() { for(DF_LONG i=0; i T* TObjectArray::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 const T* TObjectArray::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 void TObjectArray::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 const T*& TObjectArray::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 T*& TObjectArray::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 const T** TObjectArray::GetData() const { return (const T**)m_pData; } template T** TObjectArray::GetData() { return (T**)m_pData; } template DF_LONG TObjectArray::Add(T* newElement) { DF_LONG nIndex = m_nSize; SetAtGrow(nIndex, newElement); return nIndex; } template const T* TObjectArray::operator[](DF_LONG nIndex) const { return GetAt(nIndex); } template T*& TObjectArray::operator[](DF_LONG nIndex) { return ElementAt(nIndex); } template void TObjectArray::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); 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 DF_LONG TObjectArray::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 void TObjectArray::Copy(const TObjectArray& src) { ASSERT(this != &src); // cannot append to itself if(this != &src) { SetSize(src.m_nSize); for(DF_LONG i=0; i void TObjectArray::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 void TObjectArray::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 void TObjectArray::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 void TObjectArray::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 void TObjectArray::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 //取消类型定义 };//namespace using namespace NSet;