1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef WKRetainPtr_h
27#define WKRetainPtr_h
28
29#include <WebKit/WKType.h>
30#include <algorithm>
31
32namespace WebKit {
33
34enum WKAdoptTag { AdoptWK };
35
36template<typename T> class WKRetainPtr {
37public:
38    typedef T PtrType;
39
40    WKRetainPtr()
41        : m_ptr(0)
42    {
43    }
44
45    WKRetainPtr(PtrType ptr)
46        : m_ptr(ptr)
47    {
48        if (ptr)
49            WKRetain(ptr);
50    }
51
52    WKRetainPtr(WKAdoptTag, PtrType ptr)
53        : m_ptr(ptr)
54    {
55    }
56
57    template<typename U> WKRetainPtr(const WKRetainPtr<U>& o)
58        : m_ptr(o.get())
59    {
60        if (PtrType ptr = m_ptr)
61            WKRetain(ptr);
62    }
63
64    WKRetainPtr(const WKRetainPtr& o)
65        : m_ptr(o.m_ptr)
66    {
67        if (PtrType ptr = m_ptr)
68            WKRetain(ptr);
69    }
70
71    template<typename U> WKRetainPtr(WKRetainPtr<U>&& o)
72        : m_ptr(o.leakRef())
73    {
74    }
75
76    WKRetainPtr(WKRetainPtr&& o)
77        : m_ptr(o.leakRef())
78    {
79    }
80
81    ~WKRetainPtr()
82    {
83        if (PtrType ptr = m_ptr)
84            WKRelease(ptr);
85    }
86
87    PtrType get() const { return m_ptr; }
88
89    void clear()
90    {
91        PtrType ptr = m_ptr;
92        m_ptr = 0;
93        if (ptr)
94            WKRelease(ptr);
95    }
96
97    PtrType leakRef()
98    {
99        PtrType ptr = m_ptr;
100        m_ptr = 0;
101        return ptr;
102    }
103
104    PtrType operator->() const { return m_ptr; }
105    bool operator!() const { return !m_ptr; }
106
107    // This conversion operator allows implicit conversion to bool but not to other integer types.
108    typedef PtrType WKRetainPtr::*UnspecifiedBoolType;
109    operator UnspecifiedBoolType() const { return m_ptr ? &WKRetainPtr::m_ptr : 0; }
110
111    WKRetainPtr& operator=(const WKRetainPtr&);
112    template<typename U> WKRetainPtr& operator=(const WKRetainPtr<U>&);
113    WKRetainPtr& operator=(PtrType);
114    template<typename U> WKRetainPtr& operator=(U*);
115
116    WKRetainPtr& operator=(WKRetainPtr&&);
117    template<typename U> WKRetainPtr& operator=(WKRetainPtr<U>&&);
118
119    void adopt(PtrType);
120    void swap(WKRetainPtr&);
121
122private:
123    PtrType m_ptr;
124};
125
126template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(const WKRetainPtr<T>& o)
127{
128    PtrType optr = o.get();
129    if (optr)
130        WKRetain(optr);
131    PtrType ptr = m_ptr;
132    m_ptr = optr;
133    if (ptr)
134        WKRelease(ptr);
135    return *this;
136}
137
138template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(const WKRetainPtr<U>& o)
139{
140    PtrType optr = o.get();
141    if (optr)
142        WKRetain(optr);
143    PtrType ptr = m_ptr;
144    m_ptr = optr;
145    if (ptr)
146        WKRelease(ptr);
147    return *this;
148}
149
150template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(PtrType optr)
151{
152    if (optr)
153        WKRetain(optr);
154    PtrType ptr = m_ptr;
155    m_ptr = optr;
156    if (ptr)
157        WKRelease(ptr);
158    return *this;
159}
160
161template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(U* optr)
162{
163    if (optr)
164        WKRetain(optr);
165    PtrType ptr = m_ptr;
166    m_ptr = optr;
167    if (ptr)
168        WKRelease(ptr);
169    return *this;
170}
171
172template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(WKRetainPtr<T>&& o)
173{
174    adopt(o.leakRef());
175    return *this;
176}
177
178template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(WKRetainPtr<U>&& o)
179{
180    adopt(o.leakRef());
181    return *this;
182}
183
184template<typename T> inline void WKRetainPtr<T>::adopt(PtrType optr)
185{
186    PtrType ptr = m_ptr;
187    m_ptr = optr;
188    if (ptr)
189        WKRelease(ptr);
190}
191
192template<typename T> inline void WKRetainPtr<T>::swap(WKRetainPtr<T>& o)
193{
194    std::swap(m_ptr, o.m_ptr);
195}
196
197template<typename T> inline void swap(WKRetainPtr<T>& a, WKRetainPtr<T>& b)
198{
199    a.swap(b);
200}
201
202template<typename T, typename U> inline bool operator==(const WKRetainPtr<T>& a, const WKRetainPtr<U>& b)
203{
204    return a.get() == b.get();
205}
206
207template<typename T, typename U> inline bool operator==(const WKRetainPtr<T>& a, U* b)
208{
209    return a.get() == b;
210}
211
212template<typename T, typename U> inline bool operator==(T* a, const WKRetainPtr<U>& b)
213{
214    return a == b.get();
215}
216
217template<typename T, typename U> inline bool operator!=(const WKRetainPtr<T>& a, const WKRetainPtr<U>& b)
218{
219    return a.get() != b.get();
220}
221
222template<typename T, typename U> inline bool operator!=(const WKRetainPtr<T>& a, U* b)
223{
224    return a.get() != b;
225}
226
227template<typename T, typename U> inline bool operator!=(T* a, const WKRetainPtr<U>& b)
228{
229    return a != b.get();
230}
231
232#if defined(__GNUC__) && !(defined(__CC_ARM) || defined(__ARMCC__))
233#define WK_WARN_UNUSED_RETURN __attribute__((warn_unused_result))
234#else
235#define WK_WARN_UNUSED_RETURN
236#endif
237
238template<typename T> inline WKRetainPtr<T> adoptWK(T) WK_WARN_UNUSED_RETURN;
239
240#undef WK_WARN_UNUSED_RETURN
241
242template<typename T> inline WKRetainPtr<T> adoptWK(T o)
243{
244    return WKRetainPtr<T>(AdoptWK, o);
245}
246
247} // namespace WebKit
248
249using WebKit::WKRetainPtr;
250using WebKit::AdoptWK;
251using WebKit::adoptWK;
252
253#endif // WKRetainPtr_h
254