Crypto++  7.0
Free C++ class library of cryptographic schemes
smartptr.h
Go to the documentation of this file.
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 
12 NAMESPACE_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 causes dirty compile under C++11"</a>
36 template <class T> class member_ptr
37 {
38 public:
39  explicit member_ptr(T *p = NULLPTR) : m_p(p) {}
40 
41  ~member_ptr();
42 
43  const T& operator*() const { return *m_p; }
44  T& operator*() { return *m_p; }
45 
46  const T* operator->() const { return m_p; }
47  T* operator->() { return m_p; }
48 
49  const T* get() const { return m_p; }
50  T* get() { return m_p; }
51 
52  T* release()
53  {
54  T *old_p = m_p;
55  m_p = NULLPTR;
56  return old_p;
57  }
58 
59  void reset(T *p = 0);
60 
61 protected:
62  member_ptr(const member_ptr<T>& rhs); // copy not allowed
63  void operator=(const member_ptr<T>& rhs); // assignment not allowed
64 
65  T *m_p;
66 };
67 
68 template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
69 template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;}
70 
71 // ********************************************************
72 
73 /// \brief Value pointer
74 /// \tparam T class or type
75 template<class T> class value_ptr : public member_ptr<T>
76 {
77 public:
78  value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {}
79  value_ptr(T *p = NULLPTR) : member_ptr<T>(p) {}
80  value_ptr(const value_ptr<T>& rhs)
81  : member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULLPTR) {}
82 
83  value_ptr<T>& operator=(const value_ptr<T>& rhs);
84  bool operator==(const value_ptr<T>& rhs)
85  {
86  return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p);
87  }
88 };
89 
90 template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
91 {
92  T *old_p = this->m_p;
93  this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULLPTR;
94  delete old_p;
95  return *this;
96 }
97 
98 // ********************************************************
99 
100 /// \brief A pointer which can be copied and cloned
101 /// \tparam T class or type
102 /// \details \p T should adhere to the \p Clonable interface
103 template<class T> class clonable_ptr : public member_ptr<T>
104 {
105 public:
106  clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {}
107  clonable_ptr(T *p = NULLPTR) : member_ptr<T>(p) {}
108  clonable_ptr(const clonable_ptr<T>& rhs)
109  : member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULLPTR) {}
110 
111  clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs);
112 };
113 
114 template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs)
115 {
116  T *old_p = this->m_p;
117  this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULLPTR;
118  delete old_p;
119  return *this;
120 }
121 
122 // ********************************************************
123 
124 /// \brief Reference counted pointer
125 /// \tparam T class or type
126 /// \details users should declare \p m_referenceCount as <tt>std::atomic<unsigned></tt>
127 /// (or similar) under C++ 11
128 template<class T> class counted_ptr
129 {
130 public:
131  explicit counted_ptr(T *p = 0);
132  counted_ptr(const T &r) : m_p(0) {attach(r);}
133  counted_ptr(const counted_ptr<T>& rhs);
134 
135  ~counted_ptr();
136 
137  const T& operator*() const { return *m_p; }
138  T& operator*() { return *m_p; }
139 
140  const T* operator->() const { return m_p; }
141  T* operator->() { return get(); }
142 
143  const T* get() const { return m_p; }
144  T* get();
145 
146  void attach(const T &p);
147 
148  counted_ptr<T> & operator=(const counted_ptr<T>& rhs);
149 
150 private:
151  T *m_p;
152 };
153 
154 template <class T> counted_ptr<T>::counted_ptr(T *p)
155  : m_p(p)
156 {
157  if (m_p)
158  m_p->m_referenceCount = 1;
159 }
160 
161 template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs)
162  : m_p(rhs.m_p)
163 {
164  if (m_p)
165  m_p->m_referenceCount++;
166 }
167 
168 template <class T> counted_ptr<T>::~counted_ptr()
169 {
170  if (m_p && --m_p->m_referenceCount == 0)
171  delete m_p;
172 }
173 
174 template <class T> void counted_ptr<T>::attach(const T &r)
175 {
176  if (m_p && --m_p->m_referenceCount == 0)
177  delete m_p;
178  if (r.m_referenceCount == 0)
179  {
180  m_p = r.clone();
181  m_p->m_referenceCount = 1;
182  }
183  else
184  {
185  m_p = const_cast<T *>(&r);
186  m_p->m_referenceCount++;
187  }
188 }
189 
190 template <class T> T* counted_ptr<T>::get()
191 {
192  if (m_p && m_p->m_referenceCount > 1)
193  {
194  T *temp = m_p->clone();
195  m_p->m_referenceCount--;
196  m_p = temp;
197  m_p->m_referenceCount = 1;
198  }
199  return m_p;
200 }
201 
202 template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
203 {
204  if (m_p != rhs.m_p)
205  {
206  if (m_p && --m_p->m_referenceCount == 0)
207  delete m_p;
208  m_p = rhs.m_p;
209  if (m_p)
210  m_p->m_referenceCount++;
211  }
212  return *this;
213 }
214 
215 // ********************************************************
216 
217 /// \brief Manages resources for an array of objects
218 /// \tparam T class or type
219 template <class T> class vector_member_ptrs
220 {
221 public:
222  /// Construct an arry of \p T
223  /// \param size the size of the array, in elements
224  /// \details If \p T is a Plain Old Dataype (POD), then the array is uninitialized.
225  vector_member_ptrs(size_t size=0)
226  : m_size(size), m_ptr(new member_ptr<T>[size]) {}
228  {delete [] this->m_ptr;}
229 
230  member_ptr<T>& operator[](size_t index)
231  {CRYPTOPP_ASSERT(index<this->m_size); return this->m_ptr[index];}
232  const member_ptr<T>& operator[](size_t index) const
233  {CRYPTOPP_ASSERT(index<this->m_size); return this->m_ptr[index];}
234 
235  size_t size() const {return this->m_size;}
236  void resize(size_t newSize)
237  {
238  member_ptr<T> *newPtr = new member_ptr<T>[newSize];
239  for (size_t i=0; i<this->m_size && i<newSize; i++)
240  newPtr[i].reset(this->m_ptr[i].release());
241  delete [] this->m_ptr;
242  this->m_size = newSize;
243  this->m_ptr = newPtr;
244  }
245 
246 private:
247  vector_member_ptrs(const vector_member_ptrs<T> &c); // copy not allowed
248  void operator=(const vector_member_ptrs<T> &x); // assignment not allowed
249 
250  size_t m_size;
251  member_ptr<T> *m_ptr;
252 };
253 
254 NAMESPACE_END
255 
256 #endif
Library configuration file.
Common C++ header files.
Pointer that overloads operator ->
Definition: smartptr.h:36
Reference counted pointer.
Definition: smartptr.h:128
Manages resources for a single object.
Definition: smartptr.h:18
A pointer which can be copied and cloned.
Definition: smartptr.h:103
Manages resources for an array of objects.
Definition: smartptr.h:219
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
vector_member_ptrs(size_t size=0)
Construct an arry of T.
Definition: smartptr.h:225
Value pointer.
Definition: smartptr.h:75
Crypto++ library namespace.