// Copyright (C) 2000 Sean Cavanaugh // This file is licensed under the terms of the Lesser GNU Public License // (see LPGL.txt, or http://www.gnu.org/copyleft/lesser.txt) #if !defined(AFX_ReferenceArray_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_) #define AFX_ReferenceArray_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #include "assert.h" #include "limits.h" #include "ReferenceCounter.h" /*! \author Sean Cavanaugh \email sean@dimensionalrift.com \cvsauthor $Author: sean $ \date $Date: 2000/09/11 20:28:24 $ \version $Revision: 1.1 $ \brief ReferenceArray is exactly the same as ReferencePtr, except it expects the objects pointing to it to be allocated with new[] instead (and thusly the object is deleted with delete[] when the reference count hits zero) Additionally it provides a [] operator which returns a refernece to the item in the list. No bounds checking is performed. Arrays of basic data types (char, int, float, etc) should use ReferencePtr, as delete[] is not required for them. ReferencePtr can also handle void types as a template parameter. */ template class ReferenceArrayBlock { public: DATA_T* pData; // User defined data block mutable ReferenceCounter ReferenceCount; }; template class ReferenceArray { public: // Construction ReferenceArray(); ReferenceArray(DATA_T* other); ReferenceArray(const ReferenceArray& other); virtual ~ReferenceArray(); // Assignment ReferenceArray& operator=(const ReferenceArray& other); ReferenceArray& operator=(DATA_T* other); // Dereferencing operator DATA_T*() const {return m_pData->pData;} DATA_T& operator[](unsigned int offset) const {return m_pData->pData[offset];} DATA_T& operator[](int offset) const {return m_pData->pData[offset];} protected: // Internal methods void Alloc(); // Allocate the m_pData void Release(); // Releases a reference count (possibly freeing memory) protected: // Member data ReferenceArrayBlock* m_pData; }; template ReferenceArray::ReferenceArray() { Alloc(); } template ReferenceArray::ReferenceArray(DATA_T* other) { Alloc(); m_pData->pData = other; m_pData->ReferenceCount = 1; } template ReferenceArray::ReferenceArray(const ReferenceArray& other) { m_pData = other.m_pData; m_pData->ReferenceCount++; } template ReferenceArray::~ReferenceArray() { Release(); } template ReferenceArray& ReferenceArray::operator=(const ReferenceArray& other) { if (m_pData != other.m_pData) { Release(); m_pData = other.m_pData; m_pData->ReferenceCount++; } return *this; } template ReferenceArray& ReferenceArray::operator=(DATA_T* other) { if (m_pData->ReferenceCount.dec() <= 0) { delete[] m_pData->pData; m_pData->pData = other; m_pData->ReferenceCount = 1; } else { Alloc(); m_pData->pData = other; } return *this; } template void ReferenceArray::Alloc() { m_pData = new ReferenceArrayBlock; m_pData->ReferenceCount = 1; m_pData->pData = NULL; } template void ReferenceArray::Release() { assert(m_pData != NULL); if (m_pData->ReferenceCount.dec() <= 0) { delete[] m_pData->pData; m_pData->pData = NULL; delete m_pData; m_pData = NULL; } } #endif // !defined(AFX_ReferenceArray_H__BAEBCE9D_CD68_40AF_8A54_B23A0D14E807__INCLUDED_)