1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qmetatype.h"
41 #include "qmetatype_p.h"
42 #include "qobjectdefs.h"
43 #include "qdatetime.h"
44 #include "qbytearray.h"
45 #include "qreadwritelock.h"
46 #include "qstring.h"
47 #include "qstringlist.h"
48 #include "qvector.h"
49 #include "qlocale.h"
50 #if QT_CONFIG(easingcurve)
51 #include "qeasingcurve.h"
52 #endif
53 #include "quuid.h"
54 #include "qvariant.h"
55 #include "qdatastream.h"
56 #include "qregexp.h"
57 #include "qmetatypeswitcher_p.h"
58 
59 #if QT_CONFIG(regularexpression)
60 #  include "qregularexpression.h"
61 #endif
62 
63 #ifndef QT_BOOTSTRAPPED
64 #  include "qbitarray.h"
65 #  include "qurl.h"
66 #  include "qvariant.h"
67 #  include "qjsonvalue.h"
68 #  include "qjsonobject.h"
69 #  include "qjsonarray.h"
70 #  include "qjsondocument.h"
71 #  include "qcborvalue.h"
72 #  include "qcborarray.h"
73 #  include "qcbormap.h"
74 #  include "qbytearraylist.h"
75 #endif
76 
77 #if QT_CONFIG(itemmodel)
78 #  include "qabstractitemmodel.h"
79 #endif
80 
81 #ifndef QT_NO_GEOM_VARIANT
82 # include "qsize.h"
83 # include "qpoint.h"
84 # include "qrect.h"
85 # include "qline.h"
86 #endif
87 
88 QT_BEGIN_NAMESPACE
89 
90 #define NS(x) QT_PREPEND_NAMESPACE(x)
91 
92 
93 namespace {
94 struct DefinedTypesFilter {
95     template<typename T>
96     struct Acceptor {
97         static const bool IsAccepted = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && QModulesPrivate::QTypeModuleInfo<T>::IsCore;
98     };
99 };
100 } // namespace
101 
102 /*!
103     \macro Q_DECLARE_OPAQUE_POINTER(PointerType)
104     \relates QMetaType
105     \since 5.0
106 
107     This macro enables pointers to forward-declared types (\a PointerType)
108     to be registered with QMetaType using either Q_DECLARE_METATYPE()
109     or qRegisterMetaType().
110 
111     \sa Q_DECLARE_METATYPE(), qRegisterMetaType()
112 */
113 
114 /*!
115     \macro Q_DECLARE_METATYPE(Type)
116     \relates QMetaType
117 
118     This macro makes the type \a Type known to QMetaType as long as it
119     provides a public default constructor, a public copy constructor and
120     a public destructor.
121     It is needed to use the type \a Type as a custom type in QVariant.
122 
123     This macro requires that \a Type is a fully defined type at the point where
124     it is used. For pointer types, it also requires that the pointed to type is
125     fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to
126     register pointers to forward declared types.
127 
128     Ideally, this macro should be placed below the declaration of
129     the class or struct. If that is not possible, it can be put in
130     a private header file which has to be included every time that
131     type is used in a QVariant.
132 
133     Adding a Q_DECLARE_METATYPE() makes the type known to all template
134     based functions, including QVariant. Note that if you intend to
135     use the type in \e queued signal and slot connections or in
136     QObject's property system, you also have to call
137     qRegisterMetaType() since the names are resolved at runtime.
138 
139     This example shows a typical use case of Q_DECLARE_METATYPE():
140 
141     \snippet code/src_corelib_kernel_qmetatype.cpp 0
142 
143     If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
144     has to be outside the namespace:
145 
146     \snippet code/src_corelib_kernel_qmetatype.cpp 1
147 
148     Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
149 
150     \snippet code/src_corelib_kernel_qmetatype.cpp 2
151 
152     Some types are registered automatically and do not need this macro:
153 
154     \list
155     \li Pointers to classes derived from QObject
156     \li QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T>
157         where T is a registered meta type
158     \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are
159         registered meta types
160     \li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject
161     \li Enumerations registered with Q_ENUM or Q_FLAG
162     \li Classes that have a Q_GADGET macro
163     \endlist
164 
165     \sa qRegisterMetaType()
166 */
167 
168 /*!
169     \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container)
170     \relates QMetaType
171 
172     This macro makes the container \a Container known to QMetaType as a sequential
173     container. This makes it possible to put an instance of Container<T> into
174     a QVariant, if T itself is known to QMetaType.
175 
176     Note that all of the Qt sequential containers already have built-in
177     support, and it is not necessary to use this macro with them. The
178     std::vector and std::list containers also have built-in support.
179 
180     This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE():
181 
182     \snippet code/src_corelib_kernel_qmetatype.cpp 10
183 */
184 
185 /*!
186     \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)
187     \relates QMetaType
188 
189     This macro makes the container \a Container known to QMetaType as an associative
190     container. This makes it possible to put an instance of Container<T, U> into
191     a QVariant, if T and U are themselves known to QMetaType.
192 
193     Note that all of the Qt associative containers already have built-in
194     support, and it is not necessary to use this macro with them. The
195     std::map container also has built-in support.
196 
197     This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE():
198 
199     \snippet code/src_corelib_kernel_qmetatype.cpp 11
200 */
201 
202 /*!
203     \macro Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer)
204     \relates QMetaType
205 
206     This macro makes the smart pointer \a SmartPointer known to QMetaType as a
207     smart pointer. This makes it possible to put an instance of SmartPointer<T> into
208     a QVariant, if T is a type which inherits QObject.
209 
210     Note that the QWeakPointer, QSharedPointer and QPointer already have built-in
211     support, and it is not necessary to use this macro with them.
212 
213     This example shows a typical use of Q_DECLARE_SMART_POINTER_METATYPE():
214 
215     \snippet code/src_corelib_kernel_qmetatype.cpp 13
216 */
217 
218 /*!
219     \enum QMetaType::Type
220 
221     These are the built-in types supported by QMetaType:
222 
223     \value Void \c void
224     \value Bool \c bool
225     \value Int \c int
226     \value UInt \c{unsigned int}
227     \value Double \c double
228     \value QChar QChar
229     \value QString QString
230     \value QByteArray QByteArray
231     \value Nullptr \c{std::nullptr_t}
232 
233     \value VoidStar \c{void *}
234     \value Long \c{long}
235     \value LongLong LongLong
236     \value Short \c{short}
237     \value Char \c{char}
238     \value ULong \c{unsigned long}
239     \value ULongLong ULongLong
240     \value UShort \c{unsigned short}
241     \value SChar \c{signed char}
242     \value UChar \c{unsigned char}
243     \value Float \c float
244     \value QObjectStar QObject *
245     \value QVariant QVariant
246 
247     \value QCursor QCursor
248     \value QDate QDate
249     \value QSize QSize
250     \value QTime QTime
251     \value QVariantList QVariantList
252     \value QPolygon QPolygon
253     \value QPolygonF QPolygonF
254     \value QColor QColor
255     \value QColorSpace QColorSpace (introduced in Qt 5.15)
256     \value QSizeF QSizeF
257     \value QRectF QRectF
258     \value QLine QLine
259     \value QTextLength QTextLength
260     \value QStringList QStringList
261     \value QVariantMap QVariantMap
262     \value QVariantHash QVariantHash
263     \value QIcon QIcon
264     \value QPen QPen
265     \value QLineF QLineF
266     \value QTextFormat QTextFormat
267     \value QRect QRect
268     \value QPoint QPoint
269     \value QUrl QUrl
270     \value QRegExp QRegExp
271     \value QRegularExpression QRegularExpression
272     \value QDateTime QDateTime
273     \value QPointF QPointF
274     \value QPalette QPalette
275     \value QFont QFont
276     \value QBrush QBrush
277     \value QRegion QRegion
278     \value QBitArray QBitArray
279     \value QImage QImage
280     \value QKeySequence QKeySequence
281     \value QSizePolicy QSizePolicy
282     \value QPixmap QPixmap
283     \value QLocale QLocale
284     \value QBitmap QBitmap
285     \value QMatrix QMatrix
286     \value QTransform QTransform
287     \value QMatrix4x4 QMatrix4x4
288     \value QVector2D QVector2D
289     \value QVector3D QVector3D
290     \value QVector4D QVector4D
291     \value QQuaternion QQuaternion
292     \value QEasingCurve QEasingCurve
293     \value QJsonValue QJsonValue
294     \value QJsonObject QJsonObject
295     \value QJsonArray QJsonArray
296     \value QJsonDocument QJsonDocument
297     \value QCborValue QCborValue
298     \value QCborArray QCborArray
299     \value QCborMap QCborMap
300     \value QCborSimpleType QCborSimpleType
301     \value QModelIndex QModelIndex
302     \value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
303     \value QUuid QUuid
304     \value QByteArrayList QByteArrayList
305 
306     \value User  Base value for user types
307     \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
308     \omitvalue LastCoreType
309     \omitvalue LastGuiType
310 
311     Additional types can be registered using Q_DECLARE_METATYPE().
312 
313     \sa type(), typeName()
314 */
315 
316 /*!
317     \enum QMetaType::TypeFlag
318 
319     The enum describes attributes of a type supported by QMetaType.
320 
321     \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
322     \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
323     \value MovableType An instance of a type having this attribute can be safely moved by memcpy.
324     \omitvalue SharedPointerToQObject
325     \value IsEnumeration This type is an enumeration
326     \value PointerToQObject This type is a pointer to a derived of QObject
327     \omitvalue WeakPointerToQObject
328     \omitvalue TrackingPointerToQObject
329     \omitvalue WasDeclaredAsMetaType
330     \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit
331     \omitvalue PointerToGadget
332 */
333 
334 /*!
335     \class QMetaType
336     \inmodule QtCore
337     \brief The QMetaType class manages named types in the meta-object system.
338 
339     \ingroup objectmodel
340     \threadsafe
341 
342     The class is used as a helper to marshall types in QVariant and
343     in queued signals and slots connections. It associates a type
344     name to a type so that it can be created and destructed
345     dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
346     to make them available to QVariant and other template-based functions.
347     Call qRegisterMetaType() to make types available to non-template based
348     functions, such as the queued signal and slot connections.
349 
350     Any class or struct that has a public default
351     constructor, a public copy constructor, and a public destructor
352     can be registered.
353 
354     The following code allocates and destructs an instance of
355     \c{MyClass}:
356 
357     \snippet code/src_corelib_kernel_qmetatype.cpp 3
358 
359     If we want the stream operators \c operator<<() and \c
360     operator>>() to work on QVariant objects that store custom types,
361     the custom type must provide \c operator<<() and \c operator>>()
362     operators.
363 
364     \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
365 */
366 
367 /*!
368     \fn bool QMetaType::isValid() const
369     \since 5.0
370 
371     Returns \c true if this QMetaType object contains valid
372     information about a type, false otherwise.
373 */
374 
375 /*!
376     \fn bool QMetaType::isRegistered() const
377     \since 5.0
378 
379     Returns \c true if this QMetaType object contains valid
380     information about a type, false otherwise.
381 */
382 
383 /*!
384     \fn int QMetaType::id() const
385     \since 5.13
386 
387     Returns id type hold by this QMetatype instance.
388 */
389 
390 /*!
391     \fn bool QMetaType::sizeOf() const
392     \since 5.0
393 
394     Returns the size of the type in bytes (i.e. sizeof(T),
395     where T is the actual type for which this QMetaType instance
396     was constructed for).
397 
398     This function is typically used together with construct()
399     to perform low-level management of the memory used by a type.
400 
401     \sa QMetaType::construct(), QMetaType::sizeOf()
402 */
403 
404 /*!
405     \fn TypeFlags QMetaType::flags() const
406     \since 5.0
407 
408     Returns flags of the type for which this QMetaType instance was constructed.
409 
410     \sa QMetaType::TypeFlags, QMetaType::typeFlags()
411 */
412 
413 /*!
414     \fn const QMetaObject *QMetaType::metaObject() const
415     \since 5.5
416 
417     return a QMetaObject relative to this type.
418 
419     If the type is a pointer type to a subclass of QObject, flags() contains
420     QMetaType::PointerToQObject and this function returns the corresponding QMetaObject. This can
421     be used to in combinaison with QMetaObject::construct to create QObject of this type.
422 
423     If the type is a Q_GADGET, flags() contains QMetaType::IsGadget, and this function returns its
424     QMetaObject.  This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
425     pointer of this type. (given by QVariant::data for example)
426 
427     If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function
428     returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or
429     \nullptr otherwise
430 
431     \sa QMetaType::metaObjectForType(), QMetaType::flags()
432 */
433 
434 /*!
435     \fn void *QMetaType::create(const void *copy = 0) const
436     \since 5.0
437 
438     Returns a copy of \a copy, assuming it is of the type that this
439     QMetaType instance was created for. If \a copy is \nullptr, creates
440     a default constructed instance.
441 
442     \sa QMetaType::destroy()
443 */
444 
445 /*!
446     \fn void QMetaType::destroy(void *data) const
447     \since 5.0
448 
449     Destroys the \a data, assuming it is of the type that this
450     QMetaType instance was created for.
451 
452     \sa QMetaType::create()
453 */
454 
455 /*!
456     \fn void *QMetaType::construct(int type, const void *copy)
457     \deprecated
458 
459     Constructs a value of the given type which is a copy of \a copy.
460     The default value for \a copy is \nullptr.
461 
462     Deprecated, use the static function QMetaType::create(int type,
463     const void *copy) instead.
464 */
465 /*!
466     \fn void *QMetaType::construct(void *where, const void *copy = 0) const
467     \since 5.0
468 
469     Constructs a value of the type that this QMetaType instance
470     was constructed for in the existing memory addressed by \a where,
471     that is a copy of \a copy, and returns \a where. If \a copy is
472     zero, the value is default constructed.
473 
474     This is a low-level function for explicitly managing the memory
475     used to store the type. Consider calling create() if you don't
476     need this level of control (that is, use "new" rather than
477     "placement new").
478 
479     You must ensure that \a where points to a location where the new
480     value can be stored and that \a where is suitably aligned.
481     The type's size can be queried by calling sizeOf().
482 
483     The rule of thumb for alignment is that a type is aligned to its
484     natural boundary, which is the smallest power of 2 that is bigger
485     than the type, unless that alignment is larger than the maximum
486     useful alignment for the platform. For practical purposes,
487     alignment larger than 2 * sizeof(void*) is only necessary for
488     special hardware instructions (e.g., aligned SSE loads and stores
489     on x86).
490 */
491 
492 /*!
493     \fn void QMetaType::destruct(void *data) const
494     \since 5.0
495 
496     Destructs the value, located at \a data, assuming that it is
497     of the type for which this QMetaType instance was constructed for.
498 
499     Unlike destroy(), this function only invokes the type's
500     destructor, it doesn't invoke the delete operator.
501     \sa QMetaType::construct()
502 */
503 
504 /*!
505     \fn QMetaType::~QMetaType()
506 
507     Destructs this object.
508 */
509 
510 /*!
511     \fn template<typename T> QMetaType QMetaType::fromType()
512     \since 5.15
513 
514     Returns the QMetaType corresponding to the type in the template parameter.
515 */
516 
517 /*! \fn bool operator==(const QMetaType &a, const QMetaType &b)
518     \since 5.15
519     \relates QMetaType
520     \overload
521 
522     Returns \c true if the QMetaType \a a represents the same type
523     as the QMetaType \a b, otherwise returns \c false.
524 */
525 
526 /*! \fn bool operator!=(const QMetaType &a, const QMetaType &b)
527     \since 5.15
528     \relates QMetaType
529     \overload
530 
531     Returns \c true if the QMetaType \a a represents a different type
532     than the QMetaType \a b, otherwise returns \c false.
533 */
534 
535 #define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
536     { #RealName, sizeof(#RealName) - 1, MetaTypeId },
537 
538 #define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
539     { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },
540 
541 #define QT_ADD_STATIC_METATYPE_HACKS_ITER(MetaTypeName, TypeId, Name) \
542     QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeName, Name)
543 
544 static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
545     QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
546     QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
547     QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
548     {nullptr, 0, QMetaType::UnknownType}
549 };
550 
551 Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = nullptr;
552 Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeWidgetsHelper = nullptr;
553 Q_CORE_EXPORT const QMetaObject *qMetaObjectWidgetsHelper = nullptr;
554 
555 class QCustomTypeInfo : public QMetaTypeInterface
556 {
557 public:
QCustomTypeInfo()558     QCustomTypeInfo()
559         : alias(-1)
560     {
561         QMetaTypeInterface empty = QT_METATYPE_INTERFACE_INIT(void);
562         *static_cast<QMetaTypeInterface*>(this) = empty;
563     }
564     QByteArray typeName;
565     int alias;
566 };
567 
568 template<typename T, typename Key>
569 class QMetaTypeFunctionRegistry
570 {
571 public:
~QMetaTypeFunctionRegistry()572     ~QMetaTypeFunctionRegistry()
573     {
574         const QWriteLocker locker(&lock);
575         map.clear();
576     }
577 
contains(Key k) const578     bool contains(Key k) const
579     {
580         const QReadLocker locker(&lock);
581         return map.contains(k);
582     }
583 
insertIfNotContains(Key k,const T * f)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 
function(Key k) const594     const T *function(Key k) const
595     {
596         const QReadLocker locker(&lock);
597         return map.value(k, nullptr);
598     }
599 
remove(int from,int to)600     void remove(int from, int to)
601     {
602         const Key k(from, to);
603         const QWriteLocker locker(&lock);
604         map.remove(k);
605     }
606 private:
607     mutable QReadWriteLock lock;
608     QHash<Key, const T *> map;
609 };
610 
611 typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
612 QMetaTypeConverterRegistry;
613 typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
614 QMetaTypeComparatorRegistry;
615 typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
616 QMetaTypeDebugStreamRegistry;
617 
618 Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value);
619 Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value);
620 
621 Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>,customTypes)622 Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
623 Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
624 Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
625 Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
626 Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
627 
628 /*!
629     \fn bool QMetaType::registerConverter()
630     \since 5.2
631     Registers the possibility of an implicit conversion from type From to type To in the meta
632     type system. Returns \c true if the registration succeeded, otherwise false.
633 */
634 
635 /*!
636     \fn  template<typename MemberFunction, int> bool QMetaType::registerConverter(MemberFunction function)
637     \since 5.2
638     \overload
639     Registers a method \a function like To From::function() const as converter from type From
640     to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
641 */
642 
643 /*!
644     \fn template<typename MemberFunctionOk, char> bool QMetaType::registerConverter(MemberFunctionOk function)
645     \since 5.2
646     \overload
647     Registers a method \a function like To From::function(bool *ok) const as converter from type From
648     to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
649 */
650 
651 /*!
652     \fn template<typename UnaryFunction> bool QMetaType::registerConverter(UnaryFunction function)
653     \since 5.2
654     \overload
655     Registers a unary function object \a function as converter from type From
656     to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
657 */
658 
659 /*!
660     \fn bool QMetaType::registerComparators()
661     \since 5.2
662     Registers comparison operators for the user-registered type T. This requires T to have
663     both an operator== and an operator<.
664     Returns \c true if the registration succeeded, otherwise false.
665 */
666 
667 /*!
668     \fn bool QMetaType::registerEqualsComparator()
669     \since 5.5
670     Registers equals operator for the user-registered type T. This requires T to have
671     an operator==.
672     Returns \c true if the registration succeeded, otherwise false.
673 */
674 
675 #ifndef QT_NO_DEBUG_STREAM
676 /*!
677     \fn bool QMetaType::registerDebugStreamOperator()
678     Registers the debug stream operator for the user-registered type T. This requires T to have
679     an operator<<(QDebug dbg, T).
680     Returns \c true if the registration succeeded, otherwise false.
681 */
682 #endif
683 
684 /*!
685     Registers function \a f as converter function from type id \a from to \a to.
686     If there's already a conversion registered, this does nothing but deleting \a f.
687     Returns \c true if the registration succeeded, otherwise false.
688     \since 5.2
689     \internal
690 */
691 bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to)
692 {
693     if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from, to), f)) {
694         qWarning("Type conversion already registered from type %s to type %s",
695                  QMetaType::typeName(from), QMetaType::typeName(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  */
unregisterConverterFunction(int from,int to)706 void QMetaType::unregisterConverterFunction(int from, int to)
707 {
708     if (customTypesConversionRegistry.isDestroyed())
709         return;
710     customTypesConversionRegistry()->remove(from, to);
711 }
712 
registerComparatorFunction(const QtPrivate::AbstractComparatorFunction * f,int type)713 bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type)
714 {
715     if (!customTypesComparatorRegistry()->insertIfNotContains(type, f)) {
716         qWarning("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  */
hasRegisteredComparators(int typeId)732 bool QMetaType::hasRegisteredComparators(int typeId)
733 {
734     return customTypesComparatorRegistry()->contains(typeId);
735 }
736 
737 #ifndef QT_NO_DEBUG_STREAM
registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction * f,int type)738 bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f,
739                                                     int type)
740 {
741     if (!customTypesDebugStreamRegistry()->insertIfNotContains(type, f)) {
742         qWarning("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 */
hasRegisteredDebugStreamOperator(int typeId)759 bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
760 {
761     return customTypesDebugStreamRegistry()->contains(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 */
convert(const void * from,int fromTypeId,void * to,int toTypeId)770 bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
771 {
772     const QtPrivate::AbstractConverterFunction * const f =
773         customTypesConversionRegistry()->function(qMakePair(fromTypeId, 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 */
compare(const void * lhs,const void * rhs,int typeId,int * result)783 bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
784 {
785     const QtPrivate::AbstractComparatorFunction * const f =
786         customTypesComparatorRegistry()->function(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 */
equals(const void * lhs,const void * rhs,int typeId,int * result)804 bool QMetaType::equals(const void *lhs, const void *rhs, int typeId, int *result)
805 {
806     const QtPrivate::AbstractComparatorFunction * const f
807         = customTypesComparatorRegistry()->function(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 */
debugStream(QDebug & dbg,const void * rhs,int typeId)822 bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
823 {
824     const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(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 */
hasRegisteredConverterFunction(int fromTypeId,int toTypeId)843 bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId)
844 {
845     return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId));
846 }
847 
848 #ifndef QT_NO_DATASTREAM
849 /*!
850     \internal
851 */
registerStreamOperators(const char * typeName,SaveOperator saveOp,LoadOperator loadOp)852 void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
853                                         LoadOperator loadOp)
854 {
855     registerStreamOperators(type(typeName), saveOp, loadOp);
856 }
857 
858 /*!
859     \internal
860 */
registerStreamOperators(int idx,SaveOperator saveOp,LoadOperator loadOp)861 void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
862                                         LoadOperator loadOp)
863 {
864     if (idx < User)
865         return; //builtin types should not be registered;
866     QVector<QCustomTypeInfo> *ct = customTypes();
867     if (!ct)
868         return;
869     QWriteLocker locker(customTypesLock());
870     QCustomTypeInfo &inf = (*ct)[idx - User];
871     inf.saveOp = saveOp;
872     inf.loadOp = loadOp;
873 }
874 #endif // QT_NO_DATASTREAM
875 
876 // We don't officially support constexpr in MSVC 2015, but the limited support it
877 // has is enough for the code below.
878 
879 #define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
880     #RealName "\0"
881 #define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
882     short(sizeof(#RealName)),
883 #define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
884     TypeId,
885 
886 namespace {
887 // All type names in one long string.
888 constexpr char metaTypeStrings[] = QT_FOR_EACH_STATIC_TYPE(STRINGIFY_TYPE_NAME);
889 
890 // The sizes of the strings in the metaTypeStrings string (including terminating null)
891 constexpr short metaTypeNameSizes[] = {
892     QT_FOR_EACH_STATIC_TYPE(CALCULATE_TYPE_LEN)
893 };
894 
895 // The type IDs, in the order of the metaTypeStrings data
896 constexpr short metaTypeIds[] = {
897     QT_FOR_EACH_STATIC_TYPE(MAP_TYPE_ID_TO_IDX)
898 };
899 
900 constexpr int MetaTypeNameCount = sizeof(metaTypeNameSizes) / sizeof(metaTypeNameSizes[0]);
901 
902 template <typename IntegerSequence> struct MetaTypeOffsets;
903 template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds...>>
904 {
905     // This would have been a lot easier if the meta types that the macro
906     // QT_FOR_EACH_STATIC_TYPE declared were in sorted, ascending order, but
907     // they're not (i.e., the first one declared is QMetaType::Void == 43,
908     // followed by QMetaType::Bool == 1)... As a consequence, we need to use
909     // the C++11 constexpr function calculateOffsetForTypeId below in order to
910     // create the offset array.
911 
findTypeId__anon740a09600311::MetaTypeOffsets912     static constexpr int findTypeId(int typeId, int i = 0)
913     {
914         return i >= MetaTypeNameCount ? -1 :
915                 metaTypeIds[i] == typeId ? i : findTypeId(typeId, i + 1);
916     }
917 
calculateOffsetForIdx__anon740a09600311::MetaTypeOffsets918     static constexpr short calculateOffsetForIdx(int i)
919     {
920         return i < 0 ? -1 :
921                i == 0 ? 0 : metaTypeNameSizes[i - 1] + calculateOffsetForIdx(i - 1);
922     }
923 
calculateOffsetForTypeId__anon740a09600311::MetaTypeOffsets924     static constexpr short calculateOffsetForTypeId(int typeId)
925     {
926         return calculateOffsetForIdx(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)];
MetaTypeOffsets__anon740a09600311::MetaTypeOffsets940     constexpr MetaTypeOffsets() : offsets{calculateOffsetForTypeId(TypeIds)...} {}
941 
operator []__anon740a09600311::MetaTypeOffsets942     const char *operator[](int typeId) const noexcept
943     {
944         short o = offsets[typeId];
945         return o < 0 ? nullptr : metaTypeStrings + o;
946     }
947 };
948 } // anonymous namespace
949 
950 constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {};
951 #undef STRINGIFY_TYPE_NAME
952 #undef CALCULATE_TYPE_LEN
953 #undef MAP_TYPE_ID_TO_IDX
954 
955 /*!
956     Returns the type name associated with the given \a typeId, or a null
957     pointer if no matching type was found. The returned pointer must not be
958     deleted.
959 
960     \sa type(), isRegistered(), Type, name()
961 */
typeName(int typeId)962 const char *QMetaType::typeName(int typeId)
963 {
964     const uint type = typeId;
965     if (Q_LIKELY(type <= QMetaType::HighestInternalId)) {
966         return metaTypeNames[typeId];
967     } else if (Q_UNLIKELY(type < QMetaType::User)) {
968         return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash...
969     }
970 
971     const QVector<QCustomTypeInfo> * const ct = customTypes();
972     QReadLocker locker(customTypesLock());
973     return ct && uint(ct->count()) > type - QMetaType::User && !ct->at(type - QMetaType::User).typeName.isEmpty()
974             ? ct->at(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 */
name() const989 QByteArray QMetaType::name() const
990 {
991     return QMetaType::typeName(m_typeId);
992 }
993 
994 /*
995     Similar to QMetaType::type(), but only looks in the static set of types.
996 */
qMetaTypeStaticType(const char * typeName,int length)997 static inline int qMetaTypeStaticType(const char *typeName, int length)
998 {
999     int i = 0;
1000     while (types[i].typeName && ((length != types[i].typeNameLength)
1001                                  || memcmp(typeName, types[i].typeName, 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 */
qMetaTypeCustomType_unlocked(const char * typeName,int length,int * firstInvalidIndex=nullptr)1013 static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = nullptr)
1014 {
1015     const QVector<QCustomTypeInfo> * const ct = customTypes();
1016     if (!ct)
1017         return QMetaType::UnknownType;
1018 
1019     if (firstInvalidIndex)
1020         *firstInvalidIndex = -1;
1021     for (int v = 0; v < ct->count(); ++v) {
1022         const QCustomTypeInfo &customInfo = ct->at(v);
1023         if ((length == customInfo.typeName.size())
1024             && !memcmp(typeName, customInfo.typeName.constData(), 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  */
registerType(const char * typeName,Deleter deleter,Creator creator)1041 int QMetaType::registerType(const char *typeName, Deleter deleter,
1042                             Creator creator)
1043 {
1044     return registerType(typeName, deleter, creator,
1045                         QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Destruct,
1046                         QtMetaTypePrivate::QMetaTypeFunctionHelper<void>::Construct, 0, TypeFlags(), 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  */
unregisterType(int type)1060 bool QMetaType::unregisterType(int type)
1061 {
1062     QWriteLocker locker(customTypesLock());
1063     QVector<QCustomTypeInfo> *ct = customTypes();
1064 
1065     // check if user type
1066     if ((type < User) || ((type - User) >= ct->size()))
1067         return false;
1068 
1069     // only types without Q_DECLARE_METATYPE can be unregistered
1070     if (ct->data()[type - User].flags & WasDeclaredAsMetaType)
1071         return false;
1072 
1073     // invalidate type and all its alias entries
1074     for (int v = 0; v < ct->count(); ++v) {
1075         if (((v + User) == type) || (ct->at(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  */
registerType(const char * typeName,Deleter deleter,Creator creator,Destructor destructor,Constructor constructor,int size,TypeFlags flags,const QMetaObject * metaObject)1091 int QMetaType::registerType(const char *typeName, Deleter deleter,
1092                             Creator creator,
1093                             Destructor destructor,
1094                             Constructor constructor,
1095                             int size, TypeFlags flags, const QMetaObject *metaObject)
1096 {
1097 #ifdef QT_NO_QOBJECT
1098     NS(QByteArray) normalizedTypeName = typeName;
1099 #else
1100     NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(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  */
registerType(const char * typeName,TypedDestructor destructor,TypedConstructor constructor,int size,TypeFlags flags,const QMetaObject * metaObject)1114 int QMetaType::registerType(const char *typeName,
1115                             TypedDestructor destructor,
1116                             TypedConstructor constructor,
1117                             int size,
1118                             TypeFlags flags,
1119                             const QMetaObject *metaObject)
1120 {
1121 #ifdef QT_NO_QOBJECT
1122     NS(QByteArray) normalizedTypeName = typeName;
1123 #else
1124     NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1125 #endif
1126 
1127     return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
1128 }
1129 
1130 
registerNormalizedType(const NS (QByteArray)& normalizedTypeName,QMetaType::Destructor destructor,QMetaType::Constructor constructor,QMetaType::TypedDestructor typedDestructor,QMetaType::TypedConstructor typedConstructor,int size,QMetaType::TypeFlags flags,const QMetaObject * metaObject)1131 static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
1132                                   QMetaType::Destructor destructor,
1133                                   QMetaType::Constructor constructor,
1134                                   QMetaType::TypedDestructor typedDestructor,
1135                                   QMetaType::TypedConstructor typedConstructor,
1136                                   int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject)
1137 {
1138     QVector<QCustomTypeInfo> *ct = customTypes();
1139     if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor))
1140         return -1;
1141 
1142     int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
1143                                   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(normalizedTypeName.constData(),
1151                                            normalizedTypeName.size(),
1152                                            &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(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(idx - QMetaType::User).size;
1180             previousFlags = ct->at(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(idx);
1196         previousFlags = QMetaType::typeFlags(idx);
1197     }
1198 
1199     if (Q_UNLIKELY(previousSize != size)) {
1200         qFatal("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 */
registerNormalizedType(const NS (QByteArray)& normalizedTypeName,Deleter deleter,Creator creator,Destructor destructor,Constructor constructor,int size,TypeFlags flags,const QMetaObject * metaObject)1229 int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
1230                             Creator creator,
1231                             Destructor destructor,
1232                             Constructor constructor,
1233                             int size, TypeFlags flags, const QMetaObject *metaObject)
1234 {
1235     Q_UNUSED(deleter);
1236     Q_UNUSED(creator);
1237     return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
1238 }
1239 
1240 
1241 /*!
1242     \internal
1243     \since 5.5
1244 
1245     Registers a user type for marshalling, with \a normalizedTypeName,
1246     a \a destructor, a \a constructor, and a \a size. Returns the type's
1247     handle, or -1 if the type could not be registered.
1248 
1249     \note normalizedTypeName is not checked for conformance with
1250     Qt's normalized format, so it must already conform.
1251 
1252     ### TODO Qt6: remove me
1253  */
registerNormalizedType(const NS (QByteArray)& normalizedTypeName,Destructor destructor,Constructor constructor,int size,TypeFlags flags,const QMetaObject * metaObject)1254 int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
1255                             Destructor destructor,
1256                             Constructor constructor,
1257                             int size, TypeFlags flags, const QMetaObject *metaObject)
1258 {
1259     return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, nullptr, 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  */
registerNormalizedType(const NS (QByteArray)& normalizedTypeName,TypedDestructor destructor,TypedConstructor constructor,int size,TypeFlags flags,const QMetaObject * metaObject)1273 int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
1274                             TypedDestructor destructor,
1275                             TypedConstructor constructor,
1276                             int size, TypeFlags flags, const QMetaObject *metaObject)
1277 {
1278     return NS(registerNormalizedType)(normalizedTypeName, nullptr, nullptr, destructor, 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 */
registerTypedef(const char * typeName,int aliasId)1287 int QMetaType::registerTypedef(const char* typeName, int aliasId)
1288 {
1289 #ifdef QT_NO_QOBJECT
1290     NS(QByteArray) normalizedTypeName = typeName;
1291 #else
1292     NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(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 */
registerNormalizedTypedef(const NS (QByteArray)& normalizedTypeName,int aliasId)1306 int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeName, int aliasId)
1307 {
1308     QVector<QCustomTypeInfo> *ct = customTypes();
1309     if (!ct || normalizedTypeName.isEmpty())
1310         return -1;
1311 
1312     int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
1313                                   normalizedTypeName.size());
1314 
1315     if (idx == UnknownType) {
1316         QWriteLocker locker(customTypesLock());
1317         int posInVector = -1;
1318         idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
1319                                                normalizedTypeName.size(),
1320                                                &posInVector);
1321 
1322         if (idx == UnknownType) {
1323             QCustomTypeInfo inf;
1324             inf.typeName = normalizedTypeName;
1325             inf.alias = aliasId;
1326             if (posInVector == -1)
1327                 ct->append(inf);
1328             else
1329                 ct->data()[posInVector] = inf;
1330             return aliasId;
1331         }
1332     }
1333 
1334     if (idx != aliasId) {
1335         qWarning("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(idx), idx,
1339                  QMetaType::typeName(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 */
isRegistered(int type)1350 bool QMetaType::isRegistered(int type)
1351 {
1352     // predefined type
1353     if ((type >= FirstCoreType && type <= LastCoreType)
1354         || (type >= FirstGuiType && type <= LastGuiType)
1355         || (type >= FirstWidgetsType && type <= LastWidgetsType)) {
1356         return true;
1357     }
1358 
1359     QReadLocker locker(customTypesLock());
1360     const QVector<QCustomTypeInfo> * const ct = customTypes();
1361     return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
1362 }
1363 
1364 template <bool tryNormalizedType>
qMetaTypeTypeImpl(const char * typeName,int length)1365 static inline int qMetaTypeTypeImpl(const char *typeName, int length)
1366 {
1367     if (!length)
1368         return QMetaType::UnknownType;
1369     int type = qMetaTypeStaticType(typeName, length);
1370     if (type == QMetaType::UnknownType) {
1371         QReadLocker locker(customTypesLock());
1372         type = qMetaTypeCustomType_unlocked(typeName, length);
1373 #ifndef QT_NO_QOBJECT
1374         if ((type == QMetaType::UnknownType) && tryNormalizedType) {
1375             const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1376             type = qMetaTypeStaticType(normalizedTypeName.constData(),
1377                                        normalizedTypeName.size());
1378             if (type == QMetaType::UnknownType) {
1379                 type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
1380                                                     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 */
type(const char * typeName)1394 int QMetaType::type(const char *typeName)
1395 {
1396     return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName, qstrlen(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 */
qMetaTypeTypeInternal(const char * typeName)1406 int qMetaTypeTypeInternal(const char *typeName)
1407 {
1408     return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, qstrlen(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 */
type(const QT_PREPEND_NAMESPACE (QByteArray)& typeName)1420 int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
1421 {
1422     return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName.constData(), typeName.size());
1423 }
1424 
1425 #ifndef QT_NO_DATASTREAM
1426 
1427 namespace
1428 {
1429 
1430 template<typename T>
1431 class HasStreamOperator
1432 {
1433     struct Yes { char unused[1]; };
1434     struct No { char unused[2]; };
1435     Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No));
1436 
1437     template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int);
1438     template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int);
1439     template<class C> static No load(...);
1440     template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int);
1441     template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int);
1442     template<class C> static No saveMethod(...);
1443     template<class C> static No saveFunction(...);
1444     static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes));
1445     static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable &&
1446         ((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes)));
1447 public:
1448     static constexpr bool Value = LoadValue && SaveValue;
1449 };
1450 
1451 // Quick sanity checks
1452 Q_STATIC_ASSERT(HasStreamOperator<NS(QJsonDocument)>::Value);
1453 Q_STATIC_ASSERT(!HasStreamOperator<void*>::Value);
1454 Q_STATIC_ASSERT(HasStreamOperator<qint8>::Value);
1455 
1456 template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value>
1457 struct FilteredOperatorSwitch
1458 {
load__anon740a09600411::FilteredOperatorSwitch1459     static bool load(QDataStream &stream, T *data, int)
1460     {
1461         stream >> *data;
1462         return true;
1463     }
save__anon740a09600411::FilteredOperatorSwitch1464     static bool save(QDataStream &stream, const T *data, int)
1465     {
1466         stream << *data;
1467         return true;
1468     }
1469 };
1470 template<typename T>
1471 struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false>
1472 {
getMetaTypeInterface__anon740a09600411::FilteredOperatorSwitch1473     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     }
save__anon740a09600411::FilteredOperatorSwitch1481     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     }
load__anon740a09600411::FilteredOperatorSwitch1489     static bool load(QDataStream &stream, T *data, int type)
1490     {
1491         if (auto interface = getMetaTypeInterface(type)) {
1492             interface->loadOp(stream, data);
1493             return true;
1494         }
1495         return false;
1496     }
1497 };
1498 
1499 class SaveOperatorSwitch
1500 {
1501 public:
1502     QDataStream &stream;
1503     int m_type;
1504 
1505     template<typename T>
delegate(const T * data)1506     bool delegate(const T *data)
1507     {
1508         return FilteredOperatorSwitch<T>::save(stream, data, m_type);
1509     }
delegate(const char * data)1510     bool delegate(const char *data)
1511     {
1512         // force a char to be signed
1513         stream << qint8(*data);
1514         return true;
1515     }
delegate(const long * data)1516     bool delegate(const long *data)
1517     {
1518         stream << qlonglong(*data);
1519         return true;
1520     }
delegate(const unsigned long * data)1521     bool delegate(const unsigned long *data)
1522     {
1523         stream << qulonglong(*data);
1524         return true;
1525     }
delegate(const QMetaTypeSwitcher::NotBuiltinType * data)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(m_type - QMetaType::User).saveOp;
1535         }
1536         if (!saveOp)
1537             return false;
1538         saveOp(stream, data);
1539         return true;
1540     }
delegate(const void *)1541     bool delegate(const void*) { return false; }
delegate(const QMetaTypeSwitcher::UnknownType *)1542     bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; }
1543 };
1544 class LoadOperatorSwitch
1545 {
1546 public:
1547     QDataStream &stream;
1548     int m_type;
1549 
1550     template<typename T>
delegate(const T * data)1551     bool delegate(const T *data)
1552     {
1553         return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type);
1554     }
delegate(const char * data)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     }
delegate(const long * data)1563     bool delegate(const long *data)
1564     {
1565         qlonglong l;
1566         stream >> l;
1567         *const_cast<long*>(data) = l;
1568         return true;
1569     }
delegate(const unsigned long * data)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     }
delegate(const QMetaTypeSwitcher::NotBuiltinType * data)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(m_type - QMetaType::User).loadOp;
1586         }
1587         if (!loadOp)
1588             return false;
1589         loadOp(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType*>(data));
1590         return true;
1591     }
delegate(const void *)1592     bool delegate(const void*) { return false; }
delegate(const QMetaTypeSwitcher::UnknownType *)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 */
save(QDataStream & stream,int type,const void * data)1611 bool QMetaType::save(QDataStream &stream, int type, const void *data)
1612 {
1613     if (!data)
1614         return false;
1615     SaveOperatorSwitch saveOp{stream, type};
1616     return QMetaTypeSwitcher::switcher<bool>(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 */
load(QDataStream & stream,int type,void * data)1633 bool QMetaType::load(QDataStream &stream, int type, void *data)
1634 {
1635    if (!data)
1636         return false;
1637     LoadOperatorSwitch loadOp{stream, type};
1638     return QMetaTypeSwitcher::switcher<bool>(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 */
create(int type,const void * copy)1648 void *QMetaType::create(int type, const void *copy)
1649 {
1650     QMetaType info(type);
1651     if (int size = info.sizeOf())
1652         return info.construct(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 */
destroy(int type,void * data)1661 void QMetaType::destroy(int type, void *data)
1662 {
1663     QMetaType info(type);
1664     info.destruct(data);
1665     operator delete(data);
1666 }
1667 
1668 namespace {
1669 class TypeConstructor {
1670     template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1671     struct ConstructorImpl {
Construct__anon740a09600511::TypeConstructor::ConstructorImpl1672         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> {
Construct__anon740a09600511::TypeConstructor::ConstructorImpl1676         static void *Construct(const int type, void *where, const void *copy)
1677         {
1678             if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
1679                 return Q_LIKELY(qMetaTypeGuiHelper)
1680                     ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].constructor(where, copy)
1681                     : nullptr;
1682 
1683             if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
1684                 return Q_LIKELY(qMetaTypeWidgetsHelper)
1685                     ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].constructor(where, copy)
1686                     : nullptr;
1687 
1688             // This point can be reached only for known types that definition is not available, for example
1689             // in bootstrap mode. We have no other choice then ignore it.
1690             return nullptr;
1691         }
1692     };
1693 public:
TypeConstructor(const int type,void * where)1694     TypeConstructor(const int type, void *where)
1695         : m_type(type)
1696         , m_where(where)
1697     {}
1698 
1699     template<typename T>
delegate(const T * copy)1700     void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
delegate(const void *)1701     void *delegate(const void *) { return m_where; }
delegate(const QMetaTypeSwitcher::UnknownType *)1702     void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; }
delegate(const QMetaTypeSwitcher::NotBuiltinType * copy)1703     void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
1704 
1705 private:
customTypeConstructor(const int type,void * where,const void * copy)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(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 */
construct(int type,void * where,const void * copy)1756 void *QMetaType::construct(int type, void *where, const void *copy)
1757 {
1758     if (!where)
1759         return nullptr;
1760     TypeConstructor constructor(type, where);
1761     return QMetaTypeSwitcher::switcher<void*>(constructor, type, copy);
1762 }
1763 
1764 
1765 namespace {
1766 class TypeDestructor {
1767     template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1768     struct DestructorImpl {
Destruct__anon740a09600611::TypeDestructor::DestructorImpl1769         static void Destruct(const int /* type */, void *where) { QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct(where); }
1770     };
1771     template<typename T>
1772     struct DestructorImpl<T, /* IsAcceptedType = */ false> {
Destruct__anon740a09600611::TypeDestructor::DestructorImpl1773         static void Destruct(const int type, void *where)
1774         {
1775             if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
1776                 if (Q_LIKELY(qMetaTypeGuiHelper))
1777                     qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].destructor(where);
1778                 return;
1779             }
1780             if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
1781                 if (Q_LIKELY(qMetaTypeWidgetsHelper))
1782                     qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].destructor(where);
1783                 return;
1784             }
1785             // This point can be reached only for known types that definition is not available, for example
1786             // in bootstrap mode. We have no other choice then ignore it.
1787         }
1788     };
1789 public:
TypeDestructor(const int type)1790     TypeDestructor(const int type)
1791         : m_type(type)
1792     {}
1793 
1794     template<typename T>
delegate(const T * where)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.
delegate(const std::nullptr_t *)1797     void delegate(const std::nullptr_t *) {}
delegate(const void *)1798     void delegate(const void *) {}
delegate(const QMetaTypeSwitcher::UnknownType *)1799     void delegate(const QMetaTypeSwitcher::UnknownType*) {}
delegate(const QMetaTypeSwitcher::NotBuiltinType * where)1800     void delegate(const QMetaTypeSwitcher::NotBuiltinType *where)
1801     { customTypeDestructor(m_type, const_cast<void *>(static_cast<const void *>(where))); }
1802 
1803 private:
customTypeDestructor(const int type,void * where)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(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 */
destruct(int type,void * where)1837 void QMetaType::destruct(int type, void *where)
1838 {
1839     if (!where)
1840         return;
1841     TypeDestructor destructor(type);
1842     QMetaTypeSwitcher::switcher<void>(destructor, type, where);
1843 }
1844 
1845 
1846 namespace {
1847 class SizeOf {
1848     template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1849     struct SizeOfImpl {
Size__anon740a09600711::SizeOf::SizeOfImpl1850         static int Size(const int) { return QTypeInfo<T>::sizeOf; }
1851     };
1852     template<typename T>
1853     struct SizeOfImpl<T, /* IsAcceptedType = */ false> {
Size__anon740a09600711::SizeOf::SizeOfImpl1854         static int Size(const int type)
1855         {
1856             if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
1857                 return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].size : 0;
1858 
1859             if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
1860                 return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].size : 0;
1861 
1862             // This point can be reached only for known types that definition is not available, for example
1863             // in bootstrap mode. We have no other choice then ignore it.
1864             return 0;
1865         }
1866     };
1867 
1868 public:
SizeOf(int type)1869     SizeOf(int type)
1870         : m_type(type)
1871     {}
1872 
1873     template<typename T>
delegate(const T *)1874     int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
delegate(const QMetaTypeSwitcher::UnknownType *)1875     int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
delegate(const QMetaTypeSwitcher::NotBuiltinType *)1876     int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
1877 private:
customTypeSizeOf(const int type)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(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 */
sizeOf(int type)1902 int QMetaType::sizeOf(int type)
1903 {
1904     SizeOf sizeOf(type);
1905     return QMetaTypeSwitcher::switcher<int>(sizeOf, type);
1906 }
1907 
1908 namespace {
1909 class Flags
1910 {
1911     template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
1912     struct FlagsImpl
1913     {
Flags__anon740a09600811::Flags::FlagsImpl1914         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     {
Flags__anon740a09600811::Flags::FlagsImpl1922         static quint32 Flags(const int type)
1923         {
1924             if (QModulesPrivate::QTypeModuleInfo<T>::IsGui)
1925                 return Q_LIKELY(qMetaTypeGuiHelper) ? qMetaTypeGuiHelper[type - QMetaType::FirstGuiType].flags : 0;
1926 
1927             if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget)
1928                 return Q_LIKELY(qMetaTypeWidgetsHelper) ? qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType].flags : 0;
1929 
1930             // This point can be reached only for known types that definition is not available, for example
1931             // in bootstrap mode. We have no other choice then ignore it.
1932             return 0;
1933         }
1934     };
1935 public:
Flags(const int type)1936     Flags(const int type)
1937         : m_type(type)
1938     {}
1939     template<typename T>
delegate(const T *)1940     quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
delegate(const void *)1941     quint32 delegate(const void*) { return 0; }
delegate(const QMetaTypeSwitcher::UnknownType *)1942     quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
delegate(const QMetaTypeSwitcher::NotBuiltinType *)1943     quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
1944 private:
1945     const int m_type;
customTypeFlags(const int 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(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 */
typeFlags(int type)1966 QMetaType::TypeFlags QMetaType::typeFlags(int type)
1967 {
1968     Flags flags(type);
1969     return static_cast<QMetaType::TypeFlags>(QMetaTypeSwitcher::switcher<quint32>(flags, type));
1970 }
1971 
1972 #ifndef QT_BOOTSTRAPPED
1973 namespace {
1974 class MetaObject
1975 {
1976 public:
MetaObject(const int type)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     {
MetaObject__anon740a09600911::MetaObject::MetaObjectImpl1984         static const QMetaObject *MetaObject(int /*type*/)
1985         { return QtPrivate::MetaObjectForType<T>::value(); }
1986     };
1987     template<typename T>
1988     struct MetaObjectImpl<T, /* IsAcceptedType = */ false>
1989     {
MetaObject__anon740a09600911::MetaObject::MetaObjectImpl1990         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>
delegate(const T *)2004     const QMetaObject *delegate(const T *) { return MetaObjectImpl<T>::MetaObject(m_type); }
delegate(const void *)2005     const QMetaObject *delegate(const void*) { return nullptr; }
delegate(const QMetaTypeSwitcher::UnknownType *)2006     const QMetaObject *delegate(const QMetaTypeSwitcher::UnknownType*) { return nullptr; }
delegate(const QMetaTypeSwitcher::NotBuiltinType *)2007     const QMetaObject *delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customMetaObject(m_type); }
2008 private:
2009     const int m_type;
customMetaObject(const int 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(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 */
metaObjectForType(int type)2031 const QMetaObject *QMetaType::metaObjectForType(int type)
2032 {
2033 #ifndef QT_BOOTSTRAPPED
2034     MetaObject mo(type);
2035     return QMetaTypeSwitcher::switcher<const QMetaObject*>(mo, type);
2036 #else
2037     Q_UNUSED(type);
2038     return nullptr;
2039 #endif
2040 }
2041 
2042 /*!
2043     \fn int qRegisterMetaType(const char *typeName)
2044     \relates QMetaType
2045     \threadsafe
2046 
2047     Registers the type name \a typeName for the type \c{T}. Returns
2048     the internal ID used by QMetaType. Any class or struct that has a
2049     public default constructor, a public copy constructor and a public
2050     destructor can be registered.
2051 
2052     This function requires that \c{T} is a fully defined type at the point
2053     where the function is called. For pointer types, it also requires that the
2054     pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
2055     to register pointers to forward declared types.
2056 
2057     After a type has been registered, you can create and destroy
2058     objects of that type dynamically at run-time.
2059 
2060     This example registers the class \c{MyClass}:
2061 
2062     \snippet code/src_corelib_kernel_qmetatype.cpp 4
2063 
2064     This function is useful to register typedefs so they can be used
2065     by QMetaProperty, or in QueuedConnections
2066 
2067     \snippet code/src_corelib_kernel_qmetatype.cpp 9
2068 
2069     \warning This function is useful only for registering an alias (typedef)
2070     for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
2071 
2072     \sa {QMetaType::}{qRegisterMetaTypeStreamOperators()}, {QMetaType::}{isRegistered()},
2073         Q_DECLARE_METATYPE()
2074 */
2075 
2076 /*!
2077     \fn void qRegisterMetaTypeStreamOperators(const char *typeName)
2078     \relates QMetaType
2079     \threadsafe
2080 
2081     Registers the stream operators for the type \c{T} called \a
2082     typeName.
2083 
2084     Afterward, the type can be streamed using QMetaType::load() and
2085     QMetaType::save(). These functions are used when streaming a
2086     QVariant.
2087 
2088     \snippet code/src_corelib_kernel_qmetatype.cpp 5
2089 
2090     The stream operators should have the following signatures:
2091 
2092     \snippet code/src_corelib_kernel_qmetatype.cpp 6
2093 
2094     \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
2095 */
2096 
2097 /*! \typedef QMetaType::Deleter
2098     \internal
2099 */
2100 /*! \typedef QMetaType::Creator
2101     \internal
2102 */
2103 /*! \typedef QMetaType::SaveOperator
2104     \internal
2105 */
2106 /*! \typedef QMetaType::LoadOperator
2107     \internal
2108 */
2109 /*! \typedef QMetaType::Destructor
2110     \internal
2111 */
2112 /*! \typedef QMetaType::Constructor
2113     \internal
2114 */
2115 
2116 /*!
2117     \fn int qRegisterMetaType()
2118     \relates QMetaType
2119     \threadsafe
2120     \since 4.2
2121 
2122     Call this function to register the type \c T. \c T must be declared with
2123     Q_DECLARE_METATYPE(). Returns the meta type Id.
2124 
2125     Example:
2126 
2127     \snippet code/src_corelib_kernel_qmetatype.cpp 7
2128 
2129     This function requires that \c{T} is a fully defined type at the point
2130     where the function is called. For pointer types, it also requires that the
2131     pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
2132     to register pointers to forward declared types.
2133 
2134     After a type has been registered, you can create and destroy
2135     objects of that type dynamically at run-time.
2136 
2137     To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
2138     sufficient. To use the type \c T in queued signal and slot connections,
2139     \c{qRegisterMetaType<T>()} must be called before the first connection
2140     is established.
2141 
2142     Also, to use type \c T with the QObject::property() API,
2143     \c{qRegisterMetaType<T>()} must be called before it is used, typically
2144     in the constructor of the class that uses \c T, or in the \c{main()}
2145     function.
2146 
2147     \sa Q_DECLARE_METATYPE()
2148  */
2149 
2150 /*!
2151     \fn int qMetaTypeId()
2152     \relates QMetaType
2153     \threadsafe
2154     \since 4.1
2155 
2156     Returns the meta type id of type \c T at compile time. If the
2157     type was not declared with Q_DECLARE_METATYPE(), compilation will
2158     fail.
2159 
2160     Typical usage:
2161 
2162     \snippet code/src_corelib_kernel_qmetatype.cpp 8
2163 
2164     QMetaType::type() returns the same ID as qMetaTypeId(), but does
2165     a lookup at runtime based on the name of the type.
2166     QMetaType::type() is a bit slower, but compilation succeeds if a
2167     type is not registered.
2168 
2169     \sa Q_DECLARE_METATYPE(), QMetaType::type()
2170 */
2171 
2172 namespace {
2173 class TypeInfo {
2174     template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted>
2175     struct TypeInfoImpl
2176     {
TypeInfoImpl__anon740a09600a11::TypeInfo::TypeInfoImpl2177         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     {
TypeInfoImpl__anon740a09600a11::TypeInfo::TypeInfoImpl2187         TypeInfoImpl(const uint type, QMetaTypeInterface &info)
2188         {
2189             if (QModulesPrivate::QTypeModuleInfo<T>::IsGui) {
2190                 if (Q_LIKELY(qMetaTypeGuiHelper))
2191                     info = qMetaTypeGuiHelper[type - QMetaType::FirstGuiType];
2192                 return;
2193             }
2194             if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget) {
2195                 if (Q_LIKELY(qMetaTypeWidgetsHelper))
2196                     info = qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType];
2197                 return;
2198             }
2199         }
2200     };
2201 public:
2202     QMetaTypeInterface info;
TypeInfo(const uint type)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>
delegate(const T *)2210     void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
delegate(const QMetaTypeSwitcher::UnknownType *)2211     void delegate(const QMetaTypeSwitcher::UnknownType*) {}
delegate(const QMetaTypeSwitcher::NotBuiltinType *)2212     void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
2213 private:
customTypeInfo(const uint type)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(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 */
typeInfo(const int type)2232 QMetaType QMetaType::typeInfo(const int type)
2233 {
2234     TypeInfo typeInfo(type);
2235     QMetaTypeSwitcher::switcher<void>(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 */
QMetaType(const int typeId)2261 QMetaType::QMetaType(const int typeId)
2262     : m_typeId(typeId)
2263 {
2264     if (Q_UNLIKELY(typeId == UnknownType)) {
2265         // Constructs invalid QMetaType instance.
2266         m_extensionFlags = 0xffffffff;
2267         Q_ASSERT(!isValid());
2268     } else {
2269         // TODO it can be better.
2270         *this = QMetaType::typeInfo(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 */
QMetaType(const QMetaType & other)2284 QMetaType::QMetaType(const QMetaType &other)
2285     : m_typedConstructor(other.m_typedConstructor)
2286     , m_typedDestructor(other.m_typedDestructor)
2287     , m_saveOp(other.m_saveOp)
2288     , m_loadOp(other.m_loadOp)
2289     , m_constructor(other.m_constructor)
2290     , m_destructor(other.m_destructor)
2291     , m_extension(other.m_extension) // space reserved for future use
2292     , m_size(other.m_size)
2293     , m_typeFlags(other.m_typeFlags)
2294     , m_extensionFlags(other.m_extensionFlags)
2295     , m_typeId(other.m_typeId)
2296     , m_metaObject(other.m_metaObject)
2297 {}
2298 
operator =(const QMetaType & other)2299 QMetaType &QMetaType::operator =(const QMetaType &other)
2300 {
2301     m_typedConstructor = other.m_typedConstructor;
2302     m_typedDestructor = other.m_typedDestructor;
2303     m_saveOp = other.m_saveOp;
2304     m_loadOp = other.m_loadOp;
2305     m_constructor = other.m_constructor;
2306     m_destructor = other.m_destructor;
2307     m_size = other.m_size;
2308     m_typeFlags = other.m_typeFlags;
2309     m_extensionFlags = other.m_extensionFlags;
2310     m_extension = other.m_extension; // space reserved for future use
2311     m_typeId = other.m_typeId;
2312     m_metaObject = other.m_metaObject;
2313     return *this;
2314 }
2315 
2316 /*!
2317     \fn void QMetaType::ctor(const QMetaTypeInterface *info)
2318     \internal
2319 
2320     Method used for future binary compatible extensions.  The function may be
2321     called from within QMetaType's constructor to force a library call from
2322     inlined code.
2323 */
ctor(const QMetaTypeInterface * info)2324 void QMetaType::ctor(const QMetaTypeInterface *info)
2325 {
2326     // Special case for Void type, the type is valid but not constructible.
2327     // In future we may consider to remove this assert and extend this function to initialize
2328     // differently m_extensionFlags for different types. Currently it is not needed.
2329     Q_ASSERT(m_typeId == QMetaType::Void);
2330     Q_UNUSED(info);
2331     m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
2332 }
2333 
2334 /*!
2335     \fn void QMetaType::dtor()
2336     \internal
2337 
2338     Method used for future binary compatible extensions.  The function may be
2339     called from within QMetaType's destructor to force a library call from
2340     inlined code.
2341 */
dtor()2342 void QMetaType::dtor()
2343 {}
2344 
2345 /*!
2346     \fn void *QMetaType::createExtended(const void *copy) const
2347     \internal
2348 
2349     Method used for future binary compatible extensions. The function may be called
2350     during QMetaType::create to force library call from inlined code.
2351 
2352     ### TODO Qt6 remove the extension
2353 */
createExtended(const void * copy) const2354 void *QMetaType::createExtended(const void *copy) const
2355 {
2356     if (m_typeId == QMetaType::UnknownType)
2357         return nullptr;
2358     if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
2359         return m_typedConstructor(m_typeId, operator new(m_size), copy);
2360     return m_constructor(operator new(m_size), copy);
2361 }
2362 
2363 /*!
2364     \fn void QMetaType::destroyExtended(void *data) const
2365     \internal
2366 
2367     Method used for future binary compatible extensions. The function may be called
2368     during QMetaType::destroy to force library call from inlined code.
2369 
2370     ### TODO Qt6 remove the extension
2371 */
destroyExtended(void * data) const2372 void QMetaType::destroyExtended(void *data) const
2373 {
2374     if (m_typeId == QMetaType::UnknownType)
2375         return;
2376     if (Q_UNLIKELY(m_typedDestructor && !m_destructor))
2377         m_typedDestructor(m_typeId, data);
2378     else
2379         m_destructor(data);
2380     operator delete(data);
2381 }
2382 
2383 /*!
2384     \fn void *QMetaType::constructExtended(void *where, const void *copy) const
2385     \internal
2386 
2387     Method used for future binary compatible extensions. The function may be called
2388     during QMetaType::construct to force library call from inlined code.
2389 */
constructExtended(void * where,const void * copy) const2390 void *QMetaType::constructExtended(void *where, const void *copy) const
2391 {
2392     if (m_typeId == QMetaType::UnknownType)
2393         return nullptr;
2394     if (m_typedConstructor && !m_constructor)
2395         return m_typedConstructor(m_typeId, where, copy);
2396     return nullptr;
2397 }
2398 
2399 /*!
2400     \fn void QMetaType::destructExtended(void *data) const
2401     \internal
2402 
2403     Method used for future binary compatible extensions. The function may be called
2404     during QMetaType::destruct to force library call from inlined code.
2405 */
destructExtended(void * data) const2406 void QMetaType::destructExtended(void *data) const
2407 {
2408     if (m_typeId == QMetaType::UnknownType)
2409         return;
2410     if (m_typedDestructor && !m_destructor)
2411         m_typedDestructor(m_typeId, data);
2412 }
2413 
2414 /*!
2415     \fn uint QMetaType::sizeExtended() const
2416     \internal
2417 
2418     Method used for future binary compatible extensions. The function may be
2419     called from within QMetaType::size to force a library call from
2420     inlined code.
2421 */
sizeExtended() const2422 uint QMetaType::sizeExtended() const
2423 {
2424     return 0;
2425 }
2426 
2427 /*!
2428     \fn QMetaType::TypeFlags QMetaType::flagsExtended() const
2429     \internal
2430 
2431     Method used for future binary compatible extensions.  The function may be
2432     called from within QMetaType::flags to force a library call from
2433     inlined code.
2434 */
flagsExtended() const2435 QMetaType::TypeFlags QMetaType::flagsExtended() const
2436 {
2437     return { };
2438 }
2439 
2440 /*!
2441     \brief QMetaType::metaObjectExtended
2442     \internal
2443 
2444     Method used for future binary compatible extensions. The function may be
2445     called from within QMetaType::metaObject to force a library call from
2446     inlined code.
2447 */
metaObjectExtended() const2448 const QMetaObject *QMetaType::metaObjectExtended() const
2449 {
2450     return nullptr;
2451 }
2452 
2453 
2454 namespace QtPrivate
2455 {
metaObjectForQWidget()2456 const QMetaObject *metaObjectForQWidget()
2457 {
2458     if (!qMetaTypeWidgetsHelper)
2459         return nullptr;
2460     return qMetaObjectWidgetsHelper;
2461 }
2462 }
2463 
2464 namespace QtMetaTypePrivate {
2465 const bool VectorBoolElements::true_element = true;
2466 const bool VectorBoolElements::false_element = false;
2467 }
2468 
2469 QT_END_NAMESPACE
2470