// smartptr.h - originally written and placed in the public domain by Wei Dai /// \file /// \headerfile smartptr.h /// \brief Classes for automatic resource management #ifndef CRYPTOPP_SMARTPTR_H #define CRYPTOPP_SMARTPTR_H #include "config.h" #include "stdcpp.h" NAMESPACE_BEGIN(CryptoPP) /// \class simple_ptr /// \brief Manages resources for a single object /// \tparam T class or type /// \details \p simple_ptr is used frequently in the library to manage resources and /// ensure cleanup under the RAII pattern (Resource Acquisition Is Initialization). template class simple_ptr { public: simple_ptr(T *p = NULLPTR) : m_p(p) {} ~simple_ptr() { delete m_p; m_p = NULLPTR; } T *m_p; }; /// \class member_ptr /// \brief Pointer that overloads operator -> /// \tparam T class or type /// \details member_ptr is used frequently in the library to avoid the issues related to /// std::auto_ptr in C++11 (deprecated) and std::unique_ptr in C++03 (non-existent). /// \bug Issue 48: "Use of auto_ptr causes dirty compile under C++11" template class member_ptr { public: explicit member_ptr(T *p = NULLPTR) : m_p(p) {} ~member_ptr(); const T& operator*() const { return *m_p; } T& operator*() { return *m_p; } const T* operator->() const { return m_p; } T* operator->() { return m_p; } const T* get() const { return m_p; } T* get() { return m_p; } T* release() { T *old_p = m_p; m_p = NULLPTR; return old_p; } void reset(T *p = 0); protected: member_ptr(const member_ptr& rhs); // copy not allowed void operator=(const member_ptr& rhs); // assignment not allowed T *m_p; }; template member_ptr::~member_ptr() {delete m_p;} template void member_ptr::reset(T *p) {delete m_p; m_p = p;} // ******************************************************** /// \class value_ptr /// \brief Value pointer /// \tparam T class or type template class value_ptr : public member_ptr { public: value_ptr(const T &obj) : member_ptr(new T(obj)) {} value_ptr(T *p = NULLPTR) : member_ptr(p) {} value_ptr(const value_ptr& rhs) : member_ptr(rhs.m_p ? new T(*rhs.m_p) : NULLPTR) {} value_ptr& operator=(const value_ptr& rhs); bool operator==(const value_ptr& rhs) { return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); } }; template value_ptr& value_ptr::operator=(const value_ptr& rhs) { T *old_p = this->m_p; this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULLPTR; delete old_p; return *this; } // ******************************************************** /// \class clonable_ptr /// \brief A pointer which can be copied and cloned /// \tparam T class or type /// \details \p T should adhere to the \p Clonable interface template class clonable_ptr : public member_ptr { public: clonable_ptr(const T &obj) : member_ptr(obj.Clone()) {} clonable_ptr(T *p = NULLPTR) : member_ptr(p) {} clonable_ptr(const clonable_ptr& rhs) : member_ptr(rhs.m_p ? rhs.m_p->Clone() : NULLPTR) {} clonable_ptr& operator=(const clonable_ptr& rhs); }; template clonable_ptr& clonable_ptr::operator=(const clonable_ptr& rhs) { T *old_p = this->m_p; this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULLPTR; delete old_p; return *this; } // ******************************************************** /// \class counted_ptr /// \brief Reference counted pointer /// \tparam T class or type /// \details users should declare \p m_referenceCount as std::atomic /// (or similar) under C++ 11 template class counted_ptr { public: explicit counted_ptr(T *p = 0); counted_ptr(const T &r) : m_p(0) {attach(r);} counted_ptr(const counted_ptr& rhs); ~counted_ptr(); const T& operator*() const { return *m_p; } T& operator*() { return *m_p; } const T* operator->() const { return m_p; } T* operator->() { return get(); } const T* get() const { return m_p; } T* get(); void attach(const T &p); counted_ptr & operator=(const counted_ptr& rhs); private: T *m_p; }; template counted_ptr::counted_ptr(T *p) : m_p(p) { if (m_p) m_p->m_referenceCount = 1; } template counted_ptr::counted_ptr(const counted_ptr& rhs) : m_p(rhs.m_p) { if (m_p) m_p->m_referenceCount++; } template counted_ptr::~counted_ptr() { if (m_p && --m_p->m_referenceCount == 0) delete m_p; } template void counted_ptr::attach(const T &r) { if (m_p && --m_p->m_referenceCount == 0) delete m_p; if (r.m_referenceCount == 0) { m_p = r.clone(); m_p->m_referenceCount = 1; } else { m_p = const_cast(&r); m_p->m_referenceCount++; } } template T* counted_ptr::get() { if (m_p && m_p->m_referenceCount > 1) { T *temp = m_p->clone(); m_p->m_referenceCount--; m_p = temp; m_p->m_referenceCount = 1; } return m_p; } template counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) { if (m_p != rhs.m_p) { if (m_p && --m_p->m_referenceCount == 0) delete m_p; m_p = rhs.m_p; if (m_p) m_p->m_referenceCount++; } return *this; } // ******************************************************** /// \class vector_ptr /// \brief Manages resources for an array of objects /// \tparam T class or type /// \details \p vector_ptr is used frequently in the library to avoid large stack allocations, /// and manage resources and ensure cleanup under the RAII pattern (Resource Acquisition /// Is Initialization). template class vector_ptr { public: /// Construct an arry of \p T /// \param size the size of the array, in elements /// \details If \p T is a Plain Old Dataype (POD), then the array is uninitialized. vector_ptr(size_t size=0) : m_size(size), m_ptr(new T[m_size]) {} ~vector_ptr() {delete [] m_ptr;} T& operator[](size_t index) {CRYPTOPP_ASSERT(m_size && indexm_size); return this->m_ptr[index];} const T& operator[](size_t index) const {CRYPTOPP_ASSERT(m_size && indexm_size); return this->m_ptr[index];} size_t size() const {return this->m_size;} void resize(size_t newSize) { T *newPtr = new T[newSize]; for (size_t i=0; im_size && im_ptr; this->m_size = newSize; this->m_ptr = newPtr; } #ifdef __BORLANDC__ operator T *() const {return (T*)m_ptr;} #else operator const void *() const {return m_ptr;} operator void *() {return m_ptr;} operator const T *() const {return m_ptr;} operator T *() {return m_ptr;} #endif private: vector_ptr(const vector_ptr &c); // copy not allowed void operator=(const vector_ptr &x); // assignment not allowed size_t m_size; T *m_ptr; }; // ******************************************************** /// \class vector_member_ptrs /// \brief Manages resources for an array of objects /// \tparam T class or type template class vector_member_ptrs { public: /// Construct an arry of \p T /// \param size the size of the array, in elements /// \details If \p T is a Plain Old Dataype (POD), then the array is uninitialized. vector_member_ptrs(size_t size=0) : m_size(size), m_ptr(new member_ptr[size]) {} ~vector_member_ptrs() {delete [] this->m_ptr;} member_ptr& operator[](size_t index) {CRYPTOPP_ASSERT(indexm_size); return this->m_ptr[index];} const member_ptr& operator[](size_t index) const {CRYPTOPP_ASSERT(indexm_size); return this->m_ptr[index];} size_t size() const {return this->m_size;} void resize(size_t newSize) { member_ptr *newPtr = new member_ptr[newSize]; for (size_t i=0; im_size && im_ptr[i].release()); delete [] this->m_ptr; this->m_size = newSize; this->m_ptr = newPtr; } private: vector_member_ptrs(const vector_member_ptrs &c); // copy not allowed void operator=(const vector_member_ptrs &x); // assignment not allowed size_t m_size; member_ptr *m_ptr; }; NAMESPACE_END #endif