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 | {CRYPTOPP_ASSERT(m_size && index<this->m_size); return this->m_ptr[index];} |
---|
242 | const T& operator[](size_t index) const |
---|
243 | {CRYPTOPP_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]) {} |
---|
292 | ~vector_member_ptrs() |
---|
293 | {delete [] this->m_ptr;} |
---|
294 | |
---|
295 | member_ptr<T>& operator[](size_t index) |
---|
296 | {CRYPTOPP_ASSERT(index<this->m_size); return this->m_ptr[index];} |
---|
297 | const member_ptr<T>& operator[](size_t index) const |
---|
298 | {CRYPTOPP_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 |
---|