1 /**************************************************************************** 2 ** 3 ** DQt - D bindings for the Qt Toolkit 4 ** 5 ** GNU Lesser General Public License Usage 6 ** This file may be used under the terms of the GNU Lesser 7 ** General Public License version 3 as published by the Free Software 8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 9 ** packaging of this file. Please review the following information to 10 ** ensure the GNU Lesser General Public License version 3 requirements 11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 12 ** 13 ****************************************************************************/ 14 module qt.core.scopedpointer; 15 extern(C++): 16 17 import qt.config; 18 import qt.core.object; 19 import qt.helpers; 20 21 struct QScopedPointerDeleter(T) 22 { 23 static if(is(T == class)) 24 { 25 alias P = T; 26 enum IsIncompleteType = !__traits(compiles, __traits(classInstanceSize, T)); 27 } 28 else 29 { 30 alias P = T*; 31 enum IsIncompleteType = !__traits(compiles, T.sizeof); 32 } 33 static if(IsIncompleteType) 34 static void cleanup(P pointer); 35 else 36 pragma(inline, true) static void cleanup(P pointer) 37 { 38 import core.stdcpp.new_; 39 40 static if(IsIncompleteType) 41 assert(false); 42 else 43 cpp_delete(pointer); 44 } 45 } 46 47 /+ template <typename T> 48 struct QScopedPointerArrayDeleter 49 { 50 static inline void cleanup(T *pointer) 51 { 52 // Enforce a complete type. 53 // If you get a compile error here, read the section on forward declared 54 // classes in the QScopedPointer documentation. 55 typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; 56 (void) sizeof(IsIncompleteType); 57 58 delete [] pointer; 59 } 60 }; 61 62 struct QScopedPointerPodDeleter 63 { 64 static inline void cleanup(void *pointer) { if (pointer) free(pointer); } 65 }; 66 67 #ifndef QT_NO_QOBJECT +/ 68 struct QScopedPointerObjectDeleteLater(T) if(is(T : QObject)) 69 { 70 pragma(inline, true) static void cleanup(T pointer) { if (pointer) pointer.deleteLater(); } 71 } 72 73 /+ class QObject; +/ 74 alias QScopedPointerDeleteLater = QScopedPointerObjectDeleteLater!(QObject); 75 /+ #endif +/ 76 77 extern(C++, class) struct QScopedPointer(T, Cleanup = QScopedPointerDeleter!T) 78 { 79 private: 80 static if(is(T == class)) 81 { 82 alias P = T; 83 } 84 else 85 { 86 alias P = T*; 87 } 88 89 alias RestrictedBool = P/+ QScopedPointer:: * +/*; 90 public: 91 /+ explicit +/this(P p/+ = null+/)/+ noexcept+/ 92 { 93 this.d = p; 94 } 95 96 pragma(inline, true) ~this() 97 { 98 assert(false); 99 /*P oldD = this.d; 100 Cleanup.cleanup(oldD);*/ 101 } 102 103 pragma(inline, true) ref T opUnary(string op)() const if(op == "*") 104 { 105 import qt.core.global; 106 107 (mixin(Q_ASSERT(q{d}))); 108 return *d; 109 } 110 111 /+P operator ->() const/+ noexcept+/ 112 { 113 return d; 114 }+/ 115 116 /+bool operator !() const/+ noexcept+/ 117 { 118 return !d; 119 }+/ 120 121 /+ #if defined(Q_QDOC) 122 inline operator bool() const 123 { 124 return isNull() ? nullptr : &QScopedPointer::d; 125 } 126 #else +/ 127 /+auto opCast(T : RestrictedBool)() const/+ noexcept+/ 128 { 129 return isNull() ? null : &QScopedPointer.d; 130 }+/ 131 /+ #endif +/ 132 133 P data() const/+ noexcept+/ 134 { 135 return cast(P)d; 136 } 137 138 alias data this; 139 140 P get() const/+ noexcept+/ 141 { 142 return cast(P)d; 143 } 144 145 bool isNull() const/+ noexcept+/ 146 { 147 return !d; 148 } 149 150 /+ void reset(P other = null) /+ noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) +/ 151 { 152 if (d == other) 153 return; 154 P oldD = d; 155 d = other; 156 Cleanup.cleanup(oldD); 157 }+/ 158 159 /+ P take()/+ noexcept+/ 160 { 161 P oldD = d; 162 d = null; 163 return oldD; 164 }+/ 165 166 /+ void swap(QScopedPointer<T, Cleanup> &other) noexcept 167 { 168 qSwap(d, other.d); 169 } +/ 170 171 alias pointer = P; 172 173 protected: 174 P d = null; 175 176 private: 177 /+ Q_DISABLE_COPY(QScopedPointer) +/ 178 @disable this(this); 179 /+this(ref const(QScopedPointer));+//+ref QScopedPointer operator =(ref const(QScopedPointer));+/} 180 181 /+pragma(inline, true) bool operator ==(T, Cleanup)(ref const(QScopedPointer!(T, Cleanup)) lhs, ref const(QScopedPointer!(T, Cleanup)) rhs)/+ noexcept+/ 182 { 183 return lhs.data() == rhs.data(); 184 }+/ 185 186 /+pragma(inline, true) bool operator !=(T, Cleanup)(ref const(QScopedPointer!(T, Cleanup)) lhs, ref const(QScopedPointer!(T, Cleanup)) rhs)/+ noexcept+/ 187 { 188 return lhs.data() != rhs.data(); 189 }+/ 190 191 /+pragma(inline, true) bool operator ==(T, Cleanup)(ref const(QScopedPointer!(T, Cleanup)) lhs, /+ std:: +/nullptr_t)/+ noexcept+/ 192 { 193 return lhs.isNull(); 194 }+/ 195 196 /+pragma(inline, true) bool operator ==(T, Cleanup)(/+ std:: +/nullptr_t, ref const(QScopedPointer!(T, Cleanup)) rhs)/+ noexcept+/ 197 { 198 return rhs.isNull(); 199 }+/ 200 201 /+pragma(inline, true) bool operator !=(T, Cleanup)(ref const(QScopedPointer!(T, Cleanup)) lhs, /+ std:: +/nullptr_t)/+ noexcept+/ 202 { 203 return !lhs.isNull(); 204 }+/ 205 206 /+pragma(inline, true) bool operator !=(T, Cleanup)(/+ std:: +/nullptr_t, ref const(QScopedPointer!(T, Cleanup)) rhs)/+ noexcept+/ 207 { 208 return !rhs.isNull(); 209 }+/ 210 211 /+ template <class T, class Cleanup> 212 inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) noexcept 213 { p1.swap(p2); } +/ 214 215 class QScopedArrayPointer(T, Cleanup ) : QScopedPointer!(T, Cleanup) 216 { 217 private: 218 /+ template <typename Ptr> +/ 219 /+ using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type; +/ 220 public: 221 pragma(inline, true) this() 222 { 223 this.QScopedPointer!(T, Cleanup) = null; 224 } 225 226 /+ template <typename D, if_same_type<D> = true> +/ 227 /+ explicit QScopedArrayPointer(D *p) 228 : QScopedPointer<T, Cleanup>(p) 229 { 230 } +/ 231 232 pragma(inline, true) final ref T opIndex(int i) 233 { 234 return this.d[i]; 235 } 236 237 pragma(inline, true) final ref const(T) opIndex(int i) const 238 { 239 return this.d[i]; 240 } 241 242 /+ void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps 243 { QScopedPointer<T, Cleanup>::swap(other); } +/ 244 245 private: 246 /+ explicit +/ pragma(inline, true) this(void* ) { 247 // Enforce the same type. 248 249 // If you get a compile error here, make sure you declare 250 // QScopedArrayPointer with the same template type as you pass to the 251 // constructor. See also the QScopedPointer documentation. 252 253 // Storing a scalar array as a pointer to a different type is not 254 // allowed and results in undefined behavior. 255 } 256 257 /+ Q_DISABLE_COPY(QScopedArrayPointer) +/ 258 } 259 260 /+ template <typename T, typename Cleanup> 261 inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept 262 { lhs.swap(rhs); } +/ 263