1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
3// Copyright (C) 2021 Intel Corporation.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qmetatype.h"
7#include "qmetatype_p.h"
8
9#include "qbytearray.h"
10#include "qdatetime.h"
11#include "qdebug.h"
12#include "qhash.h"
13#include "qlist.h"
14#include "qlocale.h"
15#include "qmap.h"
16#include "private/qnumeric_p.h"
17#include "qobjectdefs.h"
18#include "private/qoffsetstringarray_p.h"
19#include "qreadwritelock.h"
20#include "qstring.h"
21#include "qstringlist.h"
22
23#if QT_CONFIG(easingcurve)
24#include "qeasingcurve.h"
25#endif
26
27#if QT_CONFIG(regularexpression)
28# include "qregularexpression.h"
29#endif
30
31#ifndef QT_BOOTSTRAPPED
32# include "qdatastream.h"
33
34# include "qassociativeiterable.h"
35# include "qbitarray.h"
36# include "qbytearraylist.h"
37# include "qcborarray.h"
38# include "qcbormap.h"
39# include "qcborvalue.h"
40# include "qjsonarray.h"
41# include "qjsondocument.h"
42# include "qjsonobject.h"
43# include "qjsonvalue.h"
44# include "qline.h"
45# include "qloggingcategory.h"
46# include "qmetaobject.h"
47# include "qobject.h"
48# include "qpoint.h"
49# include "qrect.h"
50# include "qsequentialiterable.h"
51# include "qsize.h"
52# include "qurl.h"
53# include "quuid.h"
54# include "qvariant.h"
55#endif
56
57#if QT_CONFIG(itemmodel)
58# include "qabstractitemmodel.h"
59#endif
60
61#include <new>
62#include <cstring>
63
64QT_BEGIN_NAMESPACE
65
66#ifndef QT_BOOTSTRAPPED
67Q_STATIC_LOGGING_CATEGORY(lcMetatypeDeprecated, "qt.core.qmetatype.deprecated");
68#endif
69
70#define NS(x) QT_PREPEND_NAMESPACE(x)
71
72QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
73
74using QtMetaTypePrivate::isInterfaceFor;
75
76namespace {
77struct QMetaTypeDeleter
78{
79 const QtPrivate::QMetaTypeInterface *iface;
80 void operator()(void *data) const
81 {
82 if (iface->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
83#ifdef __cpp_sized_deallocation
84 operator delete(data, iface->size, std::align_val_t(iface->alignment));
85#else
86 operator delete(data, std::align_val_t(iface->alignment));
87#endif
88 } else {
89#ifdef __cpp_sized_deallocation
90 operator delete(data, iface->size);
91#else
92 operator delete(data);
93#endif
94 }
95 }
96};
97} // namespace
98
99#ifndef QT_BOOTSTRAPPED
100namespace {
101struct QMetaTypeCustomRegistry
102{
103#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
104 QMetaTypeCustomRegistry()
105 {
106 /* qfloat16 was neither a builtin, nor unconditionally registered
107 in QtCore in Qt <= 6.2.
108 Inserting it as an alias ensures that a QMetaType::id call
109 will get the correct built-in type-id (the interface pointers
110 might still not match, but we already deal with that case.
111 */
112 aliases.insert(key: "qfloat16", value: QtPrivate::qMetaTypeInterfaceForType<qfloat16>());
113 }
114#endif
115
116 QReadWriteLock lock;
117 QList<const QtPrivate::QMetaTypeInterface *> registry;
118 QHash<QByteArray, const QtPrivate::QMetaTypeInterface *> aliases;
119 // index of first empty (unregistered) type in registry, if any.
120 int firstEmpty = 0;
121
122 int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
123 {
124 // we got here because cti->typeId is 0, so this is a custom meta type
125 // (not read-only)
126 auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
127 {
128 QWriteLocker l(&lock);
129 if (int id = ti->typeId.loadRelaxed())
130 return id;
131 QByteArray name =
132#ifndef QT_NO_QOBJECT
133 QMetaObject::normalizedType
134#endif
135 (type: ti->name);
136 if (auto ti2 = aliases.value(key: name)) {
137 const auto id = ti2->typeId.loadRelaxed();
138 ti->typeId.storeRelaxed(newValue: id);
139 return id;
140 }
141 aliases[name] = ti;
142 int size = registry.size();
143 while (firstEmpty < size && registry[firstEmpty])
144 ++firstEmpty;
145 if (firstEmpty < size) {
146 registry[firstEmpty] = ti;
147 ++firstEmpty;
148 } else {
149 registry.append(t: ti);
150 firstEmpty = registry.size();
151 }
152 ti->typeId.storeRelaxed(newValue: firstEmpty + QMetaType::User);
153 }
154 if (ti->legacyRegisterOp)
155 ti->legacyRegisterOp();
156 return ti->typeId.loadRelaxed();
157 }
158
159 void unregisterDynamicType(int id)
160 {
161 if (!id)
162 return;
163 Q_ASSERT(id > QMetaType::User);
164 QWriteLocker l(&lock);
165 int idx = id - QMetaType::User - 1;
166 auto &ti = registry[idx];
167
168 // We must unregister all names.
169 aliases.removeIf(pred: [ti] (const auto &kv) { return kv.value() == ti; });
170
171 ti = nullptr;
172
173 firstEmpty = std::min(a: firstEmpty, b: idx);
174 }
175
176 const QtPrivate::QMetaTypeInterface *getCustomType(int id)
177 {
178 QReadLocker l(&lock);
179 return registry.value(i: id - QMetaType::User - 1);
180 }
181};
182
183Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
184} // namespace
185
186// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE
187// macro (one of them, indetermine which one)
188const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
189{
190 const char *name = nullptr;
191 if (!customTypeRegistry.exists())
192 return name;
193 QMetaTypeCustomRegistry *r = &*customTypeRegistry;
194
195 QByteArrayView officialName(type_d->name);
196 QReadLocker l(&r->lock);
197 auto it = r->aliases.constBegin();
198 auto end = r->aliases.constEnd();
199 for ( ; it != end; ++it) {
200 if (it.value() != type_d)
201 continue;
202 if (it.key() == officialName)
203 continue; // skip the official name
204 name = it.key().constData();
205 ++it;
206 break;
207 }
208
209#ifndef QT_NO_DEBUG
210 QByteArrayList otherNames;
211 for ( ; it != end; ++it) {
212 if (it.value() == type_d && it.key() != officialName)
213 otherNames << it.key();
214 }
215 l.unlock();
216 if (!otherNames.isEmpty())
217 qWarning(msg: "QMetaType: type %s has more than one typedef alias: %s, %s",
218 type_d->name, name, otherNames.join(sep: ", ").constData());
219#endif
220
221 return name;
222}
223#endif // !QT_BOOTSTRAPPED
224
225/*!
226 \macro Q_DECLARE_OPAQUE_POINTER(PointerType)
227 \relates QMetaType
228 \since 5.0
229
230 This macro enables pointers to forward-declared types (\a PointerType)
231 to be registered with QMetaType using either Q_DECLARE_METATYPE()
232 or qRegisterMetaType().
233
234 Do not use this macro to avoid complaints or errors from \l moc about
235 incomplete property types when the pointee type is used as a complete type in
236 other contexts in the program. Use \l{Q_MOC_INCLUDE} instead when
237 the full definition of the type is available, but you prefer a forward
238 declaration in the header to reduce compilation times.
239
240 \warning Don't use Q_DECLARE_OPAQUE_POINTER with pointers to a Q_OBJECT or
241 a gadget class, as that risks introducing inconsistent information in the
242 meta-type system.
243
244 \sa Q_DECLARE_METATYPE(), qRegisterMetaType()
245*/
246
247/*!
248 \macro Q_DECLARE_METATYPE(Type)
249 \relates QMetaType
250
251 This macro makes the type \a Type known to QMetaType as long as it
252 provides a public default constructor, a public copy constructor and
253 a public destructor.
254 It is needed to use the type \a Type as a custom type in QVariant.
255
256 This macro requires that \a Type is a fully defined type at the point where
257 it is used. For pointer types, it also requires that the pointed to type is
258 fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to
259 register pointers to forward declared types.
260
261 Ideally, this macro should be placed below the declaration of
262 the class or struct. If that is not possible, it can be put in
263 a private header file which has to be included every time that
264 type is used in a QVariant.
265
266 Adding a Q_DECLARE_METATYPE() makes the type known to all template
267 based functions, including QVariant. Note that if you intend to
268 use the type in \e queued signal and slot connections or in
269 QObject's property system, you also have to call
270 qRegisterMetaType() since the names are resolved at runtime.
271
272 This example shows a typical use case of Q_DECLARE_METATYPE():
273
274 \snippet code/src_corelib_kernel_qmetatype.cpp 0
275
276 If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
277 has to be outside the namespace:
278
279 \snippet code/src_corelib_kernel_qmetatype.cpp 1
280
281 Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
282
283 \snippet code/src_corelib_kernel_qmetatype.cpp 2
284
285 Some types are registered automatically and do not need this macro:
286
287 \list
288 \li Pointers to classes derived from QObject
289 \li QList<T>, QQueue<T>, QStack<T> or QSet<T>
290 where T is a registered meta type
291 \li QHash<T1, T2>, QMap<T1, T2> or std::pair<T1, T2> where T1 and T2 are
292 registered meta types
293 \li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject
294 \li Enumerations registered with Q_ENUM or Q_FLAG
295 \li Classes that have a Q_GADGET macro
296 \endlist
297
298 \note This method also registers the stream and debug operators for the type if they
299 are visible at registration time. As this is done automatically in some places,
300 it is strongly recommended to declare the stream operators for a type directly
301 after the type itself. Because of the argument dependent lookup rules of C++, it is
302 also strongly recommended to declare the operators in the same namespace as the type itself.
303
304 The stream operators should have the following signatures:
305
306 \snippet code/src_corelib_kernel_qmetatype.cpp 6
307
308 \sa qRegisterMetaType()
309*/
310
311/*!
312 \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container)
313 \relates QMetaType
314
315 This macro makes the container \a Container known to QMetaType as a sequential
316 container. This makes it possible to put an instance of Container<T> into
317 a QVariant, if T itself is known to QMetaType.
318
319 Note that all of the Qt sequential containers already have built-in
320 support, and it is not necessary to use this macro with them. The
321 std::vector and std::list containers also have built-in support.
322
323 This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE():
324
325 \snippet code/src_corelib_kernel_qmetatype.cpp 10
326*/
327
328/*!
329 \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)
330 \relates QMetaType
331
332 This macro makes the container \a Container known to QMetaType as an associative
333 container. This makes it possible to put an instance of Container<T, U> into
334 a QVariant, if T and U are themselves known to QMetaType.
335
336 Note that all of the Qt associative containers already have built-in
337 support, and it is not necessary to use this macro with them. The
338 std::map container also has built-in support.
339
340 This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE():
341
342 \snippet code/src_corelib_kernel_qmetatype.cpp 11
343*/
344
345/*!
346 \macro Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer)
347 \relates QMetaType
348
349 This macro makes the smart pointer \a SmartPointer known to QMetaType as a
350 smart pointer. This makes it possible to put an instance of SmartPointer<T> into
351 a QVariant, if T is a type which inherits QObject.
352
353 Note that the QWeakPointer, QSharedPointer and QPointer already have built-in
354 support, and it is not necessary to use this macro with them.
355
356 This example shows a typical use of Q_DECLARE_SMART_POINTER_METATYPE():
357
358 \snippet code/src_corelib_kernel_qmetatype.cpp 13
359*/
360
361/*!
362 \enum QMetaType::Type
363
364 These are the built-in types supported by QMetaType:
365
366 \value Void \c void
367 \value Bool \c bool
368 \value Int \c int
369 \value UInt \c{unsigned int}
370 \value Double \c double
371 \value QChar QChar
372 \value QString QString
373 \value QByteArray QByteArray
374 \value Nullptr \c{std::nullptr_t}
375
376 \value VoidStar \c{void *}
377 \value Long \c{long}
378 \value LongLong LongLong
379 \value Short \c{short}
380 \value Char \c{char}
381 \value Char16 \c{char16_t}
382 \value Char32 \c{char32_t}
383 \value ULong \c{unsigned long}
384 \value ULongLong ULongLong
385 \value UShort \c{unsigned short}
386 \value SChar \c{signed char}
387 \value UChar \c{unsigned char}
388 \value Float \c float
389 \value Float16 qfloat16
390 \omitvalue Float128
391 \omitvalue BFloat16
392 \omitvalue Int128
393 \omitvalue UInt128
394 \value QObjectStar QObject *
395
396 \value QBitArray QBitArray
397 \value QBitmap QBitmap
398 \value QBrush QBrush
399 \value QByteArrayList QByteArrayList
400 \value QCborArray QCborArray
401 \value QCborMap QCborMap
402 \value QCborSimpleType QCborSimpleType
403 \value QCborValue QCborValue
404 \value QColor QColor
405 \value QColorSpace QColorSpace (introduced in Qt 5.15)
406 \value QCursor QCursor
407 \value QDate QDate
408 \value QDateTime QDateTime
409 \value QEasingCurve QEasingCurve
410 \value QFont QFont
411 \value QIcon QIcon
412 \value QImage QImage
413 \value QJsonArray QJsonArray
414 \value QJsonDocument QJsonDocument
415 \value QJsonObject QJsonObject
416 \value QJsonValue QJsonValue
417 \value QKeySequence QKeySequence
418 \value QLine QLine
419 \value QLineF QLineF
420 \value QLocale QLocale
421 \value QMatrix4x4 QMatrix4x4
422 \value QModelIndex QModelIndex
423 \value QPalette QPalette
424 \value QPen QPen
425 \value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
426 \value QPixmap QPixmap
427 \value QPoint QPoint
428 \value QPointF QPointF
429 \value QPolygon QPolygon
430 \value QPolygonF QPolygonF
431 \value QQuaternion QQuaternion
432 \value QRect QRect
433 \value QRectF QRectF
434 \value QRegion QRegion
435 \value QRegularExpression QRegularExpression
436 \value QSize QSize
437 \value QSizeF QSizeF
438 \value QSizePolicy QSizePolicy
439 \value QStringList QStringList
440 \value QTextFormat QTextFormat
441 \value QTextLength QTextLength
442 \value QTime QTime
443 \value QTransform QTransform
444 \value QUrl QUrl
445 \value QUuid QUuid
446 \value QVariant QVariant
447 \value QVariantHash QVariantHash
448 \value QVariantList QVariantList
449 \value QVariantMap QVariantMap
450 \value QVariantPair QVariantPair
451 \value QVector2D QVector2D
452 \value QVector3D QVector3D
453 \value QVector4D QVector4D
454
455 \value User Base value for user types
456 \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
457
458 Additional types can be registered using qRegisterMetaType() or by calling
459 registerType().
460
461 \sa type()
462*/
463
464/*!
465 \enum QMetaType::TypeFlag
466
467 The enum describes attributes of a type supported by QMetaType.
468
469 \value NeedsConstruction This type has a default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
470 \value [since 6.5] NeedsCopyConstruction This type has a non-trivial copy constructor. If the flag is not set, instances can be copied with memcpy.
471 \value [since 6.5] NeedsMoveConstruction This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
472 \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.
473 \value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
474 \omitvalue MovableType
475 \omitvalue SharedPointerToQObject
476 \value IsEnumeration This type is an enumeration.
477 \value IsUnsignedEnumeration If the type is an Enumeration, its underlying type is unsigned.
478 \value PointerToQObject This type is a pointer to a class derived from QObject.
479 \value IsPointer This type is a pointer to another type.
480 \omitvalue WeakPointerToQObject
481 \omitvalue TrackingPointerToQObject
482 \omitvalue IsGadget \omit (since Qt 5.5) This type is a Q_GADGET and its corresponding QMetaObject can be accessed with QMetaType::metaObject. \endomit
483 \omitvalue PointerToGadget
484 \omitvalue IsQmlList
485 \value IsConst Indicates that values of this type are immutable; for instance, because they are pointers to const objects.
486
487 \note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
488 were incorrectly set if the either copy construtor or destructor were
489 non-trivial (that is, if the type was not trivial).
490
491 Note that the Needs flags may be set but the meta type may not have a
492 publicly-accessible constructor of the relevant type or a
493 publicly-accessible destructor.
494*/
495
496/*!
497 \class QMetaType
498 \inmodule QtCore
499 \brief The QMetaType class manages named types in the meta-object system.
500
501 \ingroup objectmodel
502 \threadsafe
503 \compares equality
504
505 The class is used as a helper to marshall types in QVariant and
506 in queued signals and slots connections. It associates a type
507 name to a type so that it can be created and destructed
508 dynamically at run-time.
509
510 Type names can be registered with QMetaType by using either
511 qRegisterMetaType() or registerType(). Registration is not required for
512 most operations; it's only required for operations that attempt to resolve
513 a type name in string form back to a QMetaType object or the type's ID.
514 Those include some old-style signal-slot connections using
515 QObject::connect(), reading user-types from \l QDataStream to \l QVariant,
516 or binding to other languages and IPC mechanisms, like QML, D-Bus,
517 JavaScript, etc.
518
519 The following code allocates and destructs an instance of \c{MyClass} by
520 its name, which requires that \c{MyClass} have been previously registered:
521
522 \snippet code/src_corelib_kernel_qmetatype.cpp 3
523
524 If we want the stream operators \c operator<<() and \c
525 operator>>() to work on QVariant objects that store custom types,
526 the custom type must provide \c operator<<() and \c operator>>()
527 operators.
528
529 \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
530*/
531
532/*!
533 \fn bool QMetaType::isValid() const
534 \since 5.0
535
536 Returns \c true if this QMetaType object contains valid
537 information about a type, false otherwise.
538
539 \sa isRegistered()
540*/
541
542/*!
543 \fn bool QMetaType::isRegistered() const
544 \since 5.0
545
546 Returns \c true if this QMetaType object has been registered with the Qt
547 global metatype registry. Registration allows the type to be found by its
548 name (using QMetaType::fromName()) or by its ID (using the constructor).
549
550 \sa qRegisterMetaType(), isValid()
551*/
552
553/*!
554 \fn int QMetaType::id() const
555 \since 5.13
556
557 Returns id type held by this QMetatype instance.
558*/
559
560/*!
561 \fn void QMetaType::registerType() const
562 \since 6.5
563
564 Registers this QMetaType with the type registry so it can be found by name,
565 using QMetaType::fromName().
566
567 \sa qRegisterMetaType()
568 */
569#ifndef QT_BOOTSTRAPPED
570/*!
571 \internal
572 Out-of-line path for registerType() and slow path id().
573 */
574int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
575{
576 Q_ASSERT(iface);
577 auto reg = customTypeRegistry();
578 if (reg) {
579 return reg->registerCustomType(cti: iface);
580 }
581 return 0;
582}
583#endif
584
585/*!
586 \fn constexpr qsizetype QMetaType::sizeOf() const
587 \since 5.0
588
589 Returns the size of the type in bytes (i.e. sizeof(T),
590 where T is the actual type for which this QMetaType instance
591 was constructed for).
592
593 This function is typically used together with construct()
594 to perform low-level management of the memory used by a type.
595
596 \sa QMetaType::construct(), QMetaType::alignOf()
597*/
598
599/*!
600 \fn constexpr int QMetaType::alignOf() const
601 \since 6.0
602
603 Returns the alignment of the type in bytes (i.e. alignof(T),
604 where T is the actual type for which this QMetaType instance
605 was constructed for).
606
607 This function is typically used together with construct()
608 to perform low-level management of the memory used by a type.
609
610 \sa QMetaType::construct(), QMetaType::sizeOf()
611
612 */
613
614/*!
615 \fn constexpr TypeFlags QMetaType::flags() const
616 \since 5.0
617
618 Returns flags of the type for which this QMetaType instance was
619 constructed. To inspect specific type traits, prefer using one of the "is-"
620 functions rather than the flags directly.
621
622 \sa QMetaType::TypeFlags, isDefaultConstructible(),
623 isCopyConstructible(), isMoveConstructible(), isDestructible(),
624 isEqualityComparable(), isOrdered()
625*/
626
627/*!
628 \fn constexpr const QMetaObject *QMetaType::metaObject() const
629 \since 5.5
630
631 Returns a QMetaObject relative to this type.
632
633 If the type is a pointer type to a subclass of QObject, flags() contains
634 QMetaType::PointerToQObject and this function returns the corresponding QMetaObject.
635 This can be used in combination with QMetaObject::newInstance() to create QObjects of this type.
636
637 If the type is a Q_GADGET, flags() contains QMetaType::IsGadget.
638 If the type is a pointer to a Q_GADGET, flags() contains QMetaType::PointerToGadget.
639 In both cases, this function returns its QMetaObject.
640 This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
641 pointer of this type for example, as given by QVariant::data().
642
643 If the type is an enumeration, flags() contains QMetaType::IsEnumeration.
644 In this case, this function returns the QMetaObject of the enclosing
645 object if the enum was registered as a Q_ENUM or \nullptr otherwise.
646
647 \sa QMetaType::flags()
648*/
649
650/*!
651 \fn void *QMetaType::create(const void *copy = nullptr) const
652 \since 5.0
653
654 Returns a copy of \a copy, assuming it is of the type that this
655 QMetaType instance was created for. If \a copy is \nullptr, creates
656 a default constructed instance.
657
658 \sa QMetaType::destroy()
659*/
660void *QMetaType::create(const void *copy) const
661{
662 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
663 return nullptr;
664
665 std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {.iface: d_ptr});
666 if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
667 where.reset(p: operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)));
668 else
669 where.reset(p: operator new(d_ptr->size));
670
671 QtMetaTypePrivate::construct(iface: d_ptr, where: where.get(), copy);
672 return where.release();
673}
674
675/*!
676 \fn void QMetaType::destroy(void *data) const
677 \since 5.0
678
679 Destroys the \a data, assuming it is of the type that this
680 QMetaType instance was created for.
681
682 \sa QMetaType::create()
683*/
684void QMetaType::destroy(void *data) const
685{
686 if (data && isDestructible()) {
687 QtMetaTypePrivate::destruct(iface: d_ptr, where: data);
688 QMetaTypeDeleter{.iface: d_ptr}(data);
689 }
690}
691
692/*!
693 \fn void *QMetaType::construct(void *where, const void *copy = nullptr) const
694 \since 5.0
695
696 Constructs a value of the type that this QMetaType instance
697 was constructed for in the existing memory addressed by \a where,
698 that is a copy of \a copy, and returns \a where. If \a copy is
699 zero, the value is default constructed.
700
701 This is a low-level function for explicitly managing the memory
702 used to store the type. Consider calling create() if you don't
703 need this level of control (that is, use "new" rather than
704 "placement new").
705
706 You must ensure that \a where points to a location where the new
707 value can be stored and that \a where is suitably aligned.
708 The type's size can be queried by calling sizeOf().
709
710 The rule of thumb for alignment is that a type is aligned to its
711 natural boundary, which is the smallest power of 2 that is bigger
712 than the type, unless that alignment is larger than the maximum
713 useful alignment for the platform. For practical purposes,
714 alignment larger than 2 * sizeof(void*) is only necessary for
715 special hardware instructions (e.g., aligned SSE loads and stores
716 on x86).
717*/
718void *QMetaType::construct(void *where, const void *copy) const
719{
720 if (!where)
721 return nullptr;
722 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
723 return nullptr;
724
725 QtMetaTypePrivate::construct(iface: d_ptr, where, copy);
726 return where;
727}
728
729/*!
730 \fn void QMetaType::destruct(void *data) const
731 \since 5.0
732
733 Destructs the value, located at \a data, assuming that it is
734 of the type for which this QMetaType instance was constructed for.
735
736 Unlike destroy(), this function only invokes the type's
737 destructor, it doesn't invoke the delete operator.
738 \sa QMetaType::construct()
739*/
740void QMetaType::destruct(void *data) const
741{
742 if (data && isDestructible())
743 QtMetaTypePrivate::destruct(iface: d_ptr, where: data);
744}
745
746static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
747{
748 std::less<const void *> less;
749 if (less(ptr1, ptr2))
750 return QPartialOrdering::Less;
751 if (less(ptr2, ptr1))
752 return QPartialOrdering::Greater;
753 return QPartialOrdering::Equivalent;
754}
755
756/*!
757 Compares the objects at \a lhs and \a rhs for ordering.
758
759 Returns QPartialOrdering::Unordered if comparison is not supported
760 or the values are unordered. Otherwise, returns
761 QPartialOrdering::Less, QPartialOrdering::Equivalent or
762 QPartialOrdering::Greater if \a lhs is less than, equivalent
763 to or greater than \a rhs, respectively.
764
765 Both objects must be of the type described by this metatype. If either \a lhs
766 or \a rhs is \nullptr, the values are unordered. Comparison is only supported
767 if the type's less than operator was visible to the metatype declaration.
768
769 If the type's equality operator was also visible, values will only compare equal if the
770 equality operator says they are. In the absence of an equality operator, when neither
771 value is less than the other, values are considered equal; if equality is also available
772 and two such values are not equal, they are considered unordered, just as NaN (not a
773 number) values of a floating point type lie outside its ordering.
774
775 \note If no less than operator was visible to the metatype declaration, values are
776 unordered even if an equality operator visible to the declaration considers them equal:
777 \c{compare() == 0} only agrees with equals() if the less than operator was visible.
778
779 \since 6.0
780 \sa equals(), isOrdered()
781*/
782QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
783{
784 if (!lhs || !rhs)
785 return QPartialOrdering::Unordered;
786 if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
787 return threeWayCompare(ptr1: *reinterpret_cast<const void * const *>(lhs),
788 ptr2: *reinterpret_cast<const void * const *>(rhs));
789 if (d_ptr && d_ptr->lessThan) {
790 if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
791 return QPartialOrdering::Equivalent;
792 if (d_ptr->lessThan(d_ptr, lhs, rhs))
793 return QPartialOrdering::Less;
794 if (d_ptr->lessThan(d_ptr, rhs, lhs))
795 return QPartialOrdering::Greater;
796 if (!d_ptr->equals)
797 return QPartialOrdering::Equivalent;
798 }
799 return QPartialOrdering::Unordered;
800}
801
802/*!
803 Compares the objects at \a lhs and \a rhs for equality.
804
805 Both objects must be of the type described by this metatype. Can only compare the
806 two objects if a less than or equality operator for the type was visible to the
807 metatype declaration. Otherwise, the metatype never considers values equal. When
808 an equality operator was visible to the metatype declaration, it is authoritative;
809 otherwise, if less than is visible, when neither value is less than the other, the
810 two are considered equal. If values are unordered (see compare() for details) they
811 are not equal.
812
813 Returns true if the two objects compare equal, otherwise false.
814
815 \since 6.0
816 \sa isEqualityComparable(), compare()
817*/
818bool QMetaType::equals(const void *lhs, const void *rhs) const
819{
820 if (!lhs || !rhs)
821 return false;
822 if (d_ptr) {
823 if (d_ptr->flags & QMetaType::IsPointer)
824 return *reinterpret_cast<const void * const *>(lhs) == *reinterpret_cast<const void * const *>(rhs);
825
826 if (d_ptr->equals)
827 return d_ptr->equals(d_ptr, lhs, rhs);
828 if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
829 return true;
830 }
831 return false;
832}
833
834/*!
835 \fn bool QMetaType::isDefaultConstructible() const noexcept
836 \since 6.5
837
838 Returns true if this type can be default-constructed. If it can be, then
839 construct() and create() can be used with a \c{copy} parameter that is
840 null.
841
842 \sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
843 */
844
845/*!
846 \fn bool QMetaType::isCopyConstructible() const noexcept
847 \since 6.5
848
849 Returns true if this type can be copy-constructed. If it can be, then
850 construct() and create() can be used with a \c{copy} parameter that is
851 not null.
852
853 \sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
854 */
855
856/*!
857 \fn bool QMetaType::isMoveConstructible() const noexcept
858 \since 6.5
859
860 Returns true if this type can be move-constructed. QMetaType currently does
861 not have an API to make use of this trait.
862
863 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
864 */
865
866/*!
867 \fn bool QMetaType::isDestructible() const noexcept
868 \since 6.5
869
870 Returns true if this type can be destroyed. If it can be, then destroy()
871 and destruct() can be called.
872
873 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
874 */
875
876bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
877{
878 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
879}
880
881bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
882{
883 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
884}
885
886bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
887{
888 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
889}
890
891bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
892{
893 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
894}
895
896/*!
897 Returns \c true if a less than or equality operator for the type described by
898 this metatype was visible to the metatype declaration, otherwise \c false.
899
900 \sa equals(), isOrdered()
901*/
902bool QMetaType::isEqualityComparable() const
903{
904 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
905}
906
907/*!
908 Returns \c true if a less than operator for the type described by this metatype
909 was visible to the metatype declaration, otherwise \c false.
910
911 \sa compare(), isEqualityComparable()
912*/
913bool QMetaType::isOrdered() const
914{
915 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
916}
917
918#ifndef QT_BOOTSTRAPPED
919/*!
920 \internal
921*/
922void QMetaType::unregisterMetaType(QMetaType type)
923{
924 const QtPrivate::QMetaTypeInterface *d_ptr = type.d_ptr;
925 if (!d_ptr)
926 return;
927
928 const int typeId = d_ptr->typeId.loadRelaxed();
929 if (typeId < QMetaType::User)
930 return;
931
932 // this is a custom meta type (not read-only)
933
934 if (auto reg = customTypeRegistry()) {
935 Q_ASSERT(reg->getCustomType(typeId) == d_ptr);
936 reg->unregisterDynamicType(id: typeId);
937 }
938
939 const_cast<QtPrivate::QMetaTypeInterface *>(d_ptr)->typeId.storeRelease(newValue: 0);
940}
941#endif
942
943/*!
944 \fn template<typename T> QMetaType QMetaType::fromType()
945 \since 5.15
946
947 Returns the QMetaType corresponding to the type in the template parameter.
948*/
949
950/*! \fn bool QMetaType::operator==(const QMetaType &lhs, const QMetaType &rhs)
951 \since 5.15
952 \overload
953
954 Returns \c true if the QMetaType \a lhs represents the same type
955 as the QMetaType \a rhs, otherwise returns \c false.
956*/
957
958/*! \fn bool QMetaType::operator!=(const QMetaType &lhs, const QMetaType &rhs)
959 \since 5.15
960 \overload
961
962 Returns \c true if the QMetaType \a lhs represents a different type
963 than the QMetaType \a rhs, otherwise returns \c false.
964*/
965
966/*! \internal */
967bool QMetaTypeModuleHelper::convert(const void *, int, void *, int) const
968{
969 return false;
970}
971
972static constexpr auto createStaticTypeToIdMap()
973{
974#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
975 #RealName,
976#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
977 RealNameStr,
978 constexpr auto staticTypeNames = qOffsetStringArray(
979 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
980 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
981 strings: "qreal"
982 );
983 constexpr int Count = staticTypeNames.count();
984#undef QT_ADD_STATIC_METATYPE
985#undef QT_ADD_STATIC_METATYPE_ALIASES_ITER
986
987#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
988 MetaTypeId,
989#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
990 QMetaType::MetaTypeName,
991 std::array<int, Count> typeIds = {
992 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
993 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
994 QMetaTypeId2<qreal>::MetaType,
995 };
996#undef QT_ADD_STATIC_METATYPE
997#undef QT_ADD_STATIC_METATYPE_ALIASES_ITER
998
999 using Base = std::remove_cv_t<decltype(staticTypeNames)>;
1000 using Array = std::remove_cv_t<decltype(typeIds)>;
1001 struct Map : Base {
1002 constexpr Map(const Base &base, const Array &typeIdMap)
1003 : Base(base), typeIdMap(typeIdMap)
1004 {}
1005 std::array<int, Count> typeIdMap;
1006 };
1007
1008 return Map(staticTypeNames, typeIds);
1009}
1010static constexpr auto types = createStaticTypeToIdMap();
1011
1012template <typename From, typename To>
1013static bool qIntegerConversionFromFPHelper(From from, To *to)
1014{
1015#ifndef Q_CC_GHS
1016 // actually is_floating_point, but include qfloat16:
1017 static_assert(std::numeric_limits<From>::is_iec559);
1018#endif
1019 static_assert(std::is_integral_v<To>);
1020 static_assert(sizeof(From) <= sizeof(double));
1021 const double fromD = static_cast<double>(from);
1022
1023 if (qt_is_nan(d: fromD)) {
1024 *to = To(0);
1025 return false;
1026 }
1027
1028 qint64 result;
1029 convertDoubleTo(v: std::round(x: fromD), value: &result);
1030 *to = To(result);
1031 return true;
1032}
1033
1034// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
1035static constexpr struct : QMetaTypeModuleHelper
1036{
1037 template<typename T, typename LiteralWrapper =
1038 std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
1039 static inline bool convertToBool(const T &source)
1040 {
1041 T str = source.toLower();
1042 return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
1043 }
1044
1045 const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
1046 switch (type) {
1047 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
1048 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
1049 QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
1050 QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
1051 QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
1052 default:
1053 return nullptr;
1054 }
1055 }
1056
1057#ifndef QT_BOOTSTRAPPED
1058 bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override
1059 {
1060 Q_ASSERT(fromTypeId != toTypeId);
1061
1062 // canConvert calls with two nullptr
1063 bool onlyCheck = (from == nullptr && to == nullptr);
1064
1065 // other callers must provide two valid pointers
1066 Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
1067
1068 using Char = char;
1069 using SChar = signed char;
1070 using UChar = unsigned char;
1071 using Short = short;
1072 using UShort = unsigned short;
1073 using Int = int;
1074 using UInt = unsigned int;
1075 using Long = long;
1076 using LongLong = qlonglong;
1077 using ULong = unsigned long;
1078 using ULongLong = qulonglong;
1079 using Float16 = qfloat16;
1080 using Float = float;
1081 using Double = double;
1082 using Bool = bool;
1083 using Nullptr = std::nullptr_t;
1084 using Char16 = char16_t;
1085 using Char32 = char32_t;
1086
1087#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From) \
1088 QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
1089#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From) \
1090 QMETATYPE_CONVERTER(To, From, result = To::number(source); return true;)
1091#define CONVERT_CBOR_AND_JSON(To) \
1092 QMETATYPE_CONVERTER(To, QCborValue, \
1093 if constexpr(std::is_same_v<To, Bool>) { \
1094 if (!source.isBool()) \
1095 return false; \
1096 result = source.toBool(); \
1097 } else { \
1098 if (!source.isInteger() && !source.isDouble()) \
1099 return false; \
1100 if constexpr(std::is_integral_v<To>) \
1101 result = source.toInteger(); \
1102 else \
1103 result = To(source.toDouble()); \
1104 } \
1105 return true; \
1106 ); \
1107 QMETATYPE_CONVERTER(To, QJsonValue, \
1108 if constexpr(std::is_same_v<To, Bool>) { \
1109 if (!source.isBool()) \
1110 return false; \
1111 result = source.toBool(); \
1112 } else { \
1113 if (!source.isDouble()) \
1114 return false; \
1115 if constexpr(std::is_integral_v<To>) \
1116 result = source.toInteger(); \
1117 else \
1118 result = To(source.toDouble()); \
1119 } \
1120 return true; \
1121 )
1122
1123#define INTEGRAL_CONVERTER(To) \
1124 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1125 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1126 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1127 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1128 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1129 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1130 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1131 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1132 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1133 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1134 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1135 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1136 QMETATYPE_CONVERTER(To, Float16, return qIntegerConversionFromFPHelper(source, &result);); \
1137 QMETATYPE_CONVERTER(To, Float, return qIntegerConversionFromFPHelper(source, &result);); \
1138 QMETATYPE_CONVERTER(To, Double, return qIntegerConversionFromFPHelper(source, &result);); \
1139 QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \
1140 QMETATYPE_CONVERTER(To, QString, \
1141 bool ok = false; \
1142 if constexpr(std::is_same_v<To, bool>) \
1143 result = (ok = true, convertToBool(source)); \
1144 else if constexpr(std::is_signed_v<To>) \
1145 result = To(source.toLongLong(&ok)); \
1146 else \
1147 result = To(source.toULongLong(&ok)); \
1148 return ok; \
1149 ); \
1150 QMETATYPE_CONVERTER(To, QByteArray, \
1151 bool ok = false; \
1152 if constexpr(std::is_same_v<To, bool>) \
1153 result = (ok = true, convertToBool(source)); \
1154 else if constexpr(std::is_signed_v<To>) \
1155 result = To(source.toLongLong(&ok)); \
1156 else \
1157 result = To(source.toULongLong(&ok)); \
1158 return ok; \
1159 ); \
1160 CONVERT_CBOR_AND_JSON(To)
1161
1162#define FLOAT_CONVERTER(To) \
1163 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1164 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1165 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1166 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1167 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1168 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1169 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1170 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1171 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1172 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1173 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1174 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1175 QMETATYPE_CONVERTER_ASSIGN(To, Float16); \
1176 QMETATYPE_CONVERTER_ASSIGN(To, Float); \
1177 QMETATYPE_CONVERTER_ASSIGN(To, Double); \
1178 QMETATYPE_CONVERTER(To, QString, \
1179 bool ok = false; \
1180 result = To(source.toDouble(&ok)); \
1181 return ok; \
1182 ); \
1183 QMETATYPE_CONVERTER(To, QByteArray, \
1184 bool ok = false; \
1185 result = To(source.toDouble(&ok)); \
1186 return ok; \
1187 ); \
1188 CONVERT_CBOR_AND_JSON(To)
1189
1190 switch (makePair(from: toTypeId, to: fromTypeId)) {
1191QT_WARNING_PUSH
1192QT_WARNING_DISABLE_CLANG("-Wtautological-compare")
1193 // integral conversions
1194 INTEGRAL_CONVERTER(Bool);
1195 INTEGRAL_CONVERTER(Char);
1196 INTEGRAL_CONVERTER(UChar);
1197 INTEGRAL_CONVERTER(SChar);
1198 INTEGRAL_CONVERTER(Short);
1199 INTEGRAL_CONVERTER(UShort);
1200 INTEGRAL_CONVERTER(Int);
1201 INTEGRAL_CONVERTER(UInt);
1202 INTEGRAL_CONVERTER(Long);
1203 INTEGRAL_CONVERTER(ULong);
1204 INTEGRAL_CONVERTER(LongLong);
1205 INTEGRAL_CONVERTER(ULongLong);
1206 FLOAT_CONVERTER(Float16);
1207 FLOAT_CONVERTER(Float);
1208 FLOAT_CONVERTER(Double);
1209
1210 QMETATYPE_CONVERTER_ASSIGN(QUrl, QString);
1211 QMETATYPE_CONVERTER(QUrl, QCborValue,
1212 if (source.isUrl()) {
1213 result = source.toUrl();
1214 return true;
1215 }
1216 return false;
1217 );
1218#if QT_CONFIG(itemmodel)
1219 QMETATYPE_CONVERTER_ASSIGN(QModelIndex, QPersistentModelIndex);
1220 QMETATYPE_CONVERTER_ASSIGN(QPersistentModelIndex, QModelIndex);
1221#endif // QT_CONFIG(itemmodel)
1222
1223 // QChar methods
1224#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From) \
1225 QMETATYPE_CONVERTER(QChar, From, result = QChar::fromUcs2(source); return true;)
1226 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char);
1227 QMETATYPE_CONVERTER_ASSIGN_QCHAR(SChar);
1228 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Short);
1229 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Long);
1230 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Int);
1231 QMETATYPE_CONVERTER_ASSIGN_QCHAR(LongLong);
1232 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Float);
1233 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UChar);
1234 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UShort);
1235 QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULong);
1236 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UInt);
1237 QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULongLong);
1238 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char16);
1239
1240 QMETATYPE_CONVERTER(Char16, QChar, result = source.unicode(); return true;)
1241
1242 // conversions to QString
1243 QMETATYPE_CONVERTER_ASSIGN(QString, QChar);
1244 QMETATYPE_CONVERTER(QString, Bool,
1245 result = source ? QStringLiteral("true") : QStringLiteral("false");
1246 return true;
1247 );
1248 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Short);
1249 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Long);
1250 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Int);
1251 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, LongLong);
1252 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UShort);
1253 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong);
1254 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt);
1255 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong);
1256 QMETATYPE_CONVERTER(QString, Float16,
1257 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1258 return true;
1259 );
1260 QMETATYPE_CONVERTER(QString, Float,
1261 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1262 return true;
1263 );
1264 QMETATYPE_CONVERTER(QString, Double,
1265 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1266 return true;
1267 );
1268 QMETATYPE_CONVERTER(QString, Char,
1269 result = QString::fromLatin1(&source, 1);
1270 return true;
1271 );
1272 QMETATYPE_CONVERTER(QString, SChar,
1273 char s = source;
1274 result = QString::fromLatin1(&s, 1);
1275 return true;
1276 );
1277 QMETATYPE_CONVERTER(QString, UChar,
1278 char s = source;
1279 result = QString::fromLatin1(&s, 1);
1280 return true;
1281 );
1282 QMETATYPE_CONVERTER(QString, Char16,
1283 result = QChar(source);
1284 return true;
1285 );
1286 QMETATYPE_CONVERTER(QString, Char32,
1287 result = QChar::fromUcs4(source).operator QStringView().toString();
1288 return true;
1289 );
1290#if QT_CONFIG(datestring)
1291 QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
1292 QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
1293 QMETATYPE_CONVERTER(QString, QDateTime, result = source.toString(Qt::ISODateWithMs); return true;);
1294#endif
1295 QMETATYPE_CONVERTER(QString, QByteArray, result = QString::fromUtf8(source); return true;);
1296 QMETATYPE_CONVERTER(QString, QStringList,
1297 return (source.size() == 1) ? (result = source.at(0), true) : false;
1298 );
1299 QMETATYPE_CONVERTER(QString, QUrl, result = source.toString(); return true;);
1300 QMETATYPE_CONVERTER(QString, QJsonValue,
1301 if (source.isString() || source.isNull()) {
1302 result = source.toString();
1303 return true;
1304 }
1305 return false;
1306 );
1307 QMETATYPE_CONVERTER(QString, Nullptr, Q_UNUSED(source); result = QString(); return true;);
1308
1309 // QByteArray
1310 QMETATYPE_CONVERTER(QByteArray, QString, result = source.toUtf8(); return true;);
1311 QMETATYPE_CONVERTER(QByteArray, Bool,
1312 result = source ? "true" : "false";
1313 return true;
1314 );
1315 QMETATYPE_CONVERTER(QByteArray, Char, result = QByteArray(source, 1); return true;);
1316 QMETATYPE_CONVERTER(QByteArray, SChar, result = QByteArray(source, 1); return true;);
1317 QMETATYPE_CONVERTER(QByteArray, UChar, result = QByteArray(source, 1); return true;);
1318 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Short);
1319 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Long);
1320 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Int);
1321 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, LongLong);
1322 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UShort);
1323 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong);
1324 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt);
1325 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong);
1326 QMETATYPE_CONVERTER(QByteArray, Float16,
1327 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1328 return true;
1329 );
1330 QMETATYPE_CONVERTER(QByteArray, Float,
1331 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1332 return true;
1333 );
1334 QMETATYPE_CONVERTER(QByteArray, Double,
1335 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1336 return true;
1337 );
1338 QMETATYPE_CONVERTER(QByteArray, Nullptr, Q_UNUSED(source); result = QByteArray(); return true;);
1339
1340 QMETATYPE_CONVERTER(QString, QUuid, result = source.toString(); return true;);
1341 QMETATYPE_CONVERTER(QUuid, QString, result = QUuid(source); return true;);
1342 QMETATYPE_CONVERTER(QByteArray, QUuid, result = source.toByteArray(); return true;);
1343 QMETATYPE_CONVERTER(QUuid, QByteArray, result = QUuid(source); return true;);
1344
1345 QMETATYPE_CONVERTER(QSize, QSizeF, result = source.toSize(); return true;);
1346 QMETATYPE_CONVERTER_ASSIGN(QSizeF, QSize);
1347 QMETATYPE_CONVERTER(QLine, QLineF, result = source.toLine(); return true;);
1348 QMETATYPE_CONVERTER_ASSIGN(QLineF, QLine);
1349 QMETATYPE_CONVERTER(QRect, QRectF, result = source.toRect(); return true;);
1350 QMETATYPE_CONVERTER_ASSIGN(QRectF, QRect);
1351 QMETATYPE_CONVERTER(QPoint, QPointF, result = source.toPoint(); return true;);
1352 QMETATYPE_CONVERTER_ASSIGN(QPointF, QPoint);
1353
1354 QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
1355
1356 QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
1357 result.reserve(source.size());
1358 for (const auto &v: source)
1359 result.append(v.toByteArray());
1360 return true;
1361 );
1362 QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
1363 result.reserve(source.size());
1364 for (const auto &v: source)
1365 result.append(QVariant(v));
1366 return true;
1367 );
1368
1369 QMETATYPE_CONVERTER(QStringList, QVariantList,
1370 result.reserve(source.size());
1371 for (const auto &v: source)
1372 result.append(v.toString());
1373 return true;
1374 );
1375 QMETATYPE_CONVERTER(QVariantList, QStringList,
1376 result.reserve(source.size());
1377 for (const auto &v: source)
1378 result.append(QVariant(v));
1379 return true;
1380 );
1381
1382 QMETATYPE_CONVERTER(QVariantHash, QVariantMap,
1383 for (auto it = source.begin(); it != source.end(); ++it)
1384 result.insert(it.key(), it.value());
1385 return true;
1386 );
1387 QMETATYPE_CONVERTER(QVariantMap, QVariantHash,
1388 for (auto it = source.begin(); it != source.end(); ++it)
1389 result.insert(it.key(), it.value());
1390 return true;
1391 );
1392 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QString);
1393 QMETATYPE_CONVERTER(QString, QCborValue,
1394 if (source.isContainer() || source.isTag())
1395 return false;
1396 result = source.toVariant().toString();
1397 return true;
1398 );
1399 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QByteArray);
1400 QMETATYPE_CONVERTER(QByteArray, QCborValue,
1401 if (source.isByteArray()) {
1402 result = source.toByteArray();
1403 return true;
1404 }
1405 return false;
1406 );
1407 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUuid);
1408 QMETATYPE_CONVERTER(QUuid, QCborValue,
1409 if (!source.isUuid())
1410 return false;
1411 result = source.toUuid();
1412 return true;
1413 );
1414 QMETATYPE_CONVERTER(QCborValue, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1415 QMETATYPE_CONVERTER(QVariantList, QCborValue,
1416 if (!source.isArray())
1417 return false;
1418 result = source.toArray().toVariantList();
1419 return true;
1420 );
1421 QMETATYPE_CONVERTER(QCborValue, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1422 QMETATYPE_CONVERTER(QVariantMap, QCborValue,
1423 if (!source.isMap())
1424 return false;
1425 result = source.toMap().toVariantMap();
1426 return true;
1427 );
1428 QMETATYPE_CONVERTER(QCborValue, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1429 QMETATYPE_CONVERTER(QVariantHash, QCborValue,
1430 if (!source.isMap())
1431 return false;
1432 result = source.toMap().toVariantHash();
1433 return true;
1434 );
1435#if QT_CONFIG(regularexpression)
1436 QMETATYPE_CONVERTER(QCborValue, QRegularExpression, result = QCborValue(source); return true;);
1437 QMETATYPE_CONVERTER(QRegularExpression, QCborValue,
1438 if (!source.isRegularExpression())
1439 return false;
1440 result = source.toRegularExpression();
1441 return true;
1442 );
1443#endif
1444
1445 QMETATYPE_CONVERTER(QCborValue, Nullptr,
1446 Q_UNUSED(source);
1447 result = QCborValue(QCborValue::Null);
1448 return true;
1449 );
1450 QMETATYPE_CONVERTER(Nullptr, QCborValue,
1451 result = nullptr;
1452 return source.isNull();
1453 );
1454 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Bool);
1455 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Int);
1456 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UInt);
1457 QMETATYPE_CONVERTER(QCborValue, ULong, result = qlonglong(source); return true;);
1458 QMETATYPE_CONVERTER(QCborValue, Long, result = qlonglong(source); return true;);
1459 QMETATYPE_CONVERTER_ASSIGN(QCborValue, LongLong);
1460 QMETATYPE_CONVERTER(QCborValue, ULongLong, result = qlonglong(source); return true;);
1461 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UShort);
1462 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UChar);
1463 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Char);
1464 QMETATYPE_CONVERTER_ASSIGN(QCborValue, SChar);
1465 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short);
1466 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Double);
1467 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float);
1468 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float16);
1469 QMETATYPE_CONVERTER(QCborValue, QStringList,
1470 result = QCborArray::fromStringList(source);
1471 return true;
1472 );
1473#if QT_CONFIG(datestring)
1474 QMETATYPE_CONVERTER(QCborValue, QDate,
1475 result = QCborValue(source.startOfDay());
1476 return true;
1477 );
1478#endif
1479 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUrl);
1480 QMETATYPE_CONVERTER(QCborValue, QJsonValue,
1481 result = QCborValue::fromJsonValue(source);
1482 return true;
1483 );
1484 QMETATYPE_CONVERTER(QCborValue, QJsonObject,
1485 result = QCborMap::fromJsonObject(source);
1486 return true;
1487 );
1488 QMETATYPE_CONVERTER(QCborValue, QJsonArray,
1489 result = QCborArray::fromJsonArray(source);
1490 return true;
1491 );
1492 QMETATYPE_CONVERTER(QCborValue, QJsonDocument,
1493 QJsonDocument doc = source;
1494 if (doc.isArray())
1495 result = QCborArray::fromJsonArray(doc.array());
1496 else
1497 result = QCborMap::fromJsonObject(doc.object());
1498 return true;
1499 );
1500 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborMap);
1501 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborArray);
1502
1503#if QT_CONFIG(datestring)
1504 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QDateTime);
1505 QMETATYPE_CONVERTER(QDateTime, QCborValue,
1506 if (source.isDateTime()) {
1507 result = source.toDateTime();
1508 return true;
1509 }
1510 return false;
1511 );
1512#endif
1513
1514 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborSimpleType);
1515 QMETATYPE_CONVERTER(QCborSimpleType, QCborValue,
1516 if (source.isSimpleType()) {
1517 result = source.toSimpleType();
1518 return true;
1519 }
1520 return false;
1521 );
1522
1523 QMETATYPE_CONVERTER(QCborArray, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1524 QMETATYPE_CONVERTER(QVariantList, QCborArray, result = source.toVariantList(); return true;);
1525 QMETATYPE_CONVERTER(QCborArray, QStringList, result = QCborArray::fromStringList(source); return true;);
1526 QMETATYPE_CONVERTER(QCborMap, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1527 QMETATYPE_CONVERTER(QVariantMap, QCborMap, result = source.toVariantMap(); return true;);
1528 QMETATYPE_CONVERTER(QCborMap, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1529 QMETATYPE_CONVERTER(QVariantHash, QCborMap, result = source.toVariantHash(); return true;);
1530
1531 QMETATYPE_CONVERTER(QCborArray, QCborValue,
1532 if (!source.isArray())
1533 return false;
1534 result = source.toArray();
1535 return true;
1536 );
1537 QMETATYPE_CONVERTER(QCborArray, QJsonDocument,
1538 if (!source.isArray())
1539 return false;
1540 result = QCborArray::fromJsonArray(source.array());
1541 return true;
1542 );
1543 QMETATYPE_CONVERTER(QCborArray, QJsonValue,
1544 if (!source.isArray())
1545 return false;
1546 result = QCborArray::fromJsonArray(source.toArray());
1547 return true;
1548 );
1549 QMETATYPE_CONVERTER(QCborArray, QJsonArray,
1550 result = QCborArray::fromJsonArray(source);
1551 return true;
1552 );
1553 QMETATYPE_CONVERTER(QCborMap, QCborValue,
1554 if (!source.isMap())
1555 return false;
1556 result = source.toMap();
1557 return true;
1558 );
1559 QMETATYPE_CONVERTER(QCborMap, QJsonDocument,
1560 if (source.isArray())
1561 return false;
1562 result = QCborMap::fromJsonObject(source.object());
1563 return true;
1564 );
1565 QMETATYPE_CONVERTER(QCborMap, QJsonValue,
1566 if (!source.isObject())
1567 return false;
1568 result = QCborMap::fromJsonObject(source.toObject());
1569 return true;
1570 );
1571 QMETATYPE_CONVERTER(QCborMap, QJsonObject,
1572 result = QCborMap::fromJsonObject(source);
1573 return true;
1574 );
1575
1576
1577 QMETATYPE_CONVERTER(QVariantList, QJsonValue,
1578 if (!source.isArray())
1579 return false;
1580 result = source.toArray().toVariantList();
1581 return true;
1582 );
1583 QMETATYPE_CONVERTER(QVariantList, QJsonArray, result = source.toVariantList(); return true;);
1584 QMETATYPE_CONVERTER(QVariantMap, QJsonValue,
1585 if (!source.isObject())
1586 return false;
1587 result = source.toObject().toVariantMap();
1588 return true;
1589 );
1590 QMETATYPE_CONVERTER(QVariantMap, QJsonObject, result = source.toVariantMap(); return true;);
1591 QMETATYPE_CONVERTER(QVariantHash, QJsonValue,
1592 if (!source.isObject())
1593 return false;
1594 result = source.toObject().toVariantHash();
1595 return true;
1596 );
1597 QMETATYPE_CONVERTER(QVariantHash, QJsonObject, result = source.toVariantHash(); return true;);
1598
1599
1600 QMETATYPE_CONVERTER(QJsonArray, QStringList, result = QJsonArray::fromStringList(source); return true;);
1601 QMETATYPE_CONVERTER(QJsonArray, QVariantList, result = QJsonArray::fromVariantList(source); return true;);
1602 QMETATYPE_CONVERTER(QJsonArray, QJsonValue,
1603 if (!source.isArray())
1604 return false;
1605 result = source.toArray();
1606 return true;
1607 );
1608 QMETATYPE_CONVERTER(QJsonArray, QJsonDocument,
1609 if (!source.isArray())
1610 return false;
1611 result = source.array();
1612 return true;
1613 );
1614 QMETATYPE_CONVERTER(QJsonArray, QCborValue,
1615 if (!source.isArray())
1616 return false;
1617 result = source.toArray().toJsonArray();
1618 return true;
1619 );
1620 QMETATYPE_CONVERTER(QJsonArray, QCborArray, result = source.toJsonArray(); return true;);
1621 QMETATYPE_CONVERTER(QJsonObject, QVariantMap, result = QJsonObject::fromVariantMap(source); return true;);
1622 QMETATYPE_CONVERTER(QJsonObject, QVariantHash, result = QJsonObject::fromVariantHash(source); return true;);
1623 QMETATYPE_CONVERTER(QJsonObject, QJsonValue,
1624 if (!source.isObject())
1625 return false;
1626 result = source.toObject();
1627 return true;
1628 );
1629 QMETATYPE_CONVERTER(QJsonObject, QJsonDocument,
1630 if (source.isArray())
1631 return false;
1632 result = source.object();
1633 return true;
1634 );
1635 QMETATYPE_CONVERTER(QJsonObject, QCborValue,
1636 if (!source.isMap())
1637 return false;
1638 result = source.toMap().toJsonObject();
1639 return true;
1640 );
1641 QMETATYPE_CONVERTER(QJsonObject, QCborMap, result = source.toJsonObject(); return true; );
1642
1643 QMETATYPE_CONVERTER(QJsonValue, Nullptr,
1644 Q_UNUSED(source);
1645 result = QJsonValue(QJsonValue::Null);
1646 return true;
1647 );
1648 QMETATYPE_CONVERTER(Nullptr, QJsonValue,
1649 result = nullptr;
1650 return source.isNull();
1651 );
1652 QMETATYPE_CONVERTER(QJsonValue, Bool,
1653 result = QJsonValue(source);
1654 return true;);
1655 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Int);
1656 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt);
1657 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double);
1658 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float);
1659 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float16);
1660 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong);
1661 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long);
1662 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong);
1663 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULongLong);
1664 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UShort);
1665 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UChar);
1666 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Char);
1667 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, SChar);
1668 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Short);
1669 QMETATYPE_CONVERTER_ASSIGN(QJsonValue, QString);
1670 QMETATYPE_CONVERTER(QJsonValue, QStringList,
1671 result = QJsonValue(QJsonArray::fromStringList(source));
1672 return true;
1673 );
1674 QMETATYPE_CONVERTER(QJsonValue, QVariantList,
1675 result = QJsonValue(QJsonArray::fromVariantList(source));
1676 return true;
1677 );
1678 QMETATYPE_CONVERTER(QJsonValue, QVariantMap,
1679 result = QJsonValue(QJsonObject::fromVariantMap(source));
1680 return true;
1681 );
1682 QMETATYPE_CONVERTER(QJsonValue, QVariantHash,
1683 result = QJsonValue(QJsonObject::fromVariantHash(source));
1684 return true;
1685 );
1686 QMETATYPE_CONVERTER(QJsonValue, QJsonObject,
1687 result = source;
1688 return true;
1689 );
1690 QMETATYPE_CONVERTER(QJsonValue, QJsonArray,
1691 result = source;
1692 return true;
1693 );
1694 QMETATYPE_CONVERTER(QJsonValue, QJsonDocument,
1695 QJsonDocument doc = source;
1696 result = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
1697 return true;
1698 );
1699 QMETATYPE_CONVERTER(QJsonValue, QCborValue,
1700 result = source.toJsonValue();
1701 return true;
1702 );
1703 QMETATYPE_CONVERTER(QJsonValue, QCborMap,
1704 result = source.toJsonObject();
1705 return true;
1706 );
1707 QMETATYPE_CONVERTER(QJsonValue, QCborArray,
1708 result = source.toJsonArray();
1709 return true;
1710 );
1711
1712 QMETATYPE_CONVERTER(QDate, QDateTime, result = source.date(); return true;);
1713 QMETATYPE_CONVERTER(QTime, QDateTime, result = source.time(); return true;);
1714 QMETATYPE_CONVERTER(QDateTime, QDate, result = source.startOfDay(); return true;);
1715#if QT_CONFIG(datestring)
1716 QMETATYPE_CONVERTER(QDate, QString,
1717 result = QDate::fromString(source, Qt::ISODate);
1718 return result.isValid();
1719 );
1720 QMETATYPE_CONVERTER(QTime, QString,
1721 result = QTime::fromString(source, Qt::ISODate);
1722 return result.isValid();
1723 );
1724 QMETATYPE_CONVERTER(QDateTime, QString,
1725 result = QDateTime::fromString(source, Qt::ISODate);
1726 return result.isValid();
1727 );
1728#endif
1729
1730QT_WARNING_POP
1731 }
1732 return false;
1733 }
1734#endif // !QT_BOOTSTRAPPED
1735} metatypeHelper = {};
1736
1737Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
1738Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
1739
1740static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
1741{
1742 if (type <= QMetaType::LastCoreType)
1743 return &metatypeHelper;
1744 if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
1745 return qMetaTypeGuiHelper;
1746 else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
1747 return qMetaTypeWidgetsHelper;
1748 return nullptr;
1749}
1750
1751#ifndef QT_BOOTSTRAPPED
1752template<typename T, typename Key>
1753class QMetaTypeFunctionRegistry
1754{
1755public:
1756 ~QMetaTypeFunctionRegistry()
1757 {
1758 const QWriteLocker locker(&lock);
1759 map.clear();
1760 }
1761
1762 bool contains(Key k) const
1763 {
1764 const QReadLocker locker(&lock);
1765 return map.contains(k);
1766 }
1767
1768 bool insertIfNotContains(Key k, const T &f)
1769 {
1770 const QWriteLocker locker(&lock);
1771 auto r = map.tryEmplace(k, f);
1772 return r.inserted;
1773 }
1774
1775 const T *function(Key k) const
1776 {
1777 const QReadLocker locker(&lock);
1778 auto it = map.find(k);
1779 return it == map.end() ? nullptr : std::addressof(*it);
1780 }
1781
1782 void remove(int from, int to)
1783 {
1784 const Key k(from, to);
1785 const QWriteLocker locker(&lock);
1786 map.remove(k);
1787 }
1788private:
1789 mutable QReadWriteLock lock;
1790 QHash<Key, T> map;
1791};
1792
1793using QMetaTypeConverterRegistry
1794 = QMetaTypeFunctionRegistry<QMetaType::ConverterFunction, std::pair<int,int>>;
1795
1796Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
1797
1798using QMetaTypeMutableViewRegistry
1799 = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, std::pair<int,int>>;
1800Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
1801
1802/*!
1803 \fn template<typename From, typename To> bool QMetaType::registerConverter()
1804 \since 5.2
1805 Registers the possibility of an implicit conversion from type From to type To in the meta
1806 type system. Returns \c true if the registration succeeded, otherwise false.
1807
1808 \snippet qmetatype/registerConverters.cpp implicit
1809*/
1810
1811/*!
1812 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)() const)
1813 \since 5.2
1814 \overload
1815 Registers a method \a function like To From::function() const as converter from type From
1816 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1817
1818 \snippet qmetatype/registerConverters.cpp member
1819*/
1820
1821/*!
1822 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)(bool*) const)
1823 \since 5.2
1824 \overload
1825 Registers a method \a function like To From::function(bool *ok) const as converter from type From
1826 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1827
1828 The \c ok pointer can be used by the function to indicate whether the conversion succeeded.
1829 \snippet qmetatype/registerConverters.cpp memberOk
1830
1831*/
1832
1833/*!
1834 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerConverter(UnaryFunction function)
1835 \since 5.2
1836 \overload
1837 Registers a unary function object \a function as converter from type From
1838 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1839
1840 \a function must take an instance of type \c From and return an instance of \c To. It can be a function
1841 pointer, a lambda or a functor object. Since Qt 6.5, the \a function can also return an instance of
1842 \c std::optional<To> to be able to indicate failed conversions.
1843 \snippet qmetatype/registerConverters.cpp unaryfunc
1844*/
1845
1846/*!
1847 Registers function \a f as converter function from type id \a from to \a to.
1848 If there's already a conversion registered, this does nothing but deleting \a f.
1849 Returns \c true if the registration succeeded, otherwise false.
1850 \since 5.2
1851 \internal
1852*/
1853bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
1854{
1855 if (!customTypesConversionRegistry()->insertIfNotContains(k: {from.id(), to.id()}, f)) {
1856 qWarning(msg: "Type conversion already registered from type %s to type %s",
1857 from.name(), to.name());
1858 return false;
1859 }
1860 return true;
1861}
1862
1863/*!
1864 \fn template<typename From, typename To> static bool QMetaType::registerMutableView(To(From::*function)())
1865 \since 6.0
1866 \overload
1867 Registers a method \a function like \c {To From::function()} as mutable view of type \c {To} on
1868 type \c {From} in the meta type system. Returns \c true if the registration succeeded, otherwise
1869 \c false.
1870*/
1871
1872/*!
1873 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerMutableView(UnaryFunction function)
1874 \since 6.0
1875 \overload
1876 Registers a unary function object \a function as mutable view of type To on type From
1877 in the meta type system. Returns \c true if the registration succeeded, otherwise \c false.
1878*/
1879
1880/*!
1881 Registers function \a f as mutable view of type id \a to on type id \a from.
1882 Returns \c true if the registration succeeded, otherwise \c false.
1883 \since 6.0
1884 \internal
1885*/
1886bool QMetaType::registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
1887{
1888 if (!customTypesMutableViewRegistry()->insertIfNotContains(k: {from.id(), to.id()}, f)) {
1889 qWarning(msg: "Mutable view on type already registered from type %s to type %s",
1890 from.name(), to.name());
1891 return false;
1892 }
1893 return true;
1894}
1895
1896/*!
1897 \internal
1898 */
1899void QMetaType::unregisterMutableViewFunction(QMetaType from, QMetaType to)
1900{
1901 if (customTypesMutableViewRegistry.isDestroyed())
1902 return;
1903 customTypesMutableViewRegistry()->remove(from: from.id(), to: to.id());
1904}
1905
1906/*!
1907 \internal
1908
1909 Invoked automatically when a converter function object is destroyed.
1910 */
1911void QMetaType::unregisterConverterFunction(QMetaType from, QMetaType to)
1912{
1913 if (customTypesConversionRegistry.isDestroyed())
1914 return;
1915 customTypesConversionRegistry()->remove(from: from.id(), to: to.id());
1916}
1917#endif // !QT_BOOTSTRAPPED
1918
1919#ifndef QT_NO_DEBUG_STREAM
1920
1921/*!
1922 \fn QDebug QMetaType::operator<<(QDebug d, QMetaType m)
1923 \since 6.5
1924 Writes the QMetaType \a m to the stream \a d, and returns the stream.
1925*/
1926QDebug operator<<(QDebug d, QMetaType m)
1927{
1928 const QDebugStateSaver saver(d);
1929 return d.nospace() << "QMetaType(" << m.name() << ")";
1930}
1931
1932/*!
1933 Streams the object at \a rhs to the debug stream \a dbg. Returns \c true
1934 on success, otherwise false.
1935 \since 5.2
1936*/
1937bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
1938{
1939 if (d_ptr && d_ptr->flags & QMetaType::IsPointer) {
1940 dbg << *reinterpret_cast<const void * const *>(rhs);
1941 return true;
1942 }
1943 if (d_ptr && d_ptr->debugStream) {
1944 d_ptr->debugStream(d_ptr, dbg, rhs);
1945 return true;
1946 }
1947 return false;
1948}
1949
1950/*!
1951 \fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
1952 \overload
1953 \deprecated
1954*/
1955
1956/*!
1957 \fn template<typename T> bool QMetaType::hasRegisteredDebugStreamOperator()
1958 \deprecated
1959 \since 5.2
1960
1961 Returns \c true, if the meta type system has a registered debug stream operator for type T.
1962 */
1963
1964/*!
1965 \fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
1966 \deprecated Use QMetaType::hasRegisteredDebugStreamOperator() instead.
1967
1968 Returns \c true, if the meta type system has a registered debug stream operator for type
1969 id \a typeId.
1970 \since 5.2
1971*/
1972
1973/*!
1974 \since 6.0
1975
1976 Returns \c true, if the meta type system has a registered debug stream operator for this
1977 meta type.
1978*/
1979bool QMetaType::hasRegisteredDebugStreamOperator() const
1980{
1981 return d_ptr && d_ptr->debugStream != nullptr;
1982}
1983#endif
1984
1985#ifndef QT_NO_QOBJECT
1986/*!
1987 \internal
1988 returns a QMetaEnum for a given meta tape type id if possible
1989*/
1990static QMetaEnum metaEnumFromType(QMetaType t)
1991{
1992 if (t.flags() & QMetaType::IsEnumeration) {
1993 if (const QMetaObject *metaObject = t.metaObject()) {
1994 QByteArrayView qflagsNamePrefix = "QFlags<";
1995 QByteArray enumName = t.name();
1996 if (enumName.endsWith(c: '>') && enumName.startsWith(bv: qflagsNamePrefix)) {
1997 // extract the template argument
1998 enumName.chop(n: 1);
1999 enumName = enumName.sliced(pos: qflagsNamePrefix.size());
2000 }
2001 if (qsizetype lastColon = enumName.lastIndexOf(c: ':'); lastColon != -1)
2002 enumName = enumName.sliced(pos: lastColon + 1);
2003 return metaObject->enumerator(index: metaObject->indexOfEnumerator(name: enumName));
2004 }
2005 }
2006 return QMetaEnum();
2007}
2008#endif
2009
2010#ifndef QT_BOOTSTRAPPED
2011static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
2012{
2013 qlonglong ll;
2014 if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
2015 qulonglong ull;
2016 switch (fromType.sizeOf()) {
2017 case 1:
2018 ull = *static_cast<const unsigned char *>(from);
2019 break;
2020 case 2:
2021 ull = *static_cast<const unsigned short *>(from);
2022 break;
2023 case 4:
2024 ull = *static_cast<const unsigned int *>(from);
2025 break;
2026 case 8:
2027 ull = *static_cast<const quint64 *>(from);
2028 break;
2029 default:
2030 Q_UNREACHABLE();
2031 }
2032 if (toType.id() == QMetaType::ULongLong) {
2033 *static_cast<qulonglong *>(to) = ull;
2034 return true;
2035 }
2036 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
2037 return QMetaType::convert(fromType: QMetaType::fromType<qulonglong>(), from: &ull, toType, to);
2038 ll = qlonglong(ull);
2039 } else {
2040 switch (fromType.sizeOf()) {
2041 case 1:
2042 ll = *static_cast<const signed char *>(from);
2043 break;
2044 case 2:
2045 ll = *static_cast<const short *>(from);
2046 break;
2047 case 4:
2048 ll = *static_cast<const int *>(from);
2049 break;
2050 case 8:
2051 ll = *static_cast<const qint64 *>(from);
2052 break;
2053 default:
2054 Q_UNREACHABLE();
2055 }
2056 if (toType.id() == QMetaType::LongLong) {
2057 *static_cast<qlonglong *>(to) = ll;
2058 return true;
2059 }
2060 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
2061 return QMetaType::convert(fromType: QMetaType::fromType<qlonglong>(), from: &ll, toType, to);
2062 }
2063#ifndef QT_NO_QOBJECT
2064 QMetaEnum en = metaEnumFromType(t: fromType);
2065 if (en.isValid()) {
2066 if (en.isFlag()) {
2067 const QByteArray keys = en.valueToKeys(value: ll);
2068 if (toType.id() == QMetaType::QString)
2069 *static_cast<QString *>(to) = QString::fromUtf8(ba: keys);
2070 else
2071 *static_cast<QByteArray *>(to) = keys;
2072 } else {
2073 const char *key = en.valueToKey(value: ll);
2074 if (toType.id() == QMetaType::QString)
2075 *static_cast<QString *>(to) = QString::fromUtf8(utf8: key);
2076 else
2077 *static_cast<QByteArray *>(to) = key;
2078 }
2079 return true;
2080 }
2081#endif
2082 if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
2083 return QMetaType::convert(fromType: QMetaType::fromType<qlonglong>(), from: &ll, toType, to);
2084 return false;
2085}
2086
2087static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
2088{
2089 int fromTypeId = fromType.id();
2090 qlonglong value = -1;
2091 bool ok = false;
2092#ifndef QT_NO_QOBJECT
2093 if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
2094 QMetaEnum en = metaEnumFromType(t: toType);
2095 if (en.isValid()) {
2096 QByteArray keys = (fromTypeId == QMetaType::QString)
2097 ? static_cast<const QString *>(from)->toUtf8()
2098 : *static_cast<const QByteArray *>(from);
2099 if (auto v = en.keysToValue64(keys: keys.constData())) {
2100 ok = true;
2101 value = *v;
2102 }
2103 }
2104 }
2105#endif
2106 if (!ok) {
2107 if (fromTypeId == QMetaType::LongLong) {
2108 value = *static_cast<const qlonglong *>(from);
2109 ok = true;
2110 } else {
2111 ok = QMetaType::convert(fromType, from, toType: QMetaType::fromType<qlonglong>(), to: &value);
2112 }
2113 }
2114
2115 if (!ok)
2116 return false;
2117
2118 switch (toType.sizeOf()) {
2119 case 1:
2120 *static_cast<signed char *>(to) = value;
2121 return true;
2122 case 2:
2123 *static_cast<qint16 *>(to) = value;
2124 return true;
2125 case 4:
2126 *static_cast<qint32 *>(to) = value;
2127 return true;
2128 case 8:
2129 *static_cast<qint64 *>(to) = value;
2130 return true;
2131 default:
2132 Q_UNREACHABLE_RETURN(false);
2133 }
2134}
2135
2136static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
2137{
2138 QSequentialIterable list;
2139 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QSequentialIterable>(), to: &list))
2140 return false;
2141
2142 QVariantList &l = *static_cast<QVariantList *>(to);
2143 l.clear();
2144 l.reserve(asize: list.size());
2145 auto end = list.end();
2146 for (auto it = list.begin(); it != end; ++it)
2147 l << *it;
2148 return true;
2149}
2150
2151static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
2152{
2153 QAssociativeIterable map;
2154 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QAssociativeIterable>(), to: &map))
2155 return false;
2156
2157 QVariantMap &h = *static_cast<QVariantMap *>(to);
2158 h.clear();
2159 auto end = map.end();
2160 for (auto it = map.begin(); it != end; ++it)
2161 h.insert(key: it.key().toString(), value: it.value());
2162 return true;
2163}
2164
2165static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
2166{
2167 QAssociativeIterable map;
2168 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QAssociativeIterable>(), to: &map))
2169 return false;
2170
2171 QVariantHash &h = *static_cast<QVariantHash *>(to);
2172 h.clear();
2173 h.reserve(size: map.size());
2174 auto end = map.end();
2175 for (auto it = map.begin(); it != end; ++it)
2176 h.insert(key: it.key().toString(), value: it.value());
2177 return true;
2178}
2179
2180static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
2181{
2182 const int targetId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2183 const auto f = customTypesConversionRegistry()->function(k: {fromType.id(), targetId});
2184
2185 if (!f)
2186 return false;
2187
2188 QtMetaTypePrivate::QPairVariantInterfaceImpl pi;
2189 (*f)(from, &pi);
2190
2191 QVariant v1(pi._metaType_first);
2192 void *dataPtr;
2193 if (pi._metaType_first == QMetaType::fromType<QVariant>())
2194 dataPtr = &v1;
2195 else
2196 dataPtr = v1.data();
2197 pi.first(dataPtr);
2198
2199 QVariant v2(pi._metaType_second);
2200 if (pi._metaType_second == QMetaType::fromType<QVariant>())
2201 dataPtr = &v2;
2202 else
2203 dataPtr = v2.data();
2204 pi.second(dataPtr);
2205
2206 *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
2207 return true;
2208}
2209
2210static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
2211{
2212 using namespace QtMetaTypePrivate;
2213 const int fromTypeId = fromType.id();
2214
2215 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2216 switch (fromTypeId) {
2217 case QMetaType::QVariantList:
2218 i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
2219 return true;
2220 case QMetaType::QStringList:
2221 i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
2222 return true;
2223 case QMetaType::QByteArrayList:
2224 i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
2225 return true;
2226 case QMetaType::QString:
2227 i = QSequentialIterable(reinterpret_cast<const QString *>(from));
2228 return true;
2229 case QMetaType::QByteArray:
2230 i = QSequentialIterable(reinterpret_cast<const QByteArray *>(from));
2231 return true;
2232 default: {
2233 QSequentialIterable impl;
2234 if (QMetaType::convert(
2235 fromType, from, toType: QMetaType::fromType<QIterable<QMetaSequence>>(), to: &impl)) {
2236 i = std::move(impl);
2237 return true;
2238 }
2239 }
2240 }
2241
2242 return false;
2243}
2244
2245static bool canConvertToSequentialIterable(QMetaType fromType)
2246{
2247 switch (fromType.id()) {
2248 case QMetaType::QVariantList:
2249 case QMetaType::QStringList:
2250 case QMetaType::QByteArrayList:
2251 case QMetaType::QString:
2252 case QMetaType::QByteArray:
2253 return true;
2254 default:
2255 return QMetaType::canConvert(fromType, toType: QMetaType::fromType<QIterable<QMetaSequence>>());
2256 }
2257}
2258
2259static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
2260{
2261 switch (fromType.id()) {
2262 case QMetaType::QVariantList:
2263 case QMetaType::QStringList:
2264 case QMetaType::QByteArrayList:
2265 case QMetaType::QString:
2266 case QMetaType::QByteArray:
2267 return true;
2268 default:
2269 return QMetaType::canView(
2270 fromType, toType: QMetaType::fromType<QIterable<QMetaSequence>>());
2271 }
2272}
2273
2274static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
2275{
2276 using namespace QtMetaTypePrivate;
2277 const int fromTypeId = fromType.id();
2278
2279 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2280 switch (fromTypeId) {
2281 case QMetaType::QVariantList:
2282 i = QSequentialIterable(reinterpret_cast<QVariantList *>(from));
2283 return true;
2284 case QMetaType::QStringList:
2285 i = QSequentialIterable(reinterpret_cast<QStringList *>(from));
2286 return true;
2287 case QMetaType::QByteArrayList:
2288 i = QSequentialIterable(reinterpret_cast<QByteArrayList *>(from));
2289 return true;
2290 case QMetaType::QString:
2291 i = QSequentialIterable(reinterpret_cast<QString *>(from));
2292 return true;
2293 case QMetaType::QByteArray:
2294 i = QSequentialIterable(reinterpret_cast<QByteArray *>(from));
2295 return true;
2296 default: {
2297 QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
2298 if (QMetaType::view(
2299 fromType, from, toType: QMetaType::fromType<QIterable<QMetaSequence>>(), to: &j)) {
2300 i = std::move(j);
2301 return true;
2302 }
2303 }
2304 }
2305
2306 return false;
2307}
2308
2309static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
2310{
2311 using namespace QtMetaTypePrivate;
2312
2313 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2314 if (fromType.id() == QMetaType::QVariantMap) {
2315 i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
2316 return true;
2317 }
2318 if (fromType.id() == QMetaType::QVariantHash) {
2319 i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
2320 return true;
2321 }
2322
2323 QAssociativeIterable impl;
2324 if (QMetaType::convert(
2325 fromType, from, toType: QMetaType::fromType<QIterable<QMetaAssociation>>(), to: &impl)) {
2326 i = std::move(impl);
2327 return true;
2328 }
2329
2330 return false;
2331}
2332
2333static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
2334{
2335 if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
2336 return false; // Can not convert between pointer and value
2337
2338 const QMetaObject *f = fromType.metaObject();
2339 const QMetaObject *t = toType.metaObject();
2340 if (f && t) {
2341 return f->inherits(metaObject: t) || (t->inherits(metaObject: f));
2342 }
2343 return false;
2344}
2345
2346static bool canConvertToAssociativeIterable(QMetaType fromType)
2347{
2348 switch (fromType.id()) {
2349 case QMetaType::QVariantMap:
2350 case QMetaType::QVariantHash:
2351 return true;
2352 default:
2353 return QMetaType::canConvert(fromType, toType: QMetaType::fromType<QIterable<QMetaAssociation>>());
2354 }
2355}
2356
2357static bool canImplicitlyViewAsAssociativeIterable(QMetaType fromType)
2358{
2359 switch (fromType.id()) {
2360 case QMetaType::QVariantMap:
2361 case QMetaType::QVariantHash:
2362 return true;
2363 default:
2364 return QMetaType::canView(
2365 fromType, toType: QMetaType::fromType<QIterable<QMetaAssociation>>());
2366 }
2367}
2368
2369static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
2370{
2371 using namespace QtMetaTypePrivate;
2372 int fromTypeId = fromType.id();
2373
2374 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2375 if (fromTypeId == QMetaType::QVariantMap) {
2376 i = QAssociativeIterable(reinterpret_cast<QVariantMap *>(from));
2377 return true;
2378 }
2379 if (fromTypeId == QMetaType::QVariantHash) {
2380 i = QAssociativeIterable(reinterpret_cast<QVariantHash *>(from));
2381 return true;
2382 }
2383
2384 QIterable<QMetaAssociation> j(QMetaAssociation(), nullptr);
2385 if (QMetaType::view(
2386 fromType, from, toType: QMetaType::fromType<QIterable<QMetaAssociation>>(), to: &j)) {
2387 i = std::move(j);
2388 return true;
2389 }
2390
2391 return false;
2392}
2393
2394static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
2395{
2396 // handle QObject conversion
2397 if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
2398 QObject *fromObject = *static_cast<QObject * const *>(from);
2399 // use dynamic metatype of from if possible
2400 if (fromObject && fromObject->metaObject()->inherits(metaObject: toType.metaObject())) {
2401 *static_cast<QObject **>(to) = toType.metaObject()->cast(obj: fromObject);
2402 return true;
2403 } else if (!fromObject && fromType.metaObject()) {
2404 // if fromObject is null, use static fromType to check if conversion works
2405 *static_cast<void **>(to) = nullptr;
2406 return fromType.metaObject()->inherits(metaObject: toType.metaObject());
2407 }
2408 } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
2409 // fromType and toType are of same 'pointedness'
2410 const QMetaObject *f = fromType.metaObject();
2411 const QMetaObject *t = toType.metaObject();
2412 if (f && t && f->inherits(metaObject: t)) {
2413 toType.destruct(data: to);
2414 toType.construct(where: to, copy: from);
2415 return true;
2416 }
2417 }
2418 return false;
2419}
2420
2421/*!
2422 \fn bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
2423 \deprecated
2424
2425 Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
2426 typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
2427
2428 Both \a from and \a to have to be valid pointers.
2429
2430 \since 5.2
2431*/
2432
2433/*!
2434 Converts the object at \a from from \a fromType to the preallocated space at \a to
2435 typed \a toType. Returns \c true, if the conversion succeeded, otherwise false.
2436
2437 Both \a from and \a to have to be valid pointers.
2438
2439 \since 5.2
2440*/
2441bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
2442{
2443 if (!fromType.isValid() || !toType.isValid())
2444 return false;
2445
2446 if (fromType == toType) {
2447 // just make a copy
2448 fromType.destruct(data: to);
2449 fromType.construct(where: to, copy: from);
2450 return true;
2451 }
2452
2453 int fromTypeId = fromType.id();
2454 int toTypeId = toType.id();
2455
2456 if (auto moduleHelper = qModuleHelperForType(type: qMax(a: fromTypeId, b: toTypeId))) {
2457 if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
2458 return true;
2459 }
2460 const auto f = customTypesConversionRegistry()->function(k: {fromTypeId, toTypeId});
2461 if (f)
2462 return (*f)(from, to);
2463
2464 if (fromType.flags() & QMetaType::IsEnumeration)
2465 return convertFromEnum(fromType, from, toType, to);
2466 if (toType.flags() & QMetaType::IsEnumeration)
2467 return convertToEnum(fromType, from, toType, to);
2468 if (toTypeId == Nullptr) {
2469 *static_cast<std::nullptr_t *>(to) = nullptr;
2470 if (fromType.flags() & QMetaType::IsPointer) {
2471 if (*static_cast<const void * const *>(from) == nullptr)
2472 return true;
2473 }
2474 }
2475
2476 if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
2477 return true;
2478
2479 // handle iterables
2480 if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
2481 return true;
2482
2483 if (toTypeId == QVariantMap && convertIterableToVariantMap(fromType, from, to))
2484 return true;
2485
2486 if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
2487 return true;
2488
2489 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2490 return convertToSequentialIterable(fromType, from, to);
2491
2492 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2493 return convertToAssociativeIterable(fromType, from, to);
2494
2495 return convertMetaObject(fromType, from, toType, to);
2496}
2497
2498/*!
2499 Creates a mutable view on the object at \a from of \a fromType in the preallocated space at
2500 \a to typed \a toType. Returns \c true if the conversion succeeded, otherwise false.
2501 \since 6.0
2502*/
2503bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
2504{
2505 if (!fromType.isValid() || !toType.isValid())
2506 return false;
2507
2508 int fromTypeId = fromType.id();
2509 int toTypeId = toType.id();
2510
2511 const auto f = customTypesMutableViewRegistry()->function(k: {fromTypeId, toTypeId});
2512 if (f)
2513 return (*f)(from, to);
2514
2515 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2516 return viewAsSequentialIterable(fromType, from, to);
2517
2518 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2519 return viewAsAssociativeIterable(fromType, from, to);
2520
2521 return convertMetaObject(fromType, from, toType, to);
2522}
2523
2524/*!
2525 Returns \c true if QMetaType::view can create a mutable view of type \a toType
2526 on type \a fromType.
2527
2528 Converting between pointers of types derived from QObject will return true for this
2529 function if a qobject_cast from the type described by \a fromType to the type described
2530 by \a toType would succeed.
2531
2532 You can create a mutable view of type QSequentialIterable on any container registered with
2533 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE().
2534
2535 Similarly you can create a mutable view of type QAssociativeIterable on any container
2536 registered with Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE().
2537
2538 \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(),
2539 QAssociativeIterable, Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2540*/
2541bool QMetaType::canView(QMetaType fromType, QMetaType toType)
2542{
2543 int fromTypeId = fromType.id();
2544 int toTypeId = toType.id();
2545
2546 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2547 return false;
2548
2549 const auto f = customTypesMutableViewRegistry()->function(k: {fromTypeId, toTypeId});
2550 if (f)
2551 return true;
2552
2553 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2554 return canImplicitlyViewAsSequentialIterable(fromType);
2555
2556 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2557 return canImplicitlyViewAsAssociativeIterable(fromType);
2558
2559 if (canConvertMetaObject(fromType, toType))
2560 return true;
2561
2562 return false;
2563}
2564
2565/*!
2566 Returns \c true if QMetaType::convert can convert from \a fromType to
2567 \a toType. Note this is mostly about the ability to execute the conversion,
2568 while the actual conversion may fail when attempted (for example,
2569 converting a floating point value to an integer outside of its range).
2570
2571 The registerConverter() function can be used to register additional
2572 conversions, either between a built-in type and a non-built-in one, or
2573 between two non-built-in types. This function will return \c true if the
2574 conversion path is registered.
2575
2576 The following conversions are supported by Qt:
2577
2578 \table
2579 \header \li Type \li Automatically Cast To
2580 \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
2581 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2582 \l QMetaType::UInt, \l QMetaType::ULongLong
2583 \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
2584 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2585 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2586 \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
2587 \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
2588 \row \li \l QMetaType::QColor \li \l QMetaType::QString
2589 \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
2590 \l QMetaType::QString
2591 \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
2592 \l QMetaType::QString, \l QMetaType::QTime
2593 \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
2594 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
2595 \l QMetaType::ULongLong
2596 \row \li \l QMetaType::QFont \li \l QMetaType::QString
2597 \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
2598 \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
2599 \l QMetaType::UInt, \l QMetaType::ULongLong
2600 \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
2601 \l QMetaType::QString
2602 \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
2603 list's items can be converted to QStrings)
2604 \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
2605 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
2606 \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
2607 \l QMetaType::ULongLong
2608 \row \li \l QMetaType::QPoint \li QMetaType::QPointF
2609 \row \li \l QMetaType::QRect \li QMetaType::QRectF
2610 \row \li \l QMetaType::QString \li \l QMetaType::Bool,
2611 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
2612 \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
2613 \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
2614 \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
2615 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2616 \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
2617 \l QMetaType::QString (if the list contains exactly one item)
2618 \row \li \l QMetaType::QTime \li \l QMetaType::QString
2619 \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
2620 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
2621 \l QMetaType::QString, \l QMetaType::ULongLong
2622 \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
2623 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
2624 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
2625 \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
2626 \endtable
2627
2628 Other supported conversions include between all primitive types (\c int, \c
2629 float, \c bool, etc., including all enums) and between any pointer type and
2630 \c{std::nullptr_t}. Enumerations can also be converted to QString and
2631 QByteArray.
2632
2633 If both \a fromType and \a toType are types deriving from QObject (or
2634 pointers to them), this function will also return \c true if one of the
2635 types is derived from the other. That is, it returns true if
2636 \c{static_cast<>} from the type described by \a fromType to the type
2637 described by \a toType would compile. The convert() function operates like
2638 qobject_cast() and verifies the dynamic type of the object pointed to by
2639 the QVariant.
2640
2641 A cast from a sequential container will also return true for this
2642 function if the \a toType is QVariantList.
2643
2644 Similarly, a cast from an associative container will also return true for this
2645 function the \a toType is QVariantHash or QVariantMap.
2646
2647 \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
2648 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2649*/
2650bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
2651{
2652 int fromTypeId = fromType.id();
2653 int toTypeId = toType.id();
2654
2655 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2656 return false;
2657
2658 if (fromTypeId == toTypeId)
2659 return true;
2660
2661 if (auto moduleHelper = qModuleHelperForType(type: qMax(a: fromTypeId, b: toTypeId))) {
2662 if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
2663 return true;
2664 }
2665 const ConverterFunction * const f =
2666 customTypesConversionRegistry()->function(k: std::make_pair(x&: fromTypeId, y&: toTypeId));
2667 if (f)
2668 return true;
2669
2670 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2671 return canConvertToSequentialIterable(fromType);
2672
2673 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2674 return canConvertToAssociativeIterable(fromType);
2675 if (toTypeId == QVariantList
2676 && canConvert(fromType, toType: QMetaType::fromType<QSequentialIterable>())) {
2677 return true;
2678 }
2679
2680 if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
2681 && canConvert(fromType, toType: QMetaType::fromType<QAssociativeIterable>())) {
2682 return true;
2683 }
2684
2685 if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
2686 fromType, toType: QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
2687 return true;
2688
2689 if (fromType.flags() & IsEnumeration) {
2690 if (toTypeId == QString || toTypeId == QByteArray)
2691 return true;
2692 return canConvert(fromType: QMetaType(LongLong), toType);
2693 }
2694 if (toType.flags() & IsEnumeration) {
2695 if (fromTypeId == QString || fromTypeId == QByteArray)
2696 return true;
2697 return canConvert(fromType, toType: QMetaType(LongLong));
2698 }
2699 if (toTypeId == Nullptr && fromType.flags() & IsPointer)
2700 return true;
2701 if (canConvertMetaObject(fromType, toType))
2702 return true;
2703
2704 return false;
2705}
2706
2707/*!
2708 \fn bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
2709 \deprecated Use the non-static compare method instead
2710
2711 Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
2712 \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
2713 or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
2714*/
2715
2716/*!
2717 \fn template<typename From, typename To> bool QMetaType::hasRegisteredConverterFunction()
2718 Returns \c true, if the meta type system has a registered conversion from type From to type To.
2719 \since 5.2
2720 \overload
2721 */
2722
2723/*!
2724 Returns \c true, if the meta type system has a registered conversion from meta type id \a fromType
2725 to \a toType
2726 \since 5.2
2727*/
2728bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType)
2729{
2730 return customTypesConversionRegistry()->contains(k: {fromType.id(), toType.id()});
2731}
2732
2733/*!
2734 \internal
2735 Non-template helper ("SCARY") for IsMetaTypePair::registerConverter().
2736*/
2737bool QtPrivate::hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m)
2738{
2739 const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2740 return QMetaType::hasRegisteredConverterFunction(fromType: m, toType: to);
2741}
2742
2743/*!
2744 \internal
2745 Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerConverter().
2746*/
2747bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m)
2748{
2749 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
2750 return QMetaType::hasRegisteredConverterFunction(fromType: m, toType: to);
2751}
2752
2753/*!
2754 \internal
2755 Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerConverter().
2756*/
2757bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m)
2758{
2759 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
2760 return QMetaType::hasRegisteredConverterFunction(fromType: m, toType: to);
2761}
2762
2763/*!
2764 \fn template<typename From, typename To> bool QMetaType::hasRegisteredMutableViewFunction()
2765 Returns \c true, if the meta type system has a registered mutable view on type From of type To.
2766 \since 6.0
2767 \overload
2768*/
2769
2770/*!
2771 Returns \c true, if the meta type system has a registered mutable view on meta type id
2772 \a fromType of meta type id \a toType.
2773 \since 5.2
2774*/
2775bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType)
2776{
2777 return customTypesMutableViewRegistry()->contains(k: {fromType.id(), toType.id()});
2778}
2779
2780/*!
2781 \internal
2782 Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerMutableView().
2783*/
2784bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m)
2785{
2786 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
2787 return QMetaType::hasRegisteredMutableViewFunction(fromType: m, toType: to);
2788}
2789
2790/*!
2791 \internal
2792 Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerMutableView().
2793*/
2794bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m)
2795{
2796 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
2797 return QMetaType::hasRegisteredMutableViewFunction(fromType: m, toType: to);
2798}
2799#endif // !QT_BOOTSTRAPPED
2800
2801/*!
2802 \fn const char *QMetaType::typeName(int typeId)
2803 \deprecated
2804
2805 Returns the type name associated with the given \a typeId, or a null
2806 pointer if no matching type was found. The returned pointer must not be
2807 deleted.
2808
2809 \sa type(), isRegistered(), Type, name()
2810*/
2811
2812/*!
2813 \fn constexpr const char *QMetaType::name() const
2814 \since 5.15
2815
2816 Returns the type name associated with this QMetaType, or a null
2817 pointer if no matching type was found. The returned pointer must not be
2818 deleted.
2819
2820 \sa typeName()
2821*/
2822
2823/*
2824 Similar to QMetaType::type(), but only looks in the static set of types.
2825*/
2826static inline int qMetaTypeStaticType(QByteArrayView name)
2827{
2828 for (int i = 0; i < types.count(); ++i) {
2829 if (types.viewAt(index: i) == name)
2830 return types.typeIdMap[i];
2831 }
2832 return QMetaType::UnknownType;
2833}
2834
2835#ifndef QT_BOOTSTRAPPED
2836/*!
2837 \internal
2838
2839 Registers a user type for marshalling, as an alias of another type (typedef).
2840 Note that normalizedTypeName is not checked for conformance with Qt's normalized format,
2841 so it must already conform.
2842*/
2843void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeName,
2844 QMetaType metaType)
2845{
2846 if (!metaType.isValid())
2847 return;
2848 if (auto reg = customTypeRegistry()) {
2849 QWriteLocker lock(&reg->lock);
2850 auto &al = reg->aliases[normalizedTypeName];
2851 if (al)
2852 return;
2853 al = metaType.d_ptr;
2854 }
2855}
2856#endif // !QT_BOOTSTRAPPED
2857
2858static const QtPrivate::QMetaTypeInterface *interfaceForStaticType(int typeId)
2859{
2860 Q_ASSERT(typeId < QMetaType::User);
2861 if (auto moduleHelper = qModuleHelperForType(type: typeId))
2862 return moduleHelper->interfaceForType(typeId);
2863 return nullptr;
2864}
2865
2866static const QtPrivate::QMetaTypeInterface *interfaceForTypeNoWarning(int typeId)
2867{
2868 const QtPrivate::QMetaTypeInterface *iface = nullptr;
2869 if (typeId >= QMetaType::User) {
2870#ifndef QT_BOOTSTRAPPED
2871 if (customTypeRegistry.exists())
2872 iface = customTypeRegistry->getCustomType(id: typeId);
2873#endif
2874 } else {
2875 iface = interfaceForStaticType(typeId);
2876 }
2877 return iface;
2878}
2879
2880/*!
2881 Returns \c true if the datatype with ID \a type is registered;
2882 otherwise returns \c false.
2883
2884 \sa type(), Type
2885*/
2886bool QMetaType::isRegistered(int type)
2887{
2888 return interfaceForTypeNoWarning(typeId: type) != nullptr;
2889}
2890
2891namespace {
2892enum NormalizeTypeMode {
2893 DontNormalizeType,
2894 TryNormalizeType
2895};
2896}
2897template <NormalizeTypeMode tryNormalizedType> static inline
2898const QtPrivate::QMetaTypeInterface *qMetaTypeTypeImpl(QByteArrayView name)
2899{
2900 if (name.isEmpty())
2901 return nullptr;
2902
2903 int type = qMetaTypeStaticType(name);
2904 if (type != QMetaType::UnknownType) {
2905 return interfaceForStaticType(typeId: type);
2906#ifndef QT_BOOTSTRAPPED
2907 } else {
2908 QReadLocker locker(&customTypeRegistry()->lock);
2909 auto it = customTypeRegistry->aliases.constFind(key: name);
2910 if (it != customTypeRegistry->aliases.constEnd())
2911 return it.value();
2912
2913#ifndef QT_NO_QOBJECT
2914 if (tryNormalizedType) {
2915 const char *typeName = name.constData();
2916 const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName);
2917 type = qMetaTypeStaticType(name: normalizedTypeName);
2918 if (type == QMetaType::UnknownType) {
2919 return customTypeRegistry->aliases.value(key: normalizedTypeName);
2920 } else {
2921 return interfaceForStaticType(typeId: type);
2922 }
2923 }
2924#endif
2925#endif
2926 }
2927 return nullptr;
2928}
2929
2930/*!
2931 \fn int QMetaType::type(const char *typeName)
2932 \deprecated
2933
2934 Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
2935 no such type.
2936
2937 \sa isRegistered(), typeName(), Type
2938*/
2939
2940/*!
2941 \internal
2942
2943 Similar to QMetaType::type(); the only difference is that this function
2944 doesn't attempt to normalize the type name (i.e., the lookup will fail
2945 for type names in non-normalized form).
2946
2947 Used by only QMetaObject, which means the type is always already normalized.
2948*/
2949Q_CORE_EXPORT int qMetaTypeTypeInternal(QByteArrayView name)
2950{
2951 const QtPrivate::QMetaTypeInterface *iface = qMetaTypeTypeImpl<DontNormalizeType>(name);
2952 return iface ? iface->typeId.loadRelaxed() : QMetaType::UnknownType;
2953}
2954
2955/*!
2956 \fn int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
2957
2958 \since 5.5
2959 \overload
2960 \deprecated
2961
2962 Returns a handle to the type called \a typeName, or 0 if there is
2963 no such type.
2964
2965 \sa isRegistered(), typeName()
2966*/
2967
2968#ifndef QT_NO_DATASTREAM
2969/*!
2970 Writes the object pointed to by \a data to the given \a stream.
2971 Returns \c true if the object is saved successfully; otherwise
2972 returns \c false.
2973
2974 Normally, you should not need to call this function directly.
2975 Instead, use QVariant's \c operator<<(), which relies on save()
2976 to stream custom types.
2977
2978 \sa load()
2979*/
2980bool QMetaType::save(QDataStream &stream, const void *data) const
2981{
2982 if (!data || !isValid())
2983 return false;
2984
2985 // keep compatibility for long/ulong
2986 if (id() == QMetaType::Long) {
2987 stream << qlonglong(*(long *)data);
2988 return true;
2989 } else if (id() == QMetaType::ULong) {
2990 stream << qlonglong(*(unsigned long *)data);
2991 return true;
2992 }
2993
2994 if (!d_ptr->dataStreamOut)
2995 return false;
2996
2997 d_ptr->dataStreamOut(d_ptr, stream, data);
2998 return true;
2999}
3000
3001/*!
3002 \fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
3003 \overload
3004 \deprecated
3005*/
3006
3007/*!
3008 Reads the object of this type from the given \a stream into \a data.
3009 Returns \c true if the object is loaded successfully; otherwise
3010 returns \c false.
3011
3012 Normally, you should not need to call this function directly.
3013 Instead, use QVariant's \c operator>>(), which relies on load()
3014 to stream custom types.
3015
3016 \sa save()
3017*/
3018bool QMetaType::load(QDataStream &stream, void *data) const
3019{
3020 if (!data || !isValid())
3021 return false;
3022
3023 // keep compatibility for long/ulong
3024 if (id() == QMetaType::Long) {
3025 qlonglong ll;
3026 stream >> ll;
3027 *(long *)data = long(ll);
3028 return true;
3029 } else if (id() == QMetaType::ULong) {
3030 qulonglong ull;
3031 stream >> ull;
3032 *(unsigned long *)data = (unsigned long)(ull);
3033 return true;
3034 }
3035 if (!d_ptr->dataStreamIn)
3036 return false;
3037
3038 d_ptr->dataStreamIn(d_ptr, stream, data);
3039 return true;
3040}
3041
3042/*!
3043 \since 6.1
3044
3045 Returns \c true, if the meta type system has registered data stream operators for this
3046 meta type.
3047*/
3048bool QMetaType::hasRegisteredDataStreamOperators() const
3049{
3050 int type = id();
3051 if (type == QMetaType::Long || type == QMetaType::ULong)
3052 return true;
3053 return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
3054}
3055
3056/*!
3057 \since 6.6
3058
3059 If this metatype represents an enumeration, this method returns a
3060 metatype of a numeric class of the same signedness and size as the
3061 enums underlying type.
3062 If it represents a QFlags type, it returns QMetaType::Int.
3063 In all other cases an invalid QMetaType is returned.
3064 */
3065QMetaType QMetaType::underlyingType() const
3066{
3067 if (!d_ptr || !(flags() & IsEnumeration))
3068 return {};
3069 /* QFlags has enumeration set so that's handled here (qint32
3070 case), as QFlags uses int as the underlying type
3071 Note that we do some approximation here, as we cannot
3072 differentiate between different underlying types of the
3073 same size and signedness (consider char <-> (un)signed char,
3074 int <-> long <-> long long).
3075 */
3076 if (flags() & IsUnsignedEnumeration) {
3077 switch (sizeOf()) {
3078 case 1:
3079 return QMetaType::fromType<quint8>();
3080 case 2:
3081 return QMetaType::fromType<quint16>();
3082 case 4:
3083 return QMetaType::fromType<quint32>();
3084 case 8:
3085 return QMetaType::fromType<quint64>();
3086 default:
3087 break;
3088 }
3089 } else {
3090 switch (sizeOf()) {
3091 case 1:
3092 return QMetaType::fromType<qint8>();
3093 case 2:
3094 return QMetaType::fromType<qint16>();
3095 case 4:
3096 return QMetaType::fromType<qint32>();
3097 case 8:
3098 return QMetaType::fromType<qint64>();
3099 default:
3100 break;
3101 }
3102 }
3103 // int128 can be handled above once we have qint128
3104 return QMetaType();
3105}
3106
3107/*!
3108 \fn bool QMetaType::load(QDataStream &stream, int type, void *data)
3109 \overload
3110 \deprecated
3111*/
3112#endif // QT_NO_DATASTREAM
3113
3114/*!
3115 Returns a QMetaType matching \a typeName. The returned object is
3116 not valid if the typeName is not known to QMetaType
3117 */
3118QMetaType QMetaType::fromName(QByteArrayView typeName)
3119{
3120 return QMetaType(qMetaTypeTypeImpl<TryNormalizeType>(name: typeName));
3121}
3122
3123/*!
3124 \fn void *QMetaType::create(int type, const void *copy)
3125 \deprecated
3126
3127 Returns a copy of \a copy, assuming it is of type \a type. If \a
3128 copy is zero, creates a default constructed instance.
3129
3130 \sa destroy(), isRegistered(), Type
3131*/
3132
3133/*!
3134 \fn void QMetaType::destroy(int type, void *data)
3135 \deprecated
3136 Destroys the \a data, assuming it is of the \a type given.
3137
3138 \sa create(), isRegistered(), Type
3139*/
3140
3141/*!
3142 \fn void *QMetaType::construct(int type, void *where, const void *copy)
3143 \since 5.0
3144 \deprecated
3145
3146 Constructs a value of the given \a type in the existing memory
3147 addressed by \a where, that is a copy of \a copy, and returns
3148 \a where. If \a copy is zero, the value is default constructed.
3149
3150 This is a low-level function for explicitly managing the memory
3151 used to store the type. Consider calling create() if you don't
3152 need this level of control (that is, use "new" rather than
3153 "placement new").
3154
3155 You must ensure that \a where points to a location that can store
3156 a value of type \a type, and that \a where is suitably aligned.
3157 The type's size can be queried by calling sizeOf().
3158
3159 The rule of thumb for alignment is that a type is aligned to its
3160 natural boundary, which is the smallest power of 2 that is bigger
3161 than the type, unless that alignment is larger than the maximum
3162 useful alignment for the platform. For practical purposes,
3163 alignment larger than 2 * sizeof(void*) is only necessary for
3164 special hardware instructions (e.g., aligned SSE loads and stores
3165 on x86).
3166
3167 \sa destruct(), sizeOf()
3168*/
3169
3170
3171/*!
3172 \fn void QMetaType::destruct(int type, void *where)
3173 \since 5.0
3174 \deprecated
3175
3176 Destructs the value of the given \a type, located at \a where.
3177
3178 Unlike destroy(), this function only invokes the type's
3179 destructor, it doesn't invoke the delete operator.
3180
3181 \sa construct()
3182*/
3183
3184/*!
3185 \fn int QMetaType::sizeOf(int type)
3186 \since 5.0
3187 \deprecated
3188
3189 Returns the size of the given \a type in bytes (i.e. sizeof(T),
3190 where T is the actual type identified by the \a type argument).
3191
3192 This function is typically used together with construct()
3193 to perform low-level management of the memory used by a type.
3194
3195 \sa construct(), QMetaType::alignOf()
3196*/
3197
3198/*!
3199 \fn QMetaType::TypeFlags QMetaType::typeFlags(int type)
3200 \since 5.0
3201 \deprecated
3202
3203 Returns flags of the given \a type.
3204
3205 \sa QMetaType::TypeFlags
3206*/
3207
3208/*!
3209 \fn const QMetaObject *QMetaType::metaObjectForType(int type)
3210 \since 5.0
3211 \deprecated
3212
3213 returns QMetaType::metaObject for \a type
3214
3215 \sa metaObject()
3216*/
3217
3218/*!
3219 \fn template <typename T> int qRegisterMetaType(const char *typeName)
3220 \relates QMetaType
3221 \obsolete
3222 \threadsafe
3223
3224 Registers the type name \a typeName for the type \c{T}. Returns
3225 the internal ID used by QMetaType. Any class or struct that has a
3226 public default constructor, a public copy constructor and a public
3227 destructor can be registered.
3228
3229 This function requires that \c{T} is a fully defined type at the point
3230 where the function is called. For pointer types, it also requires that the
3231 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3232 to register pointers to forward declared types.
3233
3234 After a type has been registered, you can create and destroy
3235 objects of that type dynamically at run-time.
3236
3237 This example registers the class \c{MyClass}:
3238
3239 \snippet code/src_corelib_kernel_qmetatype.cpp 4
3240
3241 This function is useful to register typedefs so they can be used
3242 by QMetaProperty, or in QueuedConnections
3243
3244 \snippet code/src_corelib_kernel_qmetatype.cpp 9
3245
3246 \warning This function is useful only for registering an alias (typedef)
3247 for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
3248
3249 \sa {QMetaType::}{isRegistered()}, Q_DECLARE_METATYPE()
3250*/
3251
3252/*!
3253 \fn template <typename T> int qRegisterMetaType()
3254 \relates QMetaType
3255 \threadsafe
3256 \since 4.2
3257
3258 Call this function to register the type \c T. Returns the meta type Id.
3259
3260 Example:
3261
3262 \snippet code/src_corelib_kernel_qmetatype.cpp 7
3263
3264 This function requires that \c{T} is a fully defined type at the point
3265 where the function is called. For pointer types, it also requires that the
3266 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3267 to register pointers to forward declared types.
3268
3269 To use the type \c T in QMetaType, QVariant, or with the
3270 QObject::property() API, registration is not necessary.
3271
3272 To use the type \c T in queued signal and slot connections,
3273 \c{qRegisterMetaType<T>()} must be called before the first connection is
3274 established. That is typically done in the constructor of the class that
3275 uses \c T, or in the \c{main()} function.
3276
3277 After a type has been registered, it can be found by its name using
3278 QMetaType::fromName().
3279
3280 \sa Q_DECLARE_METATYPE()
3281 */
3282
3283/*!
3284 \fn int qRegisterMetaType(QMetaType meta)
3285 \relates QMetaType
3286 \threadsafe
3287 \since 6.5
3288
3289 Registers the meta type \a meta and returns its type Id.
3290
3291 This function requires that \c{T} is a fully defined type at the point
3292 where the function is called. For pointer types, it also requires that the
3293 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3294 to register pointers to forward declared types.
3295
3296 To use the type \c T in QMetaType, QVariant, or with the
3297 QObject::property() API, registration is not necessary.
3298
3299 To use the type \c T in queued signal and slot connections,
3300 \c{qRegisterMetaType<T>()} must be called before the first connection is
3301 established. That is typically done in the constructor of the class that
3302 uses \c T, or in the \c{main()} function.
3303
3304 After a type has been registered, it can be found by its name using
3305 QMetaType::fromName().
3306 */
3307
3308/*!
3309 \fn template <typename T> int qMetaTypeId()
3310 \relates QMetaType
3311 \threadsafe
3312 \since 4.1
3313
3314 Returns the meta type id of type \c T at compile time. If the
3315 type was not declared with Q_DECLARE_METATYPE(), compilation will
3316 fail.
3317
3318 Typical usage:
3319
3320 \snippet code/src_corelib_kernel_qmetatype.cpp 8
3321
3322 QMetaType::type() returns the same ID as qMetaTypeId(), but does
3323 a lookup at runtime based on the name of the type.
3324 QMetaType::type() is a bit slower, but compilation succeeds if a
3325 type is not registered.
3326
3327 \sa Q_DECLARE_METATYPE(), QMetaType::type()
3328*/
3329
3330static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
3331{
3332 const QtPrivate::QMetaTypeInterface *iface = interfaceForTypeNoWarning(typeId);
3333 if (!iface && typeId != QMetaType::UnknownType)
3334 qWarning(msg: "Trying to construct an instance of an invalid type, type id: %i", typeId);
3335
3336 return iface;
3337}
3338
3339/*!
3340 \fn QMetaType::QMetaType()
3341 \since 6.0
3342
3343 Constructs a default, invalid, QMetaType object.
3344*/
3345
3346/*!
3347 \fn QMetaType::QMetaType(int typeId)
3348 \since 5.0
3349
3350 Constructs a QMetaType object that contains all information about type \a typeId.
3351*/
3352QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
3353
3354
3355/*!
3356 \fn size_t qHash(QMetaType key, size_t seed)
3357 \qhashold{QMetaType}
3358 \since 6.4
3359*/
3360
3361namespace QtPrivate {
3362#if !defined(QT_BOOTSTRAPPED)
3363void QMetaTypeCopyTraits::warnAboutDeprecatedCopy(const char *name)
3364{
3365 qCWarning(lcMetatypeDeprecated, "QMetaType: copy construction of type '%s' is deprecated", name);
3366}
3367#endif
3368
3369#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
3370
3371// Explicit instantiation definition
3372#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
3373 template class QMetaTypeForType<Name>; \
3374 template struct QMetaTypeInterfaceWrapper<Name>;
3375QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3376QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3377QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3378QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3379QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3380
3381#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
3382#endif
3383}
3384
3385QT_END_NAMESPACE
3386

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