vhlt/template/ReferenceArray.h
2016-09-21 00:07:53 +03:00

153 lines
3.8 KiB
C++

// 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 DATA_T>
class ReferenceArrayBlock
{
public:
DATA_T* pData; // User defined data block
mutable ReferenceCounter ReferenceCount;
};
template<class DATA_T>
class ReferenceArray
{
public:
// Construction
ReferenceArray();
ReferenceArray(DATA_T* other);
ReferenceArray(const ReferenceArray<DATA_T>& other);
virtual ~ReferenceArray();
// Assignment
ReferenceArray<DATA_T>& operator=(const ReferenceArray<DATA_T>& other);
ReferenceArray<DATA_T>& 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<DATA_T>* m_pData;
};
template<class DATA_T>
ReferenceArray<DATA_T>::ReferenceArray()
{
Alloc();
}
template<class DATA_T>
ReferenceArray<DATA_T>::ReferenceArray(DATA_T* other)
{
Alloc();
m_pData->pData = other;
m_pData->ReferenceCount = 1;
}
template<class DATA_T>
ReferenceArray<DATA_T>::ReferenceArray(const ReferenceArray<DATA_T>& other)
{
m_pData = other.m_pData;
m_pData->ReferenceCount++;
}
template<class DATA_T>
ReferenceArray<DATA_T>::~ReferenceArray()
{
Release();
}
template<class DATA_T>
ReferenceArray<DATA_T>& ReferenceArray<DATA_T>::operator=(const ReferenceArray<DATA_T>& other)
{
if (m_pData != other.m_pData)
{
Release();
m_pData = other.m_pData;
m_pData->ReferenceCount++;
}
return *this;
}
template<class DATA_T>
ReferenceArray<DATA_T>& ReferenceArray<DATA_T>::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<class DATA_T>
void ReferenceArray<DATA_T>::Alloc()
{
m_pData = new ReferenceArrayBlock<DATA_T>;
m_pData->ReferenceCount = 1;
m_pData->pData = NULL;
}
template<class DATA_T>
void ReferenceArray<DATA_T>::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_)