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