1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QMETATYPE_P_H
5#define QMETATYPE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qglobal_p.h>
19#include "qmetatype.h"
20
21QT_BEGIN_NAMESPACE
22
23#define QMETATYPE_CONVERTER(To, From, assign_and_return) \
24 case makePair(QMetaType::To, QMetaType::From): \
25 if constexpr (QMetaType::To == QMetaType::From) \
26 Q_UNREACHABLE(); /* can never get here */ \
27 if (onlyCheck) \
28 return true; \
29 { \
30 const From &source = *static_cast<const From *>(from); \
31 To &result = *static_cast<To *>(to); \
32 assign_and_return \
33 }
34#define QMETATYPE_CONVERTER_ASSIGN(To, From) \
35 QMETATYPE_CONVERTER(To, From, result = To(source); return true;)
36
37#define QMETATYPE_CONVERTER_FUNCTION(To, assign_and_return) \
38 { \
39 To &result = *static_cast<To *>(r); \
40 assign_and_return \
41 }
42
43class Q_CORE_EXPORT QMetaTypeModuleHelper
44{
45 Q_DISABLE_COPY_MOVE(QMetaTypeModuleHelper)
46protected:
47 QMetaTypeModuleHelper() = default;
48 ~QMetaTypeModuleHelper() = default;
49public:
50 Q_WEAK_OVERLOAD // prevent it from entering the ABI and rendering constexpr useless
51 static constexpr auto makePair(int from, int to) -> quint64
52 {
53 return (quint64(from) << 32) + quint64(to);
54 }
55
56 virtual const QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
57 virtual bool convert(const void *, int, void *, int) const;
58};
59
60extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper;
61extern Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper;
62
63namespace QtMetaTypePrivate {
64template<typename T>
65struct TypeDefinition
66{
67 static const bool IsAvailable = true;
68};
69
70// Ignore these types, as incomplete
71#ifdef QT_BOOTSTRAPPED
72template<> struct TypeDefinition<qfloat16> { static const bool IsAvailable = false; };
73template<> struct TypeDefinition<QBitArray> { static const bool IsAvailable = false; };
74template<> struct TypeDefinition<QByteArrayList> { static const bool IsAvailable = false; };
75template<> struct TypeDefinition<QCborArray> { static const bool IsAvailable = false; };
76template<> struct TypeDefinition<QCborMap> { static const bool IsAvailable = false; };
77template<> struct TypeDefinition<QCborSimpleType> { static const bool IsAvailable = false; };
78template<> struct TypeDefinition<QCborValue> { static const bool IsAvailable = false; };
79#if QT_CONFIG(easingcurve)
80template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
81#endif
82template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = false; };
83template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
84template<> struct TypeDefinition<QJsonObject> { static const bool IsAvailable = false; };
85template<> struct TypeDefinition<QJsonValue> { static const bool IsAvailable = false; };
86template<> struct TypeDefinition<QUrl> { static const bool IsAvailable = false; };
87template<> struct TypeDefinition<QUuid> { static const bool IsAvailable = false; };
88template<> struct TypeDefinition<QRect> { static const bool IsAvailable = false; };
89template<> struct TypeDefinition<QRectF> { static const bool IsAvailable = false; };
90template<> struct TypeDefinition<QSize> { static const bool IsAvailable = false; };
91template<> struct TypeDefinition<QSizeF> { static const bool IsAvailable = false; };
92template<> struct TypeDefinition<QLine> { static const bool IsAvailable = false; };
93template<> struct TypeDefinition<QLineF> { static const bool IsAvailable = false; };
94template<> struct TypeDefinition<QPoint> { static const bool IsAvailable = false; };
95template<> struct TypeDefinition<QPointF> { static const bool IsAvailable = false; };
96#endif
97#if !QT_CONFIG(regularexpression)
98template<> struct TypeDefinition<QRegularExpression> { static const bool IsAvailable = false; };
99#endif
100#ifdef QT_NO_CURSOR
101template<> struct TypeDefinition<QCursor> { static const bool IsAvailable = false; };
102#endif
103#ifdef QT_NO_MATRIX4X4
104template<> struct TypeDefinition<QMatrix4x4> { static const bool IsAvailable = false; };
105#endif
106#ifdef QT_NO_VECTOR2D
107template<> struct TypeDefinition<QVector2D> { static const bool IsAvailable = false; };
108#endif
109#ifdef QT_NO_VECTOR3D
110template<> struct TypeDefinition<QVector3D> { static const bool IsAvailable = false; };
111#endif
112#ifdef QT_NO_VECTOR4D
113template<> struct TypeDefinition<QVector4D> { static const bool IsAvailable = false; };
114#endif
115#ifdef QT_NO_QUATERNION
116template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable = false; };
117#endif
118#ifdef QT_NO_ICON
119template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false; };
120#endif
121
122template <typename T> inline bool isInterfaceFor(const QtPrivate::QMetaTypeInterface *iface)
123{
124 // typeId for built-in types are fixed and require no registration
125 static_assert(QMetaTypeId2<T>::IsBuiltIn, "This function only works for built-in types");
126 static constexpr int typeId = QtPrivate::BuiltinMetaType<T>::value;
127 return iface->typeId.loadRelaxed() == typeId;
128}
129
130template <typename FPointer>
131inline bool checkMetaTypeFlagOrPointer(const QtPrivate::QMetaTypeInterface *iface, FPointer ptr, QMetaType::TypeFlag Flag)
132{
133 // helper to the isXxxConstructible & isDestructible functions below: a
134 // meta type has the trait if the trait is trivial or we have the pointer
135 // to perform the operation
136 Q_ASSERT(!isInterfaceFor<void>(iface));
137 Q_ASSERT(iface->size);
138 return ptr != nullptr || (iface->flags & Flag) == 0;
139}
140
141inline bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
142{
143 return checkMetaTypeFlagOrPointer(iface, ptr: iface->defaultCtr, Flag: QMetaType::NeedsConstruction);
144}
145
146inline bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
147{
148 return checkMetaTypeFlagOrPointer(iface, ptr: iface->copyCtr, Flag: QMetaType::NeedsCopyConstruction);
149}
150
151inline bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
152{
153 return checkMetaTypeFlagOrPointer(iface, ptr: iface->moveCtr, Flag: QMetaType::NeedsMoveConstruction);
154}
155
156inline bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
157{
158 /* For metatypes of revision 1, the NeedsDestruction was set even for trivially
159 destructible types, but their dtor pointer would be null.
160 For that reason, we need the additional check here.
161 */
162 return iface->revision < 1 ||
163 checkMetaTypeFlagOrPointer(iface, ptr: iface->dtor, Flag: QMetaType::NeedsDestruction);
164}
165
166inline void defaultConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
167{
168 Q_ASSERT(isDefaultConstructible(iface));
169 if (iface->defaultCtr)
170 iface->defaultCtr(iface, where);
171 else
172 memset(s: where, c: 0, n: iface->size);
173}
174
175inline void copyConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
176{
177 Q_ASSERT(isCopyConstructible(iface));
178 if (iface->copyCtr)
179 iface->copyCtr(iface, where, copy);
180 else
181 memcpy(dest: where, src: copy, n: iface->size);
182}
183
184inline void moveConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, void *copy)
185{
186 Q_ASSERT(isMoveConstructible(iface));
187 if (iface->moveCtr)
188 iface->moveCtr(iface, where, copy);
189 else
190 memcpy(dest: where, src: copy, n: iface->size);
191}
192
193inline void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
194{
195 if (copy)
196 copyConstruct(iface, where, copy);
197 else
198 defaultConstruct(iface, where);
199}
200
201inline void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
202{
203 Q_ASSERT(isDestructible(iface));
204 if (iface->dtor)
205 iface->dtor(iface, where);
206}
207
208const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
209
210template<typename T>
211static const QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
212{
213 if constexpr (QtMetaTypePrivate::TypeDefinition<T>::IsAvailable) {
214 return &QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterfaceWrapper)<T>::metaType;
215 }
216 return nullptr;
217}
218
219#define QT_METATYPE_CONVERT_ID_TO_TYPE(MetaTypeName, MetaTypeId, RealName) \
220 case QMetaType::MetaTypeName: \
221 return QtMetaTypePrivate::getInterfaceFromType<RealName>();
222
223} //namespace QtMetaTypePrivate
224
225QT_END_NAMESPACE
226
227#endif // QMETATYPE_P_H
228

source code of qtbase/src/corelib/kernel/qmetatype_p.h