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