www.pudn.com > GOS.rar > KArray.cpp
// KArray.cpp: implementation of the KArray class. // ////////////////////////////////////////////////////////////////////// #include "..\stdafx.h" #include "KArray.h" #if !defined(AFX_KARRAY_CPP__F19FEDC1_6BDB_46F8_889C_1C0688F0AD0E__INCLUDED_) #define AFX_KARRAY_CPP__F19FEDC1_6BDB_46F8_889C_1C0688F0AD0E__INCLUDED_ template__inline void ConstructElements(TYPE* pElements, int nCount) { // first do bit-wise zero initialization ZeroMemory((void*)pElements, nCount * sizeof(TYPE)); for (; nCount--; pElements++) new ((void*)pElements) TYPE; } template __inline void DestructElements(TYPE* pElements, int nCount) { // call the destructor(s) for (; nCount--; pElements++) pElements->~TYPE(); } template __inline void CopyElements(TYPE* pDest, const TYPE* pSrc, int nCount) { // default is element-copy using assignment while (nCount--) *pDest++ = *pSrc++; } ///////////////////////////////////////////////////////////////////////////// // KArray inline functions template __inline int KArray ::GetSize() const { return m_nSize; } template __inline void KArray ::RemoveAll() { SetSize(0, -1); } template __inline TYPE KArray ::GetAt(int nIndex) const { return m_pData[nIndex]; } template __inline void KArray ::SetAt(int nIndex, TYPE newElement) { m_pData[nIndex] = newElement; } template __inline TYPE& KArray ::ElementAt(int nIndex) { return m_pData[nIndex]; } template __inline const TYPE* KArray ::GetData() const { return (const TYPE*)m_pData; } template __inline TYPE* KArray ::GetData() { return (TYPE*)m_pData; } template __inline int KArray ::Add(TYPE newElement) { int nIndex = m_nSize; SetAtGrow(nIndex, newElement); return nIndex; } template __inline TYPE KArray ::operator[](int nIndex) const { return GetAt(nIndex); } template __inline TYPE& KArray ::operator[](int nIndex) { return ElementAt(nIndex); } template __inline void KArray ::InsertAt(int nIndex, TYPE newElement) { InsertAt(nIndex,newElement,1); } template __inline void KArray ::RemoveAt(int nIndex) { RemoveAt(nIndex,1); } ///////////////////////////////////////////////////////////////////////////// // KArray out-of-line functions template KArray ::KArray() { m_pData = NULL; m_nSize = m_nMaxSize = m_nGrowBy = 0; } template KArray ::~KArray() { if (m_pData != NULL) { DestructElements (m_pData, m_nSize); delete[] (BYTE*)m_pData; } } template void KArray ::SetSize(int nNewSize, int nGrowBy) { if (nGrowBy != -1) m_nGrowBy = nGrowBy; // set new size if (nNewSize == 0) { // shrink to nothing if (m_pData != NULL) { DestructElements (m_pData, m_nSize); delete[] (BYTE*)m_pData; m_pData = NULL; } m_nSize = m_nMaxSize = 0; } else if (m_pData == NULL) { m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)]; ConstructElements (m_pData, nNewSize); m_nSize = m_nMaxSize = nNewSize; } else if (nNewSize <= m_nMaxSize) { // it fits if (nNewSize > m_nSize) { // initialize the new elements ConstructElements (&m_pData[m_nSize], nNewSize-m_nSize); } else if (m_nSize > nNewSize) { // destroy the old elements DestructElements (&m_pData[nNewSize], m_nSize-nNewSize); } m_nSize = nNewSize; } else { // otherwise, grow array int 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); } int nNewMax; if (nNewSize < m_nMaxSize + nGrowBy) nNewMax = m_nMaxSize + nGrowBy; // granularity else nNewMax = nNewSize; // no slush // copy new data from old TYPE* pNewData=(TYPE*) new BYTE[nNewMax*sizeof(TYPE)]; CopyMemory(pNewData, m_pData, m_nSize * sizeof(TYPE)); ConstructElements (&pNewData[m_nSize], nNewSize-m_nSize); // get rid of old stuff (note: no destructors called) delete[] (BYTE*)m_pData; m_pData = (TYPE*)pNewData; m_nSize = nNewSize; m_nMaxSize = nNewMax; } } template int KArray ::Append(const KArray& src) { int nOldSize = m_nSize; SetSize(m_nSize + src.m_nSize); CopyElements (m_pData + nOldSize, src.m_pData, src.m_nSize); return nOldSize; } template void KArray ::Copy(const KArray& src) { SetSize(src.m_nSize); CopyElements (m_pData, src.m_pData, src.m_nSize); } template void KArray ::FreeExtra() { if (m_nSize != m_nMaxSize) { // shrink to desired size TYPE* pNewData = NULL; if (m_nSize != 0) { pNewData = (TYPE*) new BYTE[m_nSize*sizeof(TYPE)]; // copy new data from old CopyMemory(pNewData, m_pData, m_nSize * sizeof(TYPE)); } // get rid of old stuff (note: no destructors called) delete[] (BYTE*)m_pData; m_pData = pNewData; m_nMaxSize = m_nSize; } } template void KArray ::SetAtGrow(int nIndex, TYPE newElement) { if (nIndex >= m_nSize) SetSize(nIndex+1, -1); m_pData[nIndex] = newElement; } template void KArray ::InsertAt(int nIndex, TYPE newElement, int nCount /*=1*/) { 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 int nOldSize = m_nSize; SetSize(m_nSize + nCount, -1); // grow it to new size // destroy intial data before copying over it DestructElements (&m_pData[nOldSize], nCount); // shift old data up to fill gap CopyMemory(&m_pData[nIndex+nCount], &m_pData[nIndex], (nOldSize-nIndex) * sizeof(TYPE)); // re-init slots we copied from ConstructElements (&m_pData[nIndex], nCount); } // insert new value in the gap while (nCount--) m_pData[nIndex++] = newElement; } template void KArray ::RemoveAt(int nIndex, int nCount) { // just remove a range int nMoveCount = m_nSize - (nIndex + nCount); DestructElements (&m_pData[nIndex], nCount); if (nMoveCount) CopyMemory(&m_pData[nIndex], &m_pData[nIndex + nCount], nMoveCount * sizeof(TYPE)); m_nSize -= nCount; } template void KArray ::InsertAt(int nStartIndex, KArray* pNewArray) { if (pNewArray->GetSize() > 0) { InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize()); for (int i = 0; i < pNewArray->GetSize(); i++) SetAt(nStartIndex + i, pNewArray->GetAt(i)); } } #endif // !defined(AFX_KARRAY_CPP__F19FEDC1_6BDB_46F8_889C_1C0688F0AD0E__INCLUDED_)