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 QtQml 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 QFLAGPOINTER_P_H |
41 | #define QFLAGPOINTER_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <QtCore/qglobal.h> |
55 | |
56 | QT_BEGIN_NAMESPACE |
57 | |
58 | namespace QtPrivate { |
59 | template <typename T> struct QFlagPointerAlignment |
60 | { |
61 | enum : size_t { Value = Q_ALIGNOF(T) }; |
62 | }; |
63 | template <> struct QFlagPointerAlignment<void> |
64 | { |
65 | enum : size_t { Value = ~size_t(0) }; |
66 | }; |
67 | } |
68 | |
69 | template<typename T> |
70 | class QFlagPointer { |
71 | public: |
72 | inline QFlagPointer(); |
73 | inline QFlagPointer(T *); |
74 | inline QFlagPointer(const QFlagPointer<T> &o); |
75 | |
76 | inline bool isNull() const; |
77 | |
78 | inline bool flag() const; |
79 | inline void setFlag(); |
80 | inline void clearFlag(); |
81 | inline void setFlagValue(bool); |
82 | |
83 | inline bool flag2() const; |
84 | inline void setFlag2(); |
85 | inline void clearFlag2(); |
86 | inline void setFlag2Value(bool); |
87 | |
88 | inline QFlagPointer<T> &operator=(const QFlagPointer &o); |
89 | inline QFlagPointer<T> &operator=(T *); |
90 | |
91 | inline T *operator->() const; |
92 | inline T *operator*() const; |
93 | |
94 | inline T *data() const; |
95 | |
96 | inline explicit operator bool() const; |
97 | |
98 | private: |
99 | quintptr ptr_value = 0; |
100 | |
101 | static const quintptr FlagBit = 0x1; |
102 | static const quintptr Flag2Bit = 0x2; |
103 | static const quintptr FlagsMask = FlagBit | Flag2Bit; |
104 | }; |
105 | |
106 | template<typename T, typename T2> |
107 | class QBiPointer { |
108 | public: |
109 | inline QBiPointer(); |
110 | inline QBiPointer(T *); |
111 | inline QBiPointer(T2 *); |
112 | inline QBiPointer(const QBiPointer<T, T2> &o); |
113 | |
114 | inline bool isNull() const; |
115 | inline bool isT1() const; |
116 | inline bool isT2() const; |
117 | |
118 | inline bool flag() const; |
119 | inline void setFlag(); |
120 | inline void clearFlag(); |
121 | inline void setFlagValue(bool); |
122 | |
123 | inline QBiPointer<T, T2> &operator=(const QBiPointer<T, T2> &o); |
124 | inline QBiPointer<T, T2> &operator=(T *); |
125 | inline QBiPointer<T, T2> &operator=(T2 *); |
126 | |
127 | inline T *asT1() const; |
128 | inline T2 *asT2() const; |
129 | |
130 | private: |
131 | quintptr ptr_value = 0; |
132 | |
133 | static const quintptr FlagBit = 0x1; |
134 | static const quintptr Flag2Bit = 0x2; |
135 | static const quintptr FlagsMask = FlagBit | Flag2Bit; |
136 | }; |
137 | |
138 | template<typename T> |
139 | QFlagPointer<T>::QFlagPointer() |
140 | { |
141 | } |
142 | |
143 | template<typename T> |
144 | QFlagPointer<T>::QFlagPointer(T *v) |
145 | : ptr_value(quintptr(v)) |
146 | { |
147 | Q_STATIC_ASSERT_X(Q_ALIGNOF(T) >= 4, "Type T does not have sufficient alignment" ); |
148 | Q_ASSERT((ptr_value & FlagsMask) == 0); |
149 | } |
150 | |
151 | template<typename T> |
152 | QFlagPointer<T>::QFlagPointer(const QFlagPointer<T> &o) |
153 | : ptr_value(o.ptr_value) |
154 | { |
155 | } |
156 | |
157 | template<typename T> |
158 | bool QFlagPointer<T>::isNull() const |
159 | { |
160 | return 0 == (ptr_value & (~FlagsMask)); |
161 | } |
162 | |
163 | template<typename T> |
164 | bool QFlagPointer<T>::flag() const |
165 | { |
166 | return ptr_value & FlagBit; |
167 | } |
168 | |
169 | template<typename T> |
170 | void QFlagPointer<T>::setFlag() |
171 | { |
172 | ptr_value |= FlagBit; |
173 | } |
174 | |
175 | template<typename T> |
176 | void QFlagPointer<T>::clearFlag() |
177 | { |
178 | ptr_value &= ~FlagBit; |
179 | } |
180 | |
181 | template<typename T> |
182 | void QFlagPointer<T>::setFlagValue(bool v) |
183 | { |
184 | if (v) setFlag(); |
185 | else clearFlag(); |
186 | } |
187 | |
188 | template<typename T> |
189 | bool QFlagPointer<T>::flag2() const |
190 | { |
191 | return ptr_value & Flag2Bit; |
192 | } |
193 | |
194 | template<typename T> |
195 | void QFlagPointer<T>::setFlag2() |
196 | { |
197 | ptr_value|= Flag2Bit; |
198 | } |
199 | |
200 | template<typename T> |
201 | void QFlagPointer<T>::clearFlag2() |
202 | { |
203 | ptr_value &= ~Flag2Bit; |
204 | } |
205 | |
206 | template<typename T> |
207 | void QFlagPointer<T>::setFlag2Value(bool v) |
208 | { |
209 | if (v) setFlag2(); |
210 | else clearFlag2(); |
211 | } |
212 | |
213 | template<typename T> |
214 | QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o) |
215 | { |
216 | ptr_value = o.ptr_value; |
217 | return *this; |
218 | } |
219 | |
220 | template<typename T> |
221 | QFlagPointer<T> &QFlagPointer<T>::operator=(T *o) |
222 | { |
223 | Q_ASSERT((quintptr(o) & FlagsMask) == 0); |
224 | |
225 | ptr_value = quintptr(o) | (ptr_value & FlagsMask); |
226 | return *this; |
227 | } |
228 | |
229 | template<typename T> |
230 | T *QFlagPointer<T>::operator->() const |
231 | { |
232 | return (T *)(ptr_value & ~FlagsMask); |
233 | } |
234 | |
235 | template<typename T> |
236 | T *QFlagPointer<T>::operator*() const |
237 | { |
238 | return (T *)(ptr_value & ~FlagsMask); |
239 | } |
240 | |
241 | template<typename T> |
242 | T *QFlagPointer<T>::data() const |
243 | { |
244 | return (T *)(ptr_value & ~FlagsMask); |
245 | } |
246 | |
247 | template<typename T> |
248 | QFlagPointer<T>::operator bool() const |
249 | { |
250 | return data() != nullptr; |
251 | } |
252 | |
253 | template<typename T, typename T2> |
254 | QBiPointer<T, T2>::QBiPointer() |
255 | { |
256 | } |
257 | |
258 | template<typename T, typename T2> |
259 | QBiPointer<T, T2>::QBiPointer(T *v) |
260 | : ptr_value(quintptr(v)) |
261 | { |
262 | Q_STATIC_ASSERT_X(QtPrivate::QFlagPointerAlignment<T>::Value >= 4, |
263 | "Type T does not have sufficient alignment" ); |
264 | Q_ASSERT((quintptr(v) & FlagsMask) == 0); |
265 | } |
266 | |
267 | template<typename T, typename T2> |
268 | QBiPointer<T, T2>::QBiPointer(T2 *v) |
269 | : ptr_value(quintptr(v) | Flag2Bit) |
270 | { |
271 | Q_STATIC_ASSERT_X(QtPrivate::QFlagPointerAlignment<T2>::Value >= 4, |
272 | "Type T2 does not have sufficient alignment" ); |
273 | Q_ASSERT((quintptr(v) & FlagsMask) == 0); |
274 | } |
275 | |
276 | template<typename T, typename T2> |
277 | QBiPointer<T, T2>::QBiPointer(const QBiPointer<T, T2> &o) |
278 | : ptr_value(o.ptr_value) |
279 | { |
280 | } |
281 | |
282 | template<typename T, typename T2> |
283 | bool QBiPointer<T, T2>::isNull() const |
284 | { |
285 | return 0 == (ptr_value & (~FlagsMask)); |
286 | } |
287 | |
288 | template<typename T, typename T2> |
289 | bool QBiPointer<T, T2>::isT1() const |
290 | { |
291 | return !(ptr_value & Flag2Bit); |
292 | } |
293 | |
294 | template<typename T, typename T2> |
295 | bool QBiPointer<T, T2>::isT2() const |
296 | { |
297 | return ptr_value & Flag2Bit; |
298 | } |
299 | |
300 | template<typename T, typename T2> |
301 | bool QBiPointer<T, T2>::flag() const |
302 | { |
303 | return ptr_value & FlagBit; |
304 | } |
305 | |
306 | template<typename T, typename T2> |
307 | void QBiPointer<T, T2>::setFlag() |
308 | { |
309 | ptr_value |= FlagBit; |
310 | } |
311 | |
312 | template<typename T, typename T2> |
313 | void QBiPointer<T, T2>::clearFlag() |
314 | { |
315 | ptr_value &= ~FlagBit; |
316 | } |
317 | |
318 | template<typename T, typename T2> |
319 | void QBiPointer<T, T2>::setFlagValue(bool v) |
320 | { |
321 | if (v) setFlag(); |
322 | else clearFlag(); |
323 | } |
324 | |
325 | template<typename T, typename T2> |
326 | QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(const QBiPointer<T, T2> &o) |
327 | { |
328 | ptr_value = o.ptr_value; |
329 | return *this; |
330 | } |
331 | |
332 | template<typename T, typename T2> |
333 | QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T *o) |
334 | { |
335 | Q_ASSERT((quintptr(o) & FlagsMask) == 0); |
336 | |
337 | ptr_value = quintptr(o) | (ptr_value & FlagBit); |
338 | return *this; |
339 | } |
340 | |
341 | template<typename T, typename T2> |
342 | QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T2 *o) |
343 | { |
344 | Q_ASSERT((quintptr(o) & FlagsMask) == 0); |
345 | |
346 | ptr_value = quintptr(o) | (ptr_value & FlagBit) | Flag2Bit; |
347 | return *this; |
348 | } |
349 | |
350 | template<typename T, typename T2> |
351 | T *QBiPointer<T, T2>::asT1() const |
352 | { |
353 | Q_ASSERT(isT1()); |
354 | return (T *)(ptr_value & ~FlagsMask); |
355 | } |
356 | |
357 | template<typename T, typename T2> |
358 | T2 *QBiPointer<T, T2>::asT2() const |
359 | { |
360 | Q_ASSERT(isT2()); |
361 | return (T2 *)(ptr_value & ~FlagsMask); |
362 | } |
363 | |
364 | QT_END_NAMESPACE |
365 | |
366 | #endif // QFLAGPOINTER_P_H |
367 | |