// // CLUAArray implementation. // template CLUAArray::CLUAArray() : m_cElements(0), m_cMax(0), m_pData(NULL) { } template CLUAArray::~CLUAArray() { SetSize(0); } template DWORD CLUAArray::GetSize() const { return m_cElements; } template DWORD CLUAArray::GetAllocSize() const { return m_cMax; } template bool CLUAArray::IsEmpty() const { return (m_cElements ? false : true); } template VOID CLUAArray::SetSize(DWORD iNewSize) { ASSERT(iNewSize >= 0, "Size cannot be negative"); if (iNewSize) { if (m_pData) { // we already allocated enough space. if (iNewSize <= m_cMax) { if (iNewSize < m_cElements) { DestructElements(m_pData + iNewSize, m_cElements - iNewSize); } else { ConstructElements(m_pData + m_cElements, iNewSize - m_cElements); } m_cElements = iNewSize; } else // we don't have enough space. { // we allocate double of the requested size. m_cMax = iNewSize * 2; TYPE* pNewData = (TYPE*) new BYTE [m_cMax * sizeof(TYPE)]; memcpy(pNewData, m_pData, m_cElements * sizeof(TYPE)); ConstructElements(pNewData + m_cElements, iNewSize - m_cElements); delete [] (BYTE*)m_pData; m_pData = pNewData; m_cElements = iNewSize; } } else // it's an empty array, we need to allocate spaces for iNewSize elements. { m_pData = (TYPE*) new BYTE [iNewSize * sizeof(TYPE)]; ConstructElements(m_pData, iNewSize); m_cElements = m_cMax = iNewSize; } } else // if it's 0, we should destroy all the Elements in the array. { if (m_pData) { DestructElements(m_pData, m_cElements); delete [] (BYTE*)m_pData; m_pData = NULL; } m_cElements = 0; } } template VOID CLUAArray::SetAtGrow(DWORD iIndex, TYPE newElement) { ASSERT(iIndex >= 0, "Index cannot be negative"); if (iIndex >= m_cElements) { SetSize(iIndex + 1); } m_pData[iIndex] = newElement; } template DWORD CLUAArray::Add(TYPE newElement) { SetAtGrow(m_cElements, newElement); return m_cElements; } template DWORD CLUAArray::Append(const CLUAArray& src) { ASSERT(this != &src, "Cannot append to itself"); DWORD nOldSize = m_cElements; SetSize(m_cElements + src.m_cElements); CopyElements(m_pData + nOldSize, src.m_pData, src.m_cElements); return nOldSize; } template VOID CLUAArray::Copy(const CLUAArray& src) { ASSERT(this != &src, "Cannot copy to itself"); SetSize(src.m_cElements); CopyElements(m_pData, src.m_pData, src.m_cElements); } template VOID CLUAArray::RemoveAt(DWORD iIndex, DWORD nCount) { ASSERT(iIndex >= 0, "Index cannot be negative"); ASSERT(nCount >= 0, "Count cannot be negative"); ASSERT(iIndex + nCount <= m_nSize, "Requested to remove too many items"); // just remove a range int nMoveCount = m_nSize - (iIndex + nCount); if (nMoveCount) { memcpy(&m_pData[iIndex], &m_pData[iIndex + nCount], nMoveCount * sizeof(BYTE)); } m_nSize -= nCount; } template const TYPE& CLUAArray::operator[](DWORD iIndex) const { ASSERT(iIndex >= 0 && iIndex < m_cElements, "Index out of bound"); return m_pData[iIndex]; } template TYPE& CLUAArray::operator[](DWORD iIndex) { ASSERT(iIndex >= 0 && iIndex < m_cElements, "Index out of bound"); return m_pData[iIndex]; } template const TYPE& CLUAArray::GetAt(DWORD iIndex) const { ASSERT(iIndex >= 0 && iIndex < m_cElements, "Index out of bound"); return m_pData[iIndex]; } template TYPE& CLUAArray::GetAt(DWORD iIndex) { ASSERT(iIndex >= 0 && iIndex < m_cElements, "Index out of bound"); return m_pData[iIndex]; } template VOID CLUAArray::DestructElements(TYPE* pElements, DWORD nCount) { for (; nCount--; pElements++) { pElements->~TYPE(); } } // // define placement new and delete. // inline void *__cdecl operator new(size_t, void *P) { return (P); } inline void __cdecl operator delete(void *, void *) { return; } template VOID CLUAArray::ConstructElements(TYPE* pElements, DWORD nCount) { // we zero memory first here. memset(pElements, 0, nCount * sizeof(TYPE)); for (; nCount--; pElements++) { new (pElements) TYPE; } } template VOID CLUAArray::CopyElements(TYPE* pDest, const TYPE* pSrc, DWORD nCount) { while (nCount--) { *pDest++ = *pSrc++; } }