Home | History | Annotate | Download | only in wtf
      1 /*
      2  *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  *  This library is free software; you can redistribute it and/or
      5  *  modify it under the terms of the GNU Library General Public
      6  *  License as published by the Free Software Foundation; either
      7  *  version 2 of the License, or (at your option) any later version.
      8  *
      9  *  This library is distributed in the hope that it will be useful,
     10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  *  Library General Public License for more details.
     13  *
     14  *  You should have received a copy of the GNU Library General Public License
     15  *  along with this library; see the file COPYING.LIB.  If not, write to
     16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  *  Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef RetainPtr_h
     22 #define RetainPtr_h
     23 
     24 #include "TypeTraits.h"
     25 #include <algorithm>
     26 #include <CoreFoundation/CoreFoundation.h>
     27 
     28 #ifdef __OBJC__
     29 #import <Foundation/Foundation.h>
     30 #endif
     31 
     32 namespace WTF {
     33 
     34     // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
     35     // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
     36 
     37     enum AdoptCFTag { AdoptCF };
     38     enum AdoptNSTag { AdoptNS };
     39 
     40 #ifdef __OBJC__
     41     inline void adoptNSReference(id ptr)
     42     {
     43         if (ptr) {
     44             CFRetain(ptr);
     45             [ptr release];
     46         }
     47     }
     48 #endif
     49 
     50     template <typename T> class RetainPtr {
     51     public:
     52         typedef typename RemovePointer<T>::Type ValueType;
     53         typedef ValueType* PtrType;
     54 
     55         RetainPtr() : m_ptr(0) {}
     56         RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
     57 
     58         RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { }
     59         RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); }
     60 
     61         RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
     62 
     63         ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
     64 
     65         template <typename U> RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
     66 
     67         PtrType get() const { return m_ptr; }
     68 
     69         PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; }
     70 
     71         PtrType operator->() const { return m_ptr; }
     72 
     73         bool operator!() const { return !m_ptr; }
     74 
     75         // This conversion operator allows implicit conversion to bool but not to other integer types.
     76         typedef PtrType RetainPtr::*UnspecifiedBoolType;
     77         operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
     78 
     79         RetainPtr& operator=(const RetainPtr&);
     80         template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
     81         RetainPtr& operator=(PtrType);
     82         template <typename U> RetainPtr& operator=(U*);
     83 
     84         void adoptCF(PtrType);
     85         void adoptNS(PtrType);
     86 
     87         void swap(RetainPtr&);
     88 
     89     private:
     90         PtrType m_ptr;
     91     };
     92 
     93     template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
     94     {
     95         PtrType optr = o.get();
     96         if (optr)
     97             CFRetain(optr);
     98         PtrType ptr = m_ptr;
     99         m_ptr = optr;
    100         if (ptr)
    101             CFRelease(ptr);
    102         return *this;
    103     }
    104 
    105     template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
    106     {
    107         PtrType optr = o.get();
    108         if (optr)
    109             CFRetain(optr);
    110         PtrType ptr = m_ptr;
    111         m_ptr = optr;
    112         if (ptr)
    113             CFRelease(ptr);
    114         return *this;
    115     }
    116 
    117     template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
    118     {
    119         if (optr)
    120             CFRetain(optr);
    121         PtrType ptr = m_ptr;
    122         m_ptr = optr;
    123         if (ptr)
    124             CFRelease(ptr);
    125         return *this;
    126     }
    127 
    128     template <typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
    129     {
    130         PtrType ptr = m_ptr;
    131         m_ptr = optr;
    132         if (ptr)
    133             CFRelease(ptr);
    134     }
    135 
    136     template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
    137     {
    138         adoptNSReference(optr);
    139 
    140         PtrType ptr = m_ptr;
    141         m_ptr = optr;
    142         if (ptr)
    143             CFRelease(ptr);
    144     }
    145 
    146     template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
    147     {
    148         if (optr)
    149             CFRetain(optr);
    150         PtrType ptr = m_ptr;
    151         m_ptr = optr;
    152         if (ptr)
    153             CFRelease(ptr);
    154         return *this;
    155     }
    156 
    157     template <class T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
    158     {
    159         std::swap(m_ptr, o.m_ptr);
    160     }
    161 
    162     template <class T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
    163     {
    164         a.swap(b);
    165     }
    166 
    167     template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
    168     {
    169         return a.get() == b.get();
    170     }
    171 
    172     template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
    173     {
    174         return a.get() == b;
    175     }
    176 
    177     template <typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
    178     {
    179         return a == b.get();
    180     }
    181 
    182     template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
    183     {
    184         return a.get() != b.get();
    185     }
    186 
    187     template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
    188     {
    189         return a.get() != b;
    190     }
    191 
    192     template <typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
    193     {
    194         return a != b.get();
    195     }
    196 
    197 } // namespace WTF
    198 
    199 using WTF::AdoptCF;
    200 using WTF::AdoptNS;
    201 using WTF::RetainPtr;
    202 
    203 #endif // WTF_RetainPtr_h
    204