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 | #include "qmetatype.h" |
41 | #include "qmetatype_p.h" |
42 | #include "qobjectdefs.h" |
43 | #include "qdatetime.h" |
44 | #include "qbytearray.h" |
45 | #include "qreadwritelock.h" |
46 | #include "qstring.h" |
47 | #include "qstringlist.h" |
48 | #include "qvector.h" |
49 | #include "qlocale.h" |
50 | #if QT_CONFIG(easingcurve) |
51 | #include "qeasingcurve.h" |
52 | #endif |
53 | #include "quuid.h" |
54 | #include "qvariant.h" |
55 | #include "qdatastream.h" |
56 | #include "qregexp.h" |
57 | #include "qmetatypeswitcher_p.h" |
58 | |
59 | #if QT_CONFIG(regularexpression) |
60 | # include "qregularexpression.h" |
61 | #endif |
62 | |
63 | #ifndef QT_BOOTSTRAPPED |
64 | # include "qbitarray.h" |
65 | # include "qurl.h" |
66 | # include "qvariant.h" |
67 | # include "qjsonvalue.h" |
68 | # include "qjsonobject.h" |
69 | # include "qjsonarray.h" |
70 | # include "qjsondocument.h" |
71 | # include "qcborvalue.h" |
72 | # include "qcborarray.h" |
73 | # include "qcbormap.h" |
74 | # include "qbytearraylist.h" |
75 | #endif |
76 | |
77 | #if QT_CONFIG(itemmodel) |
78 | # include "qabstractitemmodel.h" |
79 | #endif |
80 | |
81 | #ifndef QT_NO_GEOM_VARIANT |
82 | # include "qsize.h" |
83 | # include "qpoint.h" |
84 | # include "qrect.h" |
85 | # include "qline.h" |
86 | #endif |
87 | |
88 | QT_BEGIN_NAMESPACE |
89 | |
90 | #define NS(x) QT_PREPEND_NAMESPACE(x) |
91 | |
92 | |
93 | namespace { |
94 | struct DefinedTypesFilter { |
95 | template<typename T> |
96 | struct Acceptor { |
97 | static const bool IsAccepted = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && QModulesPrivate::QTypeModuleInfo<T>::IsCore; |
98 | }; |
99 | }; |
100 | } // namespace |
101 | |
102 | /*! |
103 | \macro Q_DECLARE_OPAQUE_POINTER(PointerType) |
104 | \relates QMetaType |
105 | \since 5.0 |
106 | |
107 | This macro enables pointers to forward-declared types (\a PointerType) |
108 | to be registered with QMetaType using either Q_DECLARE_METATYPE() |
109 | or qRegisterMetaType(). |
110 | |
111 | \sa Q_DECLARE_METATYPE(), qRegisterMetaType() |
112 | */ |
113 | |
114 | /*! |
115 | \macro Q_DECLARE_METATYPE(Type) |
116 | \relates QMetaType |
117 | |
118 | This macro makes the type \a Type known to QMetaType as long as it |
119 | provides a public default constructor, a public copy constructor and |
120 | a public destructor. |
121 | It is needed to use the type \a Type as a custom type in QVariant. |
122 | |
123 | This macro requires that \a Type is a fully defined type at the point where |
124 | it is used. For pointer types, it also requires that the pointed to type is |
125 | fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to |
126 | register pointers to forward declared types. |
127 | |
128 | Ideally, this macro should be placed below the declaration of |
129 | the class or struct. If that is not possible, it can be put in |
130 | a private header file which has to be included every time that |
131 | type is used in a QVariant. |
132 | |
133 | Adding a Q_DECLARE_METATYPE() makes the type known to all template |
134 | based functions, including QVariant. Note that if you intend to |
135 | use the type in \e queued signal and slot connections or in |
136 | QObject's property system, you also have to call |
137 | qRegisterMetaType() since the names are resolved at runtime. |
138 | |
139 | This example shows a typical use case of Q_DECLARE_METATYPE(): |
140 | |
141 | \snippet code/src_corelib_kernel_qmetatype.cpp 0 |
142 | |
143 | If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro |
144 | has to be outside the namespace: |
145 | |
146 | \snippet code/src_corelib_kernel_qmetatype.cpp 1 |
147 | |
148 | Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant: |
149 | |
150 | \snippet code/src_corelib_kernel_qmetatype.cpp 2 |
151 | |
152 | Some types are registered automatically and do not need this macro: |
153 | |
154 | \list |
155 | \li Pointers to classes derived from QObject |
156 | \li QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T> |
157 | where T is a registered meta type |
158 | \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are |
159 | registered meta types |
160 | \li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject |
161 | \li Enumerations registered with Q_ENUM or Q_FLAG |
162 | \li Classes that have a Q_GADGET macro |
163 | \endlist |
164 | |
165 | \sa qRegisterMetaType() |
166 | */ |
167 | |
168 | /*! |
169 | \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container) |
170 | \relates QMetaType |
171 | |
172 | This macro makes the container \a Container known to QMetaType as a sequential |
173 | container. This makes it possible to put an instance of Container<T> into |
174 | a QVariant, if T itself is known to QMetaType. |
175 | |
176 | Note that all of the Qt sequential containers already have built-in |
177 | support, and it is not necessary to use this macro with them. The |
178 | std::vector and std::list containers also have built-in support. |
179 | |
180 | This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(): |
181 | |
182 | \snippet code/src_corelib_kernel_qmetatype.cpp 10 |
183 | */ |
184 | |
185 | /*! |
186 | \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container) |
187 | \relates QMetaType |
188 | |
189 | This macro makes the container \a Container known to QMetaType as an associative |
190 | container. This makes it possible to put an instance of Container<T, U> into |
191 | a QVariant, if T and U are themselves known to QMetaType. |
192 | |
193 | Note that all of the Qt associative containers already have built-in |
194 | support, and it is not necessary to use this macro with them. The |
195 | std::map container also has built-in support. |
196 | |
197 | This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(): |
198 | |
199 | \snippet code/src_corelib_kernel_qmetatype.cpp 11 |
200 | */ |
201 | |
202 | /*! |
203 | \macro Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer) |
204 | \relates QMetaType |
205 | |
206 | This macro makes the smart pointer \a SmartPointer known to QMetaType as a |
207 | smart pointer. This makes it possible to put an instance of SmartPointer<T> into |
208 | a QVariant, if T is a type which inherits QObject. |
209 | |
210 | Note that the QWeakPointer, QSharedPointer and QPointer already have built-in |
211 | support, and it is not necessary to use this macro with them. |
212 | |
213 | This example shows a typical use of Q_DECLARE_SMART_POINTER_METATYPE(): |
214 | |
215 | \snippet code/src_corelib_kernel_qmetatype.cpp 13 |
216 | */ |
217 | |
218 | /*! |
219 | \enum QMetaType::Type |
220 | |
221 | These are the built-in types supported by QMetaType: |
222 | |
223 | \value Void \c void |
224 | \value Bool \c bool |
225 | \value Int \c int |
226 | \value UInt \c{unsigned int} |
227 | \value Double \c double |
228 | \value QChar QChar |
229 | \value QString QString |
230 | \value QByteArray QByteArray |
231 | \value Nullptr \c{std::nullptr_t} |
232 | |
233 | \value VoidStar \c{void *} |
234 | \value Long \c{long} |
235 | \value LongLong LongLong |
236 | \value Short \c{short} |
237 | \value Char \c{char} |
238 | \value ULong \c{unsigned long} |
239 | \value ULongLong ULongLong |
240 | \value UShort \c{unsigned short} |
241 | \value SChar \c{signed char} |
242 | \value UChar \c{unsigned char} |
243 | \value Float \c float |
244 | \value QObjectStar QObject * |
245 | \value QVariant QVariant |
246 | |
247 | \value QCursor QCursor |
248 | \value QDate QDate |
249 | \value QSize QSize |
250 | \value QTime QTime |
251 | \value QVariantList QVariantList |
252 | \value QPolygon QPolygon |
253 | \value QPolygonF QPolygonF |
254 | \value QColor QColor |
255 | \value QColorSpace QColorSpace (introduced in Qt 5.15) |
256 | \value QSizeF QSizeF |
257 | \value QRectF QRectF |
258 | \value QLine QLine |
259 | \value QTextLength QTextLength |
260 | \value QStringList QStringList |
261 | \value QVariantMap QVariantMap |
262 | \value QVariantHash QVariantHash |
263 | \value QIcon QIcon |
264 | \value QPen QPen |
265 | \value QLineF QLineF |
266 | \value QTextFormat QTextFormat |
267 | \value QRect QRect |
268 | \value QPoint QPoint |
269 | \value QUrl QUrl |
270 | \value QRegExp QRegExp |
271 | \value QRegularExpression QRegularExpression |
272 | \value QDateTime QDateTime |
273 | \value QPointF QPointF |
274 | \value QPalette QPalette |
275 | \value QFont QFont |
276 | \value QBrush QBrush |
277 | \value QRegion QRegion |
278 | \value QBitArray QBitArray |
279 | \value QImage QImage |
280 | \value QKeySequence QKeySequence |
281 | \value QSizePolicy QSizePolicy |
282 | \value QPixmap QPixmap |
283 | \value QLocale QLocale |
284 | \value QBitmap QBitmap |
285 | \value QMatrix QMatrix |
286 | \value QTransform QTransform |
287 | \value QMatrix4x4 QMatrix4x4 |
288 | \value QVector2D QVector2D |
289 | \value QVector3D QVector3D |
290 | \value QVector4D QVector4D |
291 | \value QQuaternion QQuaternion |
292 | \value QEasingCurve QEasingCurve |
293 | \value QJsonValue QJsonValue |
294 | \value QJsonObject QJsonObject |
295 | \value QJsonArray QJsonArray |
296 | \value QJsonDocument QJsonDocument |
297 | \value QCborValue QCborValue |
298 | \value QCborArray QCborArray |
299 | \value QCborMap QCborMap |
300 | \value QCborSimpleType QCborSimpleType |
301 | \value QModelIndex QModelIndex |
302 | \value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5) |
303 | \value QUuid QUuid |
304 | \value QByteArrayList QByteArrayList |
305 | |
306 | \value User Base value for user types |
307 | \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered |
308 | \omitvalue LastCoreType |
309 | \omitvalue LastGuiType |
310 | |
311 | Additional types can be registered using Q_DECLARE_METATYPE(). |
312 | |
313 | \sa type(), typeName() |
314 | */ |
315 | |
316 | /*! |
317 | \enum QMetaType::TypeFlag |
318 | |
319 | The enum describes attributes of a type supported by QMetaType. |
320 | |
321 | \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0. |
322 | \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects. |
323 | \value MovableType An instance of a type having this attribute can be safely moved by memcpy. |
324 | \omitvalue SharedPointerToQObject |
325 | \value IsEnumeration This type is an enumeration |
326 | \value PointerToQObject This type is a pointer to a derived of QObject |
327 | \omitvalue WeakPointerToQObject |
328 | \omitvalue TrackingPointerToQObject |
329 | \omitvalue WasDeclaredAsMetaType |
330 | \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit |
331 | \omitvalue PointerToGadget |
332 | */ |
333 | |
334 | /*! |
335 | \class QMetaType |
336 | \inmodule QtCore |
337 | \brief The QMetaType class manages named types in the meta-object system. |
338 | |
339 | \ingroup objectmodel |
340 | \threadsafe |
341 | |
342 | The class is used as a helper to marshall types in QVariant and |
343 | in queued signals and slots connections. It associates a type |
344 | name to a type so that it can be created and destructed |
345 | dynamically at run-time. Declare new types with Q_DECLARE_METATYPE() |
346 | to make them available to QVariant and other template-based functions. |
347 | Call qRegisterMetaType() to make types available to non-template based |
348 | functions, such as the queued signal and slot connections. |
349 | |
350 | Any class or struct that has a public default |
351 | constructor, a public copy constructor, and a public destructor |
352 | can be registered. |
353 | |
354 | The following code allocates and destructs an instance of |
355 | \c{MyClass}: |
356 | |
357 | \snippet code/src_corelib_kernel_qmetatype.cpp 3 |
358 | |
359 | If we want the stream operators \c operator<<() and \c |
360 | operator>>() to work on QVariant objects that store custom types, |
361 | the custom type must provide \c operator<<() and \c operator>>() |
362 | operators. |
363 | |
364 | \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue() |
365 | */ |
366 | |
367 | /*! |
368 | \fn bool QMetaType::isValid() const |
369 | \since 5.0 |
370 | |
371 | Returns \c true if this QMetaType object contains valid |
372 | information about a type, false otherwise. |
373 | */ |
374 | |
375 | /*! |
376 | \fn bool QMetaType::isRegistered() const |
377 | \since 5.0 |
378 | |
379 | Returns \c true if this QMetaType object contains valid |
380 | information about a type, false otherwise. |
381 | */ |
382 | |
383 | /*! |
384 | \fn int QMetaType::id() const |
385 | \since 5.13 |
386 | |
387 | Returns id type hold by this QMetatype instance. |
388 | */ |
389 | |
390 | /*! |
391 | \fn bool QMetaType::sizeOf() const |
392 | \since 5.0 |
393 | |
394 | Returns the size of the type in bytes (i.e. sizeof(T), |
395 | where T is the actual type for which this QMetaType instance |
396 | was constructed for). |
397 | |
398 | This function is typically used together with construct() |
399 | to perform low-level management of the memory used by a type. |
400 | |
401 | \sa QMetaType::construct(), QMetaType::sizeOf() |
402 | */ |
403 | |
404 | /*! |
405 | \fn TypeFlags QMetaType::flags() const |
406 | \since 5.0 |
407 | |
408 | Returns flags of the type for which this QMetaType instance was constructed. |
409 | |
410 | \sa QMetaType::TypeFlags, QMetaType::typeFlags() |
411 | */ |
412 | |
413 | /*! |
414 | \fn const QMetaObject *QMetaType::metaObject() const |
415 | \since 5.5 |
416 | |
417 | return a QMetaObject relative to this type. |
418 | |
419 | If the type is a pointer type to a subclass of QObject, flags() contains |
420 | QMetaType::PointerToQObject and this function returns the corresponding QMetaObject. This can |
421 | be used to in combinaison with QMetaObject::construct to create QObject of this type. |
422 | |
423 | If the type is a Q_GADGET, flags() contains QMetaType::IsGadget, and this function returns its |
424 | QMetaObject. This can be used to retrieve QMetaMethod and QMetaProperty and use them on a |
425 | pointer of this type. (given by QVariant::data for example) |
426 | |
427 | If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function |
428 | returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or |
429 | \nullptr otherwise |
430 | |
431 | \sa QMetaType::metaObjectForType(), QMetaType::flags() |
432 | */ |
433 | |
434 | /*! |
435 | \fn void *QMetaType::create(const void *copy = 0) const |
436 | \since 5.0 |
437 | |
438 | Returns a copy of \a copy, assuming it is of the type that this |
439 | QMetaType instance was created for. If \a copy is \nullptr, creates |
440 | a default constructed instance. |
441 | |
442 | \sa QMetaType::destroy() |
443 | */ |
444 | |
445 | /*! |
446 | \fn void QMetaType::destroy(void *data) const |
447 | \since 5.0 |
448 | |
449 | Destroys the \a data, assuming it is of the type that this |
450 | QMetaType instance was created for. |
451 | |
452 | \sa QMetaType::create() |
453 | */ |
454 | |
455 | /*! |
456 | \fn void *QMetaType::construct(int type, const void *copy) |
457 | \deprecated |
458 | |
459 | Constructs a value of the given type which is a copy of \a copy. |
460 | The default value for \a copy is \nullptr. |
461 | |
462 | Deprecated, use the static function QMetaType::create(int type, |
463 | const void *copy) instead. |
464 | */ |
465 | /*! |
466 | \fn void *QMetaType::construct(void *where, const void *copy = 0) const |
467 | \since 5.0 |
468 | |
469 | Constructs a value of the type that this QMetaType instance |
470 | was constructed for in the existing memory addressed by \a where, |
471 | that is a copy of \a copy, and returns \a where. If \a copy is |
472 | zero, the value is default constructed. |
473 | |
474 | This is a low-level function for explicitly managing the memory |
475 | used to store the type. Consider calling create() if you don't |
476 | need this level of control (that is, use "new" rather than |
477 | "placement new"). |
478 | |
479 | You must ensure that \a where points to a location where the new |
480 | value can be stored and that \a where is suitably aligned. |
481 | The type's size can be queried by calling sizeOf(). |
482 | |
483 | The rule of thumb for alignment is that a type is aligned to its |
484 | natural boundary, which is the smallest power of 2 that is bigger |
485 | than the type, unless that alignment is larger than the maximum |
486 | useful alignment for the platform. For practical purposes, |
487 | alignment larger than 2 * sizeof(void*) is only necessary for |
488 | special hardware instructions (e.g., aligned SSE loads and stores |
489 | on x86). |
490 | */ |
491 | |
492 | /*! |
493 | \fn void QMetaType::destruct(void *data) const |
494 | \since 5.0 |
495 | |
496 | Destructs the value, located at \a data, assuming that it is |
497 | of the type for which this QMetaType instance was constructed for. |
498 | |
499 | Unlike destroy(), this function only invokes the type's |
500 | destructor, it doesn't invoke the delete operator. |
501 | \sa QMetaType::construct() |
502 | */ |
503 | |
504 | /*! |
505 | \fn QMetaType::~QMetaType() |
506 | |
507 | Destructs this object. |
508 | */ |
509 | |
510 | /*! |
511 | \fn template<typename T> QMetaType QMetaType::fromType() |
512 | \since 5.15 |
513 | |
514 | Returns the QMetaType corresponding to the type in the template parameter. |
515 | */ |
516 | |
517 | /*! \fn bool operator==(const QMetaType &a, const QMetaType &b) |
518 | \since 5.15 |
519 | \relates QMetaType |
520 | \overload |
521 | |
522 | Returns \c true if the QMetaType \a a represents the same type |
523 | as the QMetaType \a b, otherwise returns \c false. |
524 | */ |
525 | |
526 | /*! \fn bool operator!=(const QMetaType &a, const QMetaType &b) |
527 | \since 5.15 |
528 | \relates QMetaType |
529 | \overload |
530 | |
531 | Returns \c true if the QMetaType \a a represents a different type |
532 | than the QMetaType \a b, otherwise returns \c false. |
533 | */ |
534 | |
535 | #define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \ |
536 | { #RealName, sizeof(#RealName) - 1, MetaTypeId }, |
537 | |
538 | #define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \ |
539 | { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName }, |
540 | |
541 | #define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \ |
542 | QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name) |
543 | |
544 | static const struct { const char * typeName; int typeNameLength; int type; } types[] = { |
545 | QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE) |
546 | QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER) |
547 | QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER) |
548 | {.typeName: nullptr, .typeNameLength: 0, .type: QMetaType::UnknownType} |
549 | }; |
550 | |
551 | Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr; |
552 | Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr; |
553 | Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr; |
554 | |
555 | class QCustomTypeInfo : public QMetaTypeInterface |
556 | { |
557 | public: |
558 | QCustomTypeInfo() |
559 | : alias(-1) |
560 | { |
561 | QMetaTypeInterface empty = QT_METATYPE_INTERFACE_INIT(void); |
562 | *static_cast<QMetaTypeInterface*>(this) = empty; |
563 | } |
564 | QByteArray typeName; |
565 | int alias; |
566 | }; |
567 | |
568 | template<typename T, typename Key> |
569 | class QMetaTypeFunctionRegistry |
570 | { |
571 | public: |
572 | ~QMetaTypeFunctionRegistry() |
573 | { |
574 | const QWriteLocker locker(&lock); |
575 | map.clear(); |
576 | } |
577 | |
578 | bool contains(Key k) const |
579 | { |
580 | const QReadLocker locker(&lock); |
581 | return map.contains(k); |
582 | } |
583 | |
584 | bool insertIfNotContains(Key k, const T *f) |
585 | { |
586 | const QWriteLocker locker(&lock); |
587 | const T* &fun = map[k]; |
588 | if (fun) |
589 | return false; |
590 | fun = f; |
591 | return true; |
592 | } |
593 | |
594 | const T *function(Key k) const |
595 | { |
596 | const QReadLocker locker(&lock); |
597 | return map.value(k, nullptr); |
598 | } |
599 | |
600 | void remove(int from, int to) |
601 | { |
602 | const Key k(from, to); |
603 | const QWriteLocker locker(&lock); |
604 | map.remove(k); |
605 | } |
606 | private: |
607 | mutable QReadWriteLock lock; |
608 | QHash<Key, const T *> map; |
609 | }; |
610 | |
611 | typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> > |
612 | QMetaTypeConverterRegistry; |
613 | typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int> |
614 | QMetaTypeComparatorRegistry; |
615 | typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int> |
616 | QMetaTypeDebugStreamRegistry; |
617 | |
618 | Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value); |
619 | Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value); |
620 | |
621 | Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE); |
622 | Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes) |
623 | Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock) |
624 | Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry) |
625 | Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry) |
626 | Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry) |
627 | |
628 | /*! |
629 | \fn bool QMetaType::registerConverter() |
630 | \since 5.2 |
631 | Registers the possibility of an implicit conversion from type From to type To in the meta |
632 | type system. Returns \c true if the registration succeeded, otherwise false. |
633 | */ |
634 | |
635 | /*! |
636 | \fn template<typename MemberFunction, int> bool QMetaType::registerConverter(MemberFunction function) |
637 | \since 5.2 |
638 | \overload |
639 | Registers a method \a function like To From::function() const as converter from type From |
640 | to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false. |
641 | */ |
642 | |
643 | /*! |
644 | \fn template<typename MemberFunctionOk, char> bool QMetaType::registerConverter(MemberFunctionOk function) |
645 | \since 5.2 |
646 | \overload |
647 | Registers a method \a function like To From::function(bool *ok) const as converter from type From |
648 | to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false. |
649 | */ |
650 | |
651 | /*! |
652 | \fn template<typename UnaryFunction> bool QMetaType::registerConverter(UnaryFunction function) |
653 | \since 5.2 |
654 | \overload |
655 | Registers a unary function object \a function as converter from type From |
656 | to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false. |
657 | */ |
658 | |
659 | /*! |
660 | \fn bool QMetaType::registerComparators() |
661 | \since 5.2 |
662 | Registers comparison operators for the user-registered type T. This requires T to have |
663 | both an operator== and an operator<. |
664 | Returns \c true if the registration succeeded, otherwise false. |
665 | */ |
666 | |
667 | /*! |
668 | \fn bool QMetaType::registerEqualsComparator() |
669 | \since 5.5 |
670 | Registers equals operator for the user-registered type T. This requires T to have |
671 | an operator==. |
672 | Returns \c true if the registration succeeded, otherwise false. |
673 | */ |
674 | |
675 | #ifndef QT_NO_DEBUG_STREAM |
676 | /*! |
677 | \fn bool QMetaType::registerDebugStreamOperator() |
678 | Registers the debug stream operator for the user-registered type T. This requires T to have |
679 | an operator<<(QDebug dbg, T). |
680 | Returns \c true if the registration succeeded, otherwise false. |
681 | */ |
682 | #endif |
683 | |
684 | /*! |
685 | Registers function \a f as converter function from type id \a from to \a to. |
686 | If there's already a conversion registered, this does nothing but deleting \a f. |
687 | Returns \c true if the registration succeeded, otherwise false. |
688 | \since 5.2 |
689 | \internal |
690 | */ |
691 | bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to) |
692 | { |
693 | if (!customTypesConversionRegistry()->insertIfNotContains(k: qMakePair(x: from, y: to), f)) { |
694 | qWarning(msg: "Type conversion already registered from type %s to type %s", |
695 | QMetaType::typeName(type: from), QMetaType::typeName(type: to)); |
696 | return false; |
697 | } |
698 | return true; |
699 | } |
700 | |
701 | /*! |
702 | \internal |
703 | |
704 | Invoked automatically when a converter function object is destroyed. |
705 | */ |
706 | void QMetaType::unregisterConverterFunction(int from, int to) |
707 | { |
708 | if (customTypesConversionRegistry.isDestroyed()) |
709 | return; |
710 | customTypesConversionRegistry()->remove(from, to); |
711 | } |
712 | |
713 | bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type) |
714 | { |
715 | if (!customTypesComparatorRegistry()->insertIfNotContains(k: type, f)) { |
716 | qWarning(msg: "Comparators already registered for type %s", QMetaType::typeName(type)); |
717 | return false; |
718 | } |
719 | return true; |
720 | } |
721 | |
722 | /*! |
723 | \fn bool QMetaType::hasRegisteredComparators() |
724 | Returns \c true, if the meta type system has registered comparators for type T. |
725 | \since 5.2 |
726 | */ |
727 | |
728 | /*! |
729 | Returns \c true, if the meta type system has registered comparators for type id \a typeId. |
730 | \since 5.2 |
731 | */ |
732 | bool QMetaType::hasRegisteredComparators(int typeId) |
733 | { |
734 | return customTypesComparatorRegistry()->contains(k: typeId); |
735 | } |
736 | |
737 | #ifndef QT_NO_DEBUG_STREAM |
738 | bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, |
739 | int type) |
740 | { |
741 | if (!customTypesDebugStreamRegistry()->insertIfNotContains(k: type, f)) { |
742 | qWarning(msg: "Debug stream operator already registered for type %s", QMetaType::typeName(type)); |
743 | return false; |
744 | } |
745 | return true; |
746 | } |
747 | |
748 | /*! |
749 | \fn bool QMetaType::hasRegisteredDebugStreamOperator() |
750 | Returns \c true, if the meta type system has a registered debug stream operator for type T. |
751 | \since 5.2 |
752 | */ |
753 | |
754 | /*! |
755 | Returns \c true, if the meta type system has a registered debug stream operator for type |
756 | id \a typeId. |
757 | \since 5.2 |
758 | */ |
759 | bool QMetaType::hasRegisteredDebugStreamOperator(int typeId) |
760 | { |
761 | return customTypesDebugStreamRegistry()->contains(k: typeId); |
762 | } |
763 | #endif |
764 | |
765 | /*! |
766 | Converts the object at \a from from \a fromTypeId to the preallocated space at \a to |
767 | typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false. |
768 | \since 5.2 |
769 | */ |
770 | bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId) |
771 | { |
772 | const QtPrivate::AbstractConverterFunction * const f = |
773 | customTypesConversionRegistry()->function(k: qMakePair(x: fromTypeId, y: toTypeId)); |
774 | return f && f->convert(f, from, to); |
775 | } |
776 | |
777 | /*! |
778 | Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId. |
779 | \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to |
780 | or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false. |
781 | \since 5.2 |
782 | */ |
783 | bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result) |
784 | { |
785 | const QtPrivate::AbstractComparatorFunction * const f = |
786 | customTypesComparatorRegistry()->function(k: typeId); |
787 | if (!f) |
788 | return false; |
789 | if (f->equals(f, lhs, rhs)) |
790 | *result = 0; |
791 | else if (f->lessThan) |
792 | *result = f->lessThan(f, lhs, rhs) ? -1 : 1; |
793 | else |
794 | return false; |
795 | return true; |
796 | } |
797 | |
798 | /*! |
799 | Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId. |
800 | \a result is set to zero, if \a lhs equals to rhs. Returns \c true, if the comparison |
801 | succeeded, otherwise \c false. |
802 | \since 5.5 |
803 | */ |
804 | bool QMetaType::equals(const void *lhs, const void *rhs, int typeId, int *result) |
805 | { |
806 | const QtPrivate::AbstractComparatorFunction * const f |
807 | = customTypesComparatorRegistry()->function(k: typeId); |
808 | if (!f) |
809 | return false; |
810 | if (f->equals(f, lhs, rhs)) |
811 | *result = 0; |
812 | else |
813 | *result = -1; |
814 | return true; |
815 | } |
816 | |
817 | /*! |
818 | Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true |
819 | on success, otherwise false. |
820 | \since 5.2 |
821 | */ |
822 | bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId) |
823 | { |
824 | const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(k: typeId); |
825 | if (!f) |
826 | return false; |
827 | f->stream(f, dbg, rhs); |
828 | return true; |
829 | } |
830 | |
831 | /*! |
832 | \fn bool QMetaType::hasRegisteredConverterFunction() |
833 | Returns \c true, if the meta type system has a registered conversion from type From to type To. |
834 | \since 5.2 |
835 | \overload |
836 | */ |
837 | |
838 | /*! |
839 | Returns \c true, if the meta type system has a registered conversion from meta type id \a fromTypeId |
840 | to \a toTypeId |
841 | \since 5.2 |
842 | */ |
843 | bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId) |
844 | { |
845 | return customTypesConversionRegistry()->contains(k: qMakePair(x: fromTypeId, y: toTypeId)); |
846 | } |
847 | |
848 | #ifndef QT_NO_DATASTREAM |
849 | /*! |
850 | \internal |
851 | */ |
852 | void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp, |
853 | LoadOperator loadOp) |
854 | { |
855 | registerStreamOperators(type: type(typeName), saveOp, loadOp); |
856 | } |
857 | |
858 | /*! |
859 | \internal |
860 | */ |
861 | void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp, |
862 | LoadOperator loadOp) |
863 | { |
864 | if (idx < User) |
865 | return; //builtin types should not be registered; |
866 | QVector<QCustomTypeInfo> *ct = customTypes(); |
867 | if (!ct) |
868 | return; |
869 | QWriteLocker locker(customTypesLock()); |
870 | QCustomTypeInfo &inf = (*ct)[idx - User]; |
871 | inf.saveOp = saveOp; |
872 | inf.loadOp = loadOp; |
873 | } |
874 | #endif // QT_NO_DATASTREAM |
875 | |
876 | // We don't officially support constexpr in MSVC 2015, but the limited support it |
877 | // has is enough for the code below. |
878 | |
879 | #define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \ |
880 | #RealName "\0" |
881 | #define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \ |
882 | short(sizeof(#RealName)), |
883 | #define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \ |
884 | TypeId, |
885 | |
886 | namespace { |
887 | // All type names in one long string. |
888 | constexpr char metaTypeStrings[] = QT_FOR_EACH_STATIC_TYPE(STRINGIFY_TYPE_NAME); |
889 | |
890 | // The sizes of the strings in the metaTypeStrings string (including terminating null) |
891 | constexpr short metaTypeNameSizes[] = { |
892 | QT_FOR_EACH_STATIC_TYPE(CALCULATE_TYPE_LEN) |
893 | }; |
894 | |
895 | // The type IDs, in the order of the metaTypeStrings data |
896 | constexpr short metaTypeIds[] = { |
897 | QT_FOR_EACH_STATIC_TYPE(MAP_TYPE_ID_TO_IDX) |
898 | }; |
899 | |
900 | constexpr int MetaTypeNameCount = sizeof(metaTypeNameSizes) / sizeof(metaTypeNameSizes[0]); |
901 | |
902 | template <typename IntegerSequence> struct MetaTypeOffsets; |
903 | template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds...>> |
904 | { |
905 | // This would have been a lot easier if the meta types that the macro |
906 | // QT_FOR_EACH_STATIC_TYPE declared were in sorted, ascending order, but |
907 | // they're not (i.e., the first one declared is QMetaType::Void == 43, |
908 | // followed by QMetaType::Bool == 1)... As a consequence, we need to use |
909 | // the C++11 constexpr function calculateOffsetForTypeId below in order to |
910 | // create the offset array. |
911 | |
912 | static constexpr int findTypeId(int typeId, int i = 0) |
913 | { |
914 | return i >= MetaTypeNameCount ? -1 : |
915 | metaTypeIds[i] == typeId ? i : findTypeId(typeId, i: i + 1); |
916 | } |
917 | |
918 | static constexpr short calculateOffsetForIdx(int i) |
919 | { |
920 | return i < 0 ? -1 : |
921 | i == 0 ? 0 : metaTypeNameSizes[i - 1] + calculateOffsetForIdx(i: i - 1); |
922 | } |
923 | |
924 | static constexpr short calculateOffsetForTypeId(int typeId) |
925 | { |
926 | return calculateOffsetForIdx(i: findTypeId(typeId)); |
927 | #if 0 |
928 | // same as, but this is only valid in C++14: |
929 | short offset = 0; |
930 | for (int i = 0; i < MetaTypeNameCount; ++i) { |
931 | if (metaTypeIds[i] == typeId) |
932 | return offset; |
933 | offset += metaTypeNameSizes[i]; |
934 | } |
935 | return -1; |
936 | #endif |
937 | } |
938 | |
939 | short offsets[sizeof...(TypeIds)]; |
940 | constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(typeId: TypeIds)...} {} |
941 | |
942 | const char *operator[](int typeId) const noexcept |
943 | { |
944 | short o = offsets[typeId]; |
945 | return o < 0 ? nullptr : metaTypeStrings + o; |
946 | } |
947 | }; |
948 | } // anonymous namespace |
949 | |
950 | constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {}; |
951 | #undef STRINGIFY_TYPE_NAME |
952 | #undef CALCULATE_TYPE_LEN |
953 | #undef MAP_TYPE_ID_TO_IDX |
954 | |
955 | /*! |
956 | Returns the type name associated with the given \a typeId, or a null |
957 | pointer if no matching type was found. The returned pointer must not be |
958 | deleted. |
959 | |
960 | \sa type(), isRegistered(), Type, name() |
961 | */ |
962 | const char *QMetaType::typeName(int typeId) |
963 | { |
964 | const uint type = typeId; |
965 | if (Q_LIKELY(type <= QMetaType::HighestInternalId)) { |
966 | return metaTypeNames[typeId]; |
967 | } else if (Q_UNLIKELY(type < QMetaType::User)) { |
968 | return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash... |
969 | } |
970 | |
971 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
972 | QReadLocker locker(customTypesLock()); |
973 | return ct && uint(ct->count()) > type - QMetaType::User && !ct->at(i: type - QMetaType::User).typeName.isEmpty() |
974 | ? ct->at(i: type - QMetaType::User).typeName.constData() |
975 | : nullptr; |
976 | |
977 | #undef QT_METATYPE_TYPEID_TYPENAME_CONVERTER |
978 | } |
979 | |
980 | /*! |
981 | \since 5.15 |
982 | |
983 | Returns the type name associated with this QMetaType, or a null |
984 | pointer if no matching type was found. The returned pointer must not be |
985 | deleted. |
986 | |
987 | \sa typeName() |
988 | */ |
989 | QByteArray QMetaType::name() const |
990 | { |
991 | return QMetaType::typeName(typeId: m_typeId); |
992 | } |
993 | |
994 | /* |
995 | Similar to QMetaType::type(), but only looks in the static set of types. |
996 | */ |
997 | static inline int qMetaTypeStaticType(const char *typeName, int length) |
998 | { |
999 | int i = 0; |
1000 | while (types[i].typeName && ((length != types[i].typeNameLength) |
1001 | || memcmp(s1: typeName, s2: types[i].typeName, n: length))) { |
1002 | ++i; |
1003 | } |
1004 | return types[i].type; |
1005 | } |
1006 | |
1007 | /* |
1008 | Similar to QMetaType::type(), but only looks in the custom set of |
1009 | types, and doesn't lock the mutex. |
1010 | The extra \a firstInvalidIndex parameter is an easy way to avoid |
1011 | iterating over customTypes() a second time in registerNormalizedType(). |
1012 | */ |
1013 | static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = nullptr) |
1014 | { |
1015 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1016 | if (!ct) |
1017 | return QMetaType::UnknownType; |
1018 | |
1019 | if (firstInvalidIndex) |
1020 | *firstInvalidIndex = -1; |
1021 | for (int v = 0; v < ct->count(); ++v) { |
1022 | const QCustomTypeInfo &customInfo = ct->at(i: v); |
1023 | if ((length == customInfo.typeName.size()) |
1024 | && !memcmp(s1: typeName, s2: customInfo.typeName.constData(), n: length)) { |
1025 | if (customInfo.alias >= 0) |
1026 | return customInfo.alias; |
1027 | return v + QMetaType::User; |
1028 | } |
1029 | if (firstInvalidIndex && (*firstInvalidIndex < 0) && customInfo.typeName.isEmpty()) |
1030 | *firstInvalidIndex = v; |
1031 | } |
1032 | return QMetaType::UnknownType; |
1033 | } |
1034 | |
1035 | /*! |
1036 | \internal |
1037 | |
1038 | This function is needed until existing code outside of qtbase |
1039 | has been changed to call the new version of registerType(). |
1040 | */ |
1041 | int QMetaType::registerType(const char *typeName, Deleter deleter, |
1042 | Creator creator) |
1043 | { |
1044 | return registerType(typeName, deleter, creator, |
1045 | destructor: QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Destruct, |
1046 | constructor: QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, size: 0, flags: TypeFlags(), metaObject: nullptr); |
1047 | } |
1048 | |
1049 | /*! |
1050 | \internal |
1051 | \since 5.5 |
1052 | |
1053 | Unregisters the user type with the given \a typeId and all its aliases. |
1054 | Returns \c true if the type was unregistered or \c false otherwise. |
1055 | |
1056 | This function was added for QML to be able to deregister types after |
1057 | they are unloaded to prevent an infinite increase in custom types for |
1058 | applications that are unloading/reloading components often. |
1059 | */ |
1060 | bool QMetaType::unregisterType(int type) |
1061 | { |
1062 | QWriteLocker locker(customTypesLock()); |
1063 | QVector<QCustomTypeInfo> *ct = customTypes(); |
1064 | |
1065 | // check if user type |
1066 | if ((type < User) || ((type - User) >= ct->size())) |
1067 | return false; |
1068 | |
1069 | // only types without Q_DECLARE_METATYPE can be unregistered |
1070 | if (ct->data()[type - User].flags & WasDeclaredAsMetaType) |
1071 | return false; |
1072 | |
1073 | // invalidate type and all its alias entries |
1074 | for (int v = 0; v < ct->count(); ++v) { |
1075 | if (((v + User) == type) || (ct->at(i: v).alias == type)) |
1076 | ct->data()[v].typeName.clear(); |
1077 | } |
1078 | return true; |
1079 | } |
1080 | |
1081 | |
1082 | /*! |
1083 | \internal |
1084 | \since 5.0 |
1085 | |
1086 | Registers a user type for marshalling, with \a typeName, a \a |
1087 | deleter, a \a creator, a \a destructor, a \a constructor, and |
1088 | a \a size. Returns the type's handle, or -1 if the type could |
1089 | not be registered. |
1090 | */ |
1091 | int QMetaType::registerType(const char *typeName, Deleter deleter, |
1092 | Creator creator, |
1093 | Destructor destructor, |
1094 | Constructor constructor, |
1095 | int size, TypeFlags flags, const QMetaObject *metaObject) |
1096 | { |
1097 | #ifdef QT_NO_QOBJECT |
1098 | NS(QByteArray) normalizedTypeName = typeName; |
1099 | #else |
1100 | NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName); |
1101 | #endif |
1102 | |
1103 | return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject); |
1104 | } |
1105 | |
1106 | /*! |
1107 | \internal |
1108 | \since 5.12 |
1109 | |
1110 | Registers a user type for marshalling, with \a typeName, a |
1111 | \a destructor, a \a constructor, and a \a size. Returns the |
1112 | type's handle, or -1 if the type could not be registered. |
1113 | */ |
1114 | int QMetaType::registerType(const char *typeName, |
1115 | TypedDestructor destructor, |
1116 | TypedConstructor constructor, |
1117 | int size, |
1118 | TypeFlags flags, |
1119 | const QMetaObject *metaObject) |
1120 | { |
1121 | #ifdef QT_NO_QOBJECT |
1122 | NS(QByteArray) normalizedTypeName = typeName; |
1123 | #else |
1124 | NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName); |
1125 | #endif |
1126 | |
1127 | return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject); |
1128 | } |
1129 | |
1130 | |
1131 | static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName, |
1132 | QMetaType::Destructor destructor, |
1133 | QMetaType::Constructor constructor, |
1134 | QMetaType::TypedDestructor typedDestructor, |
1135 | QMetaType::TypedConstructor typedConstructor, |
1136 | int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject) |
1137 | { |
1138 | QVector<QCustomTypeInfo> *ct = customTypes(); |
1139 | if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor)) |
1140 | return -1; |
1141 | |
1142 | int idx = qMetaTypeStaticType(typeName: normalizedTypeName.constData(), |
1143 | length: normalizedTypeName.size()); |
1144 | |
1145 | int previousSize = 0; |
1146 | QMetaType::TypeFlags::Int previousFlags = 0; |
1147 | if (idx == QMetaType::UnknownType) { |
1148 | QWriteLocker locker(customTypesLock()); |
1149 | int posInVector = -1; |
1150 | idx = qMetaTypeCustomType_unlocked(typeName: normalizedTypeName.constData(), |
1151 | length: normalizedTypeName.size(), |
1152 | firstInvalidIndex: &posInVector); |
1153 | if (idx == QMetaType::UnknownType) { |
1154 | QCustomTypeInfo inf; |
1155 | inf.typeName = normalizedTypeName; |
1156 | #ifndef QT_NO_DATASTREAM |
1157 | inf.loadOp = nullptr; |
1158 | inf.saveOp = nullptr; |
1159 | #endif |
1160 | inf.alias = -1; |
1161 | inf.typedConstructor = typedConstructor; |
1162 | inf.typedDestructor = typedDestructor; |
1163 | inf.constructor = constructor; |
1164 | inf.destructor = destructor; |
1165 | inf.size = size; |
1166 | inf.flags = flags; |
1167 | inf.metaObject = metaObject; |
1168 | if (posInVector == -1) { |
1169 | idx = ct->size() + QMetaType::User; |
1170 | ct->append(t: inf); |
1171 | } else { |
1172 | idx = posInVector + QMetaType::User; |
1173 | ct->data()[posInVector] = inf; |
1174 | } |
1175 | return idx; |
1176 | } |
1177 | |
1178 | if (idx >= QMetaType::User) { |
1179 | previousSize = ct->at(i: idx - QMetaType::User).size; |
1180 | previousFlags = ct->at(i: idx - QMetaType::User).flags; |
1181 | |
1182 | // Set new/additional flags in case of old library/app. |
1183 | // Ensures that older code works in conjunction with new Qt releases |
1184 | // requiring the new flags. |
1185 | if (flags != previousFlags) { |
1186 | QCustomTypeInfo &inf = ct->data()[idx - QMetaType::User]; |
1187 | inf.flags |= flags; |
1188 | if (metaObject) |
1189 | inf.metaObject = metaObject; |
1190 | } |
1191 | } |
1192 | } |
1193 | |
1194 | if (idx < QMetaType::User) { |
1195 | previousSize = QMetaType::sizeOf(type: idx); |
1196 | previousFlags = QMetaType::typeFlags(type: idx); |
1197 | } |
1198 | |
1199 | if (Q_UNLIKELY(previousSize != size)) { |
1200 | qFatal(msg: "QMetaType::registerType: Binary compatibility break " |
1201 | "-- Size mismatch for type '%s' [%i]. Previously registered " |
1202 | "size %i, now registering size %i.", |
1203 | normalizedTypeName.constData(), idx, previousSize, size); |
1204 | } |
1205 | |
1206 | // these flags cannot change in a binary compatible way: |
1207 | const int binaryCompatibilityFlag = QMetaType::PointerToQObject | QMetaType::IsEnumeration | QMetaType::SharedPointerToQObject |
1208 | | QMetaType::WeakPointerToQObject | QMetaType::TrackingPointerToQObject; |
1209 | if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) { |
1210 | |
1211 | const char *msg = "QMetaType::registerType: Binary compatibility break. " |
1212 | "\nType flags for type '%s' [%i] don't match. Previously " |
1213 | "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). "; |
1214 | |
1215 | qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags)); |
1216 | } |
1217 | |
1218 | return idx; |
1219 | } |
1220 | |
1221 | /*! |
1222 | \internal |
1223 | \since 5.0 |
1224 | \overload |
1225 | Don't use, kept for binary compatibility |
1226 | |
1227 | ### TODO Qt6: remove me |
1228 | */ |
1229 | int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter, |
1230 | Creator creator, |
1231 | Destructor destructor, |
1232 | Constructor constructor, |
1233 | int size, TypeFlags flags, const QMetaObject *metaObject) |
1234 | { |
1235 | Q_UNUSED(deleter); |
1236 | Q_UNUSED(creator); |
1237 | return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject); |
1238 | } |
1239 | |
1240 | |
1241 | /*! |
1242 | \internal |
1243 | \since 5.5 |
1244 | |
1245 | Registers a user type for marshalling, with \a normalizedTypeName, |
1246 | a \a destructor, a \a constructor, and a \a size. Returns the type's |
1247 | handle, or -1 if the type could not be registered. |
1248 | |
1249 | \note normalizedTypeName is not checked for conformance with |
1250 | Qt's normalized format, so it must already conform. |
1251 | |
1252 | ### TODO Qt6: remove me |
1253 | */ |
1254 | int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, |
1255 | Destructor destructor, |
1256 | Constructor constructor, |
1257 | int size, TypeFlags flags, const QMetaObject *metaObject) |
1258 | { |
1259 | return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, typedDestructor: nullptr, typedConstructor: nullptr, size, flags, metaObject); |
1260 | } |
1261 | |
1262 | /*! |
1263 | \internal |
1264 | \since 5.12 |
1265 | |
1266 | Registers a user type for marshalling, with \a normalizedTypeName, |
1267 | a \a destructor, a \a constructor, and a \a size. Returns the type's |
1268 | handle, or -1 if the type could not be registered. |
1269 | |
1270 | \note normalizedTypeName is not checked for conformance with |
1271 | Qt's normalized format, so it must already conform. |
1272 | */ |
1273 | int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, |
1274 | TypedDestructor destructor, |
1275 | TypedConstructor constructor, |
1276 | int size, TypeFlags flags, const QMetaObject *metaObject) |
1277 | { |
1278 | return NS(registerNormalizedType)(normalizedTypeName, destructor: nullptr, constructor: nullptr, typedDestructor: destructor, typedConstructor: constructor, size, flags, metaObject); |
1279 | } |
1280 | |
1281 | /*! |
1282 | \internal |
1283 | \since 4.7 |
1284 | |
1285 | Registers a user type for marshalling, as an alias of another type (typedef) |
1286 | */ |
1287 | int QMetaType::registerTypedef(const char* typeName, int aliasId) |
1288 | { |
1289 | #ifdef QT_NO_QOBJECT |
1290 | NS(QByteArray) normalizedTypeName = typeName; |
1291 | #else |
1292 | NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName); |
1293 | #endif |
1294 | |
1295 | return registerNormalizedTypedef(normalizedTypeName, aliasId); |
1296 | } |
1297 | |
1298 | /*! |
1299 | \internal |
1300 | \since 5.0 |
1301 | |
1302 | Registers a user type for marshalling, as an alias of another type (typedef). |
1303 | Note that normalizedTypeName is not checked for conformance with Qt's normalized format, |
1304 | so it must already conform. |
1305 | */ |
1306 | int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeName, int aliasId) |
1307 | { |
1308 | QVector<QCustomTypeInfo> *ct = customTypes(); |
1309 | if (!ct || normalizedTypeName.isEmpty()) |
1310 | return -1; |
1311 | |
1312 | int idx = qMetaTypeStaticType(typeName: normalizedTypeName.constData(), |
1313 | length: normalizedTypeName.size()); |
1314 | |
1315 | if (idx == UnknownType) { |
1316 | QWriteLocker locker(customTypesLock()); |
1317 | int posInVector = -1; |
1318 | idx = qMetaTypeCustomType_unlocked(typeName: normalizedTypeName.constData(), |
1319 | length: normalizedTypeName.size(), |
1320 | firstInvalidIndex: &posInVector); |
1321 | |
1322 | if (idx == UnknownType) { |
1323 | QCustomTypeInfo inf; |
1324 | inf.typeName = normalizedTypeName; |
1325 | inf.alias = aliasId; |
1326 | if (posInVector == -1) |
1327 | ct->append(t: inf); |
1328 | else |
1329 | ct->data()[posInVector] = inf; |
1330 | return aliasId; |
1331 | } |
1332 | } |
1333 | |
1334 | if (idx != aliasId) { |
1335 | qWarning(msg: "QMetaType::registerTypedef: " |
1336 | "-- Type name '%s' previously registered as typedef of '%s' [%i], " |
1337 | "now registering as typedef of '%s' [%i].", |
1338 | normalizedTypeName.constData(), QMetaType::typeName(typeId: idx), idx, |
1339 | QMetaType::typeName(typeId: aliasId), aliasId); |
1340 | } |
1341 | return idx; |
1342 | } |
1343 | |
1344 | /*! |
1345 | Returns \c true if the datatype with ID \a type is registered; |
1346 | otherwise returns \c false. |
1347 | |
1348 | \sa type(), typeName(), Type |
1349 | */ |
1350 | bool QMetaType::isRegistered(int type) |
1351 | { |
1352 | // predefined type |
1353 | if ((type >= FirstCoreType && type <= LastCoreType) |
1354 | || (type >= FirstGuiType && type <= LastGuiType) |
1355 | || (type >= FirstWidgetsType && type <= LastWidgetsType)) { |
1356 | return true; |
1357 | } |
1358 | |
1359 | QReadLocker locker(customTypesLock()); |
1360 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1361 | return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(i: type - User).typeName.isEmpty()); |
1362 | } |
1363 | |
1364 | template <bool tryNormalizedType> |
1365 | static inline int qMetaTypeTypeImpl(const char *typeName, int length) |
1366 | { |
1367 | if (!length) |
1368 | return QMetaType::UnknownType; |
1369 | int type = qMetaTypeStaticType(typeName, length); |
1370 | if (type == QMetaType::UnknownType) { |
1371 | QReadLocker locker(customTypesLock()); |
1372 | type = qMetaTypeCustomType_unlocked(typeName, length); |
1373 | #ifndef QT_NO_QOBJECT |
1374 | if ((type == QMetaType::UnknownType) && tryNormalizedType) { |
1375 | const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName); |
1376 | type = qMetaTypeStaticType(typeName: normalizedTypeName.constData(), |
1377 | length: normalizedTypeName.size()); |
1378 | if (type == QMetaType::UnknownType) { |
1379 | type = qMetaTypeCustomType_unlocked(typeName: normalizedTypeName.constData(), |
1380 | length: normalizedTypeName.size()); |
1381 | } |
1382 | } |
1383 | #endif |
1384 | } |
1385 | return type; |
1386 | } |
1387 | |
1388 | /*! |
1389 | Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is |
1390 | no such type. |
1391 | |
1392 | \sa isRegistered(), typeName(), Type |
1393 | */ |
1394 | int QMetaType::type(const char *typeName) |
1395 | { |
1396 | return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName, length: qstrlen(str: typeName)); |
1397 | } |
1398 | |
1399 | /*! |
1400 | \a internal |
1401 | |
1402 | Similar to QMetaType::type(); the only difference is that this function |
1403 | doesn't attempt to normalize the type name (i.e., the lookup will fail |
1404 | for type names in non-normalized form). |
1405 | */ |
1406 | int qMetaTypeTypeInternal(const char *typeName) |
1407 | { |
1408 | return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, length: qstrlen(str: typeName)); |
1409 | } |
1410 | |
1411 | /*! |
1412 | \since 5.5 |
1413 | \overload |
1414 | |
1415 | Returns a handle to the type called \a typeName, or 0 if there is |
1416 | no such type. |
1417 | |
1418 | \sa isRegistered(), typeName() |
1419 | */ |
1420 | int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName) |
1421 | { |
1422 | return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName: typeName.constData(), length: typeName.size()); |
1423 | } |
1424 | |
1425 | #ifndef QT_NO_DATASTREAM |
1426 | |
1427 | namespace |
1428 | { |
1429 | |
1430 | template<typename T> |
1431 | class HasStreamOperator |
1432 | { |
1433 | struct Yes { char unused[1]; }; |
1434 | struct No { char unused[2]; }; |
1435 | Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); |
1436 | |
1437 | template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int); |
1438 | template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int); |
1439 | template<class C> static No load(...); |
1440 | template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int); |
1441 | template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int); |
1442 | template<class C> static No saveMethod(...); |
1443 | template<class C> static No saveFunction(...); |
1444 | static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes)); |
1445 | static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && |
1446 | ((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes))); |
1447 | public: |
1448 | static constexpr bool Value = LoadValue && SaveValue; |
1449 | }; |
1450 | |
1451 | // Quick sanity checks |
1452 | Q_STATIC_ASSERT(HasStreamOperator<NS(QJsonDocument)>::Value); |
1453 | Q_STATIC_ASSERT(!HasStreamOperator<void*>::Value); |
1454 | Q_STATIC_ASSERT(HasStreamOperator<qint8>::Value); |
1455 | |
1456 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value> |
1457 | struct FilteredOperatorSwitch |
1458 | { |
1459 | static bool load(QDataStream &stream, T *data, int) |
1460 | { |
1461 | stream >> *data; |
1462 | return true; |
1463 | } |
1464 | static bool save(QDataStream &stream, const T *data, int) |
1465 | { |
1466 | stream << *data; |
1467 | return true; |
1468 | } |
1469 | }; |
1470 | template<typename T> |
1471 | struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false> |
1472 | { |
1473 | static const QMetaTypeInterface* getMetaTypeInterface(int type) |
1474 | { |
1475 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui && qMetaTypeGuiHelper) |
1476 | return &qMetaTypeGuiHelper[type - QMetaType::FirstGuiType]; |
1477 | else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget && qMetaTypeWidgetsHelper) |
1478 | return &qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType]; |
1479 | return nullptr; |
1480 | } |
1481 | static bool save(QDataStream &stream, const T *data, int type) |
1482 | { |
1483 | if (auto interface = getMetaTypeInterface(type)) { |
1484 | interface->saveOp(stream, data); |
1485 | return true; |
1486 | } |
1487 | return false; |
1488 | } |
1489 | static bool load(QDataStream &stream, T *data, int type) |
1490 | { |
1491 | if (auto interface = getMetaTypeInterface(type)) { |
1492 | interface->loadOp(stream, data); |
1493 | return true; |
1494 | } |
1495 | return false; |
1496 | } |
1497 | }; |
1498 | |
1499 | class SaveOperatorSwitch |
1500 | { |
1501 | public: |
1502 | QDataStream &stream; |
1503 | int m_type; |
1504 | |
1505 | template<typename T> |
1506 | bool delegate(const T *data) |
1507 | { |
1508 | return FilteredOperatorSwitch<T>::save(stream, data, m_type); |
1509 | } |
1510 | bool delegate(const char *data) |
1511 | { |
1512 | // force a char to be signed |
1513 | stream << qint8(*data); |
1514 | return true; |
1515 | } |
1516 | bool delegate(const long *data) |
1517 | { |
1518 | stream << qlonglong(*data); |
1519 | return true; |
1520 | } |
1521 | bool delegate(const unsigned long *data) |
1522 | { |
1523 | stream << qulonglong(*data); |
1524 | return true; |
1525 | } |
1526 | bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data) |
1527 | { |
1528 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1529 | if (!ct) |
1530 | return false; |
1531 | QMetaType::SaveOperator saveOp = nullptr; |
1532 | { |
1533 | QReadLocker locker(customTypesLock()); |
1534 | saveOp = ct->at(i: m_type - QMetaType::User).saveOp; |
1535 | } |
1536 | if (!saveOp) |
1537 | return false; |
1538 | saveOp(stream, data); |
1539 | return true; |
1540 | } |
1541 | bool delegate(const void*) { return false; } |
1542 | bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; } |
1543 | }; |
1544 | class LoadOperatorSwitch |
1545 | { |
1546 | public: |
1547 | QDataStream &stream; |
1548 | int m_type; |
1549 | |
1550 | template<typename T> |
1551 | bool delegate(const T *data) |
1552 | { |
1553 | return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type); |
1554 | } |
1555 | bool delegate(const char *data) |
1556 | { |
1557 | // force a char to be signed |
1558 | qint8 c; |
1559 | stream >> c; |
1560 | *const_cast<char*>(data) = c; |
1561 | return true; |
1562 | } |
1563 | bool delegate(const long *data) |
1564 | { |
1565 | qlonglong l; |
1566 | stream >> l; |
1567 | *const_cast<long*>(data) = l; |
1568 | return true; |
1569 | } |
1570 | bool delegate(const unsigned long *data) |
1571 | { |
1572 | qlonglong l; |
1573 | stream >> l; |
1574 | *const_cast<unsigned long*>(data) = l; |
1575 | return true; |
1576 | } |
1577 | bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data) |
1578 | { |
1579 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1580 | if (!ct) |
1581 | return false; |
1582 | QMetaType::LoadOperator loadOp = nullptr; |
1583 | { |
1584 | QReadLocker locker(customTypesLock()); |
1585 | loadOp = ct->at(i: m_type - QMetaType::User).loadOp; |
1586 | } |
1587 | if (!loadOp) |
1588 | return false; |
1589 | loadOp(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType*>(data)); |
1590 | return true; |
1591 | } |
1592 | bool delegate(const void*) { return false; } |
1593 | bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; } |
1594 | }; |
1595 | } // namespace |
1596 | |
1597 | /*! |
1598 | Writes the object pointed to by \a data with the ID \a type to |
1599 | the given \a stream. Returns \c true if the object is saved |
1600 | successfully; otherwise returns \c false. |
1601 | |
1602 | The type must have been registered with qRegisterMetaType() and |
1603 | qRegisterMetaTypeStreamOperators() beforehand. |
1604 | |
1605 | Normally, you should not need to call this function directly. |
1606 | Instead, use QVariant's \c operator<<(), which relies on save() |
1607 | to stream custom types. |
1608 | |
1609 | \sa load(), qRegisterMetaTypeStreamOperators() |
1610 | */ |
1611 | bool QMetaType::save(QDataStream &stream, int type, const void *data) |
1612 | { |
1613 | if (!data) |
1614 | return false; |
1615 | SaveOperatorSwitch saveOp{.stream: stream, .m_type: type}; |
1616 | return QMetaTypeSwitcher::switcher<bool>(logic&: saveOp, type, data); |
1617 | } |
1618 | |
1619 | /*! |
1620 | Reads the object of the specified \a type from the given \a |
1621 | stream into \a data. Returns \c true if the object is loaded |
1622 | successfully; otherwise returns \c false. |
1623 | |
1624 | The type must have been registered with qRegisterMetaType() and |
1625 | qRegisterMetaTypeStreamOperators() beforehand. |
1626 | |
1627 | Normally, you should not need to call this function directly. |
1628 | Instead, use QVariant's \c operator>>(), which relies on load() |
1629 | to stream custom types. |
1630 | |
1631 | \sa save(), qRegisterMetaTypeStreamOperators() |
1632 | */ |
1633 | bool QMetaType::load(QDataStream &stream, int type, void *data) |
1634 | { |
1635 | if (!data) |
1636 | return false; |
1637 | LoadOperatorSwitch loadOp{.stream: stream, .m_type: type}; |
1638 | return QMetaTypeSwitcher::switcher<bool>(logic&: loadOp, type, data); |
1639 | } |
1640 | #endif // QT_NO_DATASTREAM |
1641 | |
1642 | /*! |
1643 | Returns a copy of \a copy, assuming it is of type \a type. If \a |
1644 | copy is zero, creates a default constructed instance. |
1645 | |
1646 | \sa destroy(), isRegistered(), Type |
1647 | */ |
1648 | void *QMetaType::create(int type, const void *copy) |
1649 | { |
1650 | QMetaType info(type); |
1651 | if (int size = info.sizeOf()) |
1652 | return info.construct(where: operator new(size), copy); |
1653 | return nullptr; |
1654 | } |
1655 | |
1656 | /*! |
1657 | Destroys the \a data, assuming it is of the \a type given. |
1658 | |
1659 | \sa create(), isRegistered(), Type |
1660 | */ |
1661 | void QMetaType::destroy(int type, void *data) |
1662 | { |
1663 | QMetaType info(type); |
1664 | info.destruct(data); |
1665 | operator delete(data); |
1666 | } |
1667 | |
1668 | namespace { |
1669 | class TypeConstructor { |
1670 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
1671 | struct ConstructorImpl { |
1672 | static void *Construct(const int /*type*/, void *where, const void *copy) { return QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct(where, copy); } |
1673 | }; |
1674 | template<typename T> |
1675 | struct ConstructorImpl<T, /* IsAcceptedType = */ false> { |
1676 | static void *Construct(const int type, void *where, const void *copy) |
1677 | { |
1678 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) |
1679 | return Q_LIKELY(qMetaTypeGuiHelper) |
1680 | ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy) |
1681 | : nullptr; |
1682 | |
1683 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) |
1684 | return Q_LIKELY(qMetaTypeWidgetsHelper) |
1685 | ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy) |
1686 | : nullptr; |
1687 | |
1688 | // This point can be reached only for known types that definition is not available, for example |
1689 | // in bootstrap mode. We have no other choice then ignore it. |
1690 | return nullptr; |
1691 | } |
1692 | }; |
1693 | public: |
1694 | TypeConstructor(const int type, void *where) |
1695 | : m_type(type) |
1696 | , m_where(where) |
1697 | {} |
1698 | |
1699 | template<typename T> |
1700 | void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); } |
1701 | void *delegate(const void *) { return m_where; } |
1702 | void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; } |
1703 | void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(type: m_type, where: m_where, copy); } |
1704 | |
1705 | private: |
1706 | static void *customTypeConstructor(const int type, void *where, const void *copy) |
1707 | { |
1708 | QMetaType::Constructor ctor; |
1709 | QMetaType::TypedConstructor tctor; |
1710 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1711 | { |
1712 | QReadLocker locker(customTypesLock()); |
1713 | if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User)) |
1714 | return nullptr; |
1715 | const auto &typeInfo = ct->at(i: type - QMetaType::User); |
1716 | ctor = typeInfo.constructor; |
1717 | tctor = typeInfo.typedConstructor; |
1718 | } |
1719 | Q_ASSERT_X((ctor || tctor) , "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered"); |
1720 | if (Q_UNLIKELY(tctor)) |
1721 | return tctor(type, where, copy); |
1722 | return ctor(where, copy); |
1723 | } |
1724 | |
1725 | const int m_type; |
1726 | void *m_where; |
1727 | }; |
1728 | } // namespace |
1729 | |
1730 | /*! |
1731 | \since 5.0 |
1732 | |
1733 | Constructs a value of the given \a type in the existing memory |
1734 | addressed by \a where, that is a copy of \a copy, and returns |
1735 | \a where. If \a copy is zero, the value is default constructed. |
1736 | |
1737 | This is a low-level function for explicitly managing the memory |
1738 | used to store the type. Consider calling create() if you don't |
1739 | need this level of control (that is, use "new" rather than |
1740 | "placement new"). |
1741 | |
1742 | You must ensure that \a where points to a location that can store |
1743 | a value of type \a type, and that \a where is suitably aligned. |
1744 | The type's size can be queried by calling sizeOf(). |
1745 | |
1746 | The rule of thumb for alignment is that a type is aligned to its |
1747 | natural boundary, which is the smallest power of 2 that is bigger |
1748 | than the type, unless that alignment is larger than the maximum |
1749 | useful alignment for the platform. For practical purposes, |
1750 | alignment larger than 2 * sizeof(void*) is only necessary for |
1751 | special hardware instructions (e.g., aligned SSE loads and stores |
1752 | on x86). |
1753 | |
1754 | \sa destruct(), sizeOf() |
1755 | */ |
1756 | void *QMetaType::construct(int type, void *where, const void *copy) |
1757 | { |
1758 | if (!where) |
1759 | return nullptr; |
1760 | TypeConstructor constructor(type, where); |
1761 | return QMetaTypeSwitcher::switcher<void*>(logic&: constructor, type, data: copy); |
1762 | } |
1763 | |
1764 | |
1765 | namespace { |
1766 | class TypeDestructor { |
1767 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
1768 | struct DestructorImpl { |
1769 | static void Destruct(const int /* type */, void *where) { QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct(where); } |
1770 | }; |
1771 | template<typename T> |
1772 | struct DestructorImpl<T, /* IsAcceptedType = */ false> { |
1773 | static void Destruct(const int type, void *where) |
1774 | { |
1775 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) { |
1776 | if (Q_LIKELY(qMetaTypeGuiHelper)) |
1777 | qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].destructor(where); |
1778 | return; |
1779 | } |
1780 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) { |
1781 | if (Q_LIKELY(qMetaTypeWidgetsHelper)) |
1782 | qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].destructor(where); |
1783 | return; |
1784 | } |
1785 | // This point can be reached only for known types that definition is not available, for example |
1786 | // in bootstrap mode. We have no other choice then ignore it. |
1787 | } |
1788 | }; |
1789 | public: |
1790 | TypeDestructor(const int type) |
1791 | : m_type(type) |
1792 | {} |
1793 | |
1794 | template<typename T> |
1795 | void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); } |
1796 | // MSVC2013 and earlier can not const_cast a std::nullptr_t pointer. |
1797 | void delegate(const std::nullptr_t *) {} |
1798 | void delegate(const void *) {} |
1799 | void delegate(const QMetaTypeSwitcher::UnknownType*) {} |
1800 | void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) |
1801 | { customTypeDestructor(type: m_type, where: const_cast<void *>(static_cast<const void *>(where))); } |
1802 | |
1803 | private: |
1804 | static void customTypeDestructor(const int type, void *where) |
1805 | { |
1806 | QMetaType::Destructor dtor; |
1807 | QMetaType::TypedDestructor tdtor; |
1808 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1809 | { |
1810 | QReadLocker locker(customTypesLock()); |
1811 | if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User)) |
1812 | return; |
1813 | const auto &typeInfo = ct->at(i: type - QMetaType::User); |
1814 | dtor = typeInfo.destructor; |
1815 | tdtor = typeInfo.typedDestructor; |
1816 | } |
1817 | Q_ASSERT_X((dtor || tdtor), "void QMetaType::destruct(int type, void *where)", "The type was not properly registered"); |
1818 | if (Q_UNLIKELY(tdtor)) |
1819 | return tdtor(type, where); |
1820 | dtor(where); |
1821 | } |
1822 | |
1823 | const int m_type; |
1824 | }; |
1825 | } // namespace |
1826 | |
1827 | /*! |
1828 | \since 5.0 |
1829 | |
1830 | Destructs the value of the given \a type, located at \a where. |
1831 | |
1832 | Unlike destroy(), this function only invokes the type's |
1833 | destructor, it doesn't invoke the delete operator. |
1834 | |
1835 | \sa construct() |
1836 | */ |
1837 | void QMetaType::destruct(int type, void *where) |
1838 | { |
1839 | if (!where) |
1840 | return; |
1841 | TypeDestructor destructor(type); |
1842 | QMetaTypeSwitcher::switcher<void>(logic&: destructor, type, data: where); |
1843 | } |
1844 | |
1845 | |
1846 | namespace { |
1847 | class SizeOf { |
1848 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
1849 | struct SizeOfImpl { |
1850 | static int Size(const int) { return QTypeInfo<T>::sizeOf; } |
1851 | }; |
1852 | template<typename T> |
1853 | struct SizeOfImpl<T, /* IsAcceptedType = */ false> { |
1854 | static int Size(const int type) |
1855 | { |
1856 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) |
1857 | return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].size : 0; |
1858 | |
1859 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) |
1860 | return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].size : 0; |
1861 | |
1862 | // This point can be reached only for known types that definition is not available, for example |
1863 | // in bootstrap mode. We have no other choice then ignore it. |
1864 | return 0; |
1865 | } |
1866 | }; |
1867 | |
1868 | public: |
1869 | SizeOf(int type) |
1870 | : m_type(type) |
1871 | {} |
1872 | |
1873 | template<typename T> |
1874 | int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); } |
1875 | int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; } |
1876 | int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(type: m_type); } |
1877 | private: |
1878 | static int customTypeSizeOf(const int type) |
1879 | { |
1880 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1881 | QReadLocker locker(customTypesLock()); |
1882 | if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User)) |
1883 | return 0; |
1884 | return ct->at(i: type - QMetaType::User).size; |
1885 | } |
1886 | |
1887 | const int m_type; |
1888 | }; |
1889 | } // namespace |
1890 | |
1891 | /*! |
1892 | \since 5.0 |
1893 | |
1894 | Returns the size of the given \a type in bytes (i.e. sizeof(T), |
1895 | where T is the actual type identified by the \a type argument). |
1896 | |
1897 | This function is typically used together with construct() |
1898 | to perform low-level management of the memory used by a type. |
1899 | |
1900 | \sa construct() |
1901 | */ |
1902 | int QMetaType::sizeOf(int type) |
1903 | { |
1904 | SizeOf sizeOf(type); |
1905 | return QMetaTypeSwitcher::switcher<int>(logic&: sizeOf, type); |
1906 | } |
1907 | |
1908 | namespace { |
1909 | class Flags |
1910 | { |
1911 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
1912 | struct FlagsImpl |
1913 | { |
1914 | static quint32 Flags(const int /* type */) |
1915 | { |
1916 | return QtPrivate::QMetaTypeTypeFlags<T>::Flags; |
1917 | } |
1918 | }; |
1919 | template<typename T> |
1920 | struct FlagsImpl<T, /* IsAcceptedType = */ false> |
1921 | { |
1922 | static quint32 Flags(const int type) |
1923 | { |
1924 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) |
1925 | return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].flags : 0; |
1926 | |
1927 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) |
1928 | return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].flags : 0; |
1929 | |
1930 | // This point can be reached only for known types that definition is not available, for example |
1931 | // in bootstrap mode. We have no other choice then ignore it. |
1932 | return 0; |
1933 | } |
1934 | }; |
1935 | public: |
1936 | Flags(const int type) |
1937 | : m_type(type) |
1938 | {} |
1939 | template<typename T> |
1940 | quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); } |
1941 | quint32 delegate(const void*) { return 0; } |
1942 | quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; } |
1943 | quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(type: m_type); } |
1944 | private: |
1945 | const int m_type; |
1946 | static quint32 customTypeFlags(const int type) |
1947 | { |
1948 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
1949 | if (Q_UNLIKELY(!ct || type < QMetaType::User)) |
1950 | return 0; |
1951 | QReadLocker locker(customTypesLock()); |
1952 | if (Q_UNLIKELY(ct->count() <= type - QMetaType::User)) |
1953 | return 0; |
1954 | return ct->at(i: type - QMetaType::User).flags; |
1955 | } |
1956 | }; |
1957 | } // namespace |
1958 | |
1959 | /*! |
1960 | \since 5.0 |
1961 | |
1962 | Returns flags of the given \a type. |
1963 | |
1964 | \sa QMetaType::TypeFlags |
1965 | */ |
1966 | QMetaType::TypeFlags QMetaType::typeFlags(int type) |
1967 | { |
1968 | Flags flags(type); |
1969 | return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(logic&: flags, type)); |
1970 | } |
1971 | |
1972 | #ifndef QT_BOOTSTRAPPED |
1973 | namespace { |
1974 | class MetaObject |
1975 | { |
1976 | public: |
1977 | MetaObject(const int type) |
1978 | : m_type(type) |
1979 | {} |
1980 | |
1981 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
1982 | struct MetaObjectImpl |
1983 | { |
1984 | static const QMetaObject *MetaObject(int /*type*/) |
1985 | { return QtPrivate::MetaObjectForType<T>::value(); } |
1986 | }; |
1987 | template<typename T> |
1988 | struct MetaObjectImpl<T, /* IsAcceptedType = */ false> |
1989 | { |
1990 | static const QMetaObject *MetaObject(int type) { |
1991 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) |
1992 | return Q_LIKELY(qMetaTypeGuiHelper) |
1993 | ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].metaObject |
1994 | : nullptr; |
1995 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) |
1996 | return Q_LIKELY(qMetaTypeWidgetsHelper) |
1997 | ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].metaObject |
1998 | : nullptr; |
1999 | return nullptr; |
2000 | } |
2001 | }; |
2002 | |
2003 | template <typename T> |
2004 | const QMetaObject *delegate(const T *) { return MetaObjectImpl<T>::MetaObject(m_type); } |
2005 | const QMetaObject *delegate(const void*) { return nullptr; } |
2006 | const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return nullptr; } |
2007 | const QMetaObject *delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customMetaObject(type: m_type); } |
2008 | private: |
2009 | const int m_type; |
2010 | static const QMetaObject *customMetaObject(const int type) |
2011 | { |
2012 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
2013 | if (Q_UNLIKELY(!ct || type < QMetaType::User)) |
2014 | return nullptr; |
2015 | QReadLocker locker(customTypesLock()); |
2016 | if (Q_UNLIKELY(ct->count() <= type - QMetaType::User)) |
2017 | return nullptr; |
2018 | return ct->at(i: type - QMetaType::User).metaObject; |
2019 | } |
2020 | }; |
2021 | } // namespace |
2022 | #endif |
2023 | |
2024 | /*! |
2025 | \since 5.0 |
2026 | |
2027 | returns QMetaType::metaObject for \a type |
2028 | |
2029 | \sa metaObject() |
2030 | */ |
2031 | const QMetaObject *QMetaType::metaObjectForType(int type) |
2032 | { |
2033 | #ifndef QT_BOOTSTRAPPED |
2034 | MetaObject mo(type); |
2035 | return QMetaTypeSwitcher::switcher<const QMetaObject*>(logic&: mo, type); |
2036 | #else |
2037 | Q_UNUSED(type); |
2038 | return nullptr; |
2039 | #endif |
2040 | } |
2041 | |
2042 | /*! |
2043 | \fn int qRegisterMetaType(const char *typeName) |
2044 | \relates QMetaType |
2045 | \threadsafe |
2046 | |
2047 | Registers the type name \a typeName for the type \c{T}. Returns |
2048 | the internal ID used by QMetaType. Any class or struct that has a |
2049 | public default constructor, a public copy constructor and a public |
2050 | destructor can be registered. |
2051 | |
2052 | This function requires that \c{T} is a fully defined type at the point |
2053 | where the function is called. For pointer types, it also requires that the |
2054 | pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able |
2055 | to register pointers to forward declared types. |
2056 | |
2057 | After a type has been registered, you can create and destroy |
2058 | objects of that type dynamically at run-time. |
2059 | |
2060 | This example registers the class \c{MyClass}: |
2061 | |
2062 | \snippet code/src_corelib_kernel_qmetatype.cpp 4 |
2063 | |
2064 | This function is useful to register typedefs so they can be used |
2065 | by QMetaProperty, or in QueuedConnections |
2066 | |
2067 | \snippet code/src_corelib_kernel_qmetatype.cpp 9 |
2068 | |
2069 | \warning This function is useful only for registering an alias (typedef) |
2070 | for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead. |
2071 | |
2072 | \sa {QMetaType::}{qRegisterMetaTypeStreamOperators()}, {QMetaType::}{isRegistered()}, |
2073 | Q_DECLARE_METATYPE() |
2074 | */ |
2075 | |
2076 | /*! |
2077 | \fn void qRegisterMetaTypeStreamOperators(const char *typeName) |
2078 | \relates QMetaType |
2079 | \threadsafe |
2080 | |
2081 | Registers the stream operators for the type \c{T} called \a |
2082 | typeName. |
2083 | |
2084 | Afterward, the type can be streamed using QMetaType::load() and |
2085 | QMetaType::save(). These functions are used when streaming a |
2086 | QVariant. |
2087 | |
2088 | \snippet code/src_corelib_kernel_qmetatype.cpp 5 |
2089 | |
2090 | The stream operators should have the following signatures: |
2091 | |
2092 | \snippet code/src_corelib_kernel_qmetatype.cpp 6 |
2093 | |
2094 | \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE() |
2095 | */ |
2096 | |
2097 | /*! \typedef QMetaType::Deleter |
2098 | \internal |
2099 | */ |
2100 | /*! \typedef QMetaType::Creator |
2101 | \internal |
2102 | */ |
2103 | /*! \typedef QMetaType::SaveOperator |
2104 | \internal |
2105 | */ |
2106 | /*! \typedef QMetaType::LoadOperator |
2107 | \internal |
2108 | */ |
2109 | /*! \typedef QMetaType::Destructor |
2110 | \internal |
2111 | */ |
2112 | /*! \typedef QMetaType::Constructor |
2113 | \internal |
2114 | */ |
2115 | |
2116 | /*! |
2117 | \fn int qRegisterMetaType() |
2118 | \relates QMetaType |
2119 | \threadsafe |
2120 | \since 4.2 |
2121 | |
2122 | Call this function to register the type \c T. \c T must be declared with |
2123 | Q_DECLARE_METATYPE(). Returns the meta type Id. |
2124 | |
2125 | Example: |
2126 | |
2127 | \snippet code/src_corelib_kernel_qmetatype.cpp 7 |
2128 | |
2129 | This function requires that \c{T} is a fully defined type at the point |
2130 | where the function is called. For pointer types, it also requires that the |
2131 | pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able |
2132 | to register pointers to forward declared types. |
2133 | |
2134 | After a type has been registered, you can create and destroy |
2135 | objects of that type dynamically at run-time. |
2136 | |
2137 | To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is |
2138 | sufficient. To use the type \c T in queued signal and slot connections, |
2139 | \c{qRegisterMetaType<T>()} must be called before the first connection |
2140 | is established. |
2141 | |
2142 | Also, to use type \c T with the QObject::property() API, |
2143 | \c{qRegisterMetaType<T>()} must be called before it is used, typically |
2144 | in the constructor of the class that uses \c T, or in the \c{main()} |
2145 | function. |
2146 | |
2147 | \sa Q_DECLARE_METATYPE() |
2148 | */ |
2149 | |
2150 | /*! |
2151 | \fn int qMetaTypeId() |
2152 | \relates QMetaType |
2153 | \threadsafe |
2154 | \since 4.1 |
2155 | |
2156 | Returns the meta type id of type \c T at compile time. If the |
2157 | type was not declared with Q_DECLARE_METATYPE(), compilation will |
2158 | fail. |
2159 | |
2160 | Typical usage: |
2161 | |
2162 | \snippet code/src_corelib_kernel_qmetatype.cpp 8 |
2163 | |
2164 | QMetaType::type() returns the same ID as qMetaTypeId(), but does |
2165 | a lookup at runtime based on the name of the type. |
2166 | QMetaType::type() is a bit slower, but compilation succeeds if a |
2167 | type is not registered. |
2168 | |
2169 | \sa Q_DECLARE_METATYPE(), QMetaType::type() |
2170 | */ |
2171 | |
2172 | namespace { |
2173 | class TypeInfo { |
2174 | template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted> |
2175 | struct TypeInfoImpl |
2176 | { |
2177 | TypeInfoImpl(const uint /* type */, QMetaTypeInterface &info) |
2178 | { |
2179 | QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_NO_DATASTREAM(T); |
2180 | info = tmp; |
2181 | } |
2182 | }; |
2183 | |
2184 | template<typename T> |
2185 | struct TypeInfoImpl<T, /* IsAcceptedType = */ false> |
2186 | { |
2187 | TypeInfoImpl(const uint type, QMetaTypeInterface &info) |
2188 | { |
2189 | if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) { |
2190 | if (Q_LIKELY(qMetaTypeGuiHelper)) |
2191 | info = qMetaTypeGuiHelper[type - QMetaType::FirstGuiType]; |
2192 | return; |
2193 | } |
2194 | if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) { |
2195 | if (Q_LIKELY(qMetaTypeWidgetsHelper)) |
2196 | info = qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType]; |
2197 | return; |
2198 | } |
2199 | } |
2200 | }; |
2201 | public: |
2202 | QMetaTypeInterface info; |
2203 | TypeInfo(const uint type) |
2204 | : m_type(type) |
2205 | { |
2206 | QMetaTypeInterface tmp = QT_METATYPE_INTERFACE_INIT_EMPTY(); |
2207 | info = tmp; |
2208 | } |
2209 | template<typename T> |
2210 | void delegate(const T*) { TypeInfoImpl<T>(m_type, info); } |
2211 | void delegate(const QMetaTypeSwitcher::UnknownType*) {} |
2212 | void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(type: m_type); } |
2213 | private: |
2214 | void customTypeInfo(const uint type) |
2215 | { |
2216 | const QVector<QCustomTypeInfo> * const ct = customTypes(); |
2217 | if (Q_UNLIKELY(!ct)) |
2218 | return; |
2219 | QReadLocker locker(customTypesLock()); |
2220 | if (Q_LIKELY(uint(ct->count()) > type - QMetaType::User)) |
2221 | info = ct->at(i: type - QMetaType::User); |
2222 | } |
2223 | |
2224 | const uint m_type; |
2225 | }; |
2226 | } // namespace |
2227 | |
2228 | /*! |
2229 | \fn QMetaType QMetaType::typeInfo(const int type) |
2230 | \internal |
2231 | */ |
2232 | QMetaType QMetaType::typeInfo(const int type) |
2233 | { |
2234 | TypeInfo typeInfo(type); |
2235 | QMetaTypeSwitcher::switcher<void>(logic&: typeInfo, type); |
2236 | return (typeInfo.info.constructor || typeInfo.info.typedConstructor) |
2237 | ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx | |
2238 | (typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0)) |
2239 | , static_cast<const QMetaTypeInterface *>(nullptr) // typeInfo::info is a temporary variable, we can't return address of it. |
2240 | , typeInfo.info.typedConstructor |
2241 | , typeInfo.info.typedDestructor |
2242 | , typeInfo.info.saveOp |
2243 | , typeInfo.info.loadOp |
2244 | , typeInfo.info.constructor |
2245 | , typeInfo.info.destructor |
2246 | , typeInfo.info.size |
2247 | , typeInfo.info.flags |
2248 | , type |
2249 | , typeInfo.info.metaObject) |
2250 | : QMetaType(UnknownType); |
2251 | } |
2252 | |
2253 | /*! |
2254 | \fn QMetaType::QMetaType(const int typeId) |
2255 | \since 5.0 |
2256 | |
2257 | Constructs a QMetaType object that contains all information about type \a typeId. |
2258 | |
2259 | \note The default parameter was added in Qt 5.15. |
2260 | */ |
2261 | QMetaType::QMetaType(const int typeId) |
2262 | : m_typeId(typeId) |
2263 | { |
2264 | if (Q_UNLIKELY(typeId == UnknownType)) { |
2265 | // Constructs invalid QMetaType instance. |
2266 | m_extensionFlags = 0xffffffff; |
2267 | Q_ASSERT(!isValid()); |
2268 | } else { |
2269 | // TODO it can be better. |
2270 | *this = QMetaType::typeInfo(type: typeId); |
2271 | if (m_typeId == UnknownType) |
2272 | m_extensionFlags = 0xffffffff; |
2273 | else if (m_typeId == QMetaType::Void) |
2274 | m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx; |
2275 | } |
2276 | } |
2277 | |
2278 | /*! |
2279 | \fn QMetaType::QMetaType(const QMetaType &other) |
2280 | \since 5.0 |
2281 | |
2282 | Copy constructs a QMetaType object. |
2283 | */ |
2284 | QMetaType::QMetaType(const QMetaType &other) |
2285 | : m_typedConstructor(other.m_typedConstructor) |
2286 | , m_typedDestructor(other.m_typedDestructor) |
2287 | , m_saveOp(other.m_saveOp) |
2288 | , m_loadOp(other.m_loadOp) |
2289 | , m_constructor(other.m_constructor) |
2290 | , m_destructor(other.m_destructor) |
2291 | , m_extension(other.m_extension) // space reserved for future use |
2292 | , m_size(other.m_size) |
2293 | , m_typeFlags(other.m_typeFlags) |
2294 | , m_extensionFlags(other.m_extensionFlags) |
2295 | , m_typeId(other.m_typeId) |
2296 | , m_metaObject(other.m_metaObject) |
2297 | {} |
2298 | |
2299 | QMetaType &QMetaType::operator =(const QMetaType &other) |
2300 | { |
2301 | m_typedConstructor = other.m_typedConstructor; |
2302 | m_typedDestructor = other.m_typedDestructor; |
2303 | m_saveOp = other.m_saveOp; |
2304 | m_loadOp = other.m_loadOp; |
2305 | m_constructor = other.m_constructor; |
2306 | m_destructor = other.m_destructor; |
2307 | m_size = other.m_size; |
2308 | m_typeFlags = other.m_typeFlags; |
2309 | m_extensionFlags = other.m_extensionFlags; |
2310 | m_extension = other.m_extension; // space reserved for future use |
2311 | m_typeId = other.m_typeId; |
2312 | m_metaObject = other.m_metaObject; |
2313 | return *this; |
2314 | } |
2315 | |
2316 | /*! |
2317 | \fn void QMetaType::ctor(const QMetaTypeInterface *info) |
2318 | \internal |
2319 | |
2320 | Method used for future binary compatible extensions. The function may be |
2321 | called from within QMetaType's constructor to force a library call from |
2322 | inlined code. |
2323 | */ |
2324 | void QMetaType::ctor(const QMetaTypeInterface *info) |
2325 | { |
2326 | // Special case for Void type, the type is valid but not constructible. |
2327 | // In future we may consider to remove this assert and extend this function to initialize |
2328 | // differently m_extensionFlags for different types. Currently it is not needed. |
2329 | Q_ASSERT(m_typeId == QMetaType::Void); |
2330 | Q_UNUSED(info); |
2331 | m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx; |
2332 | } |
2333 | |
2334 | /*! |
2335 | \fn void QMetaType::dtor() |
2336 | \internal |
2337 | |
2338 | Method used for future binary compatible extensions. The function may be |
2339 | called from within QMetaType's destructor to force a library call from |
2340 | inlined code. |
2341 | */ |
2342 | void QMetaType::dtor() |
2343 | {} |
2344 | |
2345 | /*! |
2346 | \fn void *QMetaType::createExtended(const void *copy) const |
2347 | \internal |
2348 | |
2349 | Method used for future binary compatible extensions. The function may be called |
2350 | during QMetaType::create to force library call from inlined code. |
2351 | |
2352 | ### TODO Qt6 remove the extension |
2353 | */ |
2354 | void *QMetaType::createExtended(const void *copy) const |
2355 | { |
2356 | if (m_typeId == QMetaType::UnknownType) |
2357 | return nullptr; |
2358 | if (Q_UNLIKELY(m_typedConstructor && !m_constructor)) |
2359 | return m_typedConstructor(m_typeId, operator new(m_size), copy); |
2360 | return m_constructor(operator new(m_size), copy); |
2361 | } |
2362 | |
2363 | /*! |
2364 | \fn void QMetaType::destroyExtended(void *data) const |
2365 | \internal |
2366 | |
2367 | Method used for future binary compatible extensions. The function may be called |
2368 | during QMetaType::destroy to force library call from inlined code. |
2369 | |
2370 | ### TODO Qt6 remove the extension |
2371 | */ |
2372 | void QMetaType::destroyExtended(void *data) const |
2373 | { |
2374 | if (m_typeId == QMetaType::UnknownType) |
2375 | return; |
2376 | if (Q_UNLIKELY(m_typedDestructor && !m_destructor)) |
2377 | m_typedDestructor(m_typeId, data); |
2378 | else |
2379 | m_destructor(data); |
2380 | operator delete(data); |
2381 | } |
2382 | |
2383 | /*! |
2384 | \fn void *QMetaType::constructExtended(void *where, const void *copy) const |
2385 | \internal |
2386 | |
2387 | Method used for future binary compatible extensions. The function may be called |
2388 | during QMetaType::construct to force library call from inlined code. |
2389 | */ |
2390 | void *QMetaType::constructExtended(void *where, const void *copy) const |
2391 | { |
2392 | if (m_typeId == QMetaType::UnknownType) |
2393 | return nullptr; |
2394 | if (m_typedConstructor && !m_constructor) |
2395 | return m_typedConstructor(m_typeId, where, copy); |
2396 | return nullptr; |
2397 | } |
2398 | |
2399 | /*! |
2400 | \fn void QMetaType::destructExtended(void *data) const |
2401 | \internal |
2402 | |
2403 | Method used for future binary compatible extensions. The function may be called |
2404 | during QMetaType::destruct to force library call from inlined code. |
2405 | */ |
2406 | void QMetaType::destructExtended(void *data) const |
2407 | { |
2408 | if (m_typeId == QMetaType::UnknownType) |
2409 | return; |
2410 | if (m_typedDestructor && !m_destructor) |
2411 | m_typedDestructor(m_typeId, data); |
2412 | } |
2413 | |
2414 | /*! |
2415 | \fn uint QMetaType::sizeExtended() const |
2416 | \internal |
2417 | |
2418 | Method used for future binary compatible extensions. The function may be |
2419 | called from within QMetaType::size to force a library call from |
2420 | inlined code. |
2421 | */ |
2422 | uint QMetaType::sizeExtended() const |
2423 | { |
2424 | return 0; |
2425 | } |
2426 | |
2427 | /*! |
2428 | \fn QMetaType::TypeFlags QMetaType::flagsExtended() const |
2429 | \internal |
2430 | |
2431 | Method used for future binary compatible extensions. The function may be |
2432 | called from within QMetaType::flags to force a library call from |
2433 | inlined code. |
2434 | */ |
2435 | QMetaType::TypeFlags QMetaType::flagsExtended() const |
2436 | { |
2437 | return { }; |
2438 | } |
2439 | |
2440 | /*! |
2441 | \brief QMetaType::metaObjectExtended |
2442 | \internal |
2443 | |
2444 | Method used for future binary compatible extensions. The function may be |
2445 | called from within QMetaType::metaObject to force a library call from |
2446 | inlined code. |
2447 | */ |
2448 | const QMetaObject *QMetaType::metaObjectExtended() const |
2449 | { |
2450 | return nullptr; |
2451 | } |
2452 | |
2453 | |
2454 | namespace QtPrivate |
2455 | { |
2456 | const QMetaObject *metaObjectForQWidget() |
2457 | { |
2458 | if (!qMetaTypeWidgetsHelper) |
2459 | return nullptr; |
2460 | return qMetaObjectWidgetsHelper; |
2461 | } |
2462 | } |
2463 | |
2464 | namespace QtMetaTypePrivate { |
2465 | const bool VectorBoolElements::true_element = true; |
2466 | const bool VectorBoolElements::false_element = false; |
2467 | } |
2468 | |
2469 | QT_END_NAMESPACE |
2470 |
Definitions
- DefinedTypesFilter
- Acceptor
- types
- qMetaTypeGuiHelper
- qMetaTypeWidgetsHelper
- qMetaObjectWidgetsHelper
- QCustomTypeInfo
- QCustomTypeInfo
- QMetaTypeFunctionRegistry
- ~QMetaTypeFunctionRegistry
- contains
- insertIfNotContains
- function
- remove
- customTypes
- customTypesLock
- customTypesConversionRegistry
- customTypesComparatorRegistry
- customTypesDebugStreamRegistry
- registerConverterFunction
- unregisterConverterFunction
- registerComparatorFunction
- hasRegisteredComparators
- registerDebugStreamOperatorFunction
- hasRegisteredDebugStreamOperator
- convert
- compare
- equals
- debugStream
- hasRegisteredConverterFunction
- registerStreamOperators
- registerStreamOperators
- metaTypeStrings
- metaTypeNameSizes
- metaTypeIds
- MetaTypeNameCount
- MetaTypeOffsets
- findTypeId
- calculateOffsetForIdx
- calculateOffsetForTypeId
- MetaTypeOffsets
- operator[]
- metaTypeNames
- typeName
- name
- qMetaTypeStaticType
- qMetaTypeCustomType_unlocked
- registerType
- unregisterType
- registerType
- registerType
- registerNormalizedType
- registerNormalizedType
- registerNormalizedType
- registerNormalizedType
- registerTypedef
- registerNormalizedTypedef
- isRegistered
- qMetaTypeTypeImpl
- type
- qMetaTypeTypeInternal
- type
- HasStreamOperator
- Yes
- No
- LoadValue
- SaveValue
- Value
- FilteredOperatorSwitch
- load
- save
- FilteredOperatorSwitch
- getMetaTypeInterface
- save
- load
- SaveOperatorSwitch
- delegate
- delegate
- delegate
- delegate
- delegate
- delegate
- delegate
- LoadOperatorSwitch
- delegate
- delegate
- delegate
- delegate
- delegate
- delegate
- delegate
- save
- load
- create
- destroy
- TypeConstructor
- ConstructorImpl
- Construct
- ConstructorImpl
- Construct
- TypeConstructor
- delegate
- delegate
- delegate
- delegate
- customTypeConstructor
- construct
- TypeDestructor
- DestructorImpl
- Destruct
- DestructorImpl
- Destruct
- TypeDestructor
- delegate
- delegate
- delegate
- delegate
- delegate
- customTypeDestructor
- destruct
- SizeOf
- SizeOfImpl
- Size
- SizeOfImpl
- Size
- SizeOf
- delegate
- delegate
- delegate
- customTypeSizeOf
- sizeOf
- Flags
- FlagsImpl
- Flags
- FlagsImpl
- Flags
- Flags
- delegate
- delegate
- delegate
- delegate
- customTypeFlags
- typeFlags
- MetaObject
- MetaObject
- MetaObjectImpl
- MetaObject
- MetaObjectImpl
- MetaObject
- delegate
- delegate
- delegate
- delegate
- customMetaObject
- metaObjectForType
- TypeInfo
- TypeInfoImpl
- TypeInfoImpl
- TypeInfoImpl
- TypeInfoImpl
- TypeInfo
- delegate
- delegate
- delegate
- customTypeInfo
- typeInfo
- QMetaType
- QMetaType
- operator =
- ctor
- dtor
- createExtended
- destroyExtended
- constructExtended
- destructExtended
- sizeExtended
- flagsExtended
- metaObjectExtended
- metaObjectForQWidget
- true_element
Learn to use CMake with our Intro Training
Find out more