123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- #pragma once
- #ifndef _WIN32
- #include <assert.h>
- #define _ASSERT assert
- #include <winpr/interlocked.h>
- #else
- #include <crtdbg.h>
- #endif
- template<class T> class CAutoArray
- {
- struct CRefNode
- {
- int m_nSize;
- LONG m_nRefCount;
- CRefNode() :m_nSize(0), m_nRefCount(1) {}
- CRefNode(int nInitSize) :m_nSize(nInitSize), m_nRefCount(1) {}
- };
- public:
- CAutoArray() :m_pData(NULL), m_pRefNode(NULL) {}
- CAutoArray(int nInitSize) :m_pData(NULL), m_pRefNode(NULL)
- {
- _ASSERT(nInitSize >= 0);
- if (nInitSize > 0)
- Init(nInitSize);
- }
- CAutoArray(T* pData, int nSize) :m_pData(NULL), m_pRefNode(NULL)
- {
- Bind(pData, nSize);
- }
- void Bind(T* pData, int nSize)
- {
- Init();
- _ASSERT(nSize >= 0);
- if (nSize == 0 || pData == NULL)
- return;
- m_pData = pData;
- m_pRefNode = new CRefNode(nSize);
- InterlockedIncrement(&(m_pRefNode->m_nRefCount));//will not delete inside class
- }
- CAutoArray(const CAutoArray<T>& Array)
- {
- m_pData = Array.m_pData;
- m_pRefNode = Array.m_pRefNode;
- if (m_pRefNode)
- InterlockedIncrement(&(m_pRefNode->m_nRefCount));
- }
- ~CAutoArray()
- {
- Init();
- }
- CAutoArray<T>& operator=(const CAutoArray<T>& Array)
- {
- if (Array.m_pData != m_pData) {
- Init();
- m_pData = Array.m_pData;
- m_pRefNode = Array.m_pRefNode;
- if (m_pRefNode)
- InterlockedIncrement(&(m_pRefNode->m_nRefCount));
- }
- return *this;
- }
- bool operator ==(const CAutoArray<T>& Array)
- {
- return m_pData == Array.m_pData;
- }
- bool operator !=(const CAutoArray<T>& Array)
- {
- return m_pData != Array.m_pData;
- }
- const T& operator[](int nIndex)const
- {
- _ASSERT(nIndex >= 0);
- _ASSERT(nIndex < GetCount() || nIndex == 0);
- return m_pData[nIndex];
- }
- T& operator[](int nIndex)
- {
- _ASSERT(nIndex >= 0);
- _ASSERT(nIndex < GetCount() || nIndex == 0);
- return GetWriteableArray()[nIndex];
- }
- void Attach(T* pData, int nSize)
- {
- if (pData == m_pData && m_pRefNode && m_pRefNode->m_nSize == nSize)
- return;
- Init();
- if (nSize == 0) {
- m_pData = NULL;
- m_pRefNode = NULL;
- } else {
- m_pData = pData;
- m_pRefNode = new CRefNode(nSize);
- }
- }
- T* Detach()
- {
- T* pRet = m_pData;
- m_pData = NULL;
- if (m_pRefNode && m_pRefNode->m_nRefCount == 1)
- delete m_pRefNode;
- m_pRefNode = NULL;
- return pRet;
- }
- void Init(int nInitSize = 0)
- {
- _ASSERT(nInitSize >= 0);
- if (m_pRefNode) {
- DecrementRef();
- }
- if (nInitSize > 0) {
- m_pData = new T[nInitSize];
- if (m_pData && m_pRefNode == NULL)
- m_pRefNode = new CRefNode(nInitSize);
- }
- }
- void Clear()
- {
- Init();
- }
- void EnlargeArray(int nNewSize)
- {
- if (nNewSize <= GetCount())
- return;
- T* pData = new T[nNewSize];
- if (pData) {
- if (m_pData) {
- for (int i = 0; i < m_pRefNode->m_nSize; i++)
- pData[i] = m_pData[i];
- if (m_pRefNode->m_nRefCount == 1) {
- delete[]m_pData;
- m_pRefNode->m_nSize = nNewSize;
- } else
- DecrementRef();
- }
- m_pData = pData;
- if (m_pRefNode == NULL)
- m_pRefNode = new CRefNode(nNewSize);
- }
- }
- void Copy(const T* pData, int nFrom, int nSize)
- {
- if (pData == NULL || nSize == 0) {
- Init();
- return;
- }
- _ASSERT(nFrom >= 0);
- _ASSERT(nSize >= 0);
- Init(nSize);
- if (m_pData) {
- const T* pS = pData + nFrom;
- for (T* pT = m_pData; pT < m_pData + nSize; pT++, pS++)
- *pT = *pS;
- }
- }
- void Copy(const CAutoArray<T>& Array)
- {
- Copy(Array, 0, Array.GetCount());
- }
- void Copy(const CAutoArray<T>& Array, int nFrom, int nSize)
- {
- if (nSize == 0)
- return;
- _ASSERT(nFrom >= 0);
- _ASSERT(nSize >= 0);
- _ASSERT(nFrom < Array.GetCount());
- int nMaxSize = Array.GetCount() - nFrom;
- if (nSize > nMaxSize)nSize = nMaxSize;
- Init(nSize);
- if (m_pData) {
- const T* pS = Array.m_pData + nFrom;
- for (T* pT = m_pData; pT < m_pData + nSize; pT++, pS++)
- *pT = *pS;
- }
- }
- void Append(const T* pData, int nFrom, int nSize)
- {
- if (pData == NULL || nSize == 0)
- return;
- _ASSERT(nFrom >= 0);
- _ASSERT(nSize >= 0);
- if (GetCount() == 0) {
- Copy(pData, nFrom, nSize);
- return;
- }
- int nOldSize = GetCount();
- EnlargeArray(nOldSize + nSize);
- if (m_pData) {
- T* pBegin = m_pData + nOldSize;
- const T* pS = pData + nFrom;
- for (T* pT = pBegin; pT < pBegin + nSize; pT++, pS++)
- *pT = *pS;
- }
- }
- void Append(const CAutoArray<T>& Array, int nFrom, int nSize)
- {
- if (nSize == 0)
- return;
- _ASSERT(nFrom >= 0);
- _ASSERT(nSize >= 0);
- _ASSERT(nFrom < Array.GetCount());
- int nMaxSize = Array.GetCount() - nFrom;
- if (nSize > nMaxSize)nSize = nMaxSize;
- if (nSize == 0)
- return;
- if (GetCount() == 0) {
- Copy(Array, nFrom, nSize);
- return;
- }
- int nOldSize = GetCount();
- EnlargeArray(nOldSize + nSize);
- if (m_pData) {
- T* pBegin = m_pData + nOldSize;
- const T* pS = Array.m_pData + nFrom;
- for (T* pT = pBegin; pT < pBegin + nSize; pT++, pS++)
- *pT = *pS;
- }
- }
- void Append(const CAutoArray<T>& Array)
- {
- Append(Array, 0, Array.GetCount());
- }
- CAutoArray<T> Clone()
- {
- return Clone(0, GetCount());
- }
- CAutoArray<T> Clone(int nFrom, int nSize)
- {
- CAutoArray<T> RetArray;
- RetArray.Copy(m_pData, nFrom, nSize);
- return RetArray;
- }
- int GetCount() const
- {
- if (m_pRefNode)
- return m_pRefNode->m_nSize;
- else
- return 0;
- }
- operator const T* () const
- {
- return m_pData;
- };
- T* GetWriteableArray()
- {
- if (m_pRefNode && m_pRefNode->m_nRefCount > 1) {
- int nSize = m_pRefNode->m_nSize;
- T* pData = new T[nSize];
- if (m_pData) {
- for (T* pT = pData, *pS = m_pData; pT < pData + nSize; pT++, pS++)
- *pT = *pS;
- DecrementRef();
- m_pData = pData;
- m_pRefNode = new CRefNode(nSize);
- }
- }
- return m_pData;
- }
- private:
- LONG DecrementRef()
- {
- _ASSERT(m_pRefNode);
- LONG nRef = InterlockedDecrement(&(m_pRefNode->m_nRefCount));
- if (nRef == 0) {
- delete[]m_pData;
- delete m_pRefNode;
- }
- m_pData = NULL;
- m_pRefNode = NULL;
- return nRef;
- }
- T* m_pData;
- CRefNode* m_pRefNode;
- };
- typedef CAutoArray<BYTE> CAutoBuffer;
|