#pragma once #ifndef _WIN32 #include #define _ASSERT assert #include #else #include #endif template 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& Array) { m_pData = Array.m_pData; m_pRefNode = Array.m_pRefNode; if (m_pRefNode) InterlockedIncrement(&(m_pRefNode->m_nRefCount)); } ~CAutoArray() { Init(); } CAutoArray& operator=(const CAutoArray& 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& Array) { return m_pData == Array.m_pData; } bool operator !=(const CAutoArray& 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& Array) { Copy(Array, 0, Array.GetCount()); } void Copy(const CAutoArray& 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& 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& Array) { Append(Array, 0, Array.GetCount()); } CAutoArray Clone() { return Clone(0, GetCount()); } CAutoArray Clone(int nFrom, int nSize) { CAutoArray 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 CAutoBuffer;