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