1 // smartptr.h - originally written and placed in the public domain by Wei Dai 2 3 /// \file smartptr.h 4 /// \brief Classes for automatic resource management 5 6 #ifndef CRYPTOPP_SMARTPTR_H 7 #define CRYPTOPP_SMARTPTR_H 8 9 #include "config.h" 10 #include "stdcpp.h" 11 NAMESPACE_BEGIN(CryptoPP)12NAMESPACE_BEGIN(CryptoPP) 13 14 /// \brief Manages resources for a single object 15 /// \tparam T class or type 16 /// \details \p simple_ptr is used frequently in the library to manage resources and 17 /// ensure cleanup under the RAII pattern (Resource Acquisition Is Initialization). 18 template <class T> class simple_ptr 19 { 20 public: 21 simple_ptr(T *p = NULLPTR) : m_p(p) {} 22 ~simple_ptr() 23 { 24 delete m_p; 25 m_p = NULLPTR; 26 } 27 28 T *m_p; 29 }; 30 31 /// \brief Pointer that overloads operator -> 32 /// \tparam T class or type 33 /// \details member_ptr is used frequently in the library to avoid the issues related to 34 /// std::auto_ptr in C++11 (deprecated) and std::unique_ptr in C++03 (non-existent). 35 /// \bug <a href="http://github.com/weidai11/cryptopp/issues/48">Issue 48: "Use of auto_ptr 36 /// causes dirty compile under C++11"</a> 37 template <class T> class member_ptr 38 { 39 public: m_p(p)40 explicit member_ptr(T *p = NULLPTR) : m_p(p) {} 41 42 ~member_ptr(); 43 44 const T& operator*() const { return *m_p; } 45 T& operator*() { return *m_p; } 46 47 const T* operator->() const { return m_p; } 48 T* operator->() { return m_p; } 49 get()50 const T* get() const { return m_p; } get()51 T* get() { return m_p; } 52 release()53 T* release() 54 { 55 T *old_p = m_p; 56 m_p = NULLPTR; 57 return old_p; 58 } 59 60 void reset(T *p = NULLPTR); 61 62 protected: 63 member_ptr(const member_ptr<T>& rhs); // copy not allowed 64 void operator=(const member_ptr<T>& rhs); // assignment not allowed 65 66 T *m_p; 67 }; 68 ~member_ptr()69template <class T> member_ptr<T>::~member_ptr() {delete m_p;} reset(T * p)70template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;} 71 72 // ******************************************************** 73 74 /// \brief Value pointer 75 /// \tparam T class or type 76 template<class T> class value_ptr : public member_ptr<T> 77 { 78 public: value_ptr(const T & obj)79 value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {} 80 value_ptr(T *p = NULLPTR) : member_ptr<T>(p) {} value_ptr(const value_ptr<T> & rhs)81 value_ptr(const value_ptr<T>& rhs) 82 : member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULLPTR) {} 83 84 value_ptr<T>& operator=(const value_ptr<T>& rhs); 85 bool operator==(const value_ptr<T>& rhs) 86 { 87 return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); 88 } 89 }; 90 91 template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs) 92 { 93 T *old_p = this->m_p; 94 this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULLPTR; 95 delete old_p; 96 return *this; 97 } 98 99 // ******************************************************** 100 101 /// \brief A pointer which can be copied and cloned 102 /// \tparam T class or type 103 /// \details \p T should adhere to the \p Clonable interface 104 template<class T> class clonable_ptr : public member_ptr<T> 105 { 106 public: clonable_ptr(const T & obj)107 clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {} 108 clonable_ptr(T *p = NULLPTR) : member_ptr<T>(p) {} clonable_ptr(const clonable_ptr<T> & rhs)109 clonable_ptr(const clonable_ptr<T>& rhs) 110 : member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULLPTR) {} 111 112 clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs); 113 }; 114 115 template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs) 116 { 117 T *old_p = this->m_p; 118 this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULLPTR; 119 delete old_p; 120 return *this; 121 } 122 123 // ******************************************************** 124 125 /// \brief Reference counted pointer 126 /// \tparam T class or type 127 /// \details users should declare \p m_referenceCount as <tt>std::atomic<unsigned></tt> 128 /// (or similar) under C++ 11 129 template<class T> class counted_ptr 130 { 131 public: 132 explicit counted_ptr(T *p = NULLPTR); counted_ptr(const T & r)133 counted_ptr(const T &r) : m_p(0) {attach(r);} 134 counted_ptr(const counted_ptr<T>& rhs); 135 136 ~counted_ptr(); 137 138 const T& operator*() const { return *m_p; } 139 T& operator*() { return *m_p; } 140 141 const T* operator->() const { return m_p; } 142 T* operator->() { return get(); } 143 get()144 const T* get() const { return m_p; } 145 T* get(); 146 147 void attach(const T &p); 148 149 counted_ptr<T> & operator=(const counted_ptr<T>& rhs); 150 151 private: 152 T *m_p; 153 }; 154 counted_ptr(T * p)155template <class T> counted_ptr<T>::counted_ptr(T *p) 156 : m_p(p) 157 { 158 if (m_p) 159 m_p->m_referenceCount = 1; 160 } 161 counted_ptr(const counted_ptr<T> & rhs)162template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs) 163 : m_p(rhs.m_p) 164 { 165 if (m_p) 166 m_p->m_referenceCount++; 167 } 168 ~counted_ptr()169template <class T> counted_ptr<T>::~counted_ptr() 170 { 171 if (m_p && --m_p->m_referenceCount == 0) 172 delete m_p; 173 } 174 attach(const T & r)175template <class T> void counted_ptr<T>::attach(const T &r) 176 { 177 if (m_p && --m_p->m_referenceCount == 0) 178 delete m_p; 179 if (r.m_referenceCount == 0) 180 { 181 m_p = r.clone(); 182 m_p->m_referenceCount = 1; 183 } 184 else 185 { 186 m_p = const_cast<T *>(&r); 187 m_p->m_referenceCount++; 188 } 189 } 190 get()191template <class T> T* counted_ptr<T>::get() 192 { 193 if (m_p && m_p->m_referenceCount > 1) 194 { 195 T *temp = m_p->clone(); 196 m_p->m_referenceCount--; 197 m_p = temp; 198 m_p->m_referenceCount = 1; 199 } 200 return m_p; 201 } 202 203 template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs) 204 { 205 if (m_p != rhs.m_p) 206 { 207 if (m_p && --m_p->m_referenceCount == 0) 208 delete m_p; 209 m_p = rhs.m_p; 210 if (m_p) 211 m_p->m_referenceCount++; 212 } 213 return *this; 214 } 215 216 // ******************************************************** 217 218 /// \brief Manages resources for an array of objects 219 /// \tparam T class or type 220 template <class T> class vector_member_ptrs 221 { 222 public: 223 /// Construct an arry of \p T 224 /// \param size the size of the array, in elements 225 /// \details If \p T is a Plain Old Dataype (POD), then the array is uninitialized. 226 vector_member_ptrs(size_t size=0) m_size(size)227 : m_size(size), m_ptr(new member_ptr<T>[size]) {} ~vector_member_ptrs()228 ~vector_member_ptrs() 229 {delete [] this->m_ptr;} 230 231 member_ptr<T>& operator[](size_t index) 232 {CRYPTOPP_ASSERT(index<this->m_size); return this->m_ptr[index];} 233 const member_ptr<T>& operator[](size_t index) const 234 {CRYPTOPP_ASSERT(index<this->m_size); return this->m_ptr[index];} 235 size()236 size_t size() const {return this->m_size;} resize(size_t newSize)237 void resize(size_t newSize) 238 { 239 member_ptr<T> *newPtr = new member_ptr<T>[newSize]; 240 for (size_t i=0; i<this->m_size && i<newSize; i++) 241 newPtr[i].reset(this->m_ptr[i].release()); 242 delete [] this->m_ptr; 243 this->m_size = newSize; 244 this->m_ptr = newPtr; 245 } 246 247 private: 248 vector_member_ptrs(const vector_member_ptrs<T> &c); // copy not allowed 249 void operator=(const vector_member_ptrs<T> &x); // assignment not allowed 250 251 size_t m_size; 252 member_ptr<T> *m_ptr; 253 }; 254 255 NAMESPACE_END 256 257 #endif 258