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