]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/RetainPtr.h
a66a12748a03b87ef6bb22807258dce2819c34f1
[apple/javascriptcore.git] / wtf / RetainPtr.h
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 <algorithm>
25 #include <CoreFoundation/CoreFoundation.h>
26
27 #ifdef __OBJC__
28 #import <Foundation/Foundation.h>
29 #endif
30
31 namespace WTF {
32
33 template <typename T> struct RemovePointer {
34 typedef T type;
35 };
36
37 template <typename T> struct RemovePointer<T*> {
38 typedef T type;
39 };
40
41 // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
42 // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
43
44 enum AdoptCFTag { AdoptCF };
45 enum AdoptNSTag { AdoptNS };
46
47 #ifdef __OBJC__
48 inline void adoptNSReference(id ptr)
49 {
50 if (ptr) {
51 CFRetain(ptr);
52 [ptr release];
53 }
54 }
55 #endif
56
57 template <typename T> class RetainPtr {
58 public:
59 typedef typename RemovePointer<T>::type ValueType;
60 typedef ValueType* PtrType;
61
62 RetainPtr() : m_ptr(0) {}
63 RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
64
65 RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { }
66 RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); }
67
68 RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
69
70 ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
71
72 template <typename U> RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
73
74 PtrType get() const { return m_ptr; }
75
76 PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; }
77
78 PtrType operator->() const { return m_ptr; }
79
80 bool operator!() const { return !m_ptr; }
81
82 // This conversion operator allows implicit conversion to bool but not to other integer types.
83 typedef PtrType RetainPtr::*UnspecifiedBoolType;
84 operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
85
86 RetainPtr& operator=(const RetainPtr&);
87 template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
88 RetainPtr& operator=(PtrType);
89 template <typename U> RetainPtr& operator=(U*);
90
91 void adoptCF(PtrType);
92 void adoptNS(PtrType);
93
94 void swap(RetainPtr&);
95
96 private:
97 PtrType m_ptr;
98 };
99
100 template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
101 {
102 PtrType optr = o.get();
103 if (optr)
104 CFRetain(optr);
105 PtrType ptr = m_ptr;
106 m_ptr = optr;
107 if (ptr)
108 CFRelease(ptr);
109 return *this;
110 }
111
112 template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
113 {
114 PtrType optr = o.get();
115 if (optr)
116 CFRetain(optr);
117 PtrType ptr = m_ptr;
118 m_ptr = optr;
119 if (ptr)
120 CFRelease(ptr);
121 return *this;
122 }
123
124 template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
125 {
126 if (optr)
127 CFRetain(optr);
128 PtrType ptr = m_ptr;
129 m_ptr = optr;
130 if (ptr)
131 CFRelease(ptr);
132 return *this;
133 }
134
135 template <typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
136 {
137 PtrType ptr = m_ptr;
138 m_ptr = optr;
139 if (ptr)
140 CFRelease(ptr);
141 }
142
143 template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
144 {
145 adoptNSReference(optr);
146
147 PtrType ptr = m_ptr;
148 m_ptr = optr;
149 if (ptr)
150 CFRelease(ptr);
151 }
152
153 template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
154 {
155 if (optr)
156 CFRetain(optr);
157 PtrType ptr = m_ptr;
158 m_ptr = optr;
159 if (ptr)
160 CFRelease(ptr);
161 return *this;
162 }
163
164 template <class T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
165 {
166 std::swap(m_ptr, o.m_ptr);
167 }
168
169 template <class T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
170 {
171 a.swap(b);
172 }
173
174 template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
175 {
176 return a.get() == b.get();
177 }
178
179 template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
180 {
181 return a.get() == b;
182 }
183
184 template <typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
185 {
186 return a == b.get();
187 }
188
189 template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
190 {
191 return a.get() != b.get();
192 }
193
194 template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
195 {
196 return a.get() != b;
197 }
198
199 template <typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
200 {
201 return a != b.get();
202 }
203
204 } // namespace WTF
205
206 using WTF::AdoptCF;
207 using WTF::AdoptNS;
208 using WTF::RetainPtr;
209
210 #endif // WTF_RetainPtr_h