1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QVARIANT_H
41#define QVARIANT_H
42
43#include <QtCore/qatomic.h>
44#include <QtCore/qbytearray.h>
45#include <QtCore/qlist.h>
46#include <QtCore/qmetatype.h>
47#include <QtCore/qmap.h>
48#include <QtCore/qhash.h>
49#include <QtCore/qstring.h>
50#include <QtCore/qstringlist.h>
51#include <QtCore/qobject.h>
52#ifndef QT_BOOTSTRAPPED
53#include <QtCore/qbytearraylist.h>
54#endif
55
56#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
57#include <variant>
58#elif defined(Q_CLANG_QDOC)
59namespace std { template<typename...> struct variant; }
60#endif
61
62QT_BEGIN_NAMESPACE
63
64
65class QBitArray;
66class QDataStream;
67class QDate;
68class QDateTime;
69class QEasingCurve;
70class QLine;
71class QLineF;
72class QLocale;
73class QMatrix;
74class QTransform;
75class QStringList;
76class QTime;
77class QPoint;
78class QPointF;
79class QSize;
80class QSizeF;
81class QRect;
82class QRectF;
83#ifndef QT_NO_REGEXP
84class QRegExp;
85#endif // QT_NO_REGEXP
86#if QT_CONFIG(regularexpression)
87class QRegularExpression;
88#endif // QT_CONFIG(regularexpression)
89class QTextFormat;
90class QTextLength;
91class QUrl;
92class QVariant;
93class QVariantComparisonHelper;
94
95template <typename T>
96inline QVariant qVariantFromValue(const T &);
97
98template<typename T>
99inline T qvariant_cast(const QVariant &);
100
101namespace QtPrivate {
102
103 template <typename Derived, typename Argument, typename ReturnType>
104 struct ObjectInvoker
105 {
106 static ReturnType invoke(Argument a)
107 {
108 return Derived::object(a);
109 }
110 };
111
112 template <typename Derived, typename Argument, typename ReturnType>
113 struct MetaTypeInvoker
114 {
115 static ReturnType invoke(Argument a)
116 {
117 return Derived::metaType(a);
118 }
119 };
120
121 template <typename Derived, typename T, typename Argument, typename ReturnType, bool = IsPointerToTypeDerivedFromQObject<T>::Value>
122 struct TreatAsQObjectBeforeMetaType : ObjectInvoker<Derived, Argument, ReturnType>
123 {
124 };
125
126 template <typename Derived, typename T, typename Argument, typename ReturnType>
127 struct TreatAsQObjectBeforeMetaType<Derived, T, Argument, ReturnType, false> : MetaTypeInvoker<Derived, Argument, ReturnType>
128 {
129 };
130
131 template<typename T> struct QVariantValueHelper;
132}
133
134class Q_CORE_EXPORT QVariant
135{
136 public:
137 enum Type {
138 Invalid = QMetaType::UnknownType,
139 Bool = QMetaType::Bool,
140 Int = QMetaType::Int,
141 UInt = QMetaType::UInt,
142 LongLong = QMetaType::LongLong,
143 ULongLong = QMetaType::ULongLong,
144 Double = QMetaType::Double,
145 Char = QMetaType::QChar,
146 Map = QMetaType::QVariantMap,
147 List = QMetaType::QVariantList,
148 String = QMetaType::QString,
149 StringList = QMetaType::QStringList,
150 ByteArray = QMetaType::QByteArray,
151 BitArray = QMetaType::QBitArray,
152 Date = QMetaType::QDate,
153 Time = QMetaType::QTime,
154 DateTime = QMetaType::QDateTime,
155 Url = QMetaType::QUrl,
156 Locale = QMetaType::QLocale,
157 Rect = QMetaType::QRect,
158 RectF = QMetaType::QRectF,
159 Size = QMetaType::QSize,
160 SizeF = QMetaType::QSizeF,
161 Line = QMetaType::QLine,
162 LineF = QMetaType::QLineF,
163 Point = QMetaType::QPoint,
164 PointF = QMetaType::QPointF,
165 RegExp = QMetaType::QRegExp,
166 RegularExpression = QMetaType::QRegularExpression,
167 Hash = QMetaType::QVariantHash,
168 EasingCurve = QMetaType::QEasingCurve,
169 Uuid = QMetaType::QUuid,
170#if QT_CONFIG(itemmodel)
171 ModelIndex = QMetaType::QModelIndex,
172 PersistentModelIndex = QMetaType::QPersistentModelIndex,
173#endif
174 LastCoreType = QMetaType::LastCoreType,
175
176 Font = QMetaType::QFont,
177 Pixmap = QMetaType::QPixmap,
178 Brush = QMetaType::QBrush,
179 Color = QMetaType::QColor,
180 Palette = QMetaType::QPalette,
181 Image = QMetaType::QImage,
182 Polygon = QMetaType::QPolygon,
183 Region = QMetaType::QRegion,
184 Bitmap = QMetaType::QBitmap,
185 Cursor = QMetaType::QCursor,
186 KeySequence = QMetaType::QKeySequence,
187 Pen = QMetaType::QPen,
188 TextLength = QMetaType::QTextLength,
189 TextFormat = QMetaType::QTextFormat,
190 Matrix = QMetaType::QMatrix,
191 Transform = QMetaType::QTransform,
192 Matrix4x4 = QMetaType::QMatrix4x4,
193 Vector2D = QMetaType::QVector2D,
194 Vector3D = QMetaType::QVector3D,
195 Vector4D = QMetaType::QVector4D,
196 Quaternion = QMetaType::QQuaternion,
197 PolygonF = QMetaType::QPolygonF,
198 Icon = QMetaType::QIcon,
199 LastGuiType = QMetaType::LastGuiType,
200
201 SizePolicy = QMetaType::QSizePolicy,
202
203 UserType = QMetaType::User,
204 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
205 };
206
207 QVariant() Q_DECL_NOTHROW : d() {}
208 ~QVariant();
209 QVariant(Type type);
210 QVariant(int typeId, const void *copy);
211 QVariant(int typeId, const void *copy, uint flags);
212 QVariant(const QVariant &other);
213
214#ifndef QT_NO_DATASTREAM
215 QVariant(QDataStream &s);
216#endif
217
218 QVariant(int i);
219 QVariant(uint ui);
220 QVariant(qlonglong ll);
221 QVariant(qulonglong ull);
222 QVariant(bool b);
223 QVariant(double d);
224 QVariant(float f);
225#ifndef QT_NO_CAST_FROM_ASCII
226 QT_ASCII_CAST_WARN QVariant(const char *str);
227#endif
228
229 QVariant(const QByteArray &bytearray);
230 QVariant(const QBitArray &bitarray);
231 QVariant(const QString &string);
232 QVariant(QLatin1String string);
233 QVariant(const QStringList &stringlist);
234 QVariant(QChar qchar);
235 QVariant(const QDate &date);
236 QVariant(const QTime &time);
237 QVariant(const QDateTime &datetime);
238 QVariant(const QList<QVariant> &list);
239 QVariant(const QMap<QString,QVariant> &map);
240 QVariant(const QHash<QString,QVariant> &hash);
241#ifndef QT_NO_GEOM_VARIANT
242 QVariant(const QSize &size);
243 QVariant(const QSizeF &size);
244 QVariant(const QPoint &pt);
245 QVariant(const QPointF &pt);
246 QVariant(const QLine &line);
247 QVariant(const QLineF &line);
248 QVariant(const QRect &rect);
249 QVariant(const QRectF &rect);
250#endif
251 QVariant(const QLocale &locale);
252#ifndef QT_NO_REGEXP
253 QVariant(const QRegExp &regExp);
254#endif // QT_NO_REGEXP
255#if QT_CONFIG(regularexpression)
256 QVariant(const QRegularExpression &re);
257#endif // QT_CONFIG(regularexpression)
258#ifndef QT_BOOTSTRAPPED
259 QVariant(const QUrl &url);
260 QVariant(const QEasingCurve &easing);
261 QVariant(const QUuid &uuid);
262 QVariant(const QJsonValue &jsonValue);
263 QVariant(const QJsonObject &jsonObject);
264 QVariant(const QJsonArray &jsonArray);
265 QVariant(const QJsonDocument &jsonDocument);
266#endif // QT_BOOTSTRAPPED
267#if QT_CONFIG(itemmodel)
268 QVariant(const QModelIndex &modelIndex);
269 QVariant(const QPersistentModelIndex &modelIndex);
270#endif
271
272 QVariant& operator=(const QVariant &other);
273#ifdef Q_COMPILER_RVALUE_REFS
274 inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d)
275 { other.d = Private(); }
276 inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW
277 { qSwap(d, other.d); return *this; }
278#endif
279
280 inline void swap(QVariant &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
281
282 Type type() const;
283 int userType() const;
284 const char *typeName() const;
285
286 bool canConvert(int targetTypeId) const;
287 bool convert(int targetTypeId);
288
289 inline bool isValid() const;
290 bool isNull() const;
291
292 void clear();
293
294 void detach();
295 inline bool isDetached() const;
296
297 int toInt(bool *ok = nullptr) const;
298 uint toUInt(bool *ok = nullptr) const;
299 qlonglong toLongLong(bool *ok = nullptr) const;
300 qulonglong toULongLong(bool *ok = nullptr) const;
301 bool toBool() const;
302 double toDouble(bool *ok = nullptr) const;
303 float toFloat(bool *ok = nullptr) const;
304 qreal toReal(bool *ok = nullptr) const;
305 QByteArray toByteArray() const;
306 QBitArray toBitArray() const;
307 QString toString() const;
308 QStringList toStringList() const;
309 QChar toChar() const;
310 QDate toDate() const;
311 QTime toTime() const;
312 QDateTime toDateTime() const;
313 QList<QVariant> toList() const;
314 QMap<QString, QVariant> toMap() const;
315 QHash<QString, QVariant> toHash() const;
316
317#ifndef QT_NO_GEOM_VARIANT
318 QPoint toPoint() const;
319 QPointF toPointF() const;
320 QRect toRect() const;
321 QSize toSize() const;
322 QSizeF toSizeF() const;
323 QLine toLine() const;
324 QLineF toLineF() const;
325 QRectF toRectF() const;
326#endif
327 QLocale toLocale() const;
328#ifndef QT_NO_REGEXP
329 QRegExp toRegExp() const;
330#endif // QT_NO_REGEXP
331#if QT_CONFIG(regularexpression)
332 QRegularExpression toRegularExpression() const;
333#endif // QT_CONFIG(regularexpression)
334#ifndef QT_BOOTSTRAPPED
335 QUrl toUrl() const;
336 QEasingCurve toEasingCurve() const;
337 QUuid toUuid() const;
338 QJsonValue toJsonValue() const;
339 QJsonObject toJsonObject() const;
340 QJsonArray toJsonArray() const;
341 QJsonDocument toJsonDocument() const;
342#endif // QT_BOOTSTRAPPED
343#if QT_CONFIG(itemmodel)
344 QModelIndex toModelIndex() const;
345 QPersistentModelIndex toPersistentModelIndex() const;
346#endif
347
348#ifndef QT_NO_DATASTREAM
349 void load(QDataStream &ds);
350 void save(QDataStream &ds) const;
351#endif
352 static const char *typeToName(int typeId);
353 static Type nameToType(const char *name);
354
355 void *data();
356 const void *constData() const;
357 inline const void *data() const { return constData(); }
358
359 template<typename T>
360 inline void setValue(const T &value);
361
362 template<typename T>
363 inline T value() const
364 { return qvariant_cast<T>(*this); }
365
366 template<typename T>
367 static inline QVariant fromValue(const T &value)
368 { return qVariantFromValue(value); }
369
370#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
371 template<typename... Types>
372 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
373 {
374 if (value.valueless_by_exception())
375 return QVariant();
376 return std::visit([](const auto &arg) { return fromValue(arg); }, value);
377 }
378#endif
379
380 template<typename T>
381 bool canConvert() const
382 { return canConvert(qMetaTypeId<T>()); }
383
384 public:
385 struct PrivateShared
386 {
387 inline PrivateShared(void *v) : ptr(v), ref(1) { }
388 void *ptr;
389 QAtomicInt ref;
390 };
391 struct Private
392 {
393 inline Private() Q_DECL_NOTHROW : type(Invalid), is_shared(false), is_null(true)
394 { data.ptr = nullptr; }
395
396 // Internal constructor for initialized variants.
397 explicit inline Private(uint variantType) Q_DECL_NOTHROW
398 : type(variantType), is_shared(false), is_null(false)
399 {}
400
401 inline Private(const Private &other) Q_DECL_NOTHROW
402 : data(other.data), type(other.type),
403 is_shared(other.is_shared), is_null(other.is_null)
404 {}
405 union Data
406 {
407 char c;
408 uchar uc;
409 short s;
410 signed char sc;
411 ushort us;
412 int i;
413 uint u;
414 long l;
415 ulong ul;
416 bool b;
417 double d;
418 float f;
419 qreal real;
420 qlonglong ll;
421 qulonglong ull;
422 QObject *o;
423 void *ptr;
424 PrivateShared *shared;
425 } data;
426 uint type : 30;
427 uint is_shared : 1;
428 uint is_null : 1;
429 };
430 public:
431 typedef void (*f_construct)(Private *, const void *);
432 typedef void (*f_clear)(Private *);
433 typedef bool (*f_null)(const Private *);
434#ifndef QT_NO_DATASTREAM
435 typedef void (*f_load)(Private *, QDataStream &);
436 typedef void (*f_save)(const Private *, QDataStream &);
437#endif
438 typedef bool (*f_compare)(const Private *, const Private *);
439 typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *);
440 typedef bool (*f_canConvert)(const QVariant::Private *d, int t);
441 typedef void (*f_debugStream)(QDebug, const QVariant &);
442 struct Handler {
443 f_construct construct;
444 f_clear clear;
445 f_null isNull;
446#ifndef QT_NO_DATASTREAM
447 f_load load;
448 f_save save;
449#endif
450 f_compare compare;
451 f_convert convert;
452 f_canConvert canConvert;
453 f_debugStream debugStream;
454 };
455
456 inline bool operator==(const QVariant &v) const
457 { return cmp(v); }
458 inline bool operator!=(const QVariant &v) const
459 { return !cmp(v); }
460 inline bool operator<(const QVariant &v) const
461 { return compare(v) < 0; }
462 inline bool operator<=(const QVariant &v) const
463 { return compare(v) <= 0; }
464 inline bool operator>(const QVariant &v) const
465 { return compare(v) > 0; }
466 inline bool operator>=(const QVariant &v) const
467 { return compare(v) >= 0; }
468
469protected:
470 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
471#ifndef QT_NO_DEBUG_STREAM
472 friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
473#endif
474// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC for QTBUG-41810 .
475#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
476 template<typename T>
477 friend inline T qvariant_cast(const QVariant &);
478 template<typename T> friend struct QtPrivate::QVariantValueHelper;
479protected:
480#else
481public:
482#endif
483 Private d;
484 void create(int type, const void *copy);
485 bool cmp(const QVariant &other) const;
486 int compare(const QVariant &other) const;
487 bool convert(const int t, void *ptr) const; // ### Qt6: drop const
488
489private:
490 // force compile error, prevent QVariant(bool) to be called
491 inline QVariant(void *) Q_DECL_EQ_DELETE;
492 // QVariant::Type is marked as \obsolete, but we don't want to
493 // provide a constructor from its intended replacement,
494 // QMetaType::Type, instead, because the idea behind these
495 // constructors is flawed in the first place. But we also don't
496 // want QVariant(QMetaType::String) to compile and falsely be an
497 // int variant, so delete this constructor:
498 QVariant(QMetaType::Type) Q_DECL_EQ_DELETE;
499
500 // These constructors don't create QVariants of the type associcated
501 // with the enum, as expected, but they would create a QVariant of
502 // type int with the value of the enum value.
503 // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
504 // example.
505 QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE;
506 QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE;
507 QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE;
508 QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE;
509#ifdef QT_NO_CAST_FROM_ASCII
510 // force compile error when implicit conversion is not wanted
511 inline QVariant(const char *) Q_DECL_EQ_DELETE;
512#endif
513public:
514 typedef Private DataPtr;
515 inline DataPtr &data_ptr() { return d; }
516 inline const DataPtr &data_ptr() const { return d; }
517};
518
519template <typename T>
520inline QVariant qVariantFromValue(const T &t)
521{
522 return QVariant(qMetaTypeId<T>(), &t, QTypeInfo<T>::isPointer);
523}
524
525template <>
526inline QVariant qVariantFromValue(const QVariant &t) { return t; }
527
528#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
529template <>
530inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); }
531#endif
532
533template <typename T>
534inline void qVariantSetValue(QVariant &v, const T &t)
535{
536 //if possible we reuse the current QVariant private
537 const uint type = qMetaTypeId<T>();
538 QVariant::Private &d = v.data_ptr();
539 if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
540 d.type = type;
541 d.is_null = false;
542 T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
543 if (QTypeInfo<T>::isComplex)
544 old->~T();
545 new (old) T(t); //call the copy constructor
546 } else {
547 v = QVariant(type, &t, QTypeInfo<T>::isPointer);
548 }
549}
550
551template <>
552inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t)
553{
554 v = t;
555}
556
557inline bool QVariant::isValid() const { return d.type != Invalid; }
558
559template<typename T>
560inline void QVariant::setValue(const T &avalue)
561{ qVariantSetValue(*this, avalue); }
562
563#ifndef QT_NO_DATASTREAM
564Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
565Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
566Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p);
567Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
568#endif
569
570inline bool QVariant::isDetached() const
571{ return !d.is_shared || d.data.shared->ref.load() == 1; }
572
573
574#ifdef Q_QDOC
575 inline bool operator==(const QVariant &v1, const QVariant &v2);
576 inline bool operator!=(const QVariant &v1, const QVariant &v2);
577#else
578
579/* Helper class to add one more level of indirection to prevent
580 implicit casts.
581*/
582class QVariantComparisonHelper
583{
584public:
585 inline QVariantComparisonHelper(const QVariant &var)
586 : v(&var) {}
587private:
588 friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
589 const QVariant *v;
590};
591
592inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
593{
594 return v1.cmp(*v2.v);
595}
596
597inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
598{
599 return !operator==(v1, v2);
600}
601#endif
602Q_DECLARE_SHARED(QVariant)
603
604class Q_CORE_EXPORT QSequentialIterable
605{
606 QtMetaTypePrivate::QSequentialIterableImpl m_impl;
607public:
608 struct Q_CORE_EXPORT const_iterator
609 {
610 private:
611 QtMetaTypePrivate::QSequentialIterableImpl m_impl;
612 QAtomicInt *ref;
613 friend class QSequentialIterable;
614 explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_);
615
616 explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_);
617
618 void begin();
619 void end();
620 public:
621 ~const_iterator();
622
623 const_iterator(const const_iterator &other);
624
625 const_iterator& operator=(const const_iterator &other);
626
627 const QVariant operator*() const;
628 bool operator==(const const_iterator &o) const;
629 bool operator!=(const const_iterator &o) const;
630 const_iterator &operator++();
631 const_iterator operator++(int);
632 const_iterator &operator--();
633 const_iterator operator--(int);
634 const_iterator &operator+=(int j);
635 const_iterator &operator-=(int j);
636 const_iterator operator+(int j) const;
637 const_iterator operator-(int j) const;
638 friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
639 };
640
641 friend struct const_iterator;
642
643#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
644 explicit QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl);
645#else
646 explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl);
647#endif
648
649 const_iterator begin() const;
650 const_iterator end() const;
651
652 QVariant at(int idx) const;
653 int size() const;
654
655 bool canReverseIterate() const;
656};
657
658class Q_CORE_EXPORT QAssociativeIterable
659{
660 QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
661public:
662 struct Q_CORE_EXPORT const_iterator
663 {
664 private:
665 QtMetaTypePrivate::QAssociativeIterableImpl m_impl;
666 QAtomicInt *ref;
667 friend class QAssociativeIterable;
668 explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_);
669
670 explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_);
671
672 void begin();
673 void end();
674 void find(const QVariant &key);
675 public:
676 ~const_iterator();
677 const_iterator(const const_iterator &other);
678
679 const_iterator& operator=(const const_iterator &other);
680
681 const QVariant key() const;
682
683 const QVariant value() const;
684
685 const QVariant operator*() const;
686 bool operator==(const const_iterator &o) const;
687 bool operator!=(const const_iterator &o) const;
688 const_iterator &operator++();
689 const_iterator operator++(int);
690 const_iterator &operator--();
691 const_iterator operator--(int);
692 const_iterator &operator+=(int j);
693 const_iterator &operator-=(int j);
694 const_iterator operator+(int j) const;
695 const_iterator operator-(int j) const;
696 friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
697 };
698
699 friend struct const_iterator;
700
701#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
702 explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl);
703#else
704 explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl);
705#endif
706
707 const_iterator begin() const;
708 const_iterator end() const;
709 const_iterator find(const QVariant &key) const;
710
711 QVariant value(const QVariant &key) const;
712
713 int size() const;
714};
715
716#ifndef QT_MOC
717namespace QtPrivate {
718 template<typename T>
719 struct QVariantValueHelper : TreatAsQObjectBeforeMetaType<QVariantValueHelper<T>, T, const QVariant &, T>
720 {
721 static T metaType(const QVariant &v)
722 {
723 const int vid = qMetaTypeId<T>();
724 if (vid == v.userType())
725 return *reinterpret_cast<const T *>(v.constData());
726 T t;
727 if (v.convert(vid, &t))
728 return t;
729 return T();
730 }
731#ifndef QT_NO_QOBJECT
732 static T object(const QVariant &v)
733 {
734 return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject
735 ? v.d.data.o
736 : QVariantValueHelper::metaType(v));
737 }
738#endif
739 };
740
741 template<typename T>
742 struct QVariantValueHelperInterface : QVariantValueHelper<T>
743 {
744 };
745
746 template<>
747 struct QVariantValueHelperInterface<QSequentialIterable>
748 {
749 static QSequentialIterable invoke(const QVariant &v)
750 {
751 const int typeId = v.userType();
752 if (typeId == qMetaTypeId<QVariantList>()) {
753 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QVariantList*>(v.constData())));
754 }
755 if (typeId == qMetaTypeId<QStringList>()) {
756 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QStringList*>(v.constData())));
757 }
758#ifndef QT_BOOTSTRAPPED
759 if (typeId == qMetaTypeId<QByteArrayList>()) {
760 return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast<const QByteArrayList*>(v.constData())));
761 }
762#endif
763 return QSequentialIterable(v.value<QtMetaTypePrivate::QSequentialIterableImpl>());
764 }
765 };
766 template<>
767 struct QVariantValueHelperInterface<QAssociativeIterable>
768 {
769 static QAssociativeIterable invoke(const QVariant &v)
770 {
771 const int typeId = v.userType();
772 if (typeId == qMetaTypeId<QVariantMap>()) {
773 return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantMap*>(v.constData())));
774 }
775 if (typeId == qMetaTypeId<QVariantHash>()) {
776 return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast<const QVariantHash*>(v.constData())));
777 }
778 return QAssociativeIterable(v.value<QtMetaTypePrivate::QAssociativeIterableImpl>());
779 }
780 };
781 template<>
782 struct QVariantValueHelperInterface<QVariantList>
783 {
784 static QVariantList invoke(const QVariant &v)
785 {
786 const int typeId = v.userType();
787 if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
788 QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
789 QVariantList l;
790 l.reserve(iter.size());
791 for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
792 l << *it;
793 return l;
794 }
795 return QVariantValueHelper<QVariantList>::invoke(v);
796 }
797 };
798 template<>
799 struct QVariantValueHelperInterface<QVariantHash>
800 {
801 static QVariantHash invoke(const QVariant &v)
802 {
803 const int typeId = v.userType();
804 if (typeId == qMetaTypeId<QVariantMap>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
805 QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
806 QVariantHash l;
807 l.reserve(iter.size());
808 for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
809 l.insertMulti(it.key().toString(), it.value());
810 return l;
811 }
812 return QVariantValueHelper<QVariantHash>::invoke(v);
813 }
814 };
815 template<>
816 struct QVariantValueHelperInterface<QVariantMap>
817 {
818 static QVariantMap invoke(const QVariant &v)
819 {
820 const int typeId = v.userType();
821 if (typeId == qMetaTypeId<QVariantHash>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
822 QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
823 QVariantMap l;
824 for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
825 l.insertMulti(it.key().toString(), it.value());
826 return l;
827 }
828 return QVariantValueHelper<QVariantMap>::invoke(v);
829 }
830 };
831 template<>
832 struct QVariantValueHelperInterface<QPair<QVariant, QVariant> >
833 {
834 static QPair<QVariant, QVariant> invoke(const QVariant &v)
835 {
836 const int typeId = v.userType();
837 if (typeId == qMetaTypeId<QPair<QVariant, QVariant> >())
838 return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
839
840 if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>())) {
841 QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
842
843 const QtMetaTypePrivate::VariantData d1 = pi.first();
844 QVariant v1(d1.metaTypeId, d1.data, d1.flags);
845 if (d1.metaTypeId == qMetaTypeId<QVariant>())
846 v1 = *reinterpret_cast<const QVariant*>(d1.data);
847
848 const QtMetaTypePrivate::VariantData d2 = pi.second();
849 QVariant v2(d2.metaTypeId, d2.data, d2.flags);
850 if (d2.metaTypeId == qMetaTypeId<QVariant>())
851 v2 = *reinterpret_cast<const QVariant*>(d2.data);
852
853 return QPair<QVariant, QVariant>(v1, v2);
854 }
855 return QVariantValueHelper<QPair<QVariant, QVariant> >::invoke(v);
856 }
857 };
858}
859
860template<typename T> inline T qvariant_cast(const QVariant &v)
861{
862 return QtPrivate::QVariantValueHelperInterface<T>::invoke(v);
863}
864
865template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
866{
867 if (v.userType() == QMetaType::QVariant)
868 return *reinterpret_cast<const QVariant *>(v.constData());
869 return v;
870}
871
872#if QT_DEPRECATED_SINCE(5, 0)
873template<typename T>
874inline QT_DEPRECATED T qVariantValue(const QVariant &variant)
875{ return qvariant_cast<T>(variant); }
876
877template<typename T>
878inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant)
879{ return variant.template canConvert<T>(); }
880#endif
881
882#endif
883
884#ifndef QT_NO_DEBUG_STREAM
885Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
886Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
887#endif
888
889QT_END_NAMESPACE
890
891#endif // QVARIANT_H
892