CByteArray源码解析

来源:互联网 发布:淘宝手机充值退款 编辑:程序博客网 时间:2024/05/28 11:30

(1)CByteArray简介

   CByteArray是MFC中BYTE一种集合类,用于申明CByteArray类的数据,并且用相关函数对其进行处理。该类是8位无符号整数 BYTE类型,范围0—255,头文件是Afxcoll.h。

类CByteArray支持以字节为单位动态建立数组

类CByteArray的成员函数与类CObArray的成员函数类似。因此,也可以参考类CObArray的文档。只需把函数参数或返回值中出现的CObject指针换成BYTE就可以了。例如,类CObArray中的函数:

在使用数组之前,要调用SetSize设置它的大小并分配内存。如果没有使用SetSize,在数组中增加元素会引起数组内存空间频繁的重新分配以及数据拷贝。内存频繁的重新分配和数据拷贝会影响性能并造成内存碎片

(2)CByteArray成员函数

构造函数

CByteArray构造一个空的字节数组

边界

GetSize数组中元素的个数(数组大小)
GetUpperBound返回数组的最大有效下标
SetSize设置数组元素的个数(数组大小)

操作

FreeExtra释放数组中当前已有数据的最大上界后所有未占用的内存
RemoveAll删除数组中所有的元素

元素存取

GetAt返回指定下标处的数组元素的值
SetAt数组中指定下标的元素赋值,但不能动态增长数组(指定的下标不能越界)
ElementAt返回对数组中某个字节的临时参考
GetData允许访问数组中的元素。可以为NULL

数组增长

SetAtGrow数组中指定下标的元素赋值,在下标越界时动态增长数组Add在数组末尾增添一个元素,必要时增长数组Append在数组末尾接上另一个数组,必要时增长数组
Copy把另一个数组的内容拷贝到本数组,必要时增长数组

插入/删除

InsertAt在指定的下标处插入元素(或另外一个数组的内容)
RemoveAt删除指定下标处的一个元素
操作符operator[]取指定下标处元素的值,或者给其赋值
(3)源码

CByteArray.h

///////////////////////////////////////////////////////////////////////////////// 整理的微软CByteArray源码,删除了部分功能(如Serialize/Dump/AssertValid等)///////////////////////////////////////////////////////////////////////////////#ifndef _ByteArray_H__#define _ByteArray_H__class CByteArray : public CObject{public:// ConstructionCByteArray();// 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 elementsBYTE GetAt(INT_PTR nIndex) const;void SetAt(INT_PTR nIndex, BYTE newElement);BYTE& ElementAt(INT_PTR nIndex);// Direct Access to the element data (may return NULL)const BYTE* GetData() const;BYTE* GetData();// Potentially growing the arrayvoid SetAtGrow(INT_PTR nIndex, BYTE newElement);INT_PTR Add(BYTE newElement);INT_PTR Append(const CByteArray& src);void Copy(const CByteArray& src);// overloaded operator helpersBYTE operator[](INT_PTR nIndex) const;BYTE& operator[](INT_PTR nIndex);// Operations that move elements aroundvoid InsertAt(INT_PTR nIndex, BYTE newElement, INT_PTR nCount = 1);void RemoveAt(INT_PTR nIndex, INT_PTR nCount = 1);void InsertAt(INT_PTR nStartIndex, CByteArray* pNewArray);// Implementationprotected:BYTE* m_pData;       // the actual array of dataINT_PTR m_nSize;     // # of elements (upperBound - 1)INT_PTR m_nMaxSize;  // max allocatedINT_PTR m_nGrowBy;   // grow amountpublic:~CByteArray();protected:// local typedefs for class templatestypedef BYTE BASE_TYPE;typedef BYTE BASE_ARG_TYPE;};#endif


CByteArray.cpp

///////////////////////////////////////////////////////////////////////////////// 整理的微软CByteArray源码,删除了部分功能(如Serialize/Dump/AssertValid等)// 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"#include <wchar.h>#include "ByteArray.h"/////////////////////////////////////////////////////////////////////////////CByteArray::CByteArray(){m_pData = NULL;m_nSize = m_nMaxSize = m_nGrowBy = 0;}CByteArray::~CByteArray(){ASSERT_VALID(this);delete[] (BYTE*)m_pData;}void CByteArray::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 nothingdelete[] (BYTE*)m_pData;m_pData = NULL;m_nSize = m_nMaxSize = 0;}else if (m_pData == NULL){// create one with exact size#ifdef SIZE_T_MAXENSURE_ARG(nNewSize <= SIZE_T_MAX/sizeof(BYTE));    // no overflow#endifm_pData = (BYTE*) new BYTE[nNewSize * sizeof(BYTE)];memset(m_pData, 0, nNewSize * sizeof(BYTE));  // zero fillm_nSize = m_nMaxSize = nNewSize;}else if (nNewSize <= m_nMaxSize){// it fitsif (nNewSize > m_nSize){// initialize the new elementsmemset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(BYTE));}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(BYTE)); // no overflow#endifBYTE* pNewData = (BYTE*) new BYTE[nNewMax * sizeof(BYTE)];// copy new data from old Checked::memcpy_s(pNewData, nNewMax * sizeof(BYTE), m_pData, m_nSize * sizeof(BYTE));// construct remaining elementsASSERT(nNewSize > m_nSize);memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(BYTE));// get rid of old stuff (note: no destructors called)delete[] (BYTE*)m_pData;m_pData = pNewData;m_nSize = nNewSize;m_nMaxSize = nNewMax;}}INT_PTR CByteArray::Append(const CByteArray& 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);Checked::memcpy_s(m_pData + nOldSize, src.m_nSize * sizeof(BYTE),src.m_pData, src.m_nSize * sizeof(BYTE));return nOldSize;}void CByteArray::Copy(const CByteArray& src){ASSERT_VALID(this);ASSERT(this != &src);   // cannot append to itselfif(this != &src){SetSize(src.m_nSize);Checked::memcpy_s(m_pData, src.m_nSize * sizeof(BYTE),src.m_pData, src.m_nSize * sizeof(BYTE));}}void CByteArray::FreeExtra(){ASSERT_VALID(this);if (m_nSize != m_nMaxSize){// shrink to desired size#ifdef SIZE_T_MAXASSERT(m_nSize <= SIZE_T_MAX/sizeof(BYTE)); // no overflow#endifBYTE* pNewData = NULL;if (m_nSize != 0){pNewData = (BYTE*) new BYTE[m_nSize * sizeof(BYTE)];// copy new data from old Checked::memcpy_s(pNewData, m_nSize * sizeof(BYTE), m_pData, m_nSize * sizeof(BYTE));}// get rid of old stuff (note: no destructors called)delete[] (BYTE*)m_pData;m_pData = pNewData;m_nMaxSize = m_nSize;}}/////////////////////////////////////////////////////////////////////////////void CByteArray::SetAtGrow(INT_PTR nIndex, BYTE newElement){ASSERT_VALID(this);ASSERT(nIndex >= 0);if(nIndex < 0)AfxThrowInvalidArgException();if (nIndex >= m_nSize)SetSize(nIndex+1);m_pData[nIndex] = newElement;}void CByteArray::InsertAt(INT_PTR nIndex, BYTE newElement, 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;SetSize(m_nSize + nCount);  // grow it to new size// shift old data up to fill gap Checked::memmove_s(&m_pData[nIndex+nCount], (m_nSize-(nCount+nIndex)) * sizeof(BYTE), &m_pData[nIndex], (nOldSize-nIndex) * sizeof(BYTE));// re-init slots we copied frommemset(&m_pData[nIndex], 0, nCount * sizeof(BYTE));}// insert new value in the gapASSERT(nIndex + nCount <= m_nSize);// copy elements into the empty spacewhile (nCount--)m_pData[nIndex++] = newElement;}void CByteArray::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);if (nMoveCount){Checked::memmove_s(&m_pData[nIndex], (size_t)nMoveCount * sizeof(BYTE), &m_pData[nUpperBound], (size_t)nMoveCount * sizeof(BYTE));}m_nSize -= nCount;}void CByteArray::InsertAt(INT_PTR nStartIndex, CByteArray* pNewArray){ASSERT_VALID(this);ASSERT(pNewArray != NULL);ASSERT_KINDOF(CByteArray, 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 CByteArray::GetSize() const{ return m_nSize; }INT_PTR CByteArray::GetCount() const{ return m_nSize; }BOOL CByteArray::IsEmpty() const{ return m_nSize == 0; }INT_PTR CByteArray::GetUpperBound() const{ return m_nSize-1;}void CByteArray::RemoveAll(){ SetSize(0); }BYTE CByteArray::GetAt(INT_PTR nIndex) const{ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();return m_pData[nIndex]; }void CByteArray::SetAt(INT_PTR nIndex, BYTE newElement){ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();m_pData[nIndex] = newElement; }BYTE& CByteArray::ElementAt(INT_PTR nIndex){ ASSERT(nIndex >= 0 && nIndex < m_nSize);if( nIndex < 0 || nIndex >= m_nSize )AfxThrowInvalidArgException();return m_pData[nIndex]; }const BYTE* CByteArray::GetData() const{ return (const BYTE*)m_pData; }BYTE* CByteArray::GetData(){ return (BYTE*)m_pData; }INT_PTR CByteArray::Add(BYTE newElement){ INT_PTR nIndex = m_nSize;SetAtGrow(nIndex, newElement);return nIndex; }BYTE CByteArray::operator[](INT_PTR nIndex) const{ return GetAt(nIndex); }BYTE& CByteArray::operator[](INT_PTR nIndex){ return ElementAt(nIndex); }/////////////////////////////////////////////////////////////////////////////

注:简介部分内容参考百度百科

0 0