smartptr.h 6.2 KB

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