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