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