CStringArray源码解析

来源:互联网 发布:网络打印机远程打印 编辑:程序博客网 时间:2024/05/21 14:36

(1)成员函数

Construction

CStringArrayConstructs an empty array for CStringobjects.

Bounds

GetSizeGets number of elements in this array.GetUpperBoundReturns the largest valid index.SetSizeSets the number of elements to be contained in this array.

Operations

FreeExtraFrees all unused memory above the current upper bound.RemoveAllRemoves all the elements from this array.

Element Access

GetAtReturns the value at a given index.SetAtSets the value for a given index; array not allowed to grow.ElementAtReturns a temporary reference to the element pointer within the array.GetDataAllows access to elements in the array. Can be NULL.

Growing the Array

SetAtGrowSets the value for a given index; grows the array if necessary.AddAdds an element to the end of the array; grows the array if necessary.AppendAppends another array to the array; grows the array if necessary.CopyCopies anolther array to the array; grows the array if necessary.

Insertion/Removal

InsertAtInserts an element (or all the elements in another array) at a specified index.RemoveAtRemoves an element at a specific index.

Operators

operator []Sets or gets the element at the specified index.(2)CStringArray.h
class CStringArray : public CObject{DECLARE_SERIAL(CStringArray)public:// ConstructionCStringArray();// AttributesINT_PTR GetSize() const;INT_PTR GetCount() const;BOOL IsEmpty() const;INT_PTR GetUpperBound() const;void SetSize(INT_PTR nNewSize, INT_PTR nGrowBy = -1);// Operations// Clean upvoid FreeExtra();void RemoveAll();// Accessing elementsconst CString& GetAt(INT_PTR nIndex) const;void SetAt(INT_PTR nIndex, LPCTSTR newElement);void SetAt(INT_PTR nIndex, const CString& newElement);CString& ElementAt(INT_PTR nIndex);// Direct Access to the element data (may return NULL)const CString* GetData() const;CString* GetData();// Potentially growing the arrayvoid SetAtGrow(INT_PTR nIndex, LPCTSTR newElement);void SetAtGrow(INT_PTR nIndex, const CString& newElement);INT_PTR Add(LPCTSTR newElement);INT_PTR Add(const CString& newElement);INT_PTR Append(const CStringArray& src);void Copy(const CStringArray& src);// overloaded operator helpersconst CString& operator[](INT_PTR nIndex) const;CString& operator[](INT_PTR nIndex);// Operations that move elements aroundvoid InsertAt(INT_PTR nIndex, LPCTSTR newElement, INT_PTR nCount = 1);void InsertAt(INT_PTR nIndex, const CString& newElement, INT_PTR nCount = 1);void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1);void InsertAt(INT_PTR nStartIndex, const CStringArray* pNewArray);// Implementationprotected:CString* m_pData;   // the actual array of dataINT_PTR m_nSize;     // # of elements (upperBound - 1)INT_PTR m_nMaxSize;  // max allocatedINT_PTR m_nGrowBy;   // grow amountvoid InsertEmpty(INT_PTR nIndex, INT_PTR nCount);public:~CStringArray();void Serialize(CArchive&);#ifdef _DEBUGvoid Dump(CDumpContext&) const;void AssertValid() const;#endifprotected:// local typedefs for class templatestypedef CString BASE_TYPE;typedef LPCTSTR BASE_ARG_TYPE;};

(3)CStringArray.cpp
/////////////////////////////////////////////////////////////////////////////// NOTE: we allocate an array of 'm_nMaxSize' elements, but only//  the current size 'm_nSize' contains properly constructed//  objects.#include "stdafx.h"#include <wchar.h>#include "elements.h"  // used for special creation#define new DEBUG_NEW/////////////////////////////////////////////////////////////////////////////// Special implementations for CStrings// it is faster to bit-wise copy a CString than to call an official//   constructor - since an empty CString can be bit-wise copied/////////////////////////////////////////////////////////////////////////////static void _ConstructElements(CString* pNewData, INT_PTR nCount){ASSERT(nCount >= 0);while (nCount--){ConstructElement(pNewData);pNewData++;}}static void _DestructElements(CString* pOldData, INT_PTR nCount){ASSERT(nCount >= 0);while (nCount--){DestructElement(pOldData);pOldData++;}}static void _CopyElements(CString* pDest, CString* pSrc, INT_PTR nCount){ASSERT(nCount >= 0);while (nCount--){*pDest = *pSrc;++pDest;++pSrc;}}/////////////////////////////////////////////////////////////////////////////CStringArray::CStringArray(){m_pData = NULL;m_nSize = m_nMaxSize = m_nGrowBy = 0;}CStringArray::~CStringArray(){AFX_BEGIN_DESTRUCTORASSERT_VALID(this);_DestructElements(m_pData, m_nSize);delete[] (BYTE*)m_pData;AFX_END_DESTRUCTOR}void CStringArray::SetSize(INT_PTR nNewSize, INT_PTR nGrowBy){ASSERT_VALID(this);ASSERT(nNewSize >= 0);if(nNewSize < 0 )AfxThrowInvalidArgException();if (nGrowBy >= 0)m_nGrowBy = nGrowBy;  // set new sizeif (nNewSize == 0){// shrink to nothing_DestructElements(m_pData, m_nSize);delete[] (BYTE*)m_pData;m_pData = NULL;m_nSize = m_nMaxSize = 0;}else if (m_pData == NULL){// create one with exact size#ifdef SIZE_T_MAXASSERT(nNewSize <= SIZE_T_MAX/sizeof(CString));    // no overflow#endifm_pData = (CString*) new BYTE[nNewSize * sizeof(CString)];_ConstructElements(m_pData, nNewSize);m_nSize = m_nMaxSize = nNewSize;}else if (nNewSize <= m_nMaxSize){// it fitsif (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 arrayINT_PTR nGrowArrayBy = m_nGrowBy;if (nGrowArrayBy == 0){// heuristically determine growth when nGrowArrayBy == 0//  (this avoids heap fragmentation in many situations)nGrowArrayBy = min(1024, max(4, m_nSize / 8));}INT_PTR nNewMax;if (nNewSize < m_nMaxSize + nGrowArrayBy)nNewMax = m_nMaxSize + nGrowArrayBy;  // granularityelsenNewMax = nNewSize;  // no slushASSERT(nNewMax >= m_nMaxSize);  // no wrap aroundif(nNewMax  < m_nMaxSize)AfxThrowInvalidArgException();#ifdef SIZE_T_MAXASSERT(nNewMax <= SIZE_T_MAX/sizeof(CString)); // no overflow#endifCString* pNewData = (CString*) new BYTE[(size_t)nNewMax * sizeof(CString)];// copy new data from old Checked::memcpy_s(pNewData, (size_t)nNewMax * sizeof(CString), m_pData, (size_t)m_nSize * sizeof(CString));// construct remaining elementsASSERT(nNewSize > m_nSize);_ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);// get rid of old stuff (note: no destructors called)delete[] (BYTE*)m_pData;m_pData = pNewData;m_nSize = nNewSize;m_nMaxSize = nNewMax;}}INT_PTR CStringArray::Append(const CStringArray& src){ASSERT_VALID(this);ASSERT(this != &src);   // cannot append to itselfif(this == &src)AfxThrowInvalidArgException();INT_PTR nOldSize = m_nSize;SetSize(m_nSize + src.m_nSize);_CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);return nOldSize;}void CStringArray::Copy(const CStringArray& src){ASSERT_VALID(this);ASSERT(this != &src);   // cannot append to itselfif(this != &src){SetSize(src.m_nSize);_CopyElements(m_pData, src.m_pData, src.m_nSize);}}void CStringArray::FreeExtra(){ASSERT_VALID(this);if (m_nSize != m_nMaxSize){// shrink to desired size#ifdef SIZE_T_MAXASSERT(m_nSize <= SIZE_T_MAX/sizeof(CString)); // no overflow#endifCString* pNewData = NULL;if (m_nSize != 0){pNewData = (CString*) new BYTE[m_nSize * sizeof(CString)];// copy new data from old Checked::memcpy_s(pNewData, m_nSize * sizeof(CString), m_pData, m_nSize * sizeof(CString));}// get rid of old stuff (note: no destructors called)delete[] (BYTE*)m_pData;m_pData = pNewData;m_nMaxSize = m_nSize;}}/////////////////////////////////////////////////////////////////////////////void CStringArray::SetAtGrow(INT_PTR nIndex, LPCTSTR newElement){ASSERT_VALID(this);ASSERT(nIndex >= 0);if(nIndex < 0)AfxThrowInvalidArgException();if (nIndex >= m_nSize)SetSize(nIndex+1);m_pData[nIndex] = newElement;}void CStringArray::SetAtGrow(INT_PTR nIndex, const CString& newElement){ASSERT_VALID(this);ASSERT(nIndex >= 0);if(nIndex < 0)AfxThrowInvalidArgException();if (nIndex >= m_nSize){// Make sure newElement is not a reference to an element in the array.// Or else, it will be invalidated by the reallocation.ENSURE((nIndex < m_nMaxSize) ||(&newElement < m_pData) ||(&newElement >= (m_pData + m_nMaxSize) ) );SetSize(nIndex+1);}m_pData[nIndex] = newElement;}void CStringArray::InsertEmpty(INT_PTR nIndex, INT_PTR nCount){ASSERT_VALID(this);ASSERT(nIndex >= 0);    // will expand to meet needASSERT(nCount > 0);     // zero or negative size not allowedif(nIndex < 0 || nCount <= 0)AfxThrowInvalidArgException();if (nIndex >= m_nSize){// adding after the end of the arraySetSize(nIndex + nCount);  // grow so nIndex is valid}else{// inserting in the middle of the arrayINT_PTR nOldSize = m_nSize;INT_PTR nOverlapSize = min(nCount, nOldSize - nIndex);SetSize(m_nSize + nCount);  // grow it to new size// destroy slots we are about to overwrite_DestructElements(&m_pData[m_nSize - nOverlapSize], nOverlapSize);// shift old data up to fill gap Checked::memmove_s(&m_pData[nIndex+nCount], (m_nSize-(nIndex+nCount)) * sizeof(CString), &m_pData[nIndex], (nOldSize-nIndex) * sizeof(CString));// re-init the now-vacant slots we moved data from_ConstructElements(&m_pData[nIndex], nOverlapSize);}// insert new value in the gapASSERT(nIndex + nCount <= m_nSize);}void CStringArray::InsertAt(INT_PTR nIndex, LPCTSTR newElement, INT_PTR nCount){// make room for new elementsInsertEmpty(nIndex, nCount);// copy elements into the empty spaceCString temp = newElement;while (nCount--)m_pData[nIndex++] = temp;}void CStringArray::InsertAt(INT_PTR nIndex, const CString& newElement, INT_PTR nCount){// make room for new elementsInsertEmpty(nIndex, nCount);// copy elements into the empty spacewhile (nCount--)m_pData[nIndex++] = newElement;}void CStringArray::RemoveAt(INT_PTR nIndex, INT_PTR nCount){ASSERT_VALID(this);ASSERT(nIndex >= 0);ASSERT(nCount >= 0);INT_PTR nUpperBound = nIndex + nCount;ASSERT(nUpperBound <= m_nSize && nUpperBound >= nIndex && nUpperBound >= nCount);if(nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))AfxThrowInvalidArgException();// just remove a rangeINT_PTR nMoveCount = m_nSize - (nUpperBound);_DestructElements(&m_pData[nIndex], nCount);if (nMoveCount){Checked::memmove_s(&m_pData[nIndex], nMoveCount * sizeof(CString), &m_pData[nUpperBound], nMoveCount * sizeof(CString));}m_nSize -= nCount;}void CStringArray::InsertAt(INT_PTR nStartIndex, const CStringArray* pNewArray){ASSERT_VALID(this);ASSERT(pNewArray != NULL);ASSERT_KINDOF(CStringArray, pNewArray);ASSERT_VALID(pNewArray);ASSERT(nStartIndex >= 0);if(pNewArray == NULL || nStartIndex < 0)AfxThrowInvalidArgException();if (pNewArray->GetSize() > 0){InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());for (INT_PTR i = 0; i < pNewArray->GetSize(); i++)SetAt(nStartIndex + i, pNewArray->GetAt(i));}}INT_PTR CStringArray::GetSize() const{ return m_nSize; }INT_PTR CStringArray::GetCount() const{ return m_nSize; }BOOL CStringArray::IsEmpty() const{ return m_nSize == 0; }INT_PTR CStringArray::GetUpperBound() const{ return m_nSize-1; }void CStringArray::RemoveAll(){ SetSize(0); }const CString& CStringArray::GetAt(INT_PTR nIndex) const{ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();return m_pData[nIndex]; }void CStringArray::SetAt(INT_PTR nIndex, LPCTSTR newElement){ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();m_pData[nIndex] = newElement; }void CStringArray::SetAt(INT_PTR nIndex, const CString& newElement){ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();m_pData[nIndex] = newElement; }CString& CStringArray::ElementAt(INT_PTR nIndex){ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();return m_pData[nIndex]; }const CString* CStringArray::GetData() const{ return (const CString*)m_pData; }CString* CStringArray::GetData(){ return (CString*)m_pData; }INT_PTR CStringArray::Add(LPCTSTR newElement){ INT_PTR nIndex = m_nSize;SetAtGrow(nIndex, newElement);return nIndex; }INT_PTR CStringArray::Add(const CString& newElement){INT_PTR nIndex = m_nSize;SetAtGrow(nIndex, newElement);return nIndex; }const CString& CStringArray::operator[](INT_PTR nIndex) const{ return GetAt(nIndex); }CString& CStringArray::operator[](INT_PTR nIndex){ return ElementAt(nIndex); }

其中依赖的elements.h
/////////////////////////////////////////////////////////////////////////////// Special implementations for CStrings// it is faster to bit-wise copy a CString than to call an official//   constructor - since an empty CString can be bit-wise copiedstatic inline void ConstructElement(CString* pNewData){ENSURE_ARG(pNewData!=NULL);new( pNewData ) CString;}static inline void DestructElement(CString* pOldData){ENSURE_ARG(pOldData!=NULL);pOldData->~CString();}static inline void CopyElement(CString* pSrc, CString* pDest){ENSURE_ARG(pSrc!=NULL && pDest!=NULL);*pSrc = *pDest;}



0 0
原创粉丝点击