1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QSCOPEDPOINTER_H |
41 | #define QSCOPEDPOINTER_H |
42 | |
43 | #include <QtCore/qglobal.h> |
44 | |
45 | #include <stdlib.h> |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | template <typename T> |
50 | struct QScopedPointerDeleter |
51 | { |
52 | static inline void cleanup(T *pointer) |
53 | { |
54 | // Enforce a complete type. |
55 | // If you get a compile error here, read the section on forward declared |
56 | // classes in the QScopedPointer documentation. |
57 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
58 | (void) sizeof(IsIncompleteType); |
59 | |
60 | delete pointer; |
61 | } |
62 | }; |
63 | |
64 | template <typename T> |
65 | struct QScopedPointerArrayDeleter |
66 | { |
67 | static inline void cleanup(T *pointer) |
68 | { |
69 | // Enforce a complete type. |
70 | // If you get a compile error here, read the section on forward declared |
71 | // classes in the QScopedPointer documentation. |
72 | typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; |
73 | (void) sizeof(IsIncompleteType); |
74 | |
75 | delete[] pointer; |
76 | } |
77 | }; |
78 | |
79 | struct QScopedPointerPodDeleter |
80 | { |
81 | static inline void cleanup(void *pointer) { if (pointer) free(pointer); } |
82 | }; |
83 | |
84 | #ifndef QT_NO_QOBJECT |
85 | template <typename T> |
86 | struct QScopedPointerObjectDeleteLater |
87 | { |
88 | static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } |
89 | }; |
90 | |
91 | class QObject; |
92 | typedef QScopedPointerObjectDeleteLater<QObject> QScopedPointerDeleteLater; |
93 | #endif |
94 | |
95 | template <typename T, typename Cleanup = QScopedPointerDeleter<T> > |
96 | class QScopedPointer |
97 | { |
98 | public: |
99 | explicit QScopedPointer(T *p = nullptr) noexcept : d(p) |
100 | { |
101 | } |
102 | |
103 | inline ~QScopedPointer() |
104 | { |
105 | T *oldD = this->d; |
106 | Cleanup::cleanup(oldD); |
107 | } |
108 | |
109 | inline T &operator*() const |
110 | { |
111 | Q_ASSERT(d); |
112 | return *d; |
113 | } |
114 | |
115 | T *operator->() const noexcept |
116 | { |
117 | return d; |
118 | } |
119 | |
120 | bool operator!() const noexcept |
121 | { |
122 | return !d; |
123 | } |
124 | |
125 | explicit operator bool() const |
126 | { |
127 | return !isNull(); |
128 | } |
129 | |
130 | T *data() const noexcept |
131 | { |
132 | return d; |
133 | } |
134 | |
135 | T *get() const noexcept |
136 | { |
137 | return d; |
138 | } |
139 | |
140 | bool isNull() const noexcept |
141 | { |
142 | return !d; |
143 | } |
144 | |
145 | void reset(T *other = nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval<T *>()))) |
146 | { |
147 | if (d == other) |
148 | return; |
149 | T *oldD = d; |
150 | d = other; |
151 | Cleanup::cleanup(oldD); |
152 | } |
153 | |
154 | T *take() noexcept |
155 | { |
156 | T *oldD = d; |
157 | d = nullptr; |
158 | return oldD; |
159 | } |
160 | |
161 | void swap(QScopedPointer<T, Cleanup> &other) noexcept |
162 | { |
163 | qSwap(d, other.d); |
164 | } |
165 | |
166 | typedef T *pointer; |
167 | |
168 | protected: |
169 | T *d; |
170 | |
171 | private: |
172 | Q_DISABLE_COPY(QScopedPointer) |
173 | }; |
174 | |
175 | template <class T, class Cleanup> |
176 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
177 | { |
178 | return lhs.data() == rhs.data(); |
179 | } |
180 | |
181 | template <class T, class Cleanup> |
182 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept |
183 | { |
184 | return lhs.data() != rhs.data(); |
185 | } |
186 | |
187 | template <class T, class Cleanup> |
188 | inline bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
189 | { |
190 | return lhs.isNull(); |
191 | } |
192 | |
193 | template <class T, class Cleanup> |
194 | inline bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept |
195 | { |
196 | return rhs.isNull(); |
197 | } |
198 | |
199 | template <class T, class Cleanup> |
200 | inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept |
201 | { |
202 | return !lhs.isNull(); |
203 | } |
204 | |
205 | template <class T, class Cleanup> |
206 | inline bool operator!=(std::nullptr_t, 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 | template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > |
216 | class QScopedArrayPointer : public QScopedPointer<T, Cleanup> |
217 | { |
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 | inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(nullptr) {} |
222 | |
223 | template <typename D, if_same_type<D> = true> |
224 | explicit QScopedArrayPointer(D *p) |
225 | : QScopedPointer<T, Cleanup>(p) |
226 | { |
227 | } |
228 | |
229 | inline T &operator[](int i) |
230 | { |
231 | return this->d[i]; |
232 | } |
233 | |
234 | inline const T &operator[](int i) const |
235 | { |
236 | return this->d[i]; |
237 | } |
238 | |
239 | void swap(QScopedArrayPointer &other) noexcept // prevent QScopedPointer <->QScopedArrayPointer swaps |
240 | { QScopedPointer<T, Cleanup>::swap(other); } |
241 | |
242 | private: |
243 | explicit inline QScopedArrayPointer(void *) |
244 | { |
245 | // Enforce the same type. |
246 | |
247 | // If you get a compile error here, make sure you declare |
248 | // QScopedArrayPointer with the same template type as you pass to the |
249 | // constructor. See also the QScopedPointer documentation. |
250 | |
251 | // Storing a scalar array as a pointer to a different type is not |
252 | // allowed and results in undefined behavior. |
253 | } |
254 | |
255 | Q_DISABLE_COPY(QScopedArrayPointer) |
256 | }; |
257 | |
258 | template <typename T, typename Cleanup> |
259 | inline void swap(QScopedArrayPointer<T, Cleanup> &lhs, QScopedArrayPointer<T, Cleanup> &rhs) noexcept |
260 | { lhs.swap(rhs); } |
261 | |
262 | QT_END_NAMESPACE |
263 | |
264 | #endif // QSCOPEDPOINTER_H |
265 | |