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
88QT_BEGIN_NAMESPACE
89
90#define NS(x) QT_PREPEND_NAMESPACE(x)
91
92
93namespace {
94struct 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
544static 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
551Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr;
552Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr;
553Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr;
554
555class QCustomTypeInfo : public QMetaTypeInterface
556{
557public:
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
568template<typename T, typename Key>
569class QMetaTypeFunctionRegistry
570{
571public:
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 }
606private:
607 mutable QReadWriteLock lock;
608 QHash<Key, const T *> map;
609};
610
611typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
612QMetaTypeConverterRegistry;
613typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
614QMetaTypeComparatorRegistry;
615typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
616QMetaTypeDebugStreamRegistry;
617
618Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value);
619Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value);
620
621Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
622Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
623Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
624Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
625Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
626Q_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*/
691bool 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 */
706void QMetaType::unregisterConverterFunction(int from, int to)
707{
708 if (customTypesConversionRegistry.isDestroyed())
709 return;
710 customTypesConversionRegistry()->remove(from, to);
711}
712
713bool 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 */
732bool QMetaType::hasRegisteredComparators(int typeId)
733{
734 return customTypesComparatorRegistry()->contains(k: typeId);
735}
736
737#ifndef QT_NO_DEBUG_STREAM
738bool 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*/
759bool 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*/
770bool 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*/
783bool 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*/
804bool 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*/
822bool 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*/
843bool 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*/
852void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
853 LoadOperator loadOp)
854{
855 registerStreamOperators(type: type(typeName), saveOp, loadOp);
856}
857
858/*!
859 \internal
860*/
861void 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
886namespace {
887// All type names in one long string.
888constexpr char metaTypeStrings[] = QT_FOR_EACH_STATIC_TYPE(STRINGIFY_TYPE_NAME);
889
890// The sizes of the strings in the metaTypeStrings string (including terminating null)
891constexpr short metaTypeNameSizes[] = {
892 QT_FOR_EACH_STATIC_TYPE(CALCULATE_TYPE_LEN)
893};
894
895// The type IDs, in the order of the metaTypeStrings data
896constexpr short metaTypeIds[] = {
897 QT_FOR_EACH_STATIC_TYPE(MAP_TYPE_ID_TO_IDX)
898};
899
900constexpr int MetaTypeNameCount = sizeof(metaTypeNameSizes) / sizeof(metaTypeNameSizes[0]);
901
902template <typename IntegerSequence> struct MetaTypeOffsets;
903template <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
950constexpr 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*/
962const 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*/
989QByteArray 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*/
997static 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*/
1013static 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 */
1041int 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 */
1060bool 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 */
1091int 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 */
1114int 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
1131static 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*/
1229int 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 */
1254int 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 */
1273int 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*/
1287int 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*/
1306int 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*/
1350bool 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
1364template <bool tryNormalizedType>
1365static 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*/
1394int 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*/
1406int 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*/
1420int 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
1427namespace
1428{
1429
1430template<typename T>
1431class 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)));
1447public:
1448 static constexpr bool Value = LoadValue && SaveValue;
1449};
1450
1451// Quick sanity checks
1452Q_STATIC_ASSERT(HasStreamOperator<NS(QJsonDocument)>::Value);
1453Q_STATIC_ASSERT(!HasStreamOperator<void*>::Value);
1454Q_STATIC_ASSERT(HasStreamOperator<qint8>::Value);
1455
1456template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value>
1457struct 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};
1470template<typename T>
1471struct 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
1499class SaveOperatorSwitch
1500{
1501public:
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};
1544class LoadOperatorSwitch
1545{
1546public:
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*/
1611bool 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*/
1633bool 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*/
1648void *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*/
1661void QMetaType::destroy(int type, void *data)
1662{
1663 QMetaType info(type);
1664 info.destruct(data);
1665 operator delete(data);
1666}
1667
1668namespace {
1669class 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 };
1693public:
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
1705private:
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*/
1756void *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
1765namespace {
1766class 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 };
1789public:
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
1803private:
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*/
1837void 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
1846namespace {
1847class 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
1868public:
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); }
1877private:
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*/
1902int QMetaType::sizeOf(int type)
1903{
1904 SizeOf sizeOf(type);
1905 return QMetaTypeSwitcher::switcher<int>(logic&: sizeOf, type);
1906}
1907
1908namespace {
1909class 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 };
1935public:
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); }
1944private:
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*/
1966QMetaType::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
1973namespace {
1974class MetaObject
1975{
1976public:
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); }
2008private:
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*/
2031const 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
2172namespace {
2173class 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 };
2201public:
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); }
2213private:
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*/
2232QMetaType 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*/
2261QMetaType::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*/
2284QMetaType::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
2299QMetaType &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*/
2324void 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*/
2342void 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*/
2354void *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*/
2372void 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*/
2390void *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*/
2406void 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*/
2422uint 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*/
2435QMetaType::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*/
2448const QMetaObject *QMetaType::metaObjectExtended() const
2449{
2450 return nullptr;
2451}
2452
2453
2454namespace QtPrivate
2455{
2456const QMetaObject *metaObjectForQWidget()
2457{
2458 if (!qMetaTypeWidgetsHelper)
2459 return nullptr;
2460 return qMetaObjectWidgetsHelper;
2461}
2462}
2463
2464namespace QtMetaTypePrivate {
2465const bool VectorBoolElements::true_element = true;
2466const bool VectorBoolElements::false_element = false;
2467}
2468
2469QT_END_NAMESPACE
2470

source code of qtbase/src/corelib/kernel/qmetatype.cpp