// // VMime library (http://vmime.sourceforge.net) // Copyright (C) 2002-2004 Vincent Richard // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #ifndef VMIME_UTILITY_SMARTPTR_HPP_INCLUDED #define VMIME_UTILITY_SMARTPTR_HPP_INCLUDED namespace vmime { namespace utility { /** Simple auto-delete pointer. */ template class auto_ptr { private: T* const m_ptr; public: auto_ptr(T* const ptr) : m_ptr(ptr) { } ~auto_ptr() { delete (m_ptr); } operator T*() { return (m_ptr); } T* const operator ->() { return (m_ptr); } T& operator *() { return (*m_ptr); } }; /** Smart auto-delete, referencable and copiable pointer. */ template class smart_ptr { private: struct data { int refCount; T* ptr; }; data* m_data; typedef std::map MapType; static MapType sm_map; public: smart_ptr() : m_data(NULL) { } smart_ptr(T* const ptr) : m_data(NULL) { if (ptr) { attach(ptr); } } smart_ptr(smart_ptr& ptr) : m_data(NULL) { if (ptr.m_data) { attach(ptr); } } ~smart_ptr() { detach(); } smart_ptr& operator=(smart_ptr& ptr) { attach(ptr); return (*this); } smart_ptr& operator=(T* const ptr) { if (!ptr) detach(); else attach(ptr); return (*this); } operator T*() { return (m_data ? m_data->ptr : NULL); } operator const T*() { return (m_data ? m_data->ptr : NULL); } T& operator *() { return (*(m_data->ptr)); } T* operator ->() { return (m_data->ptr); } const T* const ptr() const { return (m_data ? m_data->ptr : NULL); } T* const ptr() { return (m_data ? m_data->ptr : NULL); } private: void detach() { if (m_data) { if (m_data->refCount == 1) { typename MapType::iterator it = sm_map.find(m_data->ptr); if (it != sm_map.end()) sm_map.erase(it); delete (m_data->ptr); delete (m_data); } else { m_data->refCount--; } m_data = NULL; } } void attach(T* const ptr) { detach(); typename MapType::iterator it = sm_map.find(ptr); if (it != sm_map.end()) { (*it).second->refCount++; } else { m_data = new data; m_data->refCount = 1; m_data->ptr = ptr; sm_map.insert(typename MapType::value_type(ptr, m_data)); } } void attach(smart_ptr & ptr) { data* newData = ptr.m_data; if (newData) newData->refCount++; detach(); m_data = newData; } }; template typename smart_ptr ::MapType smart_ptr ::sm_map; } // utility } // vmime #endif // VMIME_UTILITY_SMARTPTR_HPP_INCLUDED