source: trunk/src-cryptopp/smartptr.h

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 8.3 KB
Line 
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
13NAMESPACE_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).
20template <class T> class simple_ptr
21{
22public:
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>
39template <class T> class member_ptr
40{
41public:
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
64protected:
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
71template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
72template <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
79template<class T> class value_ptr : public member_ptr<T>
80{
81public:
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
94template <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
108template<class T> class clonable_ptr : public member_ptr<T>
109{
110public:
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
119template <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
134template<class T> class counted_ptr
135{
136public:
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
156private:
157        T *m_p;
158};
159
160template <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
167template <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
174template <class T> counted_ptr<T>::~counted_ptr()
175{
176        if (m_p && --m_p->m_referenceCount == 0)
177                delete m_p;
178}
179
180template <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
196template <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
208template <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).
229template <class T> class vector_ptr
230{
231public:
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
271private:
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
284template <class T> class vector_member_ptrs
285{
286public:
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
311private:
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
319NAMESPACE_END
320
321#endif
Note: See TracBrowser for help on using the repository browser.