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