Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
7.9 KiB

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