ARRAY.CTT
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:18k
源码类别:
Windows编程
开发平台:
Visual C++
- ////////////////////////////////////////////////////////////////////////////
- // class CArray<TYPE, ARG_TYPE> - an array containing 'TYPE' elements,
- // passed in parameters as ARG_TYPE
- //
- // optional definitions:
- // IS_SERIAL - include serialization (see below for types)
- // IS_RAW_SERIAL - use CArchive::Write and Read for serialization
- // IS_ARCHIVE_SERIAL - use CArchive insersion, extraction for serialization
- // HAS_CREATE - call constructors and destructors
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1994-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- ////////////////////////////////////////////////////////////////////////////
- //$DECLARE_TEMPLATE
- ////////////////////////////////////////////////////////////////////////////
- template<class TYPE, class ARG_TYPE>
- class CArray : public CObject
- {
- $ifdef IS_SERIAL
- DECLARE_SERIAL(CArray)
- $else
- DECLARE_DYNAMIC(CArray)
- $endif //!IS_SERIAL
- public:
- // Construction
- CArray();
- // Attributes
- int GetSize() const;
- int GetUpperBound() const;
- void SetSize(int nNewSize, int nGrowBy = -1);
- // Operations
- // Clean up
- void FreeExtra();
- void RemoveAll();
- // Accessing elements
- TYPE GetAt(int nIndex) const;
- void SetAt(int nIndex, ARG_TYPE newElement);
- $ifdef INCLUDE_TYPEREF
- void SetAt(int nIndex, const TYPE& newElement);
- $endif
- TYPE& ElementAt(int nIndex);
- // Direct Access to the element data (may return NULL)
- const TYPE* GetData() const;
- TYPE* GetData();
- // Potentially growing the array
- void SetAtGrow(int nIndex, ARG_TYPE newElement);
- $ifdef INCLUDE_TYPEREF
- void SetAtGrow(int nIndex, const TYPE& newElement);
- $endif
- int Add(ARG_TYPE newElement);
- $ifdef INCLUDE_TYPEREF
- int Add(const TYPE& newElement);
- $endif
- int Append(const CArray& src);
- void Copy(const CArray& src);
- // overloaded operator helpers
- TYPE operator[](int nIndex) const;
- TYPE& operator[](int nIndex);
- // Operations that move elements around
- void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
- $ifdef INCLUDE_TYPEREF
- void InsertAt(int nIndex, const TYPE& newElement, int nCount = 1);
- $endif
- void RemoveAt(int nIndex, int nCount = 1);
- void InsertAt(int nStartIndex, CArray* pNewArray);
- // Implementation
- protected:
- TYPE* m_pData; // the actual array of data
- int m_nSize; // # of elements (upperBound - 1)
- int m_nMaxSize; // max allocated
- int m_nGrowBy; // grow amount
- $ifdef INCLUDE_TYPEREF
- void InsertEmpty(int nIndex, int nCount);
- $endif
- public:
- ~CArray();
- $ifdef IS_SERIAL
- void Serialize(CArchive&);
- $endif //IS_SERIAL
- #ifdef _DEBUG
- void Dump(CDumpContext&) const;
- void AssertValid() const;
- #endif
- protected:
- // local typedefs for class templates
- typedef TYPE BASE_TYPE;
- typedef ARG_TYPE BASE_ARG_TYPE;
- };
- //$IMPLEMENT_TEMPLATE_INLINES
- ////////////////////////////////////////////////////////////////////////////
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::GetSize() const
- { return m_nSize; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
- { return m_nSize-1; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::RemoveAll()
- { SetSize(0); }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
- { ASSERT(nIndex >= 0 && nIndex < m_nSize);
- return m_pData[nIndex]; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
- { ASSERT(nIndex >= 0 && nIndex < m_nSize);
- m_pData[nIndex] = newElement; }
- $ifdef INCLUDE_TYPEREF
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, const TYPE& newElement)
- { ASSERT(nIndex >= 0 && nIndex < m_nSize);
- m_pData[nIndex] = newElement; }
- $endif
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
- { ASSERT(nIndex >= 0 && nIndex < m_nSize);
- return m_pData[nIndex]; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
- { return (const TYPE*)m_pData; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE TYPE* CArray<TYPE, ARG_TYPE>::GetData()
- { return (TYPE*)m_pData; }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
- { int nIndex = m_nSize;
- SetAtGrow(nIndex, newElement);
- return nIndex; }
- $ifdef INCLUDE_TYPEREF
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::Add(const TYPE& newElement)
- { int nIndex = m_nSize;
- SetAtGrow(nIndex, newElement);
- return nIndex; }
- $endif
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
- { return GetAt(nIndex); }
- template<class TYPE, class ARG_TYPE>
- _AFXCOLL_INLINE TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
- { return ElementAt(nIndex); }
- //$IMPLEMENT_TEMPLATE
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1997 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- /////////////////////////////////////////////////////////////////////////////
- //
- // Implementation of parameterized Array
- //
- /////////////////////////////////////////////////////////////////////////////
- // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
- // the current size 'm_nSize' contains properly constructed
- // objects.
- #include "stdafx.h"
- #ifdef AFX_COLL_SEG
- #pragma code_seg(AFX_COLL_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- $ifdef HAS_CREATE
- /////////////////////////////////////////////////////////////////////////////
- #include "elements.h" // used for special creation
- static void ConstructElements(TYPE* pNewData, int nCount)
- {
- ASSERT(nCount >= 0);
- while (nCount--)
- {
- ConstructElement(pNewData);
- pNewData++;
- }
- }
- static void DestructElements(TYPE* pOldData, int nCount)
- {
- ASSERT(nCount >= 0);
- while (nCount--)
- {
- DestructElement(pOldData);
- pOldData++;
- }
- }
- static void CopyElements(TYPE* pDest, TYPE* pSrc, int nCount)
- {
- ASSERT(nCount >= 0);
- while (nCount--)
- {
- *pDest = *pSrc;
- ++pDest;
- ++pSrc;
- }
- }
- $endif //HAS_CREATE
- /////////////////////////////////////////////////////////////////////////////
- template<class TYPE, class ARG_TYPE>
- CArray<TYPE, ARG_TYPE>::CArray()
- {
- m_pData = NULL;
- m_nSize = m_nMaxSize = m_nGrowBy = 0;
- }
- template<class TYPE, ARG_TYPE>
- CArray<TYPE, ARG_TYPE>::~CArray()
- {
- ASSERT_VALID(this);
- $ifdef HAS_CREATE
- DestructElements(m_pData, m_nSize);
- $endif //HAS_CREATE
- delete[] (BYTE*)m_pData;
- }
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize, int nGrowBy)
- {
- ASSERT_VALID(this);
- ASSERT(nNewSize >= 0);
- if (nGrowBy != -1)
- m_nGrowBy = nGrowBy; // set new size
- if (nNewSize == 0)
- {
- // shrink to nothing
- $ifdef HAS_CREATE
- DestructElements(m_pData, m_nSize);
- $endif //HAS_CREATE
- 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_MAX
- ASSERT(nNewSize <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
- #endif
- m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
- $ifdef HAS_CREATE
- ConstructElements(m_pData, nNewSize);
- $else
- memset(m_pData, 0, nNewSize * sizeof(TYPE)); // zero fill
- $endif
- m_nSize = m_nMaxSize = nNewSize;
- }
- else if (nNewSize <= m_nMaxSize)
- {
- // it fits
- if (nNewSize > m_nSize)
- {
- // initialize the new elements
- $ifdef HAS_CREATE
- ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
- $else
- memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
- $endif
- }
- $ifdef HAS_CREATE
- else if (m_nSize > nNewSize) // destroy the old elements
- DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
- $endif
- 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 = min(1024, max(4, m_nSize / 8));
- }
- int nNewMax;
- if (nNewSize < m_nMaxSize + nGrowBy)
- nNewMax = m_nMaxSize + nGrowBy; // granularity
- else
- nNewMax = nNewSize; // no slush
- ASSERT(nNewMax >= m_nMaxSize); // no wrap around
- #ifdef SIZE_T_MAX
- ASSERT(nNewMax <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
- #endif
- TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
- // copy new data from old
- memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
- // construct remaining elements
- ASSERT(nNewSize > m_nSize);
- $ifdef HAS_CREATE
- ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
- $else
- memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
- $endif
- // get rid of old stuff (note: no destructors called)
- delete[] (BYTE*)m_pData;
- m_pData = pNewData;
- m_nSize = nNewSize;
- m_nMaxSize = nNewMax;
- }
- }
- template<class TYPE, class ARG_TYPE>
- int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
- {
- ASSERT_VALID(this);
- ASSERT(this != &src); // cannot append to itself
- int nOldSize = m_nSize;
- SetSize(m_nSize + src.m_nSize);
- $ifdef HAS_CREATE
- CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
- $else
- memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(TYPE));
- $endif
- return nOldSize;
- }
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
- {
- ASSERT_VALID(this);
- ASSERT(this != &src); // cannot append to itself
- SetSize(src.m_nSize);
- $ifdef HAS_CREATE
- CopyElements(m_pData, src.m_pData, src.m_nSize);
- $else
- memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(TYPE));
- $endif
- }
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::FreeExtra()
- {
- ASSERT_VALID(this);
- if (m_nSize != m_nMaxSize)
- {
- // shrink to desired size
- #ifdef SIZE_T_MAX
- ASSERT(m_nSize <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
- #endif
- TYPE* pNewData = NULL;
- if (m_nSize != 0)
- {
- pNewData = (TYPE*) new BYTE[m_nSize * sizeof(TYPE)];
- // copy new data from old
- memcpy(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<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
- {
- ASSERT_VALID(this);
- ASSERT(nIndex >= 0);
- if (nIndex >= m_nSize)
- SetSize(nIndex+1);
- m_pData[nIndex] = newElement;
- }
- $ifdef INCLUDE_TYPEREF
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, const TYPE& newElement)
- {
- ASSERT_VALID(this);
- ASSERT(nIndex >= 0);
- if (nIndex >= m_nSize)
- SetSize(nIndex+1);
- m_pData[nIndex] = newElement;
- }
- $endif
- $ifdef INCLUDE_TYPEREF
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::InsertEmpty(int nIndex, int nCount)
- {
- ASSERT_VALID(this);
- ASSERT(nIndex >= 0); // will expand to meet need
- ASSERT(nCount > 0); // zero or negative size not allowed
- if (nIndex >= m_nSize)
- {
- // adding after the end of the array
- SetSize(nIndex + nCount); // grow so nIndex is valid
- }
- else
- {
- // inserting in the middle of the array
- int nOldSize = m_nSize;
- SetSize(m_nSize + nCount); // grow it to new size
- // shift old data up to fill gap
- memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
- (nOldSize-nIndex) * sizeof(TYPE));
- // re-init slots we copied from
- $ifdef HAS_CREATE
- ConstructElements(&m_pData[nIndex], nCount);
- $else
- memset(&m_pData[nIndex], 0, nCount * sizeof(TYPE));
- $endif
- }
- // insert new value in the gap
- ASSERT(nIndex + nCount <= m_nSize);
- }
- $endif
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount)
- {
- $ifdef INCLUDE_TYPEREF
- // make room for new elements
- InsertEmpty(nIndex, nCount);
- $else
- ASSERT_VALID(this);
- ASSERT(nIndex >= 0); // will expand to meet need
- ASSERT(nCount > 0); // zero or negative size not allowed
- if (nIndex >= m_nSize)
- {
- // adding after the end of the array
- SetSize(nIndex + nCount); // grow so nIndex is valid
- }
- else
- {
- // inserting in the middle of the array
- int nOldSize = m_nSize;
- SetSize(m_nSize + nCount); // grow it to new size
- // shift old data up to fill gap
- memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
- (nOldSize-nIndex) * sizeof(TYPE));
- // re-init slots we copied from
- $ifdef HAS_CREATE
- ConstructElements(&m_pData[nIndex], nCount);
- $else
- memset(&m_pData[nIndex], 0, nCount * sizeof(TYPE));
- $endif
- }
- // insert new value in the gap
- ASSERT(nIndex + nCount <= m_nSize);
- $endif
- $ifndef INCLUDE_TYPEREF
- // copy elements into the empty space
- while (nCount--)
- m_pData[nIndex++] = newElement;
- $else
- // copy elements into the empty space
- TYPE temp = newElement;
- while (nCount--)
- m_pData[nIndex++] = temp;
- $endif
- }
- $ifdef INCLUDE_TYPEREF
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, const TYPE& newElement, int nCount)
- {
- // make room for new elements
- InsertEmpty(nIndex, nCount);
- // copy elements into the empty space
- while (nCount--)
- m_pData[nIndex++] = newElement;
- }
- $endif
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
- {
- ASSERT_VALID(this);
- ASSERT(nIndex >= 0);
- ASSERT(nCount >= 0);
- ASSERT(nIndex + nCount <= m_nSize);
- // just remove a range
- int nMoveCount = m_nSize - (nIndex + nCount);
- $ifdef HAS_CREATE
- DestructElements(&m_pData[nIndex], nCount);
- $endif
- if (nMoveCount)
- memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
- nMoveCount * sizeof(TYPE));
- m_nSize -= nCount;
- }
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::InsertAt(int nStartIndex, CArray* pNewArray)
- {
- ASSERT_VALID(this);
- ASSERT(pNewArray != NULL);
- ASSERT_KINDOF(CArray, pNewArray);
- ASSERT_VALID(pNewArray);
- ASSERT(nStartIndex >= 0);
- 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));
- }
- }
- $ifdef IS_ARCHIVE_SERIAL
- /////////////////////////////////////////////////////////////////////////////
- // Serialization
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
- CObject::Serialize(ar);
- if (ar.IsStoring())
- {
- ar.WriteCount(m_nSize);
- for (int i = 0; i < m_nSize; i++)
- ar << m_pData[i];
- }
- else
- {
- DWORD nOldSize = ar.ReadCount();
- SetSize(nOldSize);
- for (int i = 0; i < m_nSize; i++)
- ar >> m_pData[i];
- }
- }
- $endif //IS_ARCHIVE_SERIAL
- $ifdef IS_RAW_SERIAL
- /////////////////////////////////////////////////////////////////////////////
- // Serialization
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
- CObject::Serialize(ar);
- if (ar.IsStoring())
- {
- ar.WriteCount(m_nSize);
- ar.Write(m_pData, m_nSize * sizeof(TYPE));
- }
- else
- {
- DWORD nOldSize = ar.ReadCount();
- SetSize(nOldSize);
- ar.Read(m_pData, m_nSize * sizeof(TYPE));
- }
- }
- $endif //IS_RAW_SERIAL
- $ifdef IS_SWAP_SERIAL
- /////////////////////////////////////////////////////////////////////////////
- // Serialization
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
- CObject::Serialize(ar);
- if (ar.IsStoring())
- {
- ar.WriteCount(m_nSize);
- #ifdef _AFX_BYTESWAP
- if (!ar.IsByteSwapping())
- #endif
- ar.Write(m_pData, m_nSize * sizeof(TYPE));
- #ifdef _AFX_BYTESWAP
- else
- {
- // write each item individually so that it will be byte-swapped
- for (int i = 0; i < m_nSize; i++)
- ar << m_pData[i];
- }
- #endif
- }
- else
- {
- DWORD nOldSize = ar.ReadCount();
- SetSize(nOldSize);
- ar.Read(m_pData, m_nSize * sizeof(TYPE));
- #ifdef _AFX_BYTESWAP
- if (ar.IsByteSwapping())
- {
- for (int i = 0; i < m_nSize; i++)
- _AfxByteSwap(m_pData[i], (BYTE*)&m_pData[i]);
- }
- #endif
- }
- }
- $endif //IS_SWAP_SERIAL
- /////////////////////////////////////////////////////////////////////////////
- // Diagnostics
- #ifdef _DEBUG
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::Dump(CDumpContext& dc) const
- {
- CObject::Dump(dc);
- dc << "with " << m_nSize << " elements";
- if (dc.GetDepth() > 0)
- {
- for (int i = 0; i < m_nSize; i++)
- dc << "nt[" << i << "] = " << m_pData[i];
- }
- dc << "n";
- }
- template<class TYPE, class ARG_TYPE>
- void CArray<TYPE, ARG_TYPE>::AssertValid() const
- {
- CObject::AssertValid();
- if (m_pData == NULL)
- {
- ASSERT(m_nSize == 0);
- ASSERT(m_nMaxSize == 0);
- }
- else
- {
- ASSERT(m_nSize >= 0);
- ASSERT(m_nMaxSize >= 0);
- ASSERT(m_nSize <= m_nMaxSize);
- ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(TYPE)));
- }
- }
- #endif //_DEBUG
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
- $ifdef IS_SERIAL
- IMPLEMENT_SERIAL(CArray, CObject, 0)
- $else
- IMPLEMENT_DYNAMIC(CArray, CObject)
- $endif //!IS_SERIAL
- /////////////////////////////////////////////////////////////////////////////