/* * This is a part of the BugTrap package. * Copyright (c) 2005-2009 IntelleSoft. * All rights reserved. * * Description: Smart pointer class. * Author: Maksim Pyatkovskiy. * * This source code is only intended as a supplement to the * BugTrap package reference and related electronic documentation * provided with the product. See these sources for detailed * information regarding the BugTrap package. */ #pragma once struct CPtrTraits { template static void Destroy(TYPE* ptr) { delete ptr; } }; struct CArrayTraits { template static void Destroy(TYPE* ptr) { delete[] ptr; } }; template class CPtrLinkEngine { protected: TYPE* GetPtr(void) const { return m_ptr; } void Assign(TYPE* ptr); void Assign(const CPtrLinkEngine& sptr); void Release(void); private: TYPE* m_ptr; mutable const CPtrLinkEngine* m_pPrev; mutable const CPtrLinkEngine* m_pNext; }; template void CPtrLinkEngine::Assign(TYPE* ptr) { m_ptr = ptr; m_pPrev = this; m_pNext = this; } template void CPtrLinkEngine::Assign(const CPtrLinkEngine& sptr) { m_ptr = sptr.m_ptr; m_pPrev = sptr.m_pPrev; m_pNext = &sptr; sptr.m_pPrev = this; m_pPrev->m_pNext = this; } template void CPtrLinkEngine::Release(void) { if (m_pNext == this) { TRAITS::Destroy(m_ptr); } else { m_pPrev->m_pNext = m_pNext; m_pNext->m_pPrev = m_pPrev; } } template class CPtrRefEngine { protected: TYPE* GetPtr(void) const { _ASSERTE(m_pData != NULL); return m_pData->m_ptr; } void Assign(TYPE* ptr); void Assign(const CPtrRefEngine& sptr); void Release(void); private: struct CPtrData { CPtrData(void); CPtrData(TYPE* ptr); unsigned m_uNumRefs; TYPE* m_ptr; }; static CPtrData m_EmptyData; CPtrData* m_pData; }; template inline CPtrRefEngine::CPtrData::CPtrData(void) { m_ptr = NULL; m_uNumRefs = 0; } template inline CPtrRefEngine::CPtrData::CPtrData(TYPE* ptr) { m_ptr = ptr; m_uNumRefs = 1; } template typename CPtrRefEngine::CPtrData CPtrRefEngine::m_EmptyData; template void CPtrRefEngine::Assign(TYPE* ptr) { m_pData = ptr != NULL ? new CPtrData(ptr) : &m_EmptyData; } template void CPtrRefEngine::Assign(const CPtrRefEngine& sptr) { _ASSERTE(sptr.m_pData != NULL); m_pData = sptr.m_pData; if (m_pData != &m_EmptyData) ++m_pData->m_uNumRefs; } template void CPtrRefEngine::Release(void) { _ASSERTE(m_pData != NULL); if (m_pData != &m_EmptyData) { if (m_pData->m_uNumRefs == 1) { _ASSERTE(m_pData->m_ptr != NULL); TRAITS::Destroy(m_pData->m_ptr); delete m_pData; } else --m_pData->m_uNumRefs; } } template class CBaseSmartPtr : protected ENGINE { public: CBaseSmartPtr(void) { Assign(NULL); } explicit CBaseSmartPtr(TYPE* ptr) { Assign(ptr); } CBaseSmartPtr(const CBaseSmartPtr& sptr) { Assign(sptr); } ~CBaseSmartPtr(void) { Release(); } const CBaseSmartPtr& operator=(TYPE* ptr); const CBaseSmartPtr& operator=(const CBaseSmartPtr& sptr); TYPE& operator*(void) const { _ASSERTE(GetPtr() != NULL); return *GetPtr(); } TYPE* operator->(void) const { _ASSERTE(GetPtr() != NULL); return GetPtr(); } bool operator!(void) const { return (GetPtr() == NULL); } operator TYPE*(void) const { return GetPtr(); } friend bool operator==(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() == sptr2.GetPtr(); } friend bool operator!=(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() != sptr2.GetPtr(); } friend bool operator<(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() < sptr2.GetPtr(); } friend bool operator<=(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() <= sptr2.GetPtr(); } friend bool operator>(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() > sptr2.GetPtr(); } friend bool operator>=(const CBaseSmartPtr& sptr1, const CBaseSmartPtr& sptr2) { return sptr1.GetPtr() >= sptr2.GetPtr(); } }; template const CBaseSmartPtr& CBaseSmartPtr::operator=(TYPE* ptr) { Release(); Assign(ptr); return *this; } template const CBaseSmartPtr& CBaseSmartPtr::operator=(const CBaseSmartPtr& sptr) { if (this != &sptr) { Release(); Assign(sptr); } return *this; } #define CBaseClass CBaseSmartPtr template > class CSmartPtr : public CBaseClass { public: CSmartPtr(void) : CBaseClass() { } explicit CSmartPtr(TYPE* ptr) : CBaseClass(ptr) { } CSmartPtr(const CSmartPtr& sptr) : CBaseClass(sptr) { } const CSmartPtr& operator=(TYPE* ptr) { CBaseClass::operator=(ptr); return *this; } const CSmartPtr& operator=(const CSmartPtr& sptr) { CBaseClass::operator=(sptr); return *this; } }; #undef CBaseClass #define CBaseClass CBaseSmartPtr template > class CSmartArray : public CBaseClass { public: CSmartArray(void) : CBaseClass() { } explicit CSmartArray(TYPE* ptr) : CBaseClass(ptr) { } CSmartArray(const CSmartArray& sptr) : CBaseClass(sptr) { } const CSmartArray& operator=(TYPE* ptr) { CBaseClass::operator=(ptr); return *this; } const CSmartArray& operator=(const CSmartArray& sptr) { CBaseClass::operator=(sptr); return *this; } TYPE& operator[](INT_PTR index) const { _ASSERTE(GetPtr() != NULL); _ASSERTE(index >= 0); return GetPtr()[index]; } }; #undef CBaseClass