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 <WebKit2/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#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
72    template<typename U> WKRetainPtr(WKRetainPtr<U>&& o)
73        : m_ptr(o.leakRef())
74    {
75    }
76
77    WKRetainPtr(WKRetainPtr&& o)
78        : m_ptr(o.leakRef())
79    {
80    }
81#endif
82
83    ~WKRetainPtr()
84    {
85        if (PtrType ptr = m_ptr)
86            WKRelease(ptr);
87    }
88
89    PtrType get() const { return m_ptr; }
90
91    void clear()
92    {
93        PtrType ptr = m_ptr;
94        m_ptr = 0;
95        if (ptr)
96            WKRelease(ptr);
97    }
98
99    PtrType leakRef()
100    {
101        PtrType ptr = m_ptr;
102        m_ptr = 0;
103        return ptr;
104    }
105
106    PtrType operator->() const { return m_ptr; }
107    bool operator!() const { return !m_ptr; }
108
109    // This conversion operator allows implicit conversion to bool but not to other integer types.
110    typedef PtrType WKRetainPtr::*UnspecifiedBoolType;
111    operator UnspecifiedBoolType() const { return m_ptr ? &WKRetainPtr::m_ptr : 0; }
112
113    WKRetainPtr& operator=(const WKRetainPtr&);
114    template<typename U> WKRetainPtr& operator=(const WKRetainPtr<U>&);
115    WKRetainPtr& operator=(PtrType);
116    template<typename U> WKRetainPtr& operator=(U*);
117
118#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
119    WKRetainPtr& operator=(WKRetainPtr&&);
120    template<typename U> WKRetainPtr& operator=(WKRetainPtr<U>&&);
121#endif
122
123    void adopt(PtrType);
124    void swap(WKRetainPtr&);
125
126private:
127    PtrType m_ptr;
128};
129
130template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(const WKRetainPtr<T>& o)
131{
132    PtrType optr = o.get();
133    if (optr)
134        WKRetain(optr);
135    PtrType ptr = m_ptr;
136    m_ptr = optr;
137    if (ptr)
138        WKRelease(ptr);
139    return *this;
140}
141
142template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(const WKRetainPtr<U>& o)
143{
144    PtrType optr = o.get();
145    if (optr)
146        WKRetain(optr);
147    PtrType ptr = m_ptr;
148    m_ptr = optr;
149    if (ptr)
150        WKRelease(ptr);
151    return *this;
152}
153
154template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(PtrType optr)
155{
156    if (optr)
157        WKRetain(optr);
158    PtrType ptr = m_ptr;
159    m_ptr = optr;
160    if (ptr)
161        WKRelease(ptr);
162    return *this;
163}
164
165template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(U* optr)
166{
167    if (optr)
168        WKRetain(optr);
169    PtrType ptr = m_ptr;
170    m_ptr = optr;
171    if (ptr)
172        WKRelease(ptr);
173    return *this;
174}
175
176#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
177template<typename T> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(WKRetainPtr<T>&& o)
178{
179    adopt(o.leakRef());
180    return *this;
181}
182
183template<typename T> template<typename U> inline WKRetainPtr<T>& WKRetainPtr<T>::operator=(WKRetainPtr<U>&& o)
184{
185    adopt(o.leakRef());
186    return *this;
187}
188#endif
189
190template<typename T> inline void WKRetainPtr<T>::adopt(PtrType optr)
191{
192    PtrType ptr = m_ptr;
193    m_ptr = optr;
194    if (ptr)
195        WKRelease(ptr);
196}
197
198template<typename T> inline void WKRetainPtr<T>::swap(WKRetainPtr<T>& o)
199{
200    std::swap(m_ptr, o.m_ptr);
201}
202
203template<typename T> inline void swap(WKRetainPtr<T>& a, WKRetainPtr<T>& b)
204{
205    a.swap(b);
206}
207
208template<typename T, typename U> inline bool operator==(const WKRetainPtr<T>& a, const WKRetainPtr<U>& b)
209{
210    return a.get() == b.get();
211}
212
213template<typename T, typename U> inline bool operator==(const WKRetainPtr<T>& a, U* b)
214{
215    return a.get() == b;
216}
217
218template<typename T, typename U> inline bool operator==(T* a, const WKRetainPtr<U>& b)
219{
220    return a == b.get();
221}
222
223template<typename T, typename U> inline bool operator!=(const WKRetainPtr<T>& a, const WKRetainPtr<U>& b)
224{
225    return a.get() != b.get();
226}
227
228template<typename T, typename U> inline bool operator!=(const WKRetainPtr<T>& a, U* b)
229{
230    return a.get() != b;
231}
232
233template<typename T, typename U> inline bool operator!=(T* a, const WKRetainPtr<U>& b)
234{
235    return a != b.get();
236}
237
238template<typename T> inline WKRetainPtr<T> adoptWK(T) WARN_UNUSED_RETURN;
239
240template<typename T> inline WKRetainPtr<T> adoptWK(T o)
241{
242    return WKRetainPtr<T>(AdoptWK, o);
243}
244
245} // namespace WebKit
246
247using WebKit::WKRetainPtr;
248using WebKit::AdoptWK;
249using WebKit::adoptWK;
250
251#endif // WKRetainPtr_h
252