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
56QT_BEGIN_NAMESPACE
57
58namespace QtPrivate {
59template <typename T> struct QFlagPointerAlignment
60{
61 enum : size_t { Value = Q_ALIGNOF(T) };
62};
63template <> struct QFlagPointerAlignment<void>
64{
65 enum : size_t { Value = ~size_t(0) };
66};
67}
68
69template<typename T>
70class QFlagPointer {
71public:
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
98private:
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
106template<typename T, typename T2>
107class QBiPointer {
108public:
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
130private:
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
138template<typename T>
139QFlagPointer<T>::QFlagPointer()
140{
141}
142
143template<typename T>
144QFlagPointer<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
151template<typename T>
152QFlagPointer<T>::QFlagPointer(const QFlagPointer<T> &o)
153: ptr_value(o.ptr_value)
154{
155}
156
157template<typename T>
158bool QFlagPointer<T>::isNull() const
159{
160 return 0 == (ptr_value & (~FlagsMask));
161}
162
163template<typename T>
164bool QFlagPointer<T>::flag() const
165{
166 return ptr_value & FlagBit;
167}
168
169template<typename T>
170void QFlagPointer<T>::setFlag()
171{
172 ptr_value |= FlagBit;
173}
174
175template<typename T>
176void QFlagPointer<T>::clearFlag()
177{
178 ptr_value &= ~FlagBit;
179}
180
181template<typename T>
182void QFlagPointer<T>::setFlagValue(bool v)
183{
184 if (v) setFlag();
185 else clearFlag();
186}
187
188template<typename T>
189bool QFlagPointer<T>::flag2() const
190{
191 return ptr_value & Flag2Bit;
192}
193
194template<typename T>
195void QFlagPointer<T>::setFlag2()
196{
197 ptr_value|= Flag2Bit;
198}
199
200template<typename T>
201void QFlagPointer<T>::clearFlag2()
202{
203 ptr_value &= ~Flag2Bit;
204}
205
206template<typename T>
207void QFlagPointer<T>::setFlag2Value(bool v)
208{
209 if (v) setFlag2();
210 else clearFlag2();
211}
212
213template<typename T>
214QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o)
215{
216 ptr_value = o.ptr_value;
217 return *this;
218}
219
220template<typename T>
221QFlagPointer<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
229template<typename T>
230T *QFlagPointer<T>::operator->() const
231{
232 return (T *)(ptr_value & ~FlagsMask);
233}
234
235template<typename T>
236T *QFlagPointer<T>::operator*() const
237{
238 return (T *)(ptr_value & ~FlagsMask);
239}
240
241template<typename T>
242T *QFlagPointer<T>::data() const
243{
244 return (T *)(ptr_value & ~FlagsMask);
245}
246
247template<typename T>
248QFlagPointer<T>::operator bool() const
249{
250 return data() != nullptr;
251}
252
253template<typename T, typename T2>
254QBiPointer<T, T2>::QBiPointer()
255{
256}
257
258template<typename T, typename T2>
259QBiPointer<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
267template<typename T, typename T2>
268QBiPointer<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
276template<typename T, typename T2>
277QBiPointer<T, T2>::QBiPointer(const QBiPointer<T, T2> &o)
278: ptr_value(o.ptr_value)
279{
280}
281
282template<typename T, typename T2>
283bool QBiPointer<T, T2>::isNull() const
284{
285 return 0 == (ptr_value & (~FlagsMask));
286}
287
288template<typename T, typename T2>
289bool QBiPointer<T, T2>::isT1() const
290{
291 return !(ptr_value & Flag2Bit);
292}
293
294template<typename T, typename T2>
295bool QBiPointer<T, T2>::isT2() const
296{
297 return ptr_value & Flag2Bit;
298}
299
300template<typename T, typename T2>
301bool QBiPointer<T, T2>::flag() const
302{
303 return ptr_value & FlagBit;
304}
305
306template<typename T, typename T2>
307void QBiPointer<T, T2>::setFlag()
308{
309 ptr_value |= FlagBit;
310}
311
312template<typename T, typename T2>
313void QBiPointer<T, T2>::clearFlag()
314{
315 ptr_value &= ~FlagBit;
316}
317
318template<typename T, typename T2>
319void QBiPointer<T, T2>::setFlagValue(bool v)
320{
321 if (v) setFlag();
322 else clearFlag();
323}
324
325template<typename T, typename T2>
326QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(const QBiPointer<T, T2> &o)
327{
328 ptr_value = o.ptr_value;
329 return *this;
330}
331
332template<typename T, typename T2>
333QBiPointer<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
341template<typename T, typename T2>
342QBiPointer<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
350template<typename T, typename T2>
351T *QBiPointer<T, T2>::asT1() const
352{
353 Q_ASSERT(isT1());
354 return (T *)(ptr_value & ~FlagsMask);
355}
356
357template<typename T, typename T2>
358T2 *QBiPointer<T, T2>::asT2() const
359{
360 Q_ASSERT(isT2());
361 return (T2 *)(ptr_value & ~FlagsMask);
362}
363
364QT_END_NAMESPACE
365
366#endif // QFLAGPOINTER_P_H
367

source code of qtdeclarative/src/qml/qml/ftw/qflagpointer_p.h