File indexing completed on 2024-06-23 05:21:36

0001 /*
0002  * SPDX-FileCopyrightText: 2008 Trevor Pounds
0003  * SPDX-License-Identifier: MIT
0004  */
0005 
0006 #ifndef __MOCKITOPP_POINTERS_PTR__
0007 #define __MOCKITOPP_POINTERS_PTR__
0008 
0009 namespace mockitopp
0010 {
0011    namespace detail
0012    {
0013       /**
0014        * The default deleter functor used by shared_ptr
0015        * to free the underlying allocated memory.
0016        *
0017        * @author Trevor Pounds
0018        */
0019       template <typename T>
0020       struct default_ptr_deleter
0021       {
0022          void operator() (T* ptr)
0023             { delete ptr; }
0024       };
0025 
0026       /**
0027        * A reference counting "smart" pointer similar to
0028        * the ones provided by boost, tr1, c++0x, etc.
0029        *
0030        * NOTE:
0031        *
0032        *   Concurrent usage is not supported since the
0033        *   reference counter is not modified atomically.
0034        *
0035        * @author Trevor Pounds
0036        */
0037       template <typename T, typename D = default_ptr_deleter<T> >
0038       class shared_ptr
0039       {
0040          public:
0041 
0042             shared_ptr()
0043                : _ptr_impl()
0044                {}
0045 
0046             shared_ptr(const shared_ptr& rhs)
0047                : _ptr_impl(rhs._ptr_impl)
0048                { __increment(); }
0049 
0050             explicit shared_ptr(T* raw_ptr)
0051                : _ptr_impl(new shared_ptr_impl(raw_ptr, 1))
0052                {}
0053 
0054             ~shared_ptr() { __decrement(); }
0055 
0056             bool operator==(const shared_ptr& rhs) const { return _ptr_impl == rhs._ptr_impl; }
0057             bool operator!=(const shared_ptr& rhs) const { return _ptr_impl != rhs._ptr_impl; }
0058             bool operator<(const shared_ptr& rhs)  const { return _ptr_impl < rhs._ptr_impl; }
0059             bool operator>(const shared_ptr& rhs)  const { return _ptr_impl > rhs._ptr_impl; }
0060             bool operator<=(const shared_ptr& rhs) const { return _ptr_impl <= rhs._ptr_impl; }
0061             bool operator>=(const shared_ptr& rhs) const { return _ptr_impl >= rhs._ptr_impl; }
0062 
0063             shared_ptr& operator=(const shared_ptr& rhs)
0064             {
0065                if(this != &rhs)
0066                {
0067                   __decrement();
0068                   _ptr_impl = rhs._ptr_impl;
0069                   __increment();
0070                }
0071                return *this;
0072             }
0073 
0074             T* get()        const { return (_ptr_impl) ? _ptr_impl->_raw_ptr : 0; }
0075             T& operator*()  const { return *get(); }
0076             T* operator->() const { return get(); }
0077 
0078          private:
0079 
0080             struct shared_ptr_impl
0081             {
0082                T*     _raw_ptr;
0083                size_t _count;
0084 
0085                shared_ptr_impl(T* raw_ptr = 0, size_t count = 0)
0086                   : _raw_ptr(raw_ptr)
0087                   , _count(count)
0088                   {}
0089 
0090                shared_ptr_impl(const shared_ptr_impl &other)
0091                   : _raw_ptr(other._raw_ptr)
0092                   , _count(other._count)
0093                   {}
0094 
0095                ~shared_ptr_impl()
0096                   { D()(_raw_ptr); }
0097 
0098                shared_ptr_impl &operator=(const shared_ptr_impl &other)
0099                {
0100                    shared_ptr_impl tmp(other);
0101                    std::swap(*this, other);
0102                    return *this;
0103                }
0104 
0105             }* _ptr_impl;
0106 
0107             void __decrement()
0108             {
0109                if(_ptr_impl && --(_ptr_impl->_count) == 0)
0110                   { delete _ptr_impl; }
0111             }
0112 
0113             void __increment()
0114             {
0115                if(_ptr_impl)
0116                   { (_ptr_impl->_count)++; }
0117             }
0118       };
0119 
0120       /**
0121        * The default deleter functor used by shared_array
0122        * to free the underlying allocated memory.
0123        *
0124        * @author Trevor Pounds
0125        */
0126       template <typename T>
0127       struct default_array_deleter
0128       {
0129          void operator() (T* array)
0130             { delete[] array; }
0131       };
0132 
0133       /**
0134        * A reference counting "smart" array pointer similar
0135        * to the ones provided by boost, tr1, c++0x, etc.
0136        *
0137        * NOTE:
0138        *
0139        *   Concurrent usage is not supported since the
0140        *   reference counter is not modified atomically.
0141        *
0142        * @author Trevor Pounds
0143        */
0144       template <typename T, typename D = default_array_deleter<T> >
0145       class shared_array : public shared_ptr<T, D>
0146       {
0147          public:
0148 
0149             shared_array()
0150                : shared_ptr<T, D>()
0151                {}
0152 
0153             explicit shared_array(T* raw_ptr)
0154                : shared_ptr<T, D>(raw_ptr)
0155                {}
0156 
0157             T& operator[] (size_t i) const { return *(shared_array::get() + i); }
0158       };
0159 
0160       /**
0161        * A pointer that transfers ownership on copies and assignment.
0162        *
0163        * @author Trevor Pounds
0164        */
0165       template <typename T, typename D = default_ptr_deleter<T> >
0166       class owned_ptr
0167       {
0168          public:
0169 
0170             owned_ptr()
0171                : _ptr(0)
0172                {}
0173 
0174             owned_ptr(const owned_ptr& rhs)
0175                : _ptr((T*) ((size_t) rhs.release() | OWNER))
0176                {}
0177 
0178             explicit owned_ptr(T* ptr)
0179                : _ptr((T*) ((size_t) ptr | OWNER))
0180                {}
0181 
0182             ~owned_ptr() { __delete(); }
0183 
0184             owned_ptr& operator=(const owned_ptr& rhs)
0185             {
0186                if(this != &rhs)
0187                {
0188                   if(get() != rhs.get())
0189                      { __delete(); }
0190                   _ptr = rhs._ptr;
0191                   rhs.release();
0192                }
0193                return *this;
0194             }
0195 
0196             bool is_owner() const { return ((size_t) _ptr & OWNER) == OWNER; }
0197 
0198             T* get()        const { return (T*) ((size_t) _ptr & POINTER); }
0199             T& operator*()  const { return *get(); }
0200             T* operator->() const { return get(); }
0201             T* release()    const { return (_ptr = get()); }
0202 
0203          private:
0204 
0205             static const size_t OWNER   = 0x1;
0206             static const size_t POINTER = ~OWNER;
0207 
0208             mutable T* _ptr;
0209 
0210             void __delete()
0211             {
0212                if(is_owner())
0213                {
0214                   D()(get());
0215                   _ptr = 0;
0216                }
0217             }
0218       };
0219 
0220       /**
0221        * An array pointer that transfers ownership on copies and assignment.
0222        *
0223        * @author Trevor Pounds
0224        */
0225       template <typename T, typename D = default_array_deleter<T> >
0226       class owned_array : public owned_ptr<T, D>
0227       {
0228          public:
0229 
0230             owned_array()
0231                : owned_ptr<T, D>()
0232                {}
0233 
0234             explicit owned_array(T* ptr)
0235                : owned_ptr<T, D>(ptr)
0236                {}
0237 
0238             T& operator[] (size_t i) const { return *(owned_array::get() + i); }
0239       };
0240    } // namespace detail
0241 } // namespace mockitopp
0242 
0243 #endif //__MOCKITOPP_POINTERS_PTR__