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