1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Copyright (C) 2018 Intel Corporation.
5** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the QtCore module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qvariant.h"
43#include "qbitarray.h"
44#include "qbytearray.h"
45#include "qdatastream.h"
46#include "qdebug.h"
47#include "qmap.h"
48#include "qdatetime.h"
49#if QT_CONFIG(easingcurve)
50#include "qeasingcurve.h"
51#endif
52#include "qlist.h"
53#if QT_CONFIG(regularexpression)
54#include "qregularexpression.h"
55#endif
56#include "qstring.h"
57#include "qstringlist.h"
58#include "qurl.h"
59#include "qlocale.h"
60#include "qregexp.h"
61#include "quuid.h"
62#if QT_CONFIG(itemmodel)
63#include "qabstractitemmodel.h"
64#endif
65#ifndef QT_BOOTSTRAPPED
66#include "qcborarray.h"
67#include "qcborcommon.h"
68#include "qcbormap.h"
69#include "qjsonvalue.h"
70#include "qjsonobject.h"
71#include "qjsonarray.h"
72#include "qjsondocument.h"
73#include "qbytearraylist.h"
74#endif
75#include "private/qvariant_p.h"
76#include "private/qlocale_p.h"
77#include "qmetatype_p.h"
78#include <qmetaobject.h>
79
80#ifndef QT_NO_GEOM_VARIANT
81#include "qsize.h"
82#include "qpoint.h"
83#include "qrect.h"
84#include "qline.h"
85#endif
86
87#include <cmath>
88#include <float.h>
89#include <cstring>
90
91QT_BEGIN_NAMESPACE
92
93namespace {
94class HandlersManager
95{
96 static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount];
97public:
98 const QVariant::Handler *operator[] (const uint typeId) const
99 {
100 return Handlers[QModulesPrivate::moduleForType(typeId)];
101 }
102
103 void registerHandler(const QModulesPrivate::Names name, const QVariant::Handler *handler)
104 {
105 Handlers[name] = handler;
106 }
107};
108} // namespace
109
110namespace {
111struct CoreTypesFilter {
112 template<typename T>
113 struct Acceptor {
114 static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsCore && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
115 };
116};
117} // annonymous
118
119namespace { // annonymous used to hide QVariant handlers
120
121static void construct(QVariant::Private *x, const void *copy)
122{
123 QVariantConstructor<CoreTypesFilter> constructor(x, copy);
124 QMetaTypeSwitcher::switcher<void>(logic&: constructor, type: x->type);
125}
126
127static void clear(QVariant::Private *d)
128{
129 QVariantDestructor<CoreTypesFilter> cleaner(d);
130 QMetaTypeSwitcher::switcher<void>(logic&: cleaner, type: d->type);
131}
132
133static bool isNull(const QVariant::Private *d)
134{
135 QVariantIsNull<CoreTypesFilter> isNull(d);
136 return QMetaTypeSwitcher::switcher<bool>(logic&: isNull, type: d->type);
137}
138
139/*!
140 \internal
141
142 Compares \a a to \a b. The caller guarantees that \a a and \a b
143 are of the same type.
144 */
145static bool compare(const QVariant::Private *a, const QVariant::Private *b)
146{
147 QVariantComparator<CoreTypesFilter> comparator(a, b);
148 return QMetaTypeSwitcher::switcher<bool>(logic&: comparator, type: a->type);
149}
150
151/*!
152 \internal
153 */
154static qlonglong qMetaTypeNumber(const QVariant::Private *d)
155{
156 switch (d->type) {
157 case QMetaType::Int:
158 return d->data.i;
159 case QMetaType::LongLong:
160 return d->data.ll;
161 case QMetaType::Char:
162 return qlonglong(d->data.c);
163 case QMetaType::SChar:
164 return qlonglong(d->data.sc);
165 case QMetaType::Short:
166 return qlonglong(d->data.s);
167 case QMetaType::Long:
168 return qlonglong(d->data.l);
169 case QMetaType::Float:
170 return qRound64(d: d->data.f);
171 case QMetaType::Double:
172 return qRound64(d: d->data.d);
173#ifndef QT_BOOTSTRAPPED
174 case QMetaType::QJsonValue:
175 return v_cast<QJsonValue>(d)->toDouble();
176 case QMetaType::QCborValue:
177 return v_cast<QCborValue>(d)->toInteger();
178#endif
179 }
180 Q_ASSERT(false);
181 return 0;
182}
183
184static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
185{
186 switch (d->type) {
187 case QMetaType::UInt:
188 return d->data.u;
189 case QMetaType::ULongLong:
190 return d->data.ull;
191 case QMetaType::UChar:
192 return d->data.uc;
193 case QMetaType::UShort:
194 return d->data.us;
195 case QMetaType::ULong:
196 return d->data.ul;
197 }
198 Q_ASSERT(false);
199 return 0;
200}
201
202static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
203{
204 *ok = true;
205
206 switch (uint(d->type)) {
207 case QMetaType::QString:
208 return v_cast<QString>(d)->toLongLong(ok);
209 case QMetaType::QChar:
210 return v_cast<QChar>(d)->unicode();
211 case QMetaType::QByteArray:
212 return v_cast<QByteArray>(d)->toLongLong(ok);
213 case QMetaType::Bool:
214 return qlonglong(d->data.b);
215#ifndef QT_BOOTSTRAPPED
216 case QMetaType::QCborValue:
217 if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble())
218 break;
219 return qMetaTypeNumber(d);
220 case QMetaType::QJsonValue:
221 if (!v_cast<QJsonValue>(d)->isDouble())
222 break;
223 Q_FALLTHROUGH();
224#endif
225 case QMetaType::Double:
226 case QMetaType::Int:
227 case QMetaType::Char:
228 case QMetaType::SChar:
229 case QMetaType::Short:
230 case QMetaType::Long:
231 case QMetaType::Float:
232 case QMetaType::LongLong:
233 return qMetaTypeNumber(d);
234 case QMetaType::ULongLong:
235 case QMetaType::UInt:
236 case QMetaType::UChar:
237 case QMetaType::UShort:
238 case QMetaType::ULong:
239
240 return qlonglong(qMetaTypeUNumber(d));
241 }
242
243 QMetaType typeInfo(d->type);
244 if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
245 switch (typeInfo.sizeOf()) {
246 case 1:
247 return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc;
248 case 2:
249 return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s;
250 case 4:
251 return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i;
252 case 8:
253 return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll;
254 }
255 }
256
257 *ok = false;
258 return Q_INT64_C(0);
259}
260
261static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
262{
263 *ok = true;
264 switch (uint(d->type)) {
265 case QMetaType::Double:
266 return qreal(d->data.d);
267 case QMetaType::Float:
268 return qreal(d->data.f);
269 case QMetaType::ULongLong:
270 case QMetaType::UInt:
271 case QMetaType::UChar:
272 case QMetaType::UShort:
273 case QMetaType::ULong:
274 return qreal(qMetaTypeUNumber(d));
275#ifndef QT_BOOTSTRAPPED
276 case QMetaType::QCborValue:
277 return v_cast<QCborValue>(d)->toDouble();
278 case QMetaType::QJsonValue:
279 return v_cast<QJsonValue>(d)->toDouble();
280#endif
281 default:
282 // includes enum conversion as well as invalid types
283 return qreal(qConvertToNumber(d, ok));
284 }
285}
286
287static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
288{
289 *ok = true;
290
291 switch (uint(d->type)) {
292 case QMetaType::QString:
293 return v_cast<QString>(d)->toULongLong(ok);
294 case QMetaType::QChar:
295 return v_cast<QChar>(d)->unicode();
296 case QMetaType::QByteArray:
297 return v_cast<QByteArray>(d)->toULongLong(ok);
298 case QMetaType::Bool:
299 return qulonglong(d->data.b);
300#ifndef QT_BOOTSTRAPPED
301 case QMetaType::QCborValue:
302 if (v_cast<QCborValue>(d)->isDouble())
303 return qulonglong(qConvertToRealNumber(d, ok));
304 if (!v_cast<QCborValue>(d)->isInteger())
305 return false;
306 return qulonglong(qMetaTypeNumber(d));
307 case QMetaType::QJsonValue:
308 if (!v_cast<QJsonValue>(d)->isDouble())
309 break;
310 Q_FALLTHROUGH();
311#endif
312 case QMetaType::Double:
313 case QMetaType::Int:
314 case QMetaType::Char:
315 case QMetaType::SChar:
316 case QMetaType::Short:
317 case QMetaType::Long:
318 case QMetaType::Float:
319 case QMetaType::LongLong:
320 return qulonglong(qMetaTypeNumber(d));
321 case QMetaType::ULongLong:
322 case QMetaType::UInt:
323 case QMetaType::UChar:
324 case QMetaType::UShort:
325 case QMetaType::ULong:
326 return qMetaTypeUNumber(d);
327 }
328
329 QMetaType typeInfo(d->type);
330 if (typeInfo.flags() & QMetaType::IsEnumeration) {
331 switch (typeInfo.sizeOf()) {
332 case 1:
333 return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc;
334 case 2:
335 return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us;
336 case 4:
337 return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u;
338 case 8:
339 return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull;
340 }
341 }
342
343 *ok = false;
344 return Q_UINT64_C(0);
345}
346
347template<typename TInput, typename LiteralWrapper>
348inline bool qt_convertToBool(const QVariant::Private *const d)
349{
350 TInput str = v_cast<TInput>(d)->toLower();
351 return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
352}
353
354/*!
355 \internal
356 Returns the internal data pointer from \a d.
357 */
358
359static const void *constData(const QVariant::Private &d)
360{
361 return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.c);
362}
363
364#ifndef QT_NO_QOBJECT
365/*!
366 \internal
367 returns a QMetaEnum for a given meta tape type id if possible
368*/
369static QMetaEnum metaEnumFromType(int type)
370{
371 QMetaType t(type);
372 if (t.flags() & QMetaType::IsEnumeration) {
373 if (const QMetaObject *metaObject = t.metaObject()) {
374 const char *enumName = QMetaType::typeName(type);
375 const char *lastColon = std::strrchr(s: enumName, c: ':');
376 if (lastColon)
377 enumName = lastColon + 1;
378 return metaObject->enumerator(index: metaObject->indexOfEnumerator(name: enumName));
379 }
380 }
381 return QMetaEnum();
382}
383#endif
384
385/*!
386 \internal
387
388 Converts \a d to type \a t, which is placed in \a result.
389 */
390static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
391{
392 Q_ASSERT(d->type != uint(t));
393 Q_ASSERT(result);
394
395 if (d->type >= QMetaType::User || t >= QMetaType::User) {
396 const bool isOk = QMetaType::convert(from: constData(d: *d), fromTypeId: d->type, to: result, toTypeId: t);
397 if (ok)
398 *ok = isOk;
399 if (isOk)
400 return true;
401 }
402
403 bool dummy;
404 if (!ok)
405 ok = &dummy;
406
407 switch (uint(t)) {
408#ifndef QT_BOOTSTRAPPED
409 case QMetaType::QUrl:
410 switch (d->type) {
411 case QMetaType::QString:
412 *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
413 break;
414 case QMetaType::QCborValue:
415 if (v_cast<QCborValue>(d)->isUrl()) {
416 *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl();
417 break;
418 }
419 return false;
420 default:
421 return false;
422 }
423 break;
424#endif // QT_BOOTSTRAPPED
425#if QT_CONFIG(itemmodel)
426 case QMetaType::QModelIndex:
427 switch (d->type) {
428 case QMetaType::QPersistentModelIndex:
429 *static_cast<QModelIndex *>(result) = QModelIndex(*v_cast<QPersistentModelIndex>(d));
430 break;
431 default:
432 return false;
433 }
434 break;
435 case QMetaType::QPersistentModelIndex:
436 switch (d->type) {
437 case QMetaType::QModelIndex:
438 *static_cast<QPersistentModelIndex *>(result) = QPersistentModelIndex(*v_cast<QModelIndex>(d));
439 break;
440 default:
441 return false;
442 }
443 break;
444#endif // QT_CONFIG(itemmodel)
445 case QMetaType::QString: {
446 QString *str = static_cast<QString *>(result);
447 switch (d->type) {
448 case QMetaType::QChar:
449 *str = *v_cast<QChar>(d);
450 break;
451 case QMetaType::Char:
452 case QMetaType::SChar:
453 case QMetaType::UChar:
454 *str = QChar::fromLatin1(c: d->data.c);
455 break;
456 case QMetaType::Short:
457 case QMetaType::Long:
458 case QMetaType::Int:
459 case QMetaType::LongLong:
460 *str = QString::number(qMetaTypeNumber(d));
461 break;
462 case QMetaType::UInt:
463 case QMetaType::ULongLong:
464 case QMetaType::UShort:
465 case QMetaType::ULong:
466 *str = QString::number(qMetaTypeUNumber(d));
467 break;
468 case QMetaType::Float:
469 *str = QString::number(d->data.f, f: 'g', prec: QLocale::FloatingPointShortest);
470 break;
471 case QMetaType::Double:
472 *str = QString::number(d->data.d, f: 'g', prec: QLocale::FloatingPointShortest);
473 break;
474#if QT_CONFIG(datestring)
475 case QMetaType::QDate:
476 *str = v_cast<QDate>(d)->toString(format: Qt::ISODate);
477 break;
478 case QMetaType::QTime:
479 *str = v_cast<QTime>(d)->toString(f: Qt::ISODateWithMs);
480 break;
481 case QMetaType::QDateTime:
482 *str = v_cast<QDateTime>(d)->toString(format: Qt::ISODateWithMs);
483 break;
484#endif
485 case QMetaType::Bool:
486 *str = d->data.b ? QStringLiteral("true") : QStringLiteral("false");
487 break;
488 case QMetaType::QByteArray:
489 *str = QString::fromUtf8(str: v_cast<QByteArray>(d)->constData());
490 break;
491 case QMetaType::QStringList:
492 if (v_cast<QStringList>(d)->count() == 1)
493 *str = v_cast<QStringList>(d)->at(i: 0);
494 break;
495#ifndef QT_BOOTSTRAPPED
496 case QMetaType::QUrl:
497 *str = v_cast<QUrl>(d)->toString();
498 break;
499 case QMetaType::QJsonValue:
500 if (v_cast<QJsonValue>(d)->isString())
501 *str = v_cast<QJsonValue>(d)->toString();
502 else if (!v_cast<QJsonValue>(d)->isNull())
503 return false;
504 break;
505 case QMetaType::QCborValue:
506 if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag())
507 return false;
508 *str = v_cast<QCborValue>(d)->toVariant().toString();
509 break;
510#endif
511 case QMetaType::QUuid:
512 *str = v_cast<QUuid>(d)->toString();
513 break;
514 case QMetaType::Nullptr:
515 *str = QString();
516 break;
517 default:
518#ifndef QT_NO_QOBJECT
519 {
520 QMetaEnum en = metaEnumFromType(type: d->type);
521 if (en.isValid()) {
522 *str = QString::fromUtf8(str: en.valueToKey(value: qConvertToNumber(d, ok)));
523 return *ok;
524 }
525 }
526#endif
527 return false;
528 }
529 break;
530 }
531 case QMetaType::QChar: {
532 QChar *c = static_cast<QChar *>(result);
533 switch (d->type) {
534 case QMetaType::Int:
535 case QMetaType::LongLong:
536 case QMetaType::Char:
537 case QMetaType::SChar:
538 case QMetaType::Short:
539 case QMetaType::Long:
540 case QMetaType::Float:
541 *c = QChar(ushort(qMetaTypeNumber(d)));
542 break;
543 case QMetaType::UInt:
544 case QMetaType::ULongLong:
545 case QMetaType::UChar:
546 case QMetaType::UShort:
547 case QMetaType::ULong:
548 *c = QChar(ushort(qMetaTypeUNumber(d)));
549 break;
550 default:
551 return false;
552 }
553 break;
554 }
555#ifndef QT_NO_GEOM_VARIANT
556 case QMetaType::QSize: {
557 QSize *s = static_cast<QSize *>(result);
558 switch (d->type) {
559 case QMetaType::QSizeF:
560 *s = v_cast<QSizeF>(d)->toSize();
561 break;
562 default:
563 return false;
564 }
565 break;
566 }
567
568 case QMetaType::QSizeF: {
569 QSizeF *s = static_cast<QSizeF *>(result);
570 switch (d->type) {
571 case QMetaType::QSize:
572 *s = QSizeF(*(v_cast<QSize>(d)));
573 break;
574 default:
575 return false;
576 }
577 break;
578 }
579
580 case QMetaType::QLine: {
581 QLine *s = static_cast<QLine *>(result);
582 switch (d->type) {
583 case QMetaType::QLineF:
584 *s = v_cast<QLineF>(d)->toLine();
585 break;
586 default:
587 return false;
588 }
589 break;
590 }
591
592 case QMetaType::QLineF: {
593 QLineF *s = static_cast<QLineF *>(result);
594 switch (d->type) {
595 case QMetaType::QLine:
596 *s = QLineF(*(v_cast<QLine>(d)));
597 break;
598 default:
599 return false;
600 }
601 break;
602 }
603#endif
604 case QMetaType::QStringList:
605 if (d->type == QMetaType::QVariantList) {
606 QStringList *slst = static_cast<QStringList *>(result);
607 const QVariantList *list = v_cast<QVariantList >(d);
608 const int size = list->size();
609 slst->reserve(alloc: size);
610 for (int i = 0; i < size; ++i)
611 slst->append(t: list->at(i).toString());
612 } else if (d->type == QMetaType::QString) {
613 QStringList *slst = static_cast<QStringList *>(result);
614 *slst = QStringList(*v_cast<QString>(d));
615 } else {
616 return false;
617 }
618 break;
619 case QMetaType::QDate: {
620 QDate *dt = static_cast<QDate *>(result);
621 if (d->type == QMetaType::QDateTime)
622 *dt = v_cast<QDateTime>(d)->date();
623#if QT_CONFIG(datestring)
624 else if (d->type == QMetaType::QString)
625 *dt = QDate::fromString(s: *v_cast<QString>(d), f: Qt::ISODate);
626#endif
627 else
628 return false;
629
630 return dt->isValid();
631 }
632 case QMetaType::QTime: {
633 QTime *t = static_cast<QTime *>(result);
634 switch (d->type) {
635 case QMetaType::QDateTime:
636 *t = v_cast<QDateTime>(d)->time();
637 break;
638#if QT_CONFIG(datestring)
639 case QMetaType::QString:
640 *t = QTime::fromString(s: *v_cast<QString>(d), f: Qt::ISODate);
641 break;
642#endif
643 default:
644 return false;
645 }
646 return t->isValid();
647 }
648 case QMetaType::QDateTime: {
649 QDateTime *dt = static_cast<QDateTime *>(result);
650 switch (d->type) {
651#if QT_CONFIG(datestring)
652 case QMetaType::QString:
653 *dt = QDateTime::fromString(s: *v_cast<QString>(d), f: Qt::ISODate);
654 break;
655# ifndef QT_BOOTSTRAPPED
656 case QMetaType::QCborValue:
657 if (v_cast<QCborValue>(d)->isDateTime())
658 *dt = v_cast<QCborValue>(d)->toDateTime();
659 else
660 return false;
661 break;
662# endif
663#endif
664 case QMetaType::QDate:
665 *dt = v_cast<QDate>(d)->startOfDay();
666 break;
667 default:
668 return false;
669 }
670 return dt->isValid();
671 }
672 case QMetaType::QByteArray: {
673 QByteArray *ba = static_cast<QByteArray *>(result);
674 switch (d->type) {
675 case QMetaType::QString:
676 *ba = v_cast<QString>(d)->toUtf8();
677 break;
678 case QMetaType::Double:
679 *ba = QByteArray::number(d->data.d, f: 'g', prec: QLocale::FloatingPointShortest);
680 break;
681 case QMetaType::Float:
682 *ba = QByteArray::number(d->data.f, f: 'g', prec: QLocale::FloatingPointShortest);
683 break;
684 case QMetaType::Char:
685 case QMetaType::SChar:
686 case QMetaType::UChar:
687 *ba = QByteArray(1, d->data.c);
688 break;
689 case QMetaType::Int:
690 case QMetaType::LongLong:
691 case QMetaType::Short:
692 case QMetaType::Long:
693 *ba = QByteArray::number(qMetaTypeNumber(d));
694 break;
695 case QMetaType::UInt:
696 case QMetaType::ULongLong:
697 case QMetaType::UShort:
698 case QMetaType::ULong:
699 *ba = QByteArray::number(qMetaTypeUNumber(d));
700 break;
701 case QMetaType::Bool:
702 *ba = QByteArray(d->data.b ? "true" : "false");
703 break;
704 case QMetaType::QUuid:
705 *ba = v_cast<QUuid>(d)->toByteArray();
706 break;
707 case QMetaType::Nullptr:
708 *ba = QByteArray();
709 break;
710#ifndef QT_BOOTSTRAPPED
711 case QMetaType::QCborValue:
712 if (v_cast<QCborValue>(d)->isByteArray())
713 *ba = v_cast<QCborValue>(d)->toByteArray();
714 else
715 return false;
716 break;
717#endif
718 default:
719#ifndef QT_NO_QOBJECT
720 {
721 QMetaEnum en = metaEnumFromType(type: d->type);
722 if (en.isValid()) {
723 *ba = en.valueToKey(value: qConvertToNumber(d, ok));
724 return *ok;
725 }
726 }
727#endif
728 return false;
729 }
730 }
731 break;
732 case QMetaType::Short:
733 *static_cast<short *>(result) = short(qConvertToNumber(d, ok));
734 return *ok;
735 case QMetaType::Long:
736 *static_cast<long *>(result) = long(qConvertToNumber(d, ok));
737 return *ok;
738 case QMetaType::UShort:
739 *static_cast<ushort *>(result) = ushort(qConvertToUnsignedNumber(d, ok));
740 return *ok;
741 case QMetaType::ULong:
742 *static_cast<ulong *>(result) = ulong(qConvertToUnsignedNumber(d, ok));
743 return *ok;
744 case QMetaType::Int:
745 *static_cast<int *>(result) = int(qConvertToNumber(d, ok));
746 return *ok;
747 case QMetaType::UInt:
748 *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok));
749 return *ok;
750 case QMetaType::LongLong:
751 *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok);
752 return *ok;
753 case QMetaType::ULongLong: {
754 *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok);
755 return *ok;
756 }
757 case QMetaType::SChar: {
758 signed char s = qConvertToNumber(d, ok);
759 *static_cast<signed char*>(result) = s;
760 return *ok;
761 }
762 case QMetaType::UChar: {
763 *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok);
764 return *ok;
765 }
766 case QMetaType::Bool: {
767 bool *b = static_cast<bool *>(result);
768 switch(d->type) {
769 case QMetaType::QByteArray:
770 *b = qt_convertToBool<QByteArray, const char*>(d);
771 break;
772 case QMetaType::QString:
773 *b = qt_convertToBool<QString, QLatin1String>(d);
774 break;
775 case QMetaType::QChar:
776 *b = !v_cast<QChar>(d)->isNull();
777 break;
778 case QMetaType::Double:
779 case QMetaType::Int:
780 case QMetaType::LongLong:
781 case QMetaType::Char:
782 case QMetaType::SChar:
783 case QMetaType::Short:
784 case QMetaType::Long:
785 case QMetaType::Float:
786 *b = qMetaTypeNumber(d) != Q_INT64_C(0);
787 break;
788 case QMetaType::UInt:
789 case QMetaType::ULongLong:
790 case QMetaType::UChar:
791 case QMetaType::UShort:
792 case QMetaType::ULong:
793 *b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
794 break;
795#ifndef QT_BOOTSTRAPPED
796 case QMetaType::QCborValue:
797 *b = v_cast<QCborValue>(d)->toBool();
798 if (!v_cast<QCborValue>(d)->isBool())
799 return false;
800 break;
801 case QMetaType::QJsonValue:
802 *b = v_cast<QJsonValue>(d)->toBool(defaultValue: false);
803 if (!v_cast<QJsonValue>(d)->isBool())
804 return false;
805 break;
806#endif
807 default:
808 *b = false;
809 return false;
810 }
811 break;
812 }
813 case QMetaType::Double: {
814 double *f = static_cast<double *>(result);
815 switch (d->type) {
816 case QMetaType::QString:
817 *f = v_cast<QString>(d)->toDouble(ok);
818 break;
819 case QMetaType::QByteArray:
820 *f = v_cast<QByteArray>(d)->toDouble(ok);
821 break;
822 case QMetaType::Bool:
823 *f = double(d->data.b);
824 break;
825 case QMetaType::Float:
826 *f = double(d->data.f);
827 break;
828 case QMetaType::LongLong:
829 case QMetaType::Int:
830 case QMetaType::Char:
831 case QMetaType::SChar:
832 case QMetaType::Short:
833 case QMetaType::Long:
834 *f = double(qMetaTypeNumber(d));
835 break;
836 case QMetaType::UInt:
837 case QMetaType::ULongLong:
838 case QMetaType::UChar:
839 case QMetaType::UShort:
840 case QMetaType::ULong:
841 *f = double(qMetaTypeUNumber(d));
842 break;
843#ifndef QT_BOOTSTRAPPED
844 case QMetaType::QCborValue:
845 *f = v_cast<QCborValue>(d)->toDouble();
846 if (!v_cast<QCborValue>(d)->isDouble())
847 return false;
848 break;
849 case QMetaType::QJsonValue:
850 *f = v_cast<QJsonValue>(d)->toDouble(defaultValue: 0.0);
851 if (!v_cast<QJsonValue>(d)->isDouble())
852 return false;
853 break;
854#endif
855 default:
856 *f = 0.0;
857 return false;
858 }
859 break;
860 }
861 case QMetaType::Float: {
862 float *f = static_cast<float *>(result);
863 switch (d->type) {
864 case QMetaType::QString:
865 *f = v_cast<QString>(d)->toFloat(ok);
866 break;
867 case QMetaType::QByteArray:
868 *f = v_cast<QByteArray>(d)->toFloat(ok);
869 break;
870 case QMetaType::Bool:
871 *f = float(d->data.b);
872 break;
873 case QMetaType::Double:
874 *f = float(d->data.d);
875 break;
876 case QMetaType::LongLong:
877 case QMetaType::Int:
878 case QMetaType::Char:
879 case QMetaType::SChar:
880 case QMetaType::Short:
881 case QMetaType::Long:
882 *f = float(qMetaTypeNumber(d));
883 break;
884 case QMetaType::UInt:
885 case QMetaType::ULongLong:
886 case QMetaType::UChar:
887 case QMetaType::UShort:
888 case QMetaType::ULong:
889 *f = float(qMetaTypeUNumber(d));
890 break;
891#ifndef QT_BOOTSTRAPPED
892 case QMetaType::QCborValue:
893 *f = v_cast<QCborValue>(d)->toDouble();
894 if (!v_cast<QCborValue>(d)->isDouble())
895 return false;
896 break;
897 case QMetaType::QJsonValue:
898 *f = v_cast<QJsonValue>(d)->toDouble(defaultValue: 0.0);
899 if (!v_cast<QJsonValue>(d)->isDouble())
900 return false;
901 break;
902#endif
903 default:
904 *f = 0.0f;
905 return false;
906 }
907 break;
908 }
909 case QMetaType::QVariantList:
910 if (d->type == QMetaType::QStringList) {
911 QVariantList *lst = static_cast<QVariantList *>(result);
912 const QStringList *slist = v_cast<QStringList>(d);
913 const int size = slist->size();
914 lst->reserve(alloc: size);
915 for (int i = 0; i < size; ++i)
916 lst->append(t: QVariant(slist->at(i)));
917 } else if (qstrcmp(str1: QMetaType::typeName(type: d->type), str2: "QList<QVariant>") == 0) {
918 *static_cast<QVariantList *>(result) =
919 *static_cast<QList<QVariant> *>(d->data.shared->ptr);
920#ifndef QT_BOOTSTRAPPED
921 } else if (d->type == QMetaType::QCborValue) {
922 if (!v_cast<QCborValue>(d)->isArray())
923 return false;
924 *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList();
925 } else if (d->type == QMetaType::QCborArray) {
926 *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList();
927 } else if (d->type == QMetaType::QJsonValue) {
928 if (!v_cast<QJsonValue>(d)->isArray())
929 return false;
930 *static_cast<QVariantList *>(result) = v_cast<QJsonValue>(d)->toArray().toVariantList();
931 } else if (d->type == QMetaType::QJsonArray) {
932 *static_cast<QVariantList *>(result) = v_cast<QJsonArray>(d)->toVariantList();
933#endif
934 } else {
935 return false;
936 }
937 break;
938 case QMetaType::QVariantMap:
939 if (qstrcmp(str1: QMetaType::typeName(type: d->type), str2: "QMap<QString, QVariant>") == 0) {
940 *static_cast<QVariantMap *>(result) =
941 *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr);
942 } else if (d->type == QMetaType::QVariantHash) {
943 QVariantMap *map = static_cast<QVariantMap *>(result);
944 const QVariantHash *hash = v_cast<QVariantHash>(d);
945 const auto end = hash->end();
946 for (auto it = hash->begin(); it != end; ++it)
947 static_cast<QMultiMap<QString, QVariant> *>(map)->insert(akey: it.key(), avalue: it.value());
948#ifndef QT_BOOTSTRAPPED
949 } else if (d->type == QMetaType::QCborValue) {
950 if (!v_cast<QCborValue>(d)->isMap())
951 return false;
952 *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap();
953 } else if (d->type == QMetaType::QCborMap) {
954 *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap();
955 } else if (d->type == QMetaType::QJsonValue) {
956 if (!v_cast<QJsonValue>(d)->isObject())
957 return false;
958 *static_cast<QVariantMap *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantMap();
959 } else if (d->type == QMetaType::QJsonObject) {
960 *static_cast<QVariantMap *>(result) = v_cast<QJsonObject>(d)->toVariantMap();
961#endif
962 } else {
963 return false;
964 }
965 break;
966 case QMetaType::QVariantHash:
967 if (qstrcmp(str1: QMetaType::typeName(type: d->type), str2: "QHash<QString, QVariant>") == 0) {
968 *static_cast<QVariantHash *>(result) =
969 *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr);
970 } else if (d->type == QMetaType::QVariantMap) {
971 QVariantHash *hash = static_cast<QVariantHash *>(result);
972 const QVariantMap *map = v_cast<QVariantMap>(d);
973 const auto end = map->end();
974 for (auto it = map->begin(); it != end; ++it)
975 static_cast<QMultiHash<QString, QVariant> *>(hash)->insert(akey: it.key(), avalue: it.value());
976#ifndef QT_BOOTSTRAPPED
977 } else if (d->type == QMetaType::QCborValue) {
978 if (!v_cast<QCborValue>(d)->isMap())
979 return false;
980 *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash();
981 } else if (d->type == QMetaType::QCborMap) {
982 *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash();
983 } else if (d->type == QMetaType::QJsonValue) {
984 if (!v_cast<QJsonValue>(d)->isObject())
985 return false;
986 *static_cast<QVariantHash *>(result) = v_cast<QJsonValue>(d)->toObject().toVariantHash();
987 } else if (d->type == QMetaType::QJsonObject) {
988 *static_cast<QVariantHash *>(result) = v_cast<QJsonObject>(d)->toVariantHash();
989#endif
990 } else {
991 return false;
992 }
993 break;
994#ifndef QT_NO_GEOM_VARIANT
995 case QMetaType::QRect:
996 if (d->type == QMetaType::QRectF)
997 *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect();
998 else
999 return false;
1000 break;
1001 case QMetaType::QRectF:
1002 if (d->type == QMetaType::QRect)
1003 *static_cast<QRectF *>(result) = *v_cast<QRect>(d);
1004 else
1005 return false;
1006 break;
1007 case QMetaType::QPointF:
1008 if (d->type == QMetaType::QPoint)
1009 *static_cast<QPointF *>(result) = *v_cast<QPoint>(d);
1010 else
1011 return false;
1012 break;
1013 case QMetaType::QPoint:
1014 if (d->type == QMetaType::QPointF)
1015 *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint();
1016 else
1017 return false;
1018 break;
1019 case QMetaType::Char:
1020 {
1021 *static_cast<qint8 *>(result) = qint8(qConvertToNumber(d, ok));
1022 return *ok;
1023 }
1024#endif
1025 case QMetaType::QUuid:
1026 switch (d->type) {
1027 case QMetaType::QString:
1028 *static_cast<QUuid *>(result) = QUuid(*v_cast<QString>(d));
1029 break;
1030 case QMetaType::QByteArray:
1031 *static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d));
1032 break;
1033#ifndef QT_BOOTSTRAPPED
1034 case QMetaType::QCborValue:
1035 if (!v_cast<QCborValue>(d)->isUuid())
1036 return false;
1037 *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid();
1038 break;
1039#endif
1040 default:
1041 return false;
1042 }
1043 break;
1044 case QMetaType::Nullptr:
1045 *static_cast<std::nullptr_t *>(result) = nullptr;
1046 if (QMetaType::typeFlags(type: t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject)
1047 || d->type == QMetaType::VoidStar) {
1048 if (v_cast<const void *>(d) == nullptr)
1049 break;
1050 }
1051#ifndef QT_BOOTSTRAPPED
1052 if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull())
1053 break;
1054#endif
1055 return false;
1056
1057#ifndef QT_BOOTSTRAPPED
1058#if QT_CONFIG(regularexpression)
1059 case QMetaType::QRegularExpression:
1060 if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression())
1061 return false;
1062 *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression();
1063 break;
1064#endif
1065 case QMetaType::QJsonValue:
1066 switch (d->type) {
1067 case QMetaType::Nullptr:
1068 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null);
1069 break;
1070 case QMetaType::Bool:
1071 *static_cast<QJsonValue *>(result) = QJsonValue(d->data.b);
1072 break;
1073 case QMetaType::Int:
1074 case QMetaType::UInt:
1075 case QMetaType::Double:
1076 case QMetaType::Float:
1077 case QMetaType::ULong:
1078 case QMetaType::Long:
1079 case QMetaType::LongLong:
1080 case QMetaType::ULongLong:
1081 case QMetaType::UShort:
1082 case QMetaType::UChar:
1083 case QMetaType::Char:
1084 case QMetaType::SChar:
1085 case QMetaType::Short:
1086 *static_cast<QJsonValue *>(result) = QJsonValue(qConvertToRealNumber(d, ok));
1087 Q_ASSERT(ok);
1088 break;
1089 case QMetaType::QString:
1090 *static_cast<QJsonValue *>(result) = QJsonValue(*v_cast<QString>(d));
1091 break;
1092 case QMetaType::QStringList:
1093 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromStringList(list: *v_cast<QStringList>(d)));
1094 break;
1095 case QMetaType::QVariantList:
1096 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromVariantList(list: *v_cast<QVariantList>(d)));
1097 break;
1098 case QMetaType::QVariantMap:
1099 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantMap(map: *v_cast<QVariantMap>(d)));
1100 break;
1101 case QMetaType::QVariantHash:
1102 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantHash(map: *v_cast<QVariantHash>(d)));
1103 break;
1104 case QMetaType::QJsonObject:
1105 *static_cast<QJsonValue *>(result) = *v_cast<QJsonObject>(d);
1106 break;
1107 case QMetaType::QJsonArray:
1108 *static_cast<QJsonValue *>(result) = *v_cast<QJsonArray>(d);
1109 break;
1110 case QMetaType::QJsonDocument: {
1111 QJsonDocument doc = *v_cast<QJsonDocument>(d);
1112 *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
1113 break;
1114 }
1115 case QMetaType::QCborValue:
1116 *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue();
1117 break;
1118 case QMetaType::QCborMap:
1119 *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject();
1120 break;
1121 case QMetaType::QCborArray:
1122 *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray();
1123 break;
1124 default:
1125 *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
1126 return false;
1127 }
1128 break;
1129 case QMetaType::QJsonArray:
1130 switch (d->type) {
1131 case QMetaType::QStringList:
1132 *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(list: *v_cast<QStringList>(d));
1133 break;
1134 case QMetaType::QVariantList:
1135 *static_cast<QJsonArray *>(result) = QJsonArray::fromVariantList(list: *v_cast<QVariantList>(d));
1136 break;
1137 case QMetaType::QJsonValue:
1138 if (!v_cast<QJsonValue>(d)->isArray())
1139 return false;
1140 *static_cast<QJsonArray *>(result) = v_cast<QJsonValue>(d)->toArray();
1141 break;
1142 case QMetaType::QJsonDocument:
1143 if (!v_cast<QJsonDocument>(d)->isArray())
1144 return false;
1145 *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
1146 break;
1147 case QMetaType::QCborValue:
1148 if (!v_cast<QCborValue>(d)->isArray())
1149 return false;
1150 *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray();
1151 break;
1152 case QMetaType::QCborArray:
1153 *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray();
1154 break;
1155 default:
1156 return false;
1157 }
1158 break;
1159 case QMetaType::QJsonObject:
1160 switch (d->type) {
1161 case QMetaType::QVariantMap:
1162 *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(map: *v_cast<QVariantMap>(d));
1163 break;
1164 case QMetaType::QVariantHash:
1165 *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantHash(map: *v_cast<QVariantHash>(d));
1166 break;
1167 case QMetaType::QJsonValue:
1168 if (!v_cast<QJsonValue>(d)->isObject())
1169 return false;
1170 *static_cast<QJsonObject *>(result) = v_cast<QJsonValue>(d)->toObject();
1171 break;
1172 case QMetaType::QJsonDocument:
1173 if (v_cast<QJsonDocument>(d)->isArray())
1174 return false;
1175 *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
1176 break;
1177 case QMetaType::QCborValue:
1178 if (!v_cast<QCborValue>(d)->isMap())
1179 return false;
1180 *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject();
1181 break;
1182 case QMetaType::QCborMap:
1183 *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject();
1184 break;
1185 default:
1186 return false;
1187 }
1188 break;
1189 case QMetaType::QCborSimpleType:
1190 if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) {
1191 *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType();
1192 break;
1193 }
1194 return false;
1195 case QMetaType::QCborValue:
1196 switch (d->type) {
1197 case QMetaType::Nullptr:
1198 *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null);
1199 break;
1200 case QMetaType::Bool:
1201 *static_cast<QCborValue *>(result) = QCborValue(d->data.b);
1202 break;
1203 case QMetaType::Int:
1204 case QMetaType::UInt:
1205 case QMetaType::ULong:
1206 case QMetaType::Long:
1207 case QMetaType::LongLong:
1208 case QMetaType::ULongLong:
1209 case QMetaType::UShort:
1210 case QMetaType::UChar:
1211 case QMetaType::Char:
1212 case QMetaType::SChar:
1213 case QMetaType::Short:
1214 *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok));
1215 Q_ASSERT(ok);
1216 break;
1217 case QMetaType::Double:
1218 case QMetaType::Float:
1219 *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok));
1220 Q_ASSERT(ok);
1221 break;
1222 case QMetaType::QString:
1223 *static_cast<QCborValue *>(result) = *v_cast<QString>(d);
1224 break;
1225 case QMetaType::QStringList:
1226 *static_cast<QCborValue *>(result) = QCborArray::fromStringList(list: *v_cast<QStringList>(d));
1227 break;
1228 case QMetaType::QByteArray:
1229 *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
1230 break;
1231 case QMetaType::QDate:
1232 *static_cast<QCborValue *>(result) = QCborValue(v_cast<QDate>(d)->startOfDay());
1233 break;
1234 case QMetaType::QDateTime:
1235 *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
1236 break;
1237 case QMetaType::QUrl:
1238 *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d));
1239 break;
1240#if QT_CONFIG(regularexpression)
1241 case QMetaType::QRegularExpression:
1242 *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d));
1243 break;
1244#endif
1245 case QMetaType::QUuid:
1246 *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d));
1247 break;
1248 case QMetaType::QVariantList:
1249 *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(list: *v_cast<QVariantList>(d));
1250 break;
1251 case QMetaType::QVariantMap:
1252 *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(map: *v_cast<QVariantMap>(d));
1253 break;
1254 case QMetaType::QVariantHash:
1255 *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(hash: *v_cast<QVariantHash>(d));
1256 break;
1257 case QMetaType::QJsonValue:
1258 *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(v: *v_cast<QJsonValue>(d));
1259 break;
1260 case QMetaType::QJsonObject:
1261 *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(o: *v_cast<QJsonObject>(d));
1262 break;
1263 case QMetaType::QJsonArray:
1264 *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(array: *v_cast<QJsonArray>(d));
1265 break;
1266 case QMetaType::QJsonDocument: {
1267 QJsonDocument doc = *v_cast<QJsonDocument>(d);
1268 if (doc.isArray())
1269 *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(array: doc.array());
1270 else
1271 *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(o: doc.object());
1272 break;
1273 }
1274 case QMetaType::QCborSimpleType:
1275 *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d);
1276 break;
1277 case QMetaType::QCborMap:
1278 *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d);
1279 break;
1280 case QMetaType::QCborArray:
1281 *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d);
1282 break;
1283 default:
1284 *static_cast<QCborValue *>(result) = {};
1285 return false;
1286 }
1287 break;
1288 case QMetaType::QCborArray:
1289 switch (d->type) {
1290 case QMetaType::QStringList:
1291 *static_cast<QCborArray *>(result) = QCborArray::fromStringList(list: *v_cast<QStringList>(d));
1292 break;
1293 case QMetaType::QVariantList:
1294 *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(list: *v_cast<QVariantList>(d));
1295 break;
1296 case QMetaType::QCborValue:
1297 if (!v_cast<QCborValue>(d)->isArray())
1298 return false;
1299 *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray();
1300 break;
1301 case QMetaType::QJsonDocument:
1302 if (!v_cast<QJsonDocument>(d)->isArray())
1303 return false;
1304 *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(array: v_cast<QJsonDocument>(d)->array());
1305 break;
1306 case QMetaType::QJsonValue:
1307 if (!v_cast<QJsonValue>(d)->isArray())
1308 return false;
1309 *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(array: v_cast<QJsonValue>(d)->toArray());
1310 break;
1311 case QMetaType::QJsonArray:
1312 *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(array: *v_cast<QJsonArray>(d));
1313 break;
1314 default:
1315 return false;
1316 }
1317 break;
1318 case QMetaType::QCborMap:
1319 switch (d->type) {
1320 case QMetaType::QVariantMap:
1321 *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(map: *v_cast<QVariantMap>(d));
1322 break;
1323 case QMetaType::QVariantHash:
1324 *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(hash: *v_cast<QVariantHash>(d));
1325 break;
1326 case QMetaType::QCborValue:
1327 if (!v_cast<QCborValue>(d)->isMap())
1328 return false;
1329 *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap();
1330 break;
1331 case QMetaType::QJsonDocument:
1332 if (v_cast<QJsonDocument>(d)->isArray())
1333 return false;
1334 *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(o: v_cast<QJsonDocument>(d)->object());
1335 break;
1336 case QMetaType::QJsonValue:
1337 if (!v_cast<QJsonValue>(d)->isObject())
1338 return false;
1339 *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(o: v_cast<QJsonValue>(d)->toObject());
1340 break;
1341 case QMetaType::QJsonObject:
1342 *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(o: *v_cast<QJsonObject>(d));
1343 break;
1344 default:
1345 return false;
1346 }
1347 break;
1348#endif
1349
1350 default:
1351#ifndef QT_NO_QOBJECT
1352 if (d->type == QMetaType::QString || d->type == QMetaType::QByteArray) {
1353 QMetaEnum en = metaEnumFromType(type: t);
1354 if (en.isValid()) {
1355 QByteArray keys = (d->type == QMetaType::QString) ? v_cast<QString>(d)->toUtf8() : *v_cast<QByteArray>(d);
1356 int value = en.keysToValue(keys: keys.constData(), ok);
1357 if (*ok) {
1358 switch (QMetaType::sizeOf(type: t)) {
1359 case 1:
1360 *static_cast<signed char *>(result) = value;
1361 return true;
1362 case 2:
1363 *static_cast<qint16 *>(result) = value;
1364 return true;
1365 case 4:
1366 *static_cast<qint32 *>(result) = value;
1367 return true;
1368 case 8:
1369 *static_cast<qint64 *>(result) = value;
1370 return true;
1371 }
1372 }
1373 }
1374 }
1375#endif
1376 if (QMetaType::typeFlags(type: t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
1377 qlonglong value = qConvertToNumber(d, ok);
1378 if (*ok) {
1379 switch (QMetaType::sizeOf(type: t)) {
1380 case 1:
1381 *static_cast<signed char *>(result) = value;
1382 return true;
1383 case 2:
1384 *static_cast<qint16 *>(result) = value;
1385 return true;
1386 case 4:
1387 *static_cast<qint32 *>(result) = value;
1388 return true;
1389 case 8:
1390 *static_cast<qint64 *>(result) = value;
1391 return true;
1392 }
1393 }
1394 return *ok;
1395 }
1396 return false;
1397 }
1398 return true;
1399}
1400
1401#if !defined(QT_NO_DEBUG_STREAM)
1402static void streamDebug(QDebug dbg, const QVariant &v)
1403{
1404 QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
1405 QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
1406 QMetaTypeSwitcher::switcher<void>(logic&: stream, type: d->type);
1407}
1408#endif
1409
1410const QVariant::Handler qt_kernel_variant_handler = {
1411 .construct: construct,
1412 .clear: clear,
1413 .isNull: isNull,
1414#ifndef QT_NO_DATASTREAM
1415 .load: nullptr,
1416 .save: nullptr,
1417#endif
1418 .compare: compare,
1419 .convert: convert,
1420 .canConvert: nullptr,
1421#if !defined(QT_NO_DEBUG_STREAM)
1422 .debugStream: streamDebug
1423#else
1424 nullptr
1425#endif
1426};
1427
1428static void dummyConstruct(QVariant::Private *, const void *) { Q_ASSERT_X(false, "QVariant", "Trying to construct an unknown type"); }
1429static void dummyClear(QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to clear an unknown type"); }
1430static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; }
1431static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; }
1432static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; }
1433#if !defined(QT_NO_DEBUG_STREAM)
1434static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); }
1435#endif
1436const QVariant::Handler qt_dummy_variant_handler = {
1437 .construct: dummyConstruct,
1438 .clear: dummyClear,
1439 .isNull: dummyIsNull,
1440#ifndef QT_NO_DATASTREAM
1441 .load: nullptr,
1442 .save: nullptr,
1443#endif
1444 .compare: dummyCompare,
1445 .convert: dummyConvert,
1446 .canConvert: nullptr,
1447#if !defined(QT_NO_DEBUG_STREAM)
1448 .debugStream: dummyStreamDebug
1449#else
1450 nullptr
1451#endif
1452};
1453
1454static void customConstruct(QVariant::Private *d, const void *copy)
1455{
1456 const QMetaType type(d->type);
1457 const uint size = type.sizeOf();
1458 if (!size) {
1459 qWarning(msg: "Trying to construct an instance of an invalid type, type id: %i", d->type);
1460 d->type = QMetaType::UnknownType;
1461 return;
1462 }
1463
1464 // this logic should match with QVariantIntegrator::CanUseInternalSpace
1465 if (size <= sizeof(QVariant::Private::Data)
1466 && (type.flags() & (QMetaType::MovableType | QMetaType::IsEnumeration))) {
1467 type.construct(where: &d->data.ptr, copy);
1468 d->is_null = d->data.ptr == nullptr;
1469 d->is_shared = false;
1470 } else {
1471 // Private::Data contains long long, and long double is the biggest standard type.
1472 const size_t maxAlignment =
1473 qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double));
1474 const size_t s = sizeof(QVariant::PrivateShared);
1475 const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
1476 void *data = operator new(offset + size);
1477 void *ptr = static_cast<char *>(data) + offset;
1478 type.construct(where: ptr, copy);
1479 d->is_null = ptr == nullptr;
1480 d->is_shared = true;
1481 d->data.shared = new (data) QVariant::PrivateShared(ptr);
1482 }
1483}
1484
1485static void customClear(QVariant::Private *d)
1486{
1487 if (!d->is_shared) {
1488 QMetaType::destruct(type: d->type, where: &d->data.ptr);
1489 } else {
1490 QMetaType::destruct(type: d->type, where: d->data.shared->ptr);
1491 d->data.shared->~PrivateShared();
1492 operator delete(d->data.shared);
1493 }
1494}
1495
1496static bool customIsNull(const QVariant::Private *d)
1497{
1498 if (d->is_null)
1499 return true;
1500 const char *const typeName = QMetaType::typeName(type: d->type);
1501 if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(d->type)))
1502 qFatal(msg: "QVariant::isNull: type %d unknown to QVariant.", d->type);
1503 uint typeNameLen = qstrlen(str: typeName);
1504 if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') {
1505 const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data.ptr);
1506 return *static_cast<void *const *>(d_ptr) == nullptr;
1507 }
1508 return false;
1509}
1510
1511static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
1512{
1513 const char *const typeName = QMetaType::typeName(type: a->type);
1514 if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(a->type)))
1515 qFatal(msg: "QVariant::compare: type %d unknown to QVariant.", a->type);
1516
1517 const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
1518 const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
1519
1520 uint typeNameLen = qstrlen(str: typeName);
1521 if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
1522 return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
1523
1524 if (a->is_null && b->is_null)
1525 return true;
1526
1527 return !memcmp(s1: a_ptr, s2: b_ptr, n: QMetaType::sizeOf(type: a->type));
1528}
1529
1530static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok)
1531{
1532 if (d->type >= QMetaType::User || t >= QMetaType::User) {
1533 if (QMetaType::convert(from: constData(d: *d), fromTypeId: d->type, to: result, toTypeId: t)) {
1534 if (ok)
1535 *ok = true;
1536 return true;
1537 }
1538 }
1539 return convert(d, t, result, ok);
1540}
1541
1542#if !defined(QT_NO_DEBUG_STREAM)
1543static void customStreamDebug(QDebug dbg, const QVariant &variant) {
1544#ifndef QT_BOOTSTRAPPED
1545 QMetaType::TypeFlags flags = QMetaType::typeFlags(type: variant.userType());
1546 if (flags & QMetaType::PointerToQObject)
1547 dbg.nospace() << qvariant_cast<QObject*>(v: variant);
1548#else
1549 Q_UNUSED(dbg);
1550 Q_UNUSED(variant);
1551#endif
1552}
1553#endif
1554
1555const QVariant::Handler qt_custom_variant_handler = {
1556 .construct: customConstruct,
1557 .clear: customClear,
1558 .isNull: customIsNull,
1559#ifndef QT_NO_DATASTREAM
1560 .load: nullptr,
1561 .save: nullptr,
1562#endif
1563 .compare: customCompare,
1564 .convert: customConvert,
1565 .canConvert: nullptr,
1566#if !defined(QT_NO_DEBUG_STREAM)
1567 .debugStream: customStreamDebug
1568#else
1569 nullptr
1570#endif
1571};
1572
1573} // annonymous used to hide QVariant handlers
1574
1575static HandlersManager handlerManager;
1576Q_STATIC_ASSERT_X(!QModulesPrivate::Core, "Initialization assumes that ModulesNames::Core is 0");
1577const QVariant::Handler *HandlersManager::Handlers[QModulesPrivate::ModulesCount]
1578 = { &qt_kernel_variant_handler, &qt_dummy_variant_handler,
1579 &qt_dummy_variant_handler, &qt_custom_variant_handler };
1580
1581Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
1582{
1583 return &qt_kernel_variant_handler;
1584}
1585
1586Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names */name, const QVariant::Handler *handler)
1587{
1588 handlerManager.registerHandler(name: static_cast<QModulesPrivate::Names>(name), handler);
1589}
1590
1591/*!
1592 \class QVariant
1593 \inmodule QtCore
1594 \brief The QVariant class acts like a union for the most common Qt data types.
1595
1596 \ingroup objectmodel
1597 \ingroup shared
1598
1599
1600 Because C++ forbids unions from including types that have
1601 non-default constructors or destructors, most interesting Qt
1602 classes cannot be used in unions. Without QVariant, this would be
1603 a problem for QObject::property() and for database work, etc.
1604
1605 A QVariant object holds a single value of a single type() at a
1606 time. (Some type()s are multi-valued, for example a string list.)
1607 You can find out what type, T, the variant holds, convert it to a
1608 different type using convert(), get its value using one of the
1609 toT() functions (e.g., toSize()) and check whether the type can
1610 be converted to a particular type using canConvert().
1611
1612 The methods named toT() (e.g., toInt(), toString()) are const. If
1613 you ask for the stored type, they return a copy of the stored
1614 object. If you ask for a type that can be generated from the
1615 stored type, toT() copies and converts and leaves the object
1616 itself unchanged. If you ask for a type that cannot be generated
1617 from the stored type, the result depends on the type; see the
1618 function documentation for details.
1619
1620 Here is some example code to demonstrate the use of QVariant:
1621
1622 \snippet code/src_corelib_kernel_qvariant.cpp 0
1623
1624 You can even store QList<QVariant> and QMap<QString, QVariant>
1625 values in a variant, so you can easily construct arbitrarily
1626 complex data structures of arbitrary types. This is very powerful
1627 and versatile, but may prove less memory and speed efficient than
1628 storing specific types in standard data structures.
1629
1630 QVariant also supports the notion of null values, where you can
1631 have a defined type with no value set. However, note that QVariant
1632 types can only be cast when they have had a value set.
1633
1634 \snippet code/src_corelib_kernel_qvariant.cpp 1
1635
1636 QVariant can be extended to support other types than those
1637 mentioned in the \l Type enum. See \l{Creating Custom Qt Types}{Creating Custom Qt Types}
1638 for details.
1639
1640 \section1 A Note on GUI Types
1641
1642 Because QVariant is part of the Qt Core module, it cannot provide
1643 conversion functions to data types defined in Qt GUI, such as
1644 QColor, QImage, and QPixmap. In other words, there is no \c
1645 toColor() function. Instead, you can use the QVariant::value() or
1646 the qvariant_cast() template function. For example:
1647
1648 \snippet code/src_corelib_kernel_qvariant.cpp 2
1649
1650 The inverse conversion (e.g., from QColor to QVariant) is
1651 automatic for all data types supported by QVariant, including
1652 GUI-related types:
1653
1654 \snippet code/src_corelib_kernel_qvariant.cpp 3
1655
1656 \section1 Using canConvert() and convert() Consecutively
1657
1658 When using canConvert() and convert() consecutively, it is possible for
1659 canConvert() to return true, but convert() to return false. This
1660 is typically because canConvert() only reports the general ability of
1661 QVariant to convert between types given suitable data; it is still
1662 possible to supply data which cannot actually be converted.
1663
1664 For example, canConvert(Int) would return true when called on a variant
1665 containing a string because, in principle, QVariant is able to convert
1666 strings of numbers to integers.
1667 However, if the string contains non-numeric characters, it cannot be
1668 converted to an integer, and any attempt to convert it will fail.
1669 Hence, it is important to have both functions return true for a
1670 successful conversion.
1671
1672 \sa QMetaType
1673*/
1674
1675/*!
1676 \obsolete Use QMetaType::Type instead
1677 \enum QVariant::Type
1678
1679 This enum type defines the types of variable that a QVariant can
1680 contain.
1681
1682 \value Invalid no type
1683 \value BitArray a QBitArray
1684 \value Bitmap a QBitmap
1685 \value Bool a bool
1686 \value Brush a QBrush
1687 \value ByteArray a QByteArray
1688 \value Char a QChar
1689 \value Color a QColor
1690 \value Cursor a QCursor
1691 \value Date a QDate
1692 \value DateTime a QDateTime
1693 \value Double a double
1694 \value EasingCurve a QEasingCurve
1695 \value Uuid a QUuid
1696 \value ModelIndex a QModelIndex
1697 \value PersistentModelIndex a QPersistentModelIndex (since 5.5)
1698 \value Font a QFont
1699 \value Hash a QVariantHash
1700 \value Icon a QIcon
1701 \value Image a QImage
1702 \value Int an int
1703 \value KeySequence a QKeySequence
1704 \value Line a QLine
1705 \value LineF a QLineF
1706 \value List a QVariantList
1707 \value Locale a QLocale
1708 \value LongLong a \l qlonglong
1709 \value Map a QVariantMap
1710 \value Matrix a QMatrix
1711 \value Transform a QTransform
1712 \value Matrix4x4 a QMatrix4x4
1713 \value Palette a QPalette
1714 \value Pen a QPen
1715 \value Pixmap a QPixmap
1716 \value Point a QPoint
1717 \value PointF a QPointF
1718 \value Polygon a QPolygon
1719 \value PolygonF a QPolygonF
1720 \value Quaternion a QQuaternion
1721 \value Rect a QRect
1722 \value RectF a QRectF
1723 \value RegExp a QRegExp
1724 \value RegularExpression a QRegularExpression
1725 \value Region a QRegion
1726 \value Size a QSize
1727 \value SizeF a QSizeF
1728 \value SizePolicy a QSizePolicy
1729 \value String a QString
1730 \value StringList a QStringList
1731 \value TextFormat a QTextFormat
1732 \value TextLength a QTextLength
1733 \value Time a QTime
1734 \value UInt a \l uint
1735 \value ULongLong a \l qulonglong
1736 \value Url a QUrl
1737 \value Vector2D a QVector2D
1738 \value Vector3D a QVector3D
1739 \value Vector4D a QVector4D
1740
1741 \value UserType Base value for user-defined types.
1742
1743 \omitvalue LastGuiType
1744 \omitvalue LastCoreType
1745 \omitvalue LastType
1746*/
1747
1748/*!
1749 \fn QVariant::QVariant(QVariant &&other)
1750
1751 Move-constructs a QVariant instance, making it point at the same
1752 object that \a other was pointing to.
1753
1754 \since 5.2
1755*/
1756
1757/*!
1758 \fn QVariant &QVariant::operator=(QVariant &&other)
1759
1760 Move-assigns \a other to this QVariant instance.
1761
1762 \since 5.2
1763*/
1764
1765/*!
1766 \fn QVariant::QVariant()
1767
1768 Constructs an invalid variant.
1769*/
1770
1771
1772/*!
1773 \fn QVariant::QVariant(int typeId, const void *copy)
1774
1775 Constructs variant of type \a typeId, and initializes with
1776 \a copy if \a copy is not \nullptr.
1777
1778 Note that you have to pass the address of the variable you want stored.
1779
1780 Usually, you never have to use this constructor, use QVariant::fromValue()
1781 instead to construct variants from the pointer types represented by
1782 \c QMetaType::VoidStar, and \c QMetaType::QObjectStar.
1783
1784 \sa QVariant::fromValue(), QMetaType::Type
1785*/
1786
1787/*!
1788 \fn QVariant::QVariant(Type type)
1789
1790 Constructs an uninitialized variant of type \a type. This will create a
1791 variant in a special null state that if accessed will return a default
1792 constructed value of the \a type.
1793
1794 \sa isNull()
1795*/
1796
1797
1798
1799/*!
1800 \fn QVariant::create(int type, const void *copy)
1801
1802 \internal
1803
1804 Constructs a variant private of type \a type, and initializes with \a copy if
1805 \a copy is not \nullptr.
1806*/
1807
1808void QVariant::create(int type, const void *copy)
1809{
1810 d.type = type;
1811 handlerManager[type]->construct(&d, copy);
1812}
1813
1814/*!
1815 \fn QVariant::~QVariant()
1816
1817 Destroys the QVariant and the contained object.
1818
1819 Note that subclasses that reimplement clear() should reimplement
1820 the destructor to call clear(). This destructor calls clear(), but
1821 because it is the destructor, QVariant::clear() is called rather
1822 than a subclass's clear().
1823*/
1824
1825QVariant::~QVariant()
1826{
1827 if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char))
1828 handlerManager[d.type]->clear(&d);
1829}
1830
1831/*!
1832 \fn QVariant::QVariant(const QVariant &p)
1833
1834 Constructs a copy of the variant, \a p, passed as the argument to
1835 this constructor.
1836*/
1837
1838QVariant::QVariant(const QVariant &p)
1839 : d(p.d)
1840{
1841 if (d.is_shared) {
1842 d.data.shared->ref.ref();
1843 } else if (p.d.type > Char) {
1844 handlerManager[d.type]->construct(&d, p.constData());
1845 d.is_null = p.d.is_null;
1846 }
1847}
1848
1849#ifndef QT_NO_DATASTREAM
1850/*!
1851 Reads the variant from the data stream, \a s.
1852*/
1853QVariant::QVariant(QDataStream &s)
1854{
1855 d.is_null = true;
1856 s >> *this;
1857}
1858#endif //QT_NO_DATASTREAM
1859
1860/*!
1861 \fn QVariant::QVariant(const QString &val)
1862
1863 Constructs a new variant with a string value, \a val.
1864*/
1865
1866/*!
1867 \fn QVariant::QVariant(QLatin1String val)
1868
1869 Constructs a new variant with a string value, \a val.
1870*/
1871
1872/*!
1873 \fn QVariant::QVariant(const char *val)
1874
1875 Constructs a new variant with a string value of \a val.
1876 The variant creates a deep copy of \a val into a QString assuming
1877 UTF-8 encoding on the input \a val.
1878
1879 Note that \a val is converted to a QString for storing in the
1880 variant and QVariant::userType() will return QMetaType::QString for
1881 the variant.
1882
1883 You can disable this operator by defining \c
1884 QT_NO_CAST_FROM_ASCII when you compile your applications.
1885*/
1886
1887#ifndef QT_NO_CAST_FROM_ASCII
1888QVariant::QVariant(const char *val)
1889{
1890 QString s = QString::fromUtf8(str: val);
1891 create(type: String, copy: &s);
1892}
1893#endif
1894
1895/*!
1896 \fn QVariant::QVariant(const QStringList &val)
1897
1898 Constructs a new variant with a string list value, \a val.
1899*/
1900
1901/*!
1902 \fn QVariant::QVariant(const QMap<QString, QVariant> &val)
1903
1904 Constructs a new variant with a map of \l {QVariant}s, \a val.
1905*/
1906
1907/*!
1908 \fn QVariant::QVariant(const QHash<QString, QVariant> &val)
1909
1910 Constructs a new variant with a hash of \l {QVariant}s, \a val.
1911*/
1912
1913/*!
1914 \fn QVariant::QVariant(const QDate &val)
1915
1916 Constructs a new variant with a date value, \a val.
1917*/
1918
1919/*!
1920 \fn QVariant::QVariant(const QTime &val)
1921
1922 Constructs a new variant with a time value, \a val.
1923*/
1924
1925/*!
1926 \fn QVariant::QVariant(const QDateTime &val)
1927
1928 Constructs a new variant with a date/time value, \a val.
1929*/
1930
1931/*!
1932 \since 4.7
1933 \fn QVariant::QVariant(const QEasingCurve &val)
1934
1935 Constructs a new variant with an easing curve value, \a val.
1936*/
1937
1938/*!
1939 \since 5.0
1940 \fn QVariant::QVariant(const QUuid &val)
1941
1942 Constructs a new variant with an uuid value, \a val.
1943*/
1944
1945/*!
1946 \since 5.0
1947 \fn QVariant::QVariant(const QModelIndex &val)
1948
1949 Constructs a new variant with a QModelIndex value, \a val.
1950*/
1951
1952/*!
1953 \since 5.5
1954 \fn QVariant::QVariant(const QPersistentModelIndex &val)
1955
1956 Constructs a new variant with a QPersistentModelIndex value, \a val.
1957*/
1958
1959/*!
1960 \since 5.0
1961 \fn QVariant::QVariant(const QJsonValue &val)
1962
1963 Constructs a new variant with a json value, \a val.
1964*/
1965
1966/*!
1967 \since 5.0
1968 \fn QVariant::QVariant(const QJsonObject &val)
1969
1970 Constructs a new variant with a json object value, \a val.
1971*/
1972
1973/*!
1974 \since 5.0
1975 \fn QVariant::QVariant(const QJsonArray &val)
1976
1977 Constructs a new variant with a json array value, \a val.
1978*/
1979
1980/*!
1981 \since 5.0
1982 \fn QVariant::QVariant(const QJsonDocument &val)
1983
1984 Constructs a new variant with a json document value, \a val.
1985*/
1986
1987/*!
1988 \fn QVariant::QVariant(const QByteArray &val)
1989
1990 Constructs a new variant with a bytearray value, \a val.
1991*/
1992
1993/*!
1994 \fn QVariant::QVariant(const QBitArray &val)
1995
1996 Constructs a new variant with a bitarray value, \a val.
1997*/
1998
1999/*!
2000 \fn QVariant::QVariant(const QPoint &val)
2001
2002 Constructs a new variant with a point value of \a val.
2003 */
2004
2005/*!
2006 \fn QVariant::QVariant(const QPointF &val)
2007
2008 Constructs a new variant with a point value of \a val.
2009 */
2010
2011/*!
2012 \fn QVariant::QVariant(const QRectF &val)
2013
2014 Constructs a new variant with a rect value of \a val.
2015 */
2016
2017/*!
2018 \fn QVariant::QVariant(const QLineF &val)
2019
2020 Constructs a new variant with a line value of \a val.
2021 */
2022
2023/*!
2024 \fn QVariant::QVariant(const QLine &val)
2025
2026 Constructs a new variant with a line value of \a val.
2027 */
2028
2029/*!
2030 \fn QVariant::QVariant(const QRect &val)
2031
2032 Constructs a new variant with a rect value of \a val.
2033 */
2034
2035/*!
2036 \fn QVariant::QVariant(const QSize &val)
2037
2038 Constructs a new variant with a size value of \a val.
2039 */
2040
2041/*!
2042 \fn QVariant::QVariant(const QSizeF &val)
2043
2044 Constructs a new variant with a size value of \a val.
2045 */
2046
2047/*!
2048 \fn QVariant::QVariant(const QUrl &val)
2049
2050 Constructs a new variant with a url value of \a val.
2051 */
2052
2053/*!
2054 \fn QVariant::QVariant(int val)
2055
2056 Constructs a new variant with an integer value, \a val.
2057*/
2058
2059/*!
2060 \fn QVariant::QVariant(uint val)
2061
2062 Constructs a new variant with an unsigned integer value, \a val.
2063*/
2064
2065/*!
2066 \fn QVariant::QVariant(qlonglong val)
2067
2068 Constructs a new variant with a long long integer value, \a val.
2069*/
2070
2071/*!
2072 \fn QVariant::QVariant(qulonglong val)
2073
2074 Constructs a new variant with an unsigned long long integer value, \a val.
2075*/
2076
2077
2078/*!
2079 \fn QVariant::QVariant(bool val)
2080
2081 Constructs a new variant with a boolean value, \a val.
2082*/
2083
2084/*!
2085 \fn QVariant::QVariant(double val)
2086
2087 Constructs a new variant with a floating point value, \a val.
2088*/
2089
2090/*!
2091 \fn QVariant::QVariant(float val)
2092
2093 Constructs a new variant with a floating point value, \a val.
2094 \since 4.6
2095*/
2096
2097/*!
2098 \fn QVariant::QVariant(const QList<QVariant> &val)
2099
2100 Constructs a new variant with a list value, \a val.
2101*/
2102
2103/*!
2104 \fn QVariant::QVariant(QChar c)
2105
2106 Constructs a new variant with a char value, \a c.
2107*/
2108
2109/*!
2110 \fn QVariant::QVariant(const QLocale &l)
2111
2112 Constructs a new variant with a locale value, \a l.
2113*/
2114
2115/*!
2116 \fn QVariant::QVariant(const QRegExp &regExp)
2117
2118 Constructs a new variant with the regexp value \a regExp.
2119*/
2120
2121/*!
2122 \fn QVariant::QVariant(const QRegularExpression &re)
2123
2124 \since 5.0
2125
2126 Constructs a new variant with the regular expression value \a re.
2127*/
2128
2129QVariant::QVariant(Type type)
2130{ create(type, copy: nullptr); }
2131QVariant::QVariant(int typeId, const void *copy)
2132{ create(type: typeId, copy); d.is_null = false; }
2133
2134/*!
2135 \internal
2136 flags is true if it is a pointer type
2137 */
2138QVariant::QVariant(int typeId, const void *copy, uint flags)
2139{
2140 if (flags) { //type is a pointer type
2141 d.type = typeId;
2142 d.data.ptr = *reinterpret_cast<void *const*>(copy);
2143 } else {
2144 create(type: typeId, copy);
2145 }
2146 d.is_null = false;
2147}
2148
2149QVariant::QVariant(int val)
2150 : d(Int)
2151{ d.data.i = val; }
2152QVariant::QVariant(uint val)
2153 : d(UInt)
2154{ d.data.u = val; }
2155QVariant::QVariant(qlonglong val)
2156 : d(LongLong)
2157{ d.data.ll = val; }
2158QVariant::QVariant(qulonglong val)
2159 : d(ULongLong)
2160{ d.data.ull = val; }
2161QVariant::QVariant(bool val)
2162 : d(Bool)
2163{ d.data.b = val; }
2164QVariant::QVariant(double val)
2165 : d(Double)
2166{ d.data.d = val; }
2167QVariant::QVariant(float val)
2168 : d(QMetaType::Float)
2169{ d.data.f = val; }
2170
2171QVariant::QVariant(const QByteArray &val)
2172 : d(ByteArray)
2173{ v_construct<QByteArray>(x: &d, t: val); }
2174QVariant::QVariant(const QBitArray &val)
2175 : d(BitArray)
2176{ v_construct<QBitArray>(x: &d, t: val); }
2177QVariant::QVariant(const QString &val)
2178 : d(String)
2179{ v_construct<QString>(x: &d, t: val); }
2180QVariant::QVariant(QChar val)
2181 : d(Char)
2182{ v_construct<QChar>(x: &d, t: val); }
2183QVariant::QVariant(QLatin1String val)
2184 : d(String)
2185{ v_construct<QString>(x: &d, t: val); }
2186QVariant::QVariant(const QStringList &val)
2187 : d(StringList)
2188{ v_construct<QStringList>(x: &d, t: val); }
2189
2190QVariant::QVariant(const QDate &val)
2191 : d(Date)
2192{ v_construct<QDate>(x: &d, t: val); }
2193QVariant::QVariant(const QTime &val)
2194 : d(Time)
2195{ v_construct<QTime>(x: &d, t: val); }
2196QVariant::QVariant(const QDateTime &val)
2197 : d(DateTime)
2198{ v_construct<QDateTime>(x: &d, t: val); }
2199#if QT_CONFIG(easingcurve)
2200QVariant::QVariant(const QEasingCurve &val)
2201 : d(EasingCurve)
2202{ v_construct<QEasingCurve>(x: &d, t: val); }
2203#endif
2204QVariant::QVariant(const QList<QVariant> &list)
2205 : d(List)
2206{ v_construct<QVariantList>(x: &d, t: list); }
2207QVariant::QVariant(const QMap<QString, QVariant> &map)
2208 : d(Map)
2209{ v_construct<QVariantMap>(x: &d, t: map); }
2210QVariant::QVariant(const QHash<QString, QVariant> &hash)
2211 : d(Hash)
2212{ v_construct<QVariantHash>(x: &d, t: hash); }
2213#ifndef QT_NO_GEOM_VARIANT
2214QVariant::QVariant(const QPoint &pt)
2215 : d(Point)
2216{ v_construct<QPoint>(x: &d, t: pt); }
2217QVariant::QVariant(const QPointF &pt)
2218 : d(PointF)
2219{ v_construct<QPointF>(x: &d, t: pt); }
2220QVariant::QVariant(const QRectF &r)
2221 : d(RectF)
2222{ v_construct<QRectF>(x: &d, t: r); }
2223QVariant::QVariant(const QLineF &l)
2224 : d(LineF)
2225{ v_construct<QLineF>(x: &d, t: l); }
2226QVariant::QVariant(const QLine &l)
2227 : d(Line)
2228{ v_construct<QLine>(x: &d, t: l); }
2229QVariant::QVariant(const QRect &r)
2230 : d(Rect)
2231{ v_construct<QRect>(x: &d, t: r); }
2232QVariant::QVariant(const QSize &s)
2233 : d(Size)
2234{ v_construct<QSize>(x: &d, t: s); }
2235QVariant::QVariant(const QSizeF &s)
2236 : d(SizeF)
2237{ v_construct<QSizeF>(x: &d, t: s); }
2238#endif
2239#ifndef QT_BOOTSTRAPPED
2240QVariant::QVariant(const QUrl &u)
2241 : d(Url)
2242{ v_construct<QUrl>(x: &d, t: u); }
2243#endif
2244QVariant::QVariant(const QLocale &l)
2245 : d(Locale)
2246{ v_construct<QLocale>(x: &d, t: l); }
2247#ifndef QT_NO_REGEXP
2248QVariant::QVariant(const QRegExp &regExp)
2249 : d(RegExp)
2250{ v_construct<QRegExp>(x: &d, t: regExp); }
2251#endif // QT_NO_REGEXP
2252#if QT_CONFIG(regularexpression)
2253QVariant::QVariant(const QRegularExpression &re)
2254 : d(RegularExpression)
2255{ v_construct<QRegularExpression>(x: &d, t: re); }
2256#endif // QT_CONFIG(regularexpression)
2257QVariant::QVariant(const QUuid &uuid)
2258 : d(Uuid)
2259{ v_construct<QUuid>(x: &d, t: uuid); }
2260#ifndef QT_BOOTSTRAPPED
2261QVariant::QVariant(const QJsonValue &jsonValue)
2262 : d(QMetaType::QJsonValue)
2263{ v_construct<QJsonValue>(x: &d, t: jsonValue); }
2264QVariant::QVariant(const QJsonObject &jsonObject)
2265 : d(QMetaType::QJsonObject)
2266{ v_construct<QJsonObject>(x: &d, t: jsonObject); }
2267QVariant::QVariant(const QJsonArray &jsonArray)
2268 : d(QMetaType::QJsonArray)
2269{ v_construct<QJsonArray>(x: &d, t: jsonArray); }
2270QVariant::QVariant(const QJsonDocument &jsonDocument)
2271 : d(QMetaType::QJsonDocument)
2272{ v_construct<QJsonDocument>(x: &d, t: jsonDocument); }
2273#endif // QT_BOOTSTRAPPED
2274#if QT_CONFIG(itemmodel)
2275QVariant::QVariant(const QModelIndex &modelIndex)
2276 : d(ModelIndex)
2277{ v_construct<QModelIndex>(x: &d, t: modelIndex); }
2278QVariant::QVariant(const QPersistentModelIndex &modelIndex)
2279 : d(PersistentModelIndex)
2280{ v_construct<QPersistentModelIndex>(x: &d, t: modelIndex); }
2281#endif
2282
2283/*!
2284 Returns the storage type of the value stored in the variant.
2285 Although this function is declared as returning QVariant::Type,
2286 the return value should be interpreted as QMetaType::Type. In
2287 particular, QVariant::UserType is returned here only if the value
2288 is equal or greater than QMetaType::User.
2289
2290 Note that return values in the ranges QVariant::Char through
2291 QVariant::RegExp and QVariant::Font through QVariant::Transform
2292 correspond to the values in the ranges QMetaType::QChar through
2293 QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion.
2294
2295 Pay particular attention when working with char and QChar
2296 variants. Note that there is no QVariant constructor specifically
2297 for type char, but there is one for QChar. For a variant of type
2298 QChar, this function returns QVariant::Char, which is the same as
2299 QMetaType::QChar, but for a variant of type \c char, this function
2300 returns QMetaType::Char, which is \e not the same as
2301 QVariant::Char.
2302
2303 Also note that the types \c void*, \c long, \c short, \c unsigned
2304 \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c
2305 QObject*, and \c QWidget* are represented in QMetaType::Type but
2306 not in QVariant::Type, and they can be returned by this function.
2307 However, they are considered to be user defined types when tested
2308 against QVariant::Type.
2309
2310 To test whether an instance of QVariant contains a data type that
2311 is compatible with the data type you are interested in, use
2312 canConvert().
2313*/
2314
2315QVariant::Type QVariant::type() const
2316{
2317 return d.type >= QMetaType::User ? UserType : static_cast<Type>(d.type);
2318}
2319
2320/*!
2321 Returns the storage type of the value stored in the variant. For
2322 non-user types, this is the same as type().
2323
2324 \sa type()
2325*/
2326
2327int QVariant::userType() const
2328{
2329 return d.type;
2330}
2331
2332/*!
2333 Assigns the value of the variant \a variant to this variant.
2334*/
2335QVariant& QVariant::operator=(const QVariant &variant)
2336{
2337 if (this == &variant)
2338 return *this;
2339
2340 clear();
2341 if (variant.d.is_shared) {
2342 variant.d.data.shared->ref.ref();
2343 d = variant.d;
2344 } else if (variant.d.type > Char) {
2345 d.type = variant.d.type;
2346 handlerManager[d.type]->construct(&d, variant.constData());
2347 d.is_null = variant.d.is_null;
2348 } else {
2349 d = variant.d;
2350 }
2351
2352 return *this;
2353}
2354
2355/*!
2356 \fn void QVariant::swap(QVariant &other)
2357 \since 4.8
2358
2359 Swaps variant \a other with this variant. This operation is very
2360 fast and never fails.
2361*/
2362
2363/*!
2364 \fn void QVariant::detach()
2365
2366 \internal
2367*/
2368
2369void QVariant::detach()
2370{
2371 if (!d.is_shared || d.data.shared->ref.loadRelaxed() == 1)
2372 return;
2373
2374 Private dd;
2375 dd.type = d.type;
2376 handlerManager[d.type]->construct(&dd, constData());
2377 if (!d.data.shared->ref.deref())
2378 handlerManager[d.type]->clear(&d);
2379 d.data.shared = dd.data.shared;
2380}
2381
2382/*!
2383 \fn bool QVariant::isDetached() const
2384
2385 \internal
2386*/
2387
2388/*!
2389 Returns the name of the type stored in the variant. The returned
2390 strings describe the C++ datatype used to store the data: for
2391 example, "QFont", "QString", or "QVariantList". An Invalid
2392 variant returns 0.
2393*/
2394const char *QVariant::typeName() const
2395{
2396 return QMetaType::typeName(type: d.type);
2397}
2398
2399/*!
2400 Convert this variant to type QMetaType::UnknownType and free up any resources
2401 used.
2402*/
2403void QVariant::clear()
2404{
2405 if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char))
2406 handlerManager[d.type]->clear(&d);
2407 d.type = Invalid;
2408 d.is_null = true;
2409 d.is_shared = false;
2410}
2411
2412/*!
2413 Converts the int representation of the storage type, \a typeId, to
2414 its string representation.
2415
2416 Returns \nullptr if the type is QMetaType::UnknownType or doesn't exist.
2417*/
2418const char *QVariant::typeToName(int typeId)
2419{
2420 return QMetaType::typeName(type: typeId);
2421}
2422
2423
2424/*!
2425 Converts the string representation of the storage type given in \a
2426 name, to its enum representation.
2427
2428 If the string representation cannot be converted to any enum
2429 representation, the variant is set to \c Invalid.
2430*/
2431QVariant::Type QVariant::nameToType(const char *name)
2432{
2433 int metaType = QMetaType::type(typeName: name);
2434 return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
2435}
2436
2437#ifndef QT_NO_DATASTREAM
2438enum { MapFromThreeCount = 36 };
2439static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
2440{
2441 QMetaType::UnknownType,
2442 QMetaType::QVariantMap,
2443 QMetaType::QVariantList,
2444 QMetaType::QString,
2445 QMetaType::QStringList,
2446 QMetaType::QFont,
2447 QMetaType::QPixmap,
2448 QMetaType::QBrush,
2449 QMetaType::QRect,
2450 QMetaType::QSize,
2451 QMetaType::QColor,
2452 QMetaType::QPalette,
2453 0, // ColorGroup
2454 QMetaType::QIcon,
2455 QMetaType::QPoint,
2456 QMetaType::QImage,
2457 QMetaType::Int,
2458 QMetaType::UInt,
2459 QMetaType::Bool,
2460 QMetaType::Double,
2461 0, // Buggy ByteArray, QByteArray never had id == 20
2462 QMetaType::QPolygon,
2463 QMetaType::QRegion,
2464 QMetaType::QBitmap,
2465 QMetaType::QCursor,
2466 QMetaType::QSizePolicy,
2467 QMetaType::QDate,
2468 QMetaType::QTime,
2469 QMetaType::QDateTime,
2470 QMetaType::QByteArray,
2471 QMetaType::QBitArray,
2472 QMetaType::QKeySequence,
2473 QMetaType::QPen,
2474 QMetaType::LongLong,
2475 QMetaType::ULongLong,
2476#if QT_CONFIG(easingcurve)
2477 QMetaType::QEasingCurve
2478#endif
2479};
2480
2481/*!
2482 Internal function for loading a variant from stream \a s. Use the
2483 stream operators instead.
2484
2485 \internal
2486*/
2487void QVariant::load(QDataStream &s)
2488{
2489 clear();
2490
2491 quint32 typeId;
2492 s >> typeId;
2493 if (s.version() < QDataStream::Qt_4_0) {
2494 if (typeId >= MapFromThreeCount)
2495 return;
2496 typeId = mapIdFromQt3ToCurrent[typeId];
2497 } else if (s.version() < QDataStream::Qt_5_0) {
2498 if (typeId == 127 /* QVariant::UserType */) {
2499 typeId = QMetaType::User;
2500 } else if (typeId >= 128 && typeId != QVariant::UserType) {
2501 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
2502 // by moving all ids down by 97.
2503 typeId -= 97;
2504 } else if (typeId == 75 /* QSizePolicy */) {
2505 typeId = QMetaType::QSizePolicy;
2506 } else if (typeId > 75 && typeId <= 86) {
2507 // and as a result these types received lower ids too
2508 // QKeySequence QPen QTextLength QTextFormat QMatrix QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
2509 typeId -=1;
2510 }
2511 }
2512
2513 qint8 is_null = false;
2514 if (s.version() >= QDataStream::Qt_4_2)
2515 s >> is_null;
2516 if (typeId == QVariant::UserType) {
2517 QByteArray name;
2518 s >> name;
2519 typeId = QMetaType::type(typeName: name.constData());
2520 if (typeId == QMetaType::UnknownType) {
2521 s.setStatus(QDataStream::ReadCorruptData);
2522 qWarning(msg: "QVariant::load: unknown user type with name %s.", name.constData());
2523 return;
2524 }
2525 }
2526 create(type: typeId, copy: nullptr);
2527 d.is_null = is_null;
2528
2529 if (!isValid()) {
2530 if (s.version() < QDataStream::Qt_5_0) {
2531 // Since we wrote something, we should read something
2532 QString x;
2533 s >> x;
2534 }
2535 d.is_null = true;
2536 return;
2537 }
2538
2539 // const cast is safe since we operate on a newly constructed variant
2540 if (!QMetaType::load(stream&: s, type: d.type, data: const_cast<void *>(constData()))) {
2541 s.setStatus(QDataStream::ReadCorruptData);
2542 qWarning(msg: "QVariant::load: unable to load type %d.", d.type);
2543 }
2544}
2545
2546/*!
2547 Internal function for saving a variant to the stream \a s. Use the
2548 stream operators instead.
2549
2550 \internal
2551*/
2552void QVariant::save(QDataStream &s) const
2553{
2554 quint32 typeId = d.type >= QMetaType::User ? QMetaType::User : userType();
2555 bool fakeUserType = false;
2556 if (s.version() < QDataStream::Qt_4_0) {
2557 int i;
2558 for (i = 0; i <= MapFromThreeCount - 1; ++i) {
2559 if (mapIdFromQt3ToCurrent[i] == typeId) {
2560 typeId = i;
2561 break;
2562 }
2563 }
2564 if (i >= MapFromThreeCount) {
2565 s << QVariant();
2566 return;
2567 }
2568 } else if (s.version() < QDataStream::Qt_5_0) {
2569 if (typeId == QMetaType::User) {
2570 typeId = 127; // QVariant::UserType had this value in Qt4
2571 } else if (typeId >= 128 - 97 && typeId <= LastCoreType) {
2572 // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
2573 // by moving all ids down by 97.
2574 typeId += 97;
2575 } else if (typeId == QMetaType::QSizePolicy) {
2576 typeId = 75;
2577 } else if (typeId >= QMetaType::QKeySequence && typeId <= QMetaType::QQuaternion) {
2578 // and as a result these types received lower ids too
2579 typeId +=1;
2580 } else if (typeId == QMetaType::QPolygonF || typeId == QMetaType::QUuid) {
2581 // These existed in Qt 4 only as a custom type
2582 typeId = 127;
2583 fakeUserType = true;
2584 }
2585 }
2586 s << typeId;
2587 if (s.version() >= QDataStream::Qt_4_2)
2588 s << qint8(d.is_null);
2589 if (d.type >= QVariant::UserType || fakeUserType) {
2590 s << QMetaType::typeName(type: userType());
2591 }
2592
2593 if (!isValid()) {
2594 if (s.version() < QDataStream::Qt_5_0)
2595 s << QString();
2596 return;
2597 }
2598
2599 if (!QMetaType::save(stream&: s, type: d.type, data: constData())) {
2600 qWarning(msg: "QVariant::save: unable to save type '%s' (type id: %d).\n", QMetaType::typeName(type: d.type), d.type);
2601 Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
2602 }
2603}
2604
2605/*!
2606 \since 4.4
2607
2608 Reads a variant \a p from the stream \a s.
2609
2610 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
2611*/
2612QDataStream& operator>>(QDataStream &s, QVariant &p)
2613{
2614 p.load(s);
2615 return s;
2616}
2617
2618/*!
2619 Writes a variant \a p to the stream \a s.
2620
2621 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
2622*/
2623QDataStream& operator<<(QDataStream &s, const QVariant &p)
2624{
2625 p.save(s);
2626 return s;
2627}
2628
2629/*!
2630 Reads a variant type \a p in enum representation from the stream \a s.
2631*/
2632QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
2633{
2634 quint32 u;
2635 s >> u;
2636 p = (QVariant::Type)u;
2637
2638 return s;
2639}
2640
2641/*!
2642 Writes a variant type \a p to the stream \a s.
2643*/
2644QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
2645{
2646 s << static_cast<quint32>(p);
2647
2648 return s;
2649}
2650
2651#endif //QT_NO_DATASTREAM
2652
2653/*!
2654 \fn bool QVariant::isValid() const
2655
2656 Returns \c true if the storage type of this variant is not
2657 QMetaType::UnknownType; otherwise returns \c false.
2658*/
2659
2660template <typename T>
2661inline T qVariantToHelper(const QVariant::Private &d, const HandlersManager &handlerManager)
2662{
2663 const uint targetType = qMetaTypeId<T>();
2664 if (d.type == targetType)
2665 return *v_cast<T>(&d);
2666
2667 T ret;
2668 if (d.type >= QMetaType::User || targetType >= QMetaType::User) {
2669 const void * const from = constData(d);
2670 if (QMetaType::convert(from, fromTypeId: d.type, to: &ret, toTypeId: targetType))
2671 return ret;
2672 }
2673
2674 handlerManager[d.type]->convert(&d, targetType, &ret, nullptr);
2675 return ret;
2676}
2677
2678/*!
2679 \fn QStringList QVariant::toStringList() const
2680
2681 Returns the variant as a QStringList if the variant has userType()
2682 \l QMetaType::QStringList, \l QMetaType::QString, or
2683 \l QMetaType::QVariantList of a type that can be converted to QString;
2684 otherwise returns an empty list.
2685
2686 \sa canConvert(int targetTypeId), convert()
2687*/
2688QStringList QVariant::toStringList() const
2689{
2690 return qVariantToHelper<QStringList>(d, handlerManager);
2691}
2692
2693/*!
2694 Returns the variant as a QString if the variant has a userType()
2695 including, but not limited to:
2696
2697 \l QMetaType::QString, \l QMetaType::Bool, \l QMetaType::QByteArray,
2698 \l QMetaType::QChar, \l QMetaType::QDate, \l QMetaType::QDateTime,
2699 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
2700 \l QMetaType::QStringList, \l QMetaType::QTime, \l QMetaType::UInt, or
2701 \l QMetaType::ULongLong.
2702
2703 Calling QVariant::toString() on an unsupported variant returns an empty
2704 string.
2705
2706 \sa canConvert(int targetTypeId), convert()
2707*/
2708QString QVariant::toString() const
2709{
2710 return qVariantToHelper<QString>(d, handlerManager);
2711}
2712
2713/*!
2714 Returns the variant as a QMap<QString, QVariant> if the variant
2715 has type() \l QMetaType::QVariantMap; otherwise returns an empty map.
2716
2717 \sa canConvert(int targetTypeId), convert()
2718*/
2719QVariantMap QVariant::toMap() const
2720{
2721 return qVariantToHelper<QVariantMap>(d, handlerManager);
2722}
2723
2724/*!
2725 Returns the variant as a QHash<QString, QVariant> if the variant
2726 has type() \l QMetaType::QVariantHash; otherwise returns an empty map.
2727
2728 \sa canConvert(int targetTypeId), convert()
2729*/
2730QVariantHash QVariant::toHash() const
2731{
2732 return qVariantToHelper<QVariantHash>(d, handlerManager);
2733}
2734
2735/*!
2736 \fn QDate QVariant::toDate() const
2737
2738 Returns the variant as a QDate if the variant has userType()
2739 \l QMetaType::QDate, \l QMetaType::QDateTime, or \l QMetaType::QString;
2740 otherwise returns an invalid date.
2741
2742 If the type() is \l QMetaType::QString, an invalid date will be returned if
2743 the string cannot be parsed as a Qt::ISODate format date.
2744
2745 \sa canConvert(int targetTypeId), convert()
2746*/
2747QDate QVariant::toDate() const
2748{
2749 return qVariantToHelper<QDate>(d, handlerManager);
2750}
2751
2752/*!
2753 \fn QTime QVariant::toTime() const
2754
2755 Returns the variant as a QTime if the variant has userType()
2756 \l QMetaType::QTime, \l QMetaType::QDateTime, or \l QMetaType::QString;
2757 otherwise returns an invalid time.
2758
2759 If the type() is \l QMetaType::QString, an invalid time will be returned if
2760 the string cannot be parsed as a Qt::ISODate format time.
2761
2762 \sa canConvert(int targetTypeId), convert()
2763*/
2764QTime QVariant::toTime() const
2765{
2766 return qVariantToHelper<QTime>(d, handlerManager);
2767}
2768
2769/*!
2770 \fn QDateTime QVariant::toDateTime() const
2771
2772 Returns the variant as a QDateTime if the variant has userType()
2773 \l QMetaType::QDateTime, \l QMetaType::QDate, or \l QMetaType::QString;
2774 otherwise returns an invalid date/time.
2775
2776 If the type() is \l QMetaType::QString, an invalid date/time will be
2777 returned if the string cannot be parsed as a Qt::ISODate format date/time.
2778
2779 \sa canConvert(int targetTypeId), convert()
2780*/
2781QDateTime QVariant::toDateTime() const
2782{
2783 return qVariantToHelper<QDateTime>(d, handlerManager);
2784}
2785
2786/*!
2787 \since 4.7
2788 \fn QEasingCurve QVariant::toEasingCurve() const
2789
2790 Returns the variant as a QEasingCurve if the variant has userType()
2791 \l QMetaType::QEasingCurve; otherwise returns a default easing curve.
2792
2793 \sa canConvert(int targetTypeId), convert()
2794*/
2795#if QT_CONFIG(easingcurve)
2796QEasingCurve QVariant::toEasingCurve() const
2797{
2798 return qVariantToHelper<QEasingCurve>(d, handlerManager);
2799}
2800#endif
2801
2802/*!
2803 \fn QByteArray QVariant::toByteArray() const
2804
2805 Returns the variant as a QByteArray if the variant has userType()
2806 \l QMetaType::QByteArray or \l QMetaType::QString (converted using
2807 QString::fromUtf8()); otherwise returns an empty byte array.
2808
2809 \sa canConvert(int targetTypeId), convert()
2810*/
2811QByteArray QVariant::toByteArray() const
2812{
2813 return qVariantToHelper<QByteArray>(d, handlerManager);
2814}
2815
2816#ifndef QT_NO_GEOM_VARIANT
2817/*!
2818 \fn QPoint QVariant::toPoint() const
2819
2820 Returns the variant as a QPoint if the variant has userType()
2821 \l QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
2822 QPoint.
2823
2824 \sa canConvert(int targetTypeId), convert()
2825*/
2826QPoint QVariant::toPoint() const
2827{
2828 return qVariantToHelper<QPoint>(d, handlerManager);
2829}
2830
2831/*!
2832 \fn QRect QVariant::toRect() const
2833
2834 Returns the variant as a QRect if the variant has userType()
2835 \l QMetaType::QRect; otherwise returns an invalid QRect.
2836
2837 \sa canConvert(int targetTypeId), convert()
2838*/
2839QRect QVariant::toRect() const
2840{
2841 return qVariantToHelper<QRect>(d, handlerManager);
2842}
2843
2844/*!
2845 \fn QSize QVariant::toSize() const
2846
2847 Returns the variant as a QSize if the variant has userType()
2848 \l QMetaType::QSize; otherwise returns an invalid QSize.
2849
2850 \sa canConvert(int targetTypeId), convert()
2851*/
2852QSize QVariant::toSize() const
2853{
2854 return qVariantToHelper<QSize>(d, handlerManager);
2855}
2856
2857/*!
2858 \fn QSizeF QVariant::toSizeF() const
2859
2860 Returns the variant as a QSizeF if the variant has userType() \l
2861 QMetaType::QSizeF; otherwise returns an invalid QSizeF.
2862
2863 \sa canConvert(int targetTypeId), convert()
2864*/
2865QSizeF QVariant::toSizeF() const
2866{
2867 return qVariantToHelper<QSizeF>(d, handlerManager);
2868}
2869
2870/*!
2871 \fn QRectF QVariant::toRectF() const
2872
2873 Returns the variant as a QRectF if the variant has userType()
2874 \l QMetaType::QRect or \l QMetaType::QRectF; otherwise returns an invalid
2875 QRectF.
2876
2877 \sa canConvert(int targetTypeId), convert()
2878*/
2879QRectF QVariant::toRectF() const
2880{
2881 return qVariantToHelper<QRectF>(d, handlerManager);
2882}
2883
2884/*!
2885 \fn QLineF QVariant::toLineF() const
2886
2887 Returns the variant as a QLineF if the variant has userType()
2888 \l QMetaType::QLineF; otherwise returns an invalid QLineF.
2889
2890 \sa canConvert(int targetTypeId), convert()
2891*/
2892QLineF QVariant::toLineF() const
2893{
2894 return qVariantToHelper<QLineF>(d, handlerManager);
2895}
2896
2897/*!
2898 \fn QLine QVariant::toLine() const
2899
2900 Returns the variant as a QLine if the variant has userType()
2901 \l QMetaType::QLine; otherwise returns an invalid QLine.
2902
2903 \sa canConvert(int targetTypeId), convert()
2904*/
2905QLine QVariant::toLine() const
2906{
2907 return qVariantToHelper<QLine>(d, handlerManager);
2908}
2909
2910/*!
2911 \fn QPointF QVariant::toPointF() const
2912
2913 Returns the variant as a QPointF if the variant has userType() \l
2914 QMetaType::QPoint or \l QMetaType::QPointF; otherwise returns a null
2915 QPointF.
2916
2917 \sa canConvert(int targetTypeId), convert()
2918*/
2919QPointF QVariant::toPointF() const
2920{
2921 return qVariantToHelper<QPointF>(d, handlerManager);
2922}
2923
2924#endif // QT_NO_GEOM_VARIANT
2925
2926#ifndef QT_BOOTSTRAPPED
2927/*!
2928 \fn QUrl QVariant::toUrl() const
2929
2930 Returns the variant as a QUrl if the variant has userType()
2931 \l QMetaType::QUrl; otherwise returns an invalid QUrl.
2932
2933 \sa canConvert(int targetTypeId), convert()
2934*/
2935QUrl QVariant::toUrl() const
2936{
2937 return qVariantToHelper<QUrl>(d, handlerManager);
2938}
2939#endif
2940
2941/*!
2942 \fn QLocale QVariant::toLocale() const
2943
2944 Returns the variant as a QLocale if the variant has userType()
2945 \l QMetaType::QLocale; otherwise returns an invalid QLocale.
2946
2947 \sa canConvert(int targetTypeId), convert()
2948*/
2949QLocale QVariant::toLocale() const
2950{
2951 return qVariantToHelper<QLocale>(d, handlerManager);
2952}
2953
2954/*!
2955 \fn QRegExp QVariant::toRegExp() const
2956 \since 4.1
2957
2958 Returns the variant as a QRegExp if the variant has userType()
2959 \l QMetaType::QRegExp; otherwise returns an empty QRegExp.
2960
2961 \sa canConvert(int targetTypeId), convert()
2962*/
2963#ifndef QT_NO_REGEXP
2964QRegExp QVariant::toRegExp() const
2965{
2966 return qVariantToHelper<QRegExp>(d, handlerManager);
2967}
2968#endif
2969
2970#if QT_CONFIG(regularexpression)
2971/*!
2972 \fn QRegularExpression QVariant::toRegularExpression() const
2973 \since 5.0
2974
2975 Returns the variant as a QRegularExpression if the variant has userType() \l
2976 QRegularExpression; otherwise returns an empty QRegularExpression.
2977
2978 \sa canConvert(int targetTypeId), convert()
2979*/
2980QRegularExpression QVariant::toRegularExpression() const
2981{
2982 return qVariantToHelper<QRegularExpression>(d, handlerManager);
2983}
2984#endif // QT_CONFIG(regularexpression)
2985
2986#if QT_CONFIG(itemmodel)
2987/*!
2988 \since 5.0
2989
2990 Returns the variant as a QModelIndex if the variant has userType() \l
2991 QModelIndex; otherwise returns a default constructed QModelIndex.
2992
2993 \sa canConvert(int targetTypeId), convert(), toPersistentModelIndex()
2994*/
2995QModelIndex QVariant::toModelIndex() const
2996{
2997 return qVariantToHelper<QModelIndex>(d, handlerManager);
2998}
2999
3000/*!
3001 \since 5.5
3002
3003 Returns the variant as a QPersistentModelIndex if the variant has userType() \l
3004 QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex.
3005
3006 \sa canConvert(int targetTypeId), convert(), toModelIndex()
3007*/
3008QPersistentModelIndex QVariant::toPersistentModelIndex() const
3009{
3010 return qVariantToHelper<QPersistentModelIndex>(d, handlerManager);
3011}
3012#endif // QT_CONFIG(itemmodel)
3013
3014/*!
3015 \since 5.0
3016
3017 Returns the variant as a QUuid if the variant has type()
3018 \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString;
3019 otherwise returns a default-constructed QUuid.
3020
3021 \sa canConvert(int targetTypeId), convert()
3022*/
3023QUuid QVariant::toUuid() const
3024{
3025 return qVariantToHelper<QUuid>(d, handlerManager);
3026}
3027
3028#ifndef QT_BOOTSTRAPPED
3029/*!
3030 \since 5.0
3031
3032 Returns the variant as a QJsonValue if the variant has userType() \l
3033 QJsonValue; otherwise returns a default constructed QJsonValue.
3034
3035 \sa canConvert(int targetTypeId), convert()
3036*/
3037QJsonValue QVariant::toJsonValue() const
3038{
3039 return qVariantToHelper<QJsonValue>(d, handlerManager);
3040}
3041
3042/*!
3043 \since 5.0
3044
3045 Returns the variant as a QJsonObject if the variant has userType() \l
3046 QJsonObject; otherwise returns a default constructed QJsonObject.
3047
3048 \sa canConvert(int targetTypeId), convert()
3049*/
3050QJsonObject QVariant::toJsonObject() const
3051{
3052 return qVariantToHelper<QJsonObject>(d, handlerManager);
3053}
3054
3055/*!
3056 \since 5.0
3057
3058 Returns the variant as a QJsonArray if the variant has userType() \l
3059 QJsonArray; otherwise returns a default constructed QJsonArray.
3060
3061 \sa canConvert(int targetTypeId), convert()
3062*/
3063QJsonArray QVariant::toJsonArray() const
3064{
3065 return qVariantToHelper<QJsonArray>(d, handlerManager);
3066}
3067
3068/*!
3069 \since 5.0
3070
3071 Returns the variant as a QJsonDocument if the variant has userType() \l
3072 QJsonDocument; otherwise returns a default constructed QJsonDocument.
3073
3074 \sa canConvert(int targetTypeId), convert()
3075*/
3076QJsonDocument QVariant::toJsonDocument() const
3077{
3078 return qVariantToHelper<QJsonDocument>(d, handlerManager);
3079}
3080#endif // QT_BOOTSTRAPPED
3081
3082/*!
3083 \fn QChar QVariant::toChar() const
3084
3085 Returns the variant as a QChar if the variant has userType()
3086 \l QMetaType::QChar, \l QMetaType::Int, or \l QMetaType::UInt; otherwise
3087 returns an invalid QChar.
3088
3089 \sa canConvert(int targetTypeId), convert()
3090*/
3091QChar QVariant::toChar() const
3092{
3093 return qVariantToHelper<QChar>(d, handlerManager);
3094}
3095
3096/*!
3097 Returns the variant as a QBitArray if the variant has userType()
3098 \l QMetaType::QBitArray; otherwise returns an empty bit array.
3099
3100 \sa canConvert(int targetTypeId), convert()
3101*/
3102QBitArray QVariant::toBitArray() const
3103{
3104 return qVariantToHelper<QBitArray>(d, handlerManager);
3105}
3106
3107template <typename T>
3108inline T qNumVariantToHelper(const QVariant::Private &d,
3109 const HandlersManager &handlerManager, bool *ok, const T& val)
3110{
3111 const uint t = qMetaTypeId<T>();
3112 if (ok)
3113 *ok = true;
3114
3115 if (d.type == t)
3116 return val;
3117
3118 T ret = 0;
3119 if ((d.type >= QMetaType::User || t >= QMetaType::User)
3120 && QMetaType::convert(from: constData(d), fromTypeId: d.type, to: &ret, toTypeId: t))
3121 return ret;
3122
3123 if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok)
3124 *ok = false;
3125 return ret;
3126}
3127
3128/*!
3129 Returns the variant as an int if the variant has userType()
3130 \l QMetaType::Int, \l QMetaType::Bool, \l QMetaType::QByteArray,
3131 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::LongLong,
3132 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
3133 otherwise returns 0.
3134
3135 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3136 converted to an int; otherwise \c{*}\a{ok} is set to false.
3137
3138 \b{Warning:} If the value is convertible to a \l QMetaType::LongLong but is
3139 too large to be represented in an int, the resulting arithmetic overflow
3140 will not be reflected in \a ok. A simple workaround is to use
3141 QString::toInt().
3142
3143 \sa canConvert(int targetTypeId), convert()
3144*/
3145int QVariant::toInt(bool *ok) const
3146{
3147 return qNumVariantToHelper<int>(d, handlerManager, ok, val: d.data.i);
3148}
3149
3150/*!
3151 Returns the variant as an unsigned int if the variant has userType()
3152 \l QMetaType::UInt, \l QMetaType::Bool, \l QMetaType::QByteArray,
3153 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
3154 \l QMetaType::LongLong, \l QMetaType::QString, or \l QMetaType::ULongLong;
3155 otherwise returns 0.
3156
3157 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3158 converted to an unsigned int; otherwise \c{*}\a{ok} is set to false.
3159
3160 \b{Warning:} If the value is convertible to a \l QMetaType::ULongLong but is
3161 too large to be represented in an unsigned int, the resulting arithmetic
3162 overflow will not be reflected in \a ok. A simple workaround is to use
3163 QString::toUInt().
3164
3165 \sa canConvert(int targetTypeId), convert()
3166*/
3167uint QVariant::toUInt(bool *ok) const
3168{
3169 return qNumVariantToHelper<uint>(d, handlerManager, ok, val: d.data.u);
3170}
3171
3172/*!
3173 Returns the variant as a long long int if the variant has userType()
3174 \l QMetaType::LongLong, \l QMetaType::Bool, \l QMetaType::QByteArray,
3175 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
3176 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
3177 otherwise returns 0.
3178
3179 If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
3180 converted to an int; otherwise \c{*}\c{ok} is set to false.
3181
3182 \sa canConvert(int targetTypeId), convert()
3183*/
3184qlonglong QVariant::toLongLong(bool *ok) const
3185{
3186 return qNumVariantToHelper<qlonglong>(d, handlerManager, ok, val: d.data.ll);
3187}
3188
3189/*!
3190 Returns the variant as an unsigned long long int if the
3191 variant has type() \l QMetaType::ULongLong, \l QMetaType::Bool,
3192 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
3193 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString, or
3194 \l QMetaType::UInt; otherwise returns 0.
3195
3196 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3197 converted to an int; otherwise \c{*}\a{ok} is set to false.
3198
3199 \sa canConvert(int targetTypeId), convert()
3200*/
3201qulonglong QVariant::toULongLong(bool *ok) const
3202{
3203 return qNumVariantToHelper<qulonglong>(d, handlerManager, ok, val: d.data.ull);
3204}
3205
3206/*!
3207 Returns the variant as a bool if the variant has userType() Bool.
3208
3209 Returns \c true if the variant has userType() \l QMetaType::Bool,
3210 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
3211 \l QMetaType::LongLong, \l QMetaType::UInt, or \l QMetaType::ULongLong and
3212 the value is non-zero, or if the variant has type \l QMetaType::QString or
3213 \l QMetaType::QByteArray and its lower-case content is not one of the
3214 following: empty, "0" or "false"; otherwise returns \c false.
3215
3216 \sa canConvert(int targetTypeId), convert()
3217*/
3218bool QVariant::toBool() const
3219{
3220 if (d.type == Bool)
3221 return d.data.b;
3222
3223 bool res = false;
3224 handlerManager[d.type]->convert(&d, Bool, &res, nullptr);
3225
3226 return res;
3227}
3228
3229/*!
3230 Returns the variant as a double if the variant has userType()
3231 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
3232 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
3233 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
3234 otherwise returns 0.0.
3235
3236 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3237 converted to a double; otherwise \c{*}\a{ok} is set to false.
3238
3239 \sa canConvert(int targetTypeId), convert()
3240*/
3241double QVariant::toDouble(bool *ok) const
3242{
3243 return qNumVariantToHelper<double>(d, handlerManager, ok, val: d.data.d);
3244}
3245
3246/*!
3247 Returns the variant as a float if the variant has userType()
3248 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
3249 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
3250 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
3251 otherwise returns 0.0.
3252
3253 \since 4.6
3254
3255 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3256 converted to a double; otherwise \c{*}\a{ok} is set to false.
3257
3258 \sa canConvert(int targetTypeId), convert()
3259*/
3260float QVariant::toFloat(bool *ok) const
3261{
3262 return qNumVariantToHelper<float>(d, handlerManager, ok, val: d.data.f);
3263}
3264
3265/*!
3266 Returns the variant as a qreal if the variant has userType()
3267 \l QMetaType::Double, \l QMetaType::Float, \l QMetaType::Bool,
3268 \l QMetaType::QByteArray, \l QMetaType::Int, \l QMetaType::LongLong,
3269 \l QMetaType::QString, \l QMetaType::UInt, or \l QMetaType::ULongLong;
3270 otherwise returns 0.0.
3271
3272 \since 4.6
3273
3274 If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
3275 converted to a double; otherwise \c{*}\a{ok} is set to false.
3276
3277 \sa canConvert(int targetTypeId), convert()
3278*/
3279qreal QVariant::toReal(bool *ok) const
3280{
3281 return qNumVariantToHelper<qreal>(d, handlerManager, ok, val: d.data.real);
3282}
3283
3284/*!
3285 Returns the variant as a QVariantList if the variant has userType()
3286 \l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns
3287 an empty list.
3288
3289 \sa canConvert(int targetTypeId), convert()
3290*/
3291QVariantList QVariant::toList() const
3292{
3293 return qVariantToHelper<QVariantList>(d, handlerManager);
3294}
3295
3296
3297static const quint32 qCanConvertMatrix[QMetaType::LastCoreType + 1] =
3298{
3299/*Invalid*/ 0,
3300
3301/*Bool*/ 1 << QMetaType::Double | 1 << QMetaType::Int | 1 << QMetaType::UInt
3302 | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QByteArray
3303 | 1 << QMetaType::QString | 1 << QMetaType::QChar,
3304
3305/*Int*/ 1 << QMetaType::UInt | 1 << QMetaType::QString | 1 << QMetaType::Double
3306 | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
3307 | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray | 1 << QMetaType::Int,
3308
3309/*UInt*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
3310 | 1 << QMetaType::Bool | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
3311 | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
3312
3313/*LLong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
3314 | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::ULongLong
3315 | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
3316
3317/*ULlong*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::Double
3318 | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
3319 | 1 << QMetaType::QChar | 1 << QMetaType::QByteArray,
3320
3321/*double*/ 1 << QMetaType::Int | 1 << QMetaType::QString | 1 << QMetaType::ULongLong
3322 | 1 << QMetaType::Bool | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
3323 | 1 << QMetaType::QByteArray,
3324
3325/*QChar*/ 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::LongLong
3326 | 1 << QMetaType::ULongLong,
3327
3328/*QMap*/ 0,
3329
3330/*QList*/ 1 << QMetaType::QStringList,
3331
3332/*QString*/ 1 << QMetaType::QStringList | 1 << QMetaType::QByteArray | 1 << QMetaType::Int
3333 | 1 << QMetaType::UInt | 1 << QMetaType::Bool | 1 << QMetaType::Double
3334 | 1 << QMetaType::QDate | 1 << QMetaType::QTime | 1 << QMetaType::QDateTime
3335 | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong | 1 << QMetaType::QChar
3336 | 1 << QMetaType::QUrl | 1 << QMetaType::QUuid,
3337
3338/*QStringList*/ 1 << QMetaType::QVariantList | 1 << QMetaType::QString,
3339
3340/*QByteArray*/ 1 << QMetaType::QString | 1 << QMetaType::Int | 1 << QMetaType::UInt | 1 << QMetaType::Bool
3341 | 1 << QMetaType::Double | 1 << QMetaType::LongLong | 1 << QMetaType::ULongLong
3342 | 1 << QMetaType::QUuid,
3343
3344/*QBitArray*/ 0,
3345
3346/*QDate*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
3347
3348/*QTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDateTime,
3349
3350/*QDateTime*/ 1 << QMetaType::QString | 1 << QMetaType::QDate,
3351
3352/*QUrl*/ 1 << QMetaType::QString,
3353
3354/*QLocale*/ 0,
3355
3356/*QRect*/ 1 << QMetaType::QRectF,
3357
3358/*QRectF*/ 1 << QMetaType::QRect,
3359
3360/*QSize*/ 1 << QMetaType::QSizeF,
3361
3362/*QSizeF*/ 1 << QMetaType::QSize,
3363
3364/*QLine*/ 1 << QMetaType::QLineF,
3365
3366/*QLineF*/ 1 << QMetaType::QLine,
3367
3368/*QPoint*/ 1 << QMetaType::QPointF,
3369
3370/*QPointF*/ 1 << QMetaType::QPoint,
3371
3372/*QRegExp*/ 0,
3373
3374/*QHash*/ 0,
3375
3376/*QEasingCurve*/ 0,
3377
3378/*QUuid*/ 1 << QMetaType::QString | 1 << QMetaType::QByteArray,
3379};
3380static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix);
3381
3382#ifndef QT_BOOTSTRAPPED
3383/*
3384 Returns \c true if from inherits to.
3385*/
3386static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to)
3387{
3388 if (from && to == &QObject::staticMetaObject)
3389 return true;
3390
3391 while (from) {
3392 if (from == to)
3393 return true;
3394 from = from->superClass();
3395 }
3396
3397 return false;
3398}
3399#endif
3400
3401static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject)
3402{
3403#ifndef QT_BOOTSTRAPPED
3404 QMetaType toType(toId);
3405 if ((QMetaType::typeFlags(type: fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
3406 if (!fromObject)
3407 return true;
3408 return canConvertMetaObject(from: fromObject->metaObject(), to: toType.metaObject());
3409 }
3410#else
3411 Q_UNUSED(fromId);
3412 Q_UNUSED(toId);
3413 Q_UNUSED(fromObject);
3414#endif
3415 return false;
3416}
3417
3418
3419/*!
3420 Returns \c true if the variant's type can be cast to the requested
3421 type, \a targetTypeId. Such casting is done automatically when calling the
3422 toInt(), toBool(), ... methods.
3423
3424 The following casts are done automatically:
3425
3426 \table
3427 \header \li Type \li Automatically Cast To
3428 \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
3429 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
3430 \l QMetaType::UInt, \l QMetaType::ULongLong
3431 \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
3432 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
3433 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
3434 \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
3435 \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
3436 \row \li \l QMetaType::QColor \li \l QMetaType::QString
3437 \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
3438 \l QMetaType::QString
3439 \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
3440 \l QMetaType::QString, \l QMetaType::QTime
3441 \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
3442 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
3443 \l QMetaType::ULongLong
3444 \row \li \l QMetaType::QFont \li \l QMetaType::QString
3445 \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
3446 \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
3447 \l QMetaType::UInt, \l QMetaType::ULongLong
3448 \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
3449 \l QMetaType::QString
3450 \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
3451 list's items can be converted to QStrings)
3452 \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
3453 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
3454 \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
3455 \l QMetaType::ULongLong
3456 \row \li \l QMetaType::QPoint \li QMetaType::QPointF
3457 \row \li \l QMetaType::QRect \li QMetaType::QRectF
3458 \row \li \l QMetaType::QString \li \l QMetaType::Bool,
3459 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
3460 \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
3461 \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
3462 \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
3463 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
3464 \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
3465 \l QMetaType::QString (if the list contains exactly one item)
3466 \row \li \l QMetaType::QTime \li \l QMetaType::QString
3467 \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
3468 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
3469 \l QMetaType::QString, \l QMetaType::ULongLong
3470 \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
3471 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
3472 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
3473 \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
3474 \endtable
3475
3476 A QVariant containing a pointer to a type derived from QObject will also return true for this
3477 function if a qobject_cast to the type described by \a targetTypeId would succeed. Note that
3478 this only works for QObject subclasses which use the Q_OBJECT macro.
3479
3480 A QVariant containing a sequential container will also return true for this
3481 function if the \a targetTypeId is QVariantList. It is possible to iterate over
3482 the contents of the container without extracting it as a (copied) QVariantList:
3483
3484 \snippet code/src_corelib_kernel_qvariant.cpp 9
3485
3486 This requires that the value_type of the container is itself a metatype.
3487
3488 Similarly, a QVariant containing a sequential container will also return true for this
3489 function the \a targetTypeId is QVariantHash or QVariantMap. It is possible to iterate over
3490 the contents of the container without extracting it as a (copied) QVariantHash or QVariantMap:
3491
3492 \snippet code/src_corelib_kernel_qvariant.cpp 10
3493
3494 \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
3495 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
3496*/
3497bool QVariant::canConvert(int targetTypeId) const
3498{
3499 if (d.type == targetTypeId)
3500 return true;
3501
3502#if QT_CONFIG(itemmodel)
3503 if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex)
3504 || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex))
3505 return true;
3506#endif
3507
3508 if (targetTypeId == QMetaType::QVariantList
3509 && (d.type == QMetaType::QVariantList
3510 || d.type == QMetaType::QStringList
3511 || d.type == QMetaType::QByteArrayList
3512 || QMetaType::hasRegisteredConverterFunction(fromTypeId: d.type,
3513 toTypeId: qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>()))) {
3514 return true;
3515 }
3516
3517 if ((targetTypeId == QMetaType::QVariantHash || targetTypeId == QMetaType::QVariantMap)
3518 && (d.type == QMetaType::QVariantMap
3519 || d.type == QMetaType::QVariantHash
3520 || QMetaType::hasRegisteredConverterFunction(fromTypeId: d.type,
3521 toTypeId: qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>()))) {
3522 return true;
3523 }
3524
3525 if (targetTypeId == qMetaTypeId<QPair<QVariant, QVariant> >() &&
3526 QMetaType::hasRegisteredConverterFunction(fromTypeId: d.type,
3527 toTypeId: qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
3528 return true;
3529 }
3530
3531 if ((d.type >= QMetaType::User || targetTypeId >= QMetaType::User)
3532 && QMetaType::hasRegisteredConverterFunction(fromTypeId: d.type, toTypeId: targetTypeId)) {
3533 return true;
3534 }
3535
3536 // TODO Reimplement this function, currently it works but it is a historical mess.
3537 uint currentType = d.type;
3538 if (currentType == QMetaType::SChar || currentType == QMetaType::Char)
3539 currentType = QMetaType::UInt;
3540 if (targetTypeId == QMetaType::SChar || currentType == QMetaType::Char)
3541 targetTypeId = QMetaType::UInt;
3542 if (currentType == QMetaType::Short || currentType == QMetaType::UShort)
3543 currentType = QMetaType::Int;
3544 if (targetTypeId == QMetaType::Short || currentType == QMetaType::UShort)
3545 targetTypeId = QMetaType::Int;
3546 if (currentType == QMetaType::Float)
3547 currentType = QMetaType::Double;
3548 if (targetTypeId == QMetaType::Float)
3549 targetTypeId = QMetaType::Double;
3550
3551 if (currentType == uint(targetTypeId))
3552 return true;
3553
3554 if (targetTypeId < 0)
3555 return false;
3556 if (targetTypeId >= QMetaType::User) {
3557 if (QMetaType::typeFlags(type: targetTypeId) & QMetaType::IsEnumeration) {
3558 targetTypeId = QMetaType::Int;
3559 } else {
3560 return canConvertMetaObject(fromId: currentType, toId: targetTypeId, fromObject: d.data.o);
3561 }
3562 }
3563
3564 if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) {
3565 switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) {
3566 case QMetaType::Nullptr:
3567 case QMetaType::QString:
3568 case QMetaType::Bool:
3569 case QMetaType::Int:
3570 case QMetaType::UInt:
3571 case QMetaType::Double:
3572 case QMetaType::Float:
3573 case QMetaType::ULong:
3574 case QMetaType::Long:
3575 case QMetaType::LongLong:
3576 case QMetaType::ULongLong:
3577 case QMetaType::UShort:
3578 case QMetaType::UChar:
3579 case QMetaType::Char:
3580 case QMetaType::SChar:
3581 case QMetaType::Short:
3582 case QMetaType::QVariantList:
3583 case QMetaType::QVariantMap:
3584 case QMetaType::QVariantHash:
3585 case QMetaType::QCborValue:
3586 case QMetaType::QCborArray:
3587 case QMetaType::QCborMap:
3588 return true;
3589 default:
3590 return false;
3591 }
3592 }
3593 if (currentType == QMetaType::QJsonArray)
3594 return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
3595 || targetTypeId == QMetaType::QCborArray;
3596 if (currentType == QMetaType::QJsonObject)
3597 return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
3598 || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
3599
3600 if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
3601 switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
3602 case QMetaType::UnknownType:
3603 case QMetaType::Nullptr:
3604 case QMetaType::Bool:
3605 case QMetaType::Int:
3606 case QMetaType::UInt:
3607 case QMetaType::Double:
3608 case QMetaType::Float:
3609 case QMetaType::ULong:
3610 case QMetaType::Long:
3611 case QMetaType::LongLong:
3612 case QMetaType::ULongLong:
3613 case QMetaType::UShort:
3614 case QMetaType::UChar:
3615 case QMetaType::Char:
3616 case QMetaType::SChar:
3617 case QMetaType::Short:
3618 case QMetaType::QString:
3619 case QMetaType::QByteArray:
3620 case QMetaType::QDateTime:
3621 case QMetaType::QUrl:
3622 case QMetaType::QRegularExpression:
3623 case QMetaType::QUuid:
3624 case QMetaType::QVariantList:
3625 case QMetaType::QVariantMap:
3626 case QMetaType::QVariantHash:
3627 case QMetaType::QJsonValue:
3628 case QMetaType::QJsonArray:
3629 case QMetaType::QJsonObject:
3630 case QMetaType::QJsonDocument:
3631 case QMetaType::QCborArray:
3632 case QMetaType::QCborMap:
3633 case QMetaType::QCborSimpleType:
3634 return true;
3635 default:
3636 return false;
3637 }
3638 }
3639 if (currentType == QMetaType::QCborArray)
3640 return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
3641 || targetTypeId == QMetaType::QJsonArray;
3642 if (currentType == QMetaType::QCborMap)
3643 return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
3644 || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
3645
3646 // FIXME It should be LastCoreType intead of Uuid
3647 if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
3648 switch (uint(targetTypeId)) {
3649 case QVariant::Int:
3650 if (currentType == QVariant::KeySequence)
3651 return true;
3652 Q_FALLTHROUGH();
3653 case QVariant::UInt:
3654 case QVariant::LongLong:
3655 case QVariant::ULongLong:
3656 return currentType == QMetaType::ULong
3657 || currentType == QMetaType::Long
3658 || currentType == QMetaType::UShort
3659 || currentType == QMetaType::UChar
3660 || currentType == QMetaType::Char
3661 || currentType == QMetaType::SChar
3662 || currentType == QMetaType::Short
3663 || QMetaType::typeFlags(type: currentType) & QMetaType::IsEnumeration;
3664 case QVariant::Image:
3665 return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
3666 case QVariant::Pixmap:
3667 return currentType == QVariant::Image || currentType == QVariant::Bitmap
3668 || currentType == QVariant::Brush;
3669 case QVariant::Bitmap:
3670 return currentType == QVariant::Pixmap || currentType == QVariant::Image;
3671 case QVariant::ByteArray:
3672 return currentType == QVariant::Color || currentType == QMetaType::Nullptr
3673 || ((QMetaType::typeFlags(type: currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(type: currentType));
3674 case QVariant::String:
3675 return currentType == QVariant::KeySequence || currentType == QVariant::Font
3676 || currentType == QVariant::Color || currentType == QMetaType::Nullptr
3677 || ((QMetaType::typeFlags(type: currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(type: currentType));
3678 case QVariant::KeySequence:
3679 return currentType == QVariant::String || currentType == QVariant::Int;
3680 case QVariant::Font:
3681 return currentType == QVariant::String;
3682 case QVariant::Color:
3683 return currentType == QVariant::String || currentType == QVariant::ByteArray
3684 || currentType == QVariant::Brush;
3685 case QVariant::Brush:
3686 return currentType == QVariant::Color || currentType == QVariant::Pixmap;
3687 case QMetaType::Long:
3688 case QMetaType::Char:
3689 case QMetaType::SChar:
3690 case QMetaType::UChar:
3691 case QMetaType::ULong:
3692 case QMetaType::Short:
3693 case QMetaType::UShort:
3694 return currentType == QVariant::Int
3695 || (currentType < qCanConvertMatrixMaximumTargetType
3696 && qCanConvertMatrix[QVariant::Int] & (1U << currentType))
3697 || QMetaType::typeFlags(type: currentType) & QMetaType::IsEnumeration;
3698 case QMetaType::QObjectStar:
3699 return canConvertMetaObject(fromId: currentType, toId: targetTypeId, fromObject: d.data.o);
3700 default:
3701 return false;
3702 }
3703 }
3704
3705 if (targetTypeId == String && currentType == StringList)
3706 return v_cast<QStringList>(d: &d)->count() == 1;
3707 return currentType < qCanConvertMatrixMaximumTargetType
3708 && qCanConvertMatrix[targetTypeId] & (1U << currentType);
3709}
3710
3711/*!
3712 Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
3713 done, the variant is still changed to the requested type, but is left in a cleared
3714 null state similar to that constructed by QVariant(Type).
3715
3716 Returns \c true if the current type of the variant was successfully cast;
3717 otherwise returns \c false.
3718
3719 A QVariant containing a pointer to a type derived from QObject will also convert
3720 and return true for this function if a qobject_cast to the type described
3721 by \a targetTypeId would succeed. Note that this only works for QObject subclasses
3722 which use the Q_OBJECT macro.
3723
3724 \note converting QVariants that are null due to not being initialized or having
3725 failed a previous conversion will always fail, changing the type, remaining null,
3726 and returning \c false.
3727
3728 \sa canConvert(int targetTypeId), clear()
3729*/
3730
3731bool QVariant::convert(int targetTypeId)
3732{
3733 if (d.type == uint(targetTypeId))
3734 return true;
3735
3736 QVariant oldValue = *this;
3737
3738 clear();
3739 if (!oldValue.canConvert(targetTypeId))
3740 return false;
3741
3742 create(type: targetTypeId, copy: nullptr);
3743 // Fail if the value is not initialized or was forced null by a previous failed convert.
3744 if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr)
3745 return false;
3746
3747 if ((QMetaType::typeFlags(type: oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(type: targetTypeId) & QMetaType::PointerToQObject)) {
3748 create(type: targetTypeId, copy: &oldValue.d.data.o);
3749 return true;
3750 }
3751
3752 bool isOk = true;
3753 int converterType = std::max(a: oldValue.userType(), b: targetTypeId);
3754 if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk))
3755 isOk = false;
3756 d.is_null = !isOk;
3757 return isOk;
3758}
3759
3760/*!
3761 \fn bool QVariant::convert(const int type, void *ptr) const
3762 \internal
3763 Created for qvariant_cast() usage
3764*/
3765bool QVariant::convert(const int type, void *ptr) const
3766{
3767 return handlerManager[type]->convert(&d, type, ptr, nullptr);
3768}
3769
3770
3771/*!
3772 \fn bool operator==(const QVariant &v1, const QVariant &v2)
3773
3774 \relates QVariant
3775
3776 Returns \c true if \a v1 and \a v2 are equal; otherwise returns \c false.
3777
3778 If \a v1 and \a v2 have the same \l{QVariant::}{type()}, the
3779 type's equality operator is used for comparison. If not, it is
3780 attempted to \l{QVariant::}{convert()} \a v2 to the same type as
3781 \a v1. See \l{QVariant::}{canConvert()} for a list of possible
3782 conversions.
3783
3784 The result of the function is not affected by the result of QVariant::isNull,
3785 which means that two values can be equal even if one of them is null and
3786 another is not.
3787
3788 \warning To make this function work with a custom type registered with
3789 qRegisterMetaType(), its comparison operator must be registered using
3790 QMetaType::registerComparators().
3791*/
3792/*!
3793 \fn bool operator!=(const QVariant &v1, const QVariant &v2)
3794
3795 \relates QVariant
3796
3797 Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
3798
3799 \warning To make this function work with a custom type registered with
3800 qRegisterMetaType(), its comparison operator must be registered using
3801 QMetaType::registerComparators().
3802*/
3803
3804/*! \fn bool QVariant::operator==(const QVariant &v) const
3805
3806 Compares this QVariant with \a v and returns \c true if they are
3807 equal; otherwise returns \c false.
3808
3809 QVariant uses the equality operator of the type() it contains to
3810 check for equality. QVariant will try to convert() \a v if its
3811 type is not the same as this variant's type. See canConvert() for
3812 a list of possible conversions.
3813
3814 \warning To make this function work with a custom type registered with
3815 qRegisterMetaType(), its comparison operator must be registered using
3816 QMetaType::registerComparators().
3817*/
3818
3819/*!
3820 \fn bool QVariant::operator!=(const QVariant &v) const
3821
3822 Compares this QVariant with \a v and returns \c true if they are not
3823 equal; otherwise returns \c false.
3824
3825 \warning To make this function work with a custom type registered with
3826 qRegisterMetaType(), its comparison operator must be registered using
3827 QMetaType::registerComparators().
3828*/
3829
3830/*!
3831 \fn bool QVariant::operator<(const QVariant &v) const
3832 \obsolete
3833
3834 Compares this QVariant with \a v and returns \c true if this is less than \a v.
3835
3836 \note Comparability might not be availabe for the type stored in this QVariant
3837 or in \a v.
3838
3839 \warning To make this function work with a custom type registered with
3840 qRegisterMetaType(), its comparison operator must be registered using
3841 QMetaType::registerComparators().
3842
3843 This operator is deprecated as it cannot establish a total order required
3844 for most use of this operator, which is the reason you cannot use QVariant
3845 as the key of a QMap.
3846*/
3847
3848/*!
3849 \fn bool QVariant::operator<=(const QVariant &v) const
3850 \obsolete
3851
3852 Compares this QVariant with \a v and returns \c true if this is less or equal than \a v.
3853
3854 \note Comparability might not be available for the type stored in this QVariant
3855 or in \a v.
3856
3857 \warning To make this function work with a custom type registered with
3858 qRegisterMetaType(), its comparison operator must be registered using
3859 QMetaType::registerComparators().
3860
3861 This operator is deprecated as it cannot establish a total order.
3862*/
3863
3864/*!
3865 \fn bool QVariant::operator>(const QVariant &v) const
3866 \obsolete
3867
3868 Compares this QVariant with \a v and returns \c true if this is larger than \a v.
3869
3870 \note Comparability might not be available for the type stored in this QVariant
3871 or in \a v.
3872
3873 \warning To make this function work with a custom type registered with
3874 qRegisterMetaType(), its comparison operator must be registered using
3875 QMetaType::registerComparators().
3876
3877 This operator is deprecated as it cannot establish a total order.
3878*/
3879
3880/*!
3881 \fn bool QVariant::operator>=(const QVariant &v) const
3882 \obsolete
3883
3884 Compares this QVariant with \a v and returns \c true if this is larger or equal than \a v.
3885
3886 \note Comparability might not be available for the type stored in this QVariant
3887 or in \a v.
3888
3889 \warning To make this function work with a custom type registered with
3890 qRegisterMetaType(), its comparison operator must be registered using
3891 QMetaType::registerComparators().
3892
3893 This operator is deprecated as it cannot establish a total order.
3894*/
3895
3896static bool qIsNumericType(uint tp)
3897{
3898 static const qulonglong numericTypeBits =
3899 Q_UINT64_C(1) << QMetaType::Bool |
3900 Q_UINT64_C(1) << QMetaType::Double |
3901 Q_UINT64_C(1) << QMetaType::Float |
3902 Q_UINT64_C(1) << QMetaType::Char |
3903 Q_UINT64_C(1) << QMetaType::SChar |
3904 Q_UINT64_C(1) << QMetaType::UChar |
3905 Q_UINT64_C(1) << QMetaType::Short |
3906 Q_UINT64_C(1) << QMetaType::UShort |
3907 Q_UINT64_C(1) << QMetaType::Int |
3908 Q_UINT64_C(1) << QMetaType::UInt |
3909 Q_UINT64_C(1) << QMetaType::Long |
3910 Q_UINT64_C(1) << QMetaType::ULong |
3911 Q_UINT64_C(1) << QMetaType::LongLong |
3912 Q_UINT64_C(1) << QMetaType::ULongLong;
3913 return tp < (CHAR_BIT * sizeof numericTypeBits) ? numericTypeBits & (Q_UINT64_C(1) << tp) : false;
3914}
3915
3916static bool qIsFloatingPoint(uint tp)
3917{
3918 return tp == QMetaType::Double || tp == QMetaType::Float;
3919}
3920
3921static int normalizeLowerRanks(uint tp)
3922{
3923 static const qulonglong numericTypeBits =
3924 Q_UINT64_C(1) << QMetaType::Bool |
3925 Q_UINT64_C(1) << QMetaType::Char |
3926 Q_UINT64_C(1) << QMetaType::SChar |
3927 Q_UINT64_C(1) << QMetaType::UChar |
3928 Q_UINT64_C(1) << QMetaType::Short |
3929 Q_UINT64_C(1) << QMetaType::UShort;
3930 return numericTypeBits & (Q_UINT64_C(1) << tp) ? uint(QMetaType::Int) : tp;
3931}
3932
3933static int normalizeLong(uint tp)
3934{
3935 const uint IntType = sizeof(long) == sizeof(int) ? QMetaType::Int : QMetaType::LongLong;
3936 const uint UIntType = sizeof(ulong) == sizeof(uint) ? QMetaType::UInt : QMetaType::ULongLong;
3937 return tp == QMetaType::Long ? IntType :
3938 tp == QMetaType::ULong ? UIntType : tp;
3939}
3940
3941static int numericTypePromotion(uint t1, uint t2)
3942{
3943 Q_ASSERT(qIsNumericType(t1));
3944 Q_ASSERT(qIsNumericType(t2));
3945
3946 // C++ integral ranks: (4.13 Integer conversion rank [conv.rank])
3947 // bool < signed char < short < int < long < long long
3948 // unsigneds have the same rank as their signed counterparts
3949 // C++ integral promotion rules (4.5 Integral Promotions [conv.prom])
3950 // - any type with rank less than int can be converted to int or unsigned int
3951 // 5 Expressions [expr] paragraph 9:
3952 // - if either operand is double, the other shall be converted to double
3953 // - " " float, " " " float
3954 // - if both operands have the same type, no further conversion is needed.
3955 // - if both are signed or if both are unsigned, convert to the one with highest rank
3956 // - if the unsigned has higher or same rank, convert the signed to the unsigned one
3957 // - if the signed can represent all values of the unsigned, convert to the signed
3958 // - otherwise, convert to the unsigned corresponding to the rank of the signed
3959
3960 // floating point: we deviate from the C++ standard by always using qreal
3961 if (qIsFloatingPoint(tp: t1) || qIsFloatingPoint(tp: t2))
3962 return QMetaType::QReal;
3963
3964 // integral rules:
3965 // for all platforms we support, int can always hold the values of lower-ranked types
3966 t1 = normalizeLowerRanks(tp: t1);
3967 t2 = normalizeLowerRanks(tp: t2);
3968
3969 // normalize long / ulong: in all platforms we run, they're either the same as int or as long long
3970 t1 = normalizeLong(tp: t1);
3971 t2 = normalizeLong(tp: t2);
3972
3973 // implement the other rules
3974 // the four possibilities are Int, UInt, LongLong and ULongLong
3975 // if any of the two is ULongLong, then it wins (highest rank, unsigned)
3976 // otherwise, if one of the two is LongLong, then the other is either LongLong too or lower-ranked
3977 // otherwise, if one of the two is UInt, then the other is either UInt too or Int
3978 if (t1 == QMetaType::ULongLong || t2 == QMetaType::ULongLong)
3979 return QMetaType::ULongLong;
3980 if (t1 == QMetaType::LongLong || t2 == QMetaType::LongLong)
3981 return QMetaType::LongLong;
3982 if (t1 == QMetaType::UInt || t2 == QMetaType::UInt)
3983 return QMetaType::UInt;
3984 return QMetaType::Int;
3985}
3986
3987static int integralCompare(uint promotedType, const QVariant::Private *d1, const QVariant::Private *d2)
3988{
3989 // use toLongLong to retrieve the data, it gets us all the bits
3990 bool ok;
3991 qlonglong l1 = qConvertToNumber(d: d1, ok: &ok);
3992 Q_ASSERT(ok);
3993
3994 qlonglong l2 = qConvertToNumber(d: d2, ok: &ok);
3995 Q_ASSERT(ok);
3996
3997 if (promotedType == QMetaType::Int)
3998 return int(l1) < int(l2) ? -1 : int(l1) == int(l2) ? 0 : 1;
3999 if (promotedType == QMetaType::UInt)
4000 return uint(l1) < uint(l2) ? -1 : uint(l1) == uint(l2) ? 0 : 1;
4001 if (promotedType == QMetaType::LongLong)
4002 return l1 < l2 ? -1 : l1 == l2 ? 0 : 1;
4003 if (promotedType == QMetaType::ULongLong)
4004 return qulonglong(l1) < qulonglong(l2) ? -1 : qulonglong(l1) == qulonglong(l2) ? 0 : 1;
4005
4006 Q_UNREACHABLE();
4007 return 0;
4008}
4009
4010static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2)
4011{
4012 uint promotedType = numericTypePromotion(t1: d1->type, t2: d2->type);
4013 if (promotedType != QMetaType::QReal)
4014 return integralCompare(promotedType, d1, d2);
4015
4016 // qreal comparisons
4017 bool ok;
4018 qreal r1 = qConvertToRealNumber(d: d1, ok: &ok);
4019 Q_ASSERT(ok);
4020 qreal r2 = qConvertToRealNumber(d: d2, ok: &ok);
4021 Q_ASSERT(ok);
4022 if (r1 == r2)
4023 return 0;
4024
4025 // only do fuzzy comparisons for finite, non-zero numbers
4026 int c1 = qFpClassify(val: r1);
4027 int c2 = qFpClassify(val: r2);
4028 if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
4029 if (qFuzzyCompare(p1: r1, p2: r2))
4030 return 0;
4031 }
4032
4033 return r1 < r2 ? -1 : 1;
4034}
4035
4036/*!
4037 \internal
4038 */
4039bool QVariant::cmp(const QVariant &v) const
4040{
4041 auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2)
4042 {
4043 Q_ASSERT(d1.type == d2.type);
4044 if (d1.type >= QMetaType::User) {
4045 int result;
4046 if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), typeId: d1.type, result: &result))
4047 return result == 0;
4048 }
4049 return handlerManager[d1.type]->compare(&d1, &d2);
4050 };
4051
4052 // try numerics first, with C++ type promotion rules (no conversion)
4053 if (qIsNumericType(tp: d.type) && qIsNumericType(tp: v.d.type))
4054 return numericCompare(d1: &d, d2: &v.d) == 0;
4055
4056 if (d.type == v.d.type)
4057 return cmp_helper(d, v.d);
4058
4059 QVariant v1 = *this;
4060 QVariant v2 = v;
4061 if (v2.canConvert(targetTypeId: v1.d.type)) {
4062 if (!v2.convert(targetTypeId: v1.d.type))
4063 return false;
4064 } else {
4065 // try the opposite conversion, it might work
4066 qSwap(value1&: v1, value2&: v2);
4067 if (!v2.convert(targetTypeId: v1.d.type))
4068 return false;
4069 }
4070 return cmp_helper(v1.d, v2.d);
4071}
4072
4073/*!
4074 \internal
4075 */
4076int QVariant::compare(const QVariant &v) const
4077{
4078 // try numerics first, with C++ type promotion rules (no conversion)
4079 if (qIsNumericType(tp: d.type) && qIsNumericType(tp: v.d.type))
4080 return numericCompare(d1: &d, d2: &v.d);
4081
4082 // check for equality next, as more types implement operator== than operator<
4083 if (cmp(v))
4084 return 0;
4085
4086 const QVariant *v1 = this;
4087 const QVariant *v2 = &v;
4088 QVariant converted1;
4089 QVariant converted2;
4090
4091 if (d.type != v.d.type) {
4092 // if both types differ, try to convert
4093 if (v2->canConvert(targetTypeId: v1->d.type)) {
4094 converted2 = *v2;
4095 if (converted2.convert(targetTypeId: v1->d.type))
4096 v2 = &converted2;
4097 }
4098 if (v1->d.type != v2->d.type && v1->canConvert(targetTypeId: v2->d.type)) {
4099 converted1 = *v1;
4100 if (converted1.convert(targetTypeId: v2->d.type))
4101 v1 = &converted1;
4102 }
4103 if (v1->d.type != v2->d.type) {
4104 // if conversion fails, default to toString
4105 int r = v1->toString().compare(s: v2->toString(), cs: Qt::CaseInsensitive);
4106 if (r == 0) {
4107 // cmp(v) returned false, so we should try to agree with it.
4108 return (v1->d.type < v2->d.type) ? -1 : 1;
4109 }
4110 return r;
4111 }
4112
4113 // did we end up with two numerics? If so, restart
4114 if (qIsNumericType(tp: v1->d.type) && qIsNumericType(tp: v2->d.type))
4115 return v1->compare(v: *v2);
4116 }
4117 if (v1->d.type >= QMetaType::User) {
4118 int result;
4119 if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), typeId: d.type, result: &result))
4120 return result;
4121 }
4122 switch (v1->d.type) {
4123 case QVariant::Date:
4124 return v1->toDate() < v2->toDate() ? -1 : 1;
4125 case QVariant::Time:
4126 return v1->toTime() < v2->toTime() ? -1 : 1;
4127 case QVariant::DateTime:
4128 return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
4129 case QVariant::StringList:
4130 return v1->toStringList() < v2->toStringList() ? -1 : 1;
4131 }
4132 int r = v1->toString().compare(s: v2->toString(), cs: Qt::CaseInsensitive);
4133 if (r == 0) {
4134 // cmp(v) returned false, so we should try to agree with it.
4135 return (d.type < v.d.type) ? -1 : 1;
4136 }
4137 return r;
4138}
4139
4140/*!
4141 \internal
4142 */
4143
4144const void *QVariant::constData() const
4145{
4146 return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
4147}
4148
4149/*!
4150 \fn const void* QVariant::data() const
4151
4152 \internal
4153*/
4154
4155/*!
4156 \internal
4157*/
4158void* QVariant::data()
4159{
4160 detach();
4161 return const_cast<void *>(constData());
4162}
4163
4164
4165/*!
4166 Returns \c true if this is a null variant, false otherwise. A variant is
4167 considered null if it contains no initialized value, or the contained value
4168 is \nullptr or is an instance of a built-in type that has an isNull
4169 method, in which case the result would be the same as calling isNull on the
4170 wrapped object.
4171
4172 \warning Null variants is not a single state and two null variants may easily
4173 return \c false on the == operator if they do not contain similar null values.
4174
4175 \sa convert(int)
4176*/
4177bool QVariant::isNull() const
4178{
4179 return handlerManager[d.type]->isNull(&d);
4180}
4181
4182#ifndef QT_NO_DEBUG_STREAM
4183QDebug operator<<(QDebug dbg, const QVariant &v)
4184{
4185 QDebugStateSaver saver(dbg);
4186 const uint typeId = v.d.type;
4187 dbg.nospace() << "QVariant(";
4188 if (typeId != QMetaType::UnknownType) {
4189 dbg << QMetaType::typeName(type: typeId) << ", ";
4190 bool userStream = false;
4191 bool canConvertToString = false;
4192 if (typeId >= QMetaType::User) {
4193 userStream = QMetaType::debugStream(dbg, rhs: constData(d: v.d), typeId);
4194 canConvertToString = v.canConvert<QString>();
4195 }
4196 if (!userStream && canConvertToString)
4197 dbg << v.toString();
4198 else if (!userStream)
4199 handlerManager[typeId]->debugStream(dbg, v);
4200 } else {
4201 dbg << "Invalid";
4202 }
4203 dbg << ')';
4204 return dbg;
4205}
4206
4207QDebug operator<<(QDebug dbg, const QVariant::Type p)
4208{
4209 QDebugStateSaver saver(dbg);
4210 dbg.nospace() << "QVariant::"
4211 << (int(p) != int(QMetaType::UnknownType)
4212 ? QMetaType::typeName(type: p)
4213 : "Invalid");
4214 return dbg;
4215}
4216#endif
4217
4218
4219/*! \fn template<typename T> void QVariant::setValue(const T &value)
4220
4221 Stores a copy of \a value. If \c{T} is a type that QVariant
4222 doesn't support, QMetaType is used to store the value. A compile
4223 error will occur if QMetaType doesn't handle the type.
4224
4225 Example:
4226
4227 \snippet code/src_corelib_kernel_qvariant.cpp 4
4228
4229 \sa value(), fromValue(), canConvert()
4230 */
4231
4232/*! \fn template<typename T> T QVariant::value() const
4233
4234 Returns the stored value converted to the template type \c{T}.
4235 Call canConvert() to find out whether a type can be converted.
4236 If the value cannot be converted, a \l{default-constructed value}
4237 will be returned.
4238
4239 If the type \c{T} is supported by QVariant, this function behaves
4240 exactly as toString(), toInt() etc.
4241
4242 Example:
4243
4244 \snippet code/src_corelib_kernel_qvariant.cpp 5
4245
4246 If the QVariant contains a pointer to a type derived from QObject then
4247 \c{T} may be any QObject type. If the pointer stored in the QVariant can be
4248 qobject_cast to T, then that result is returned. Otherwise \nullptr is
4249 returned. Note that this only works for QObject subclasses which use the
4250 Q_OBJECT macro.
4251
4252 If the QVariant contains a sequential container and \c{T} is QVariantList, the
4253 elements of the container will be converted into \l {QVariant}s and returned as a QVariantList.
4254
4255 \snippet code/src_corelib_kernel_qvariant.cpp 9
4256
4257 \sa setValue(), fromValue(), canConvert(), Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE()
4258*/
4259
4260/*! \fn bool QVariant::canConvert() const
4261
4262 Returns \c true if the variant can be converted to the template type \c{T},
4263 otherwise false.
4264
4265 Example:
4266
4267 \snippet code/src_corelib_kernel_qvariant.cpp 6
4268
4269 A QVariant containing a pointer to a type derived from QObject will also return true for this
4270 function if a qobject_cast to the template type \c{T} would succeed. Note that this only works
4271 for QObject subclasses which use the Q_OBJECT macro.
4272
4273 \sa convert()
4274*/
4275
4276/*! \fn template<typename T> static QVariant QVariant::fromValue(const T &value)
4277
4278 Returns a QVariant containing a copy of \a value. Behaves
4279 exactly like setValue() otherwise.
4280
4281 Example:
4282
4283 \snippet code/src_corelib_kernel_qvariant.cpp 7
4284
4285 \note If you are working with custom types, you should use
4286 the Q_DECLARE_METATYPE() macro to register your custom type.
4287
4288 \sa setValue(), value()
4289*/
4290
4291/*! \fn template<typename... Types> QVariant QVariant::fromStdVariant(const std::variant<Types...> &value)
4292 \since 5.11
4293
4294 Returns a QVariant with the type and value of the active variant of \a value. If
4295 the active type is std::monostate a default QVariant is returned.
4296
4297 \note With this method you do not need to register the variant as a Qt metatype,
4298 since the std::variant is resolved before being stored. The component types
4299 should be registered however.
4300
4301 \sa fromValue()
4302*/
4303
4304#if QT_DEPRECATED_SINCE(5, 14)
4305/*!
4306 \fn template<typename T> QVariant qVariantFromValue(const T &value)
4307 \relates QVariant
4308 \obsolete
4309
4310 Returns a variant containing a copy of the given \a value
4311 with template type \c{T}.
4312
4313 This function is equivalent to QVariant::fromValue(\a value).
4314
4315 \note This function was provided as a workaround for MSVC 6
4316 which did not support member template functions. It is advised
4317 to use the other form in new code.
4318
4319 For example, a QObject pointer can be stored in a variant with the
4320 following code:
4321
4322 \snippet code/src_corelib_kernel_qvariant.cpp 8
4323
4324 \sa QVariant::fromValue()
4325*/
4326
4327/*! \fn template<typename T> void qVariantSetValue(QVariant &variant, const T &value)
4328 \relates QVariant
4329 \obsolete
4330
4331 Sets the contents of the given \a variant to a copy of the
4332 \a value with the specified template type \c{T}.
4333
4334 This function is equivalent to QVariant::setValue(\a value).
4335
4336 \note This function was provided as a workaround for MSVC 6
4337 which did not support member template functions. It is advised
4338 to use the other form in new code.
4339
4340 \sa QVariant::setValue()
4341*/
4342#endif
4343
4344/*!
4345 \fn template<typename T> T qvariant_cast(const QVariant &value)
4346 \relates QVariant
4347
4348 Returns the given \a value converted to the template type \c{T}.
4349
4350 This function is equivalent to QVariant::value().
4351
4352 \sa QVariant::value()
4353*/
4354
4355/*! \fn template<typename T> T qVariantValue(const QVariant &value)
4356 \relates QVariant
4357 \obsolete
4358
4359 Returns the given \a value converted to the template type \c{T}.
4360
4361 This function is equivalent to
4362 \l{QVariant::value()}{QVariant::value}<T>(\a value).
4363
4364 \note This function was provided as a workaround for MSVC 6
4365 which did not support member template functions. It is advised
4366 to use the other form in new code.
4367
4368 \sa QVariant::value(), qvariant_cast()
4369*/
4370
4371/*! \fn bool qVariantCanConvert(const QVariant &value)
4372 \relates QVariant
4373 \obsolete
4374
4375 Returns \c true if the given \a value can be converted to the
4376 template type specified; otherwise returns \c false.
4377
4378 This function is equivalent to QVariant::canConvert(\a value).
4379
4380 \note This function was provided as a workaround for MSVC 6
4381 which did not support member template functions. It is advised
4382 to use the other form in new code.
4383
4384 \sa QVariant::canConvert()
4385*/
4386
4387/*!
4388 \typedef QVariantList
4389 \relates QVariant
4390
4391 Synonym for QList<QVariant>.
4392*/
4393
4394/*!
4395 \typedef QVariantMap
4396 \relates QVariant
4397
4398 Synonym for QMap<QString, QVariant>.
4399*/
4400
4401/*!
4402 \typedef QVariantHash
4403 \relates QVariant
4404 \since 4.5
4405
4406 Synonym for QHash<QString, QVariant>.
4407*/
4408
4409/*!
4410 \typedef QVariant::DataPtr
4411 \internal
4412*/
4413/*! \typedef QVariant::f_construct
4414 \internal
4415*/
4416
4417/*! \typedef QVariant::f_clear
4418 \internal
4419*/
4420
4421/*! \typedef QVariant::f_null
4422 \internal
4423*/
4424
4425/*! \typedef QVariant::f_load
4426 \internal
4427*/
4428
4429/*! \typedef QVariant::f_save
4430 \internal
4431*/
4432
4433/*! \typedef QVariant::f_compare
4434 \internal
4435*/
4436
4437/*! \typedef QVariant::f_convert
4438 \internal
4439*/
4440
4441/*! \typedef QVariant::f_canConvert
4442 \internal
4443*/
4444
4445/*! \typedef QVariant::f_debugStream
4446 \internal
4447*/
4448
4449/*!
4450 \fn DataPtr &QVariant::data_ptr()
4451 \internal
4452*/
4453
4454/*!
4455 \fn const DataPtr &QVariant::data_ptr() const
4456 \internal
4457*/
4458
4459/*!
4460 \class QSequentialIterable
4461 \since 5.2
4462 \inmodule QtCore
4463 \brief The QSequentialIterable class is an iterable interface for a container in a QVariant.
4464
4465 This class allows several methods of accessing the elements of a container held within
4466 a QVariant. An instance of QSequentialIterable can be extracted from a QVariant if it can
4467 be converted to a QVariantList.
4468
4469 \snippet code/src_corelib_kernel_qvariant.cpp 9
4470
4471 The container itself is not copied before iterating over it.
4472
4473 \sa QVariant
4474*/
4475
4476/*!
4477 \internal
4478*/
4479#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4480QSequentialIterable::QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl)
4481#else
4482QSequentialIterable::QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl)
4483#endif
4484 : m_impl(impl)
4485{
4486}
4487
4488QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_)
4489 : m_impl(iter.m_impl), ref(ref_)
4490{
4491 ref->ref();
4492}
4493
4494QSequentialIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_)
4495 : m_impl(impl), ref(ref_)
4496{
4497 ref->ref();
4498}
4499
4500void QSequentialIterable::const_iterator::begin()
4501{
4502 m_impl.moveToBegin();
4503}
4504
4505void QSequentialIterable::const_iterator::end()
4506{
4507 m_impl.moveToEnd();
4508}
4509
4510/*! \fn QSequentialIterable::const_iterator QSequentialIterable::begin() const
4511
4512 Returns a QSequentialIterable::const_iterator for the beginning of the container. This
4513 can be used in stl-style iteration.
4514
4515 \sa end()
4516*/
4517QSequentialIterable::const_iterator QSequentialIterable::begin() const
4518{
4519 const_iterator it(*this, new QAtomicInt(0));
4520 it.begin();
4521 return it;
4522}
4523
4524/*!
4525 Returns a QSequentialIterable::const_iterator for the end of the container. This
4526 can be used in stl-style iteration.
4527
4528 \sa begin()
4529*/
4530QSequentialIterable::const_iterator QSequentialIterable::end() const
4531{
4532 const_iterator it(*this, new QAtomicInt(0));
4533 it.end();
4534 return it;
4535}
4536
4537static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
4538 QVariant v;
4539 if (d.metaTypeId == qMetaTypeId<QVariant>())
4540 v = *reinterpret_cast<const QVariant*>(d.data);
4541 else
4542 v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
4543 if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
4544 QMetaType::destroy(type: d.metaTypeId, data: const_cast<void *>(d.data));
4545 return v;
4546}
4547
4548/*!
4549 Returns the element at position \a idx in the container.
4550*/
4551QVariant QSequentialIterable::at(int idx) const
4552{
4553 const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
4554 return variantFromVariantDataHelper(d);
4555}
4556
4557/*!
4558 Returns the number of elements in the container.
4559*/
4560int QSequentialIterable::size() const
4561{
4562 return m_impl.size();
4563}
4564
4565/*!
4566 Returns whether it is possible to iterate over the container in reverse. This
4567 corresponds to the std::bidirectional_iterator_tag iterator trait of the
4568 const_iterator of the container.
4569*/
4570bool QSequentialIterable::canReverseIterate() const
4571{
4572 return m_impl._iteratorCapabilities & QtMetaTypePrivate::BiDirectionalCapability;
4573}
4574
4575/*!
4576 \class QSequentialIterable::const_iterator
4577 \since 5.2
4578 \inmodule QtCore
4579 \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant.
4580
4581 A QSequentialIterable::const_iterator can only be created by a QSequentialIterable instance,
4582 and can be used in a way similar to other stl-style iterators.
4583
4584 \snippet code/src_corelib_kernel_qvariant.cpp 9
4585
4586 \sa QSequentialIterable
4587*/
4588
4589
4590/*!
4591 Destroys the QSequentialIterable::const_iterator.
4592*/
4593QSequentialIterable::const_iterator::~const_iterator() {
4594 if (!ref->deref()) {
4595 m_impl.destroyIter();
4596 delete ref;
4597 }
4598}
4599
4600/*!
4601 Creates a copy of \a other.
4602*/
4603QSequentialIterable::const_iterator::const_iterator(const const_iterator &other)
4604 : m_impl(other.m_impl), ref(other.ref)
4605{
4606 ref->ref();
4607}
4608
4609/*!
4610 Assigns \a other to this.
4611*/
4612QSequentialIterable::const_iterator&
4613QSequentialIterable::const_iterator::operator=(const const_iterator &other)
4614{
4615 other.ref->ref();
4616 if (!ref->deref()) {
4617 m_impl.destroyIter();
4618 delete ref;
4619 }
4620 m_impl = other.m_impl;
4621 ref = other.ref;
4622 return *this;
4623}
4624
4625/*!
4626 Returns the current item, converted to a QVariant.
4627*/
4628const QVariant QSequentialIterable::const_iterator::operator*() const
4629{
4630 const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
4631 return variantFromVariantDataHelper(d);
4632}
4633
4634/*!
4635 Returns \c true if \a other points to the same item as this
4636 iterator; otherwise returns \c false.
4637
4638 \sa operator!=()
4639*/
4640bool QSequentialIterable::const_iterator::operator==(const const_iterator &other) const
4641{
4642 return m_impl.equal(other: other.m_impl);
4643}
4644
4645/*!
4646 Returns \c true if \a other points to a different item than this
4647 iterator; otherwise returns \c false.
4648
4649 \sa operator==()
4650*/
4651bool QSequentialIterable::const_iterator::operator!=(const const_iterator &other) const
4652{
4653 return !m_impl.equal(other: other.m_impl);
4654}
4655
4656/*!
4657 The prefix ++ operator (\c{++it}) advances the iterator to the
4658 next item in the container and returns an iterator to the new current
4659 item.
4660
4661 Calling this function on QSequentialIterable::end() leads to undefined results.
4662
4663 \sa operator--()
4664*/
4665QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator++()
4666{
4667 m_impl.advance(i: 1);
4668 return *this;
4669}
4670
4671/*!
4672 \overload
4673
4674 The postfix ++ operator (\c{it++}) advances the iterator to the
4675 next item in the container and returns an iterator to the previously
4676 current item.
4677*/
4678QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator++(int)
4679{
4680 QtMetaTypePrivate::QSequentialIterableImpl impl;
4681 impl.copy(other: m_impl);
4682 m_impl.advance(i: 1);
4683 return const_iterator(impl, new QAtomicInt(0));
4684}
4685
4686/*!
4687 The prefix -- operator (\c{--it}) makes the preceding item
4688 current and returns an iterator to the new current item.
4689
4690 Calling this function on QSequentialIterable::begin() leads to undefined results.
4691
4692 If the container in the QVariant does not support bi-directional iteration, calling this function
4693 leads to undefined results.
4694
4695 \sa operator++(), canReverseIterate()
4696*/
4697QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator--()
4698{
4699 m_impl.advance(i: -1);
4700 return *this;
4701}
4702
4703/*!
4704 \overload
4705
4706 The postfix -- operator (\c{it--}) makes the preceding item
4707 current and returns an iterator to the previously current item.
4708
4709 If the container in the QVariant does not support bi-directional iteration, calling this function
4710 leads to undefined results.
4711
4712 \sa canReverseIterate()
4713*/
4714QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator--(int)
4715{
4716 QtMetaTypePrivate::QSequentialIterableImpl impl;
4717 impl.copy(other: m_impl);
4718 m_impl.advance(i: -1);
4719 return const_iterator(impl, new QAtomicInt(0));
4720}
4721
4722/*!
4723 Advances the iterator by \a j items.
4724
4725 \sa operator-=(), operator+()
4726*/
4727QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator+=(int j)
4728{
4729 m_impl.advance(i: j);
4730 return *this;
4731}
4732
4733/*!
4734 Makes the iterator go back by \a j items.
4735
4736 If the container in the QVariant does not support bi-directional iteration, calling this function
4737 leads to undefined results.
4738
4739 \sa operator+=(), operator-(), canReverseIterate()
4740*/
4741QSequentialIterable::const_iterator &QSequentialIterable::const_iterator::operator-=(int j)
4742{
4743 m_impl.advance(i: -j);
4744 return *this;
4745}
4746
4747/*!
4748 Returns an iterator to the item at \a j positions forward from
4749 this iterator.
4750
4751 \sa operator-(), operator+=()
4752*/
4753QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator+(int j) const
4754{
4755 QtMetaTypePrivate::QSequentialIterableImpl impl;
4756 impl.copy(other: m_impl);
4757 impl.advance(i: j);
4758 return const_iterator(impl, new QAtomicInt(0));
4759}
4760
4761/*!
4762 Returns an iterator to the item at \a j positions backward from
4763 this iterator.
4764
4765 If the container in the QVariant does not support bi-directional iteration, calling this function
4766 leads to undefined results.
4767
4768 \sa operator+(), operator-=(), canReverseIterate()
4769*/
4770QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operator-(int j) const
4771{
4772 QtMetaTypePrivate::QSequentialIterableImpl impl;
4773 impl.copy(other: m_impl);
4774 impl.advance(i: -j);
4775 return const_iterator(impl, new QAtomicInt(0));
4776}
4777
4778/*!
4779 \class QAssociativeIterable
4780 \since 5.2
4781 \inmodule QtCore
4782 \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant.
4783
4784 This class allows several methods of accessing the elements of an associative container held within
4785 a QVariant. An instance of QAssociativeIterable can be extracted from a QVariant if it can
4786 be converted to a QVariantHash or QVariantMap.
4787
4788 \snippet code/src_corelib_kernel_qvariant.cpp 10
4789
4790 The container itself is not copied before iterating over it.
4791
4792 \sa QVariant
4793*/
4794
4795/*!
4796 \internal
4797*/
4798#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4799QAssociativeIterable::QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl)
4800#else
4801QAssociativeIterable::QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl)
4802#endif
4803 : m_impl(impl)
4804{
4805}
4806
4807QAssociativeIterable::const_iterator::const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_)
4808 : m_impl(iter.m_impl), ref(ref_)
4809{
4810 ref->ref();
4811}
4812
4813QAssociativeIterable::const_iterator::const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_)
4814 : m_impl(impl), ref(ref_)
4815{
4816 ref->ref();
4817}
4818
4819void QAssociativeIterable::const_iterator::begin()
4820{
4821 m_impl.begin();
4822}
4823
4824void QAssociativeIterable::const_iterator::end()
4825{
4826 m_impl.end();
4827}
4828
4829void QAssociativeIterable::const_iterator::find(const QVariant &key)
4830{
4831 Q_ASSERT(key.userType() == m_impl._metaType_id_key);
4832 const QtMetaTypePrivate::VariantData dkey(key.userType(), key.constData(), 0 /*key.flags()*/);
4833 m_impl.find(key: dkey);
4834}
4835
4836/*!
4837 Returns a QAssociativeIterable::const_iterator for the beginning of the container. This
4838 can be used in stl-style iteration.
4839
4840 \sa end()
4841*/
4842QAssociativeIterable::const_iterator QAssociativeIterable::begin() const
4843{
4844 const_iterator it(*this, new QAtomicInt(0));
4845 it.begin();
4846 return it;
4847}
4848
4849/*!
4850 Returns a QAssociativeIterable::const_iterator for the end of the container. This
4851 can be used in stl-style iteration.
4852
4853 \sa begin()
4854*/
4855QAssociativeIterable::const_iterator QAssociativeIterable::end() const
4856{
4857 const_iterator it(*this, new QAtomicInt(0));
4858 it.end();
4859 return it;
4860}
4861
4862/*!
4863 \since 5.5
4864
4865 Returns a QAssociativeIterable::const_iterator for the given key \a key
4866 in the container, if the types are convertible.
4867
4868 If the key is not found, returns end().
4869
4870 This can be used in stl-style iteration.
4871
4872 \sa begin(), end(), value()
4873*/
4874QAssociativeIterable::const_iterator QAssociativeIterable::find(const QVariant &key) const
4875{
4876 const_iterator it(*this, new QAtomicInt(0));
4877 QVariant key_ = key;
4878 if (key_.canConvert(targetTypeId: m_impl._metaType_id_key) && key_.convert(targetTypeId: m_impl._metaType_id_key))
4879 it.find(key: key_);
4880 else
4881 it.end();
4882 return it;
4883}
4884
4885/*!
4886 Returns the value for the given \a key in the container, if the types are convertible.
4887
4888 \sa find()
4889*/
4890QVariant QAssociativeIterable::value(const QVariant &key) const
4891{
4892 const const_iterator it = find(key);
4893 if (it == end())
4894 return QVariant();
4895 return *it;
4896}
4897
4898/*!
4899 Returns the number of elements in the container.
4900*/
4901int QAssociativeIterable::size() const
4902{
4903 return m_impl.size();
4904}
4905
4906/*!
4907 \class QAssociativeIterable::const_iterator
4908 \since 5.2
4909 \inmodule QtCore
4910 \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant.
4911
4912 A QAssociativeIterable::const_iterator can only be created by a QAssociativeIterable instance,
4913 and can be used in a way similar to other stl-style iterators.
4914
4915 \snippet code/src_corelib_kernel_qvariant.cpp 10
4916
4917 \sa QAssociativeIterable
4918*/
4919
4920
4921/*!
4922 Destroys the QAssociativeIterable::const_iterator.
4923*/
4924QAssociativeIterable::const_iterator::~const_iterator()
4925{
4926 if (!ref->deref()) {
4927 m_impl.destroyIter();
4928 delete ref;
4929 }
4930}
4931
4932/*!
4933 Creates a copy of \a other.
4934*/
4935QAssociativeIterable::const_iterator::const_iterator(const const_iterator &other)
4936 : m_impl(other.m_impl), ref(other.ref)
4937{
4938 ref->ref();
4939}
4940
4941/*!
4942 Assigns \a other to this.
4943*/
4944QAssociativeIterable::const_iterator&
4945QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
4946{
4947 other.ref->ref();
4948 if (!ref->deref()) {
4949 m_impl.destroyIter();
4950 delete ref;
4951 }
4952 m_impl = other.m_impl;
4953 ref = other.ref;
4954 return *this;
4955}
4956
4957/*!
4958 Returns the current value, converted to a QVariant.
4959*/
4960const QVariant QAssociativeIterable::const_iterator::operator*() const
4961{
4962 const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
4963 return variantFromVariantDataHelper(d);
4964}
4965
4966/*!
4967 Returns the current key, converted to a QVariant.
4968*/
4969const QVariant QAssociativeIterable::const_iterator::key() const
4970{
4971 const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
4972 return variantFromVariantDataHelper(d);
4973}
4974
4975/*!
4976 Returns the current value, converted to a QVariant.
4977*/
4978const QVariant QAssociativeIterable::const_iterator::value() const
4979{
4980 return operator*();
4981}
4982
4983/*!
4984 Returns \c true if \a other points to the same item as this
4985 iterator; otherwise returns \c false.
4986
4987 \sa operator!=()
4988*/
4989bool QAssociativeIterable::const_iterator::operator==(const const_iterator &other) const
4990{
4991 return m_impl.equal(other: other.m_impl);
4992}
4993
4994/*!
4995 Returns \c true if \a other points to a different item than this
4996 iterator; otherwise returns \c false.
4997
4998 \sa operator==()
4999*/
5000bool QAssociativeIterable::const_iterator::operator!=(const const_iterator &other) const
5001{
5002 return !m_impl.equal(other: other.m_impl);
5003}
5004
5005/*!
5006 The prefix ++ operator (\c{++it}) advances the iterator to the
5007 next item in the container and returns an iterator to the new current
5008 item.
5009
5010 Calling this function on QAssociativeIterable::end() leads to undefined results.
5011
5012 \sa operator--()
5013*/
5014QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator++()
5015{
5016 m_impl.advance(i: 1);
5017 return *this;
5018}
5019
5020/*!
5021 \overload
5022
5023 The postfix ++ operator (\c{it++}) advances the iterator to the
5024 next item in the container and returns an iterator to the previously
5025 current item.
5026*/
5027QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator++(int)
5028{
5029 QtMetaTypePrivate::QAssociativeIterableImpl impl;
5030 impl.copy(other: m_impl);
5031 m_impl.advance(i: 1);
5032 return const_iterator(impl, new QAtomicInt(0));
5033}
5034
5035/*!
5036 The prefix -- operator (\c{--it}) makes the preceding item
5037 current and returns an iterator to the new current item.
5038
5039 Calling this function on QAssociativeIterable::begin() leads to undefined results.
5040
5041 \sa operator++()
5042*/
5043QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator--()
5044{
5045 m_impl.advance(i: -1);
5046 return *this;
5047}
5048
5049/*!
5050 \overload
5051
5052 The postfix -- operator (\c{it--}) makes the preceding item
5053 current and returns an iterator to the previously current item.
5054*/
5055QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator--(int)
5056{
5057 QtMetaTypePrivate::QAssociativeIterableImpl impl;
5058 impl.copy(other: m_impl);
5059 m_impl.advance(i: -1);
5060 return const_iterator(impl, new QAtomicInt(0));
5061}
5062
5063/*!
5064 Advances the iterator by \a j items.
5065
5066 \sa operator-=(), operator+()
5067*/
5068QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator+=(int j)
5069{
5070 m_impl.advance(i: j);
5071 return *this;
5072}
5073
5074/*!
5075 Makes the iterator go back by \a j items.
5076
5077 \sa operator+=(), operator-()
5078*/
5079QAssociativeIterable::const_iterator &QAssociativeIterable::const_iterator::operator-=(int j)
5080{
5081 m_impl.advance(i: -j);
5082 return *this;
5083}
5084
5085/*!
5086 Returns an iterator to the item at \a j positions forward from
5087 this iterator.
5088
5089 \sa operator-(), operator+=()
5090*/
5091QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator+(int j) const
5092{
5093 QtMetaTypePrivate::QAssociativeIterableImpl impl;
5094 impl.copy(other: m_impl);
5095 impl.advance(i: j);
5096 return const_iterator(impl, new QAtomicInt(0));
5097}
5098
5099/*!
5100 Returns an iterator to the item at \a j positions backward from
5101 this iterator.
5102
5103 \sa operator+(), operator-=()
5104*/
5105QAssociativeIterable::const_iterator QAssociativeIterable::const_iterator::operator-(int j) const
5106{
5107 QtMetaTypePrivate::QAssociativeIterableImpl impl;
5108 impl.copy(other: m_impl);
5109 impl.advance(i: -j);
5110 return const_iterator(impl, new QAtomicInt(0));
5111}
5112
5113QT_END_NAMESPACE
5114

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