1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 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_NO_DEBUG_STREAM |
53 | #include <QtCore/qdebug.h> |
54 | #endif |
55 | #ifndef QT_BOOTSTRAPPED |
56 | #include <QtCore/qbytearraylist.h> |
57 | #endif |
58 | #include <memory> |
59 | #include <type_traits> |
60 | |
61 | #if __has_include(<variant>) && __cplusplus >= 201703L |
62 | #include <variant> |
63 | #elif defined(Q_CLANG_QDOC) |
64 | namespace std { template<typename...> struct variant; } |
65 | #endif |
66 | |
67 | QT_BEGIN_NAMESPACE |
68 | |
69 | |
70 | class QBitArray; |
71 | class QDataStream; |
72 | class QDate; |
73 | class QDateTime; |
74 | #if QT_CONFIG(easingcurve) |
75 | class QEasingCurve; |
76 | #endif |
77 | class QLine; |
78 | class QLineF; |
79 | class QLocale; |
80 | class QTransform; |
81 | class QTime; |
82 | class QPoint; |
83 | class QPointF; |
84 | class QSize; |
85 | class QSizeF; |
86 | class QRect; |
87 | class QRectF; |
88 | #if QT_CONFIG(regularexpression) |
89 | class QRegularExpression; |
90 | #endif // QT_CONFIG(regularexpression) |
91 | class QTextFormat; |
92 | class QTextLength; |
93 | class QUrl; |
94 | class QVariant; |
95 | |
96 | template<typename T> |
97 | inline T qvariant_cast(const QVariant &); |
98 | |
99 | class Q_CORE_EXPORT QVariant |
100 | { |
101 | public: |
102 | #if QT_DEPRECATED_SINCE(6, 0) |
103 | enum QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead." ) Type |
104 | { |
105 | Invalid = QMetaType::UnknownType, |
106 | Bool = QMetaType::Bool, |
107 | Int = QMetaType::Int, |
108 | UInt = QMetaType::UInt, |
109 | LongLong = QMetaType::LongLong, |
110 | ULongLong = QMetaType::ULongLong, |
111 | Double = QMetaType::Double, |
112 | Char = QMetaType::QChar, |
113 | Map = QMetaType::QVariantMap, |
114 | List = QMetaType::QVariantList, |
115 | String = QMetaType::QString, |
116 | StringList = QMetaType::QStringList, |
117 | ByteArray = QMetaType::QByteArray, |
118 | BitArray = QMetaType::QBitArray, |
119 | Date = QMetaType::QDate, |
120 | Time = QMetaType::QTime, |
121 | DateTime = QMetaType::QDateTime, |
122 | Url = QMetaType::QUrl, |
123 | Locale = QMetaType::QLocale, |
124 | Rect = QMetaType::QRect, |
125 | RectF = QMetaType::QRectF, |
126 | Size = QMetaType::QSize, |
127 | SizeF = QMetaType::QSizeF, |
128 | Line = QMetaType::QLine, |
129 | LineF = QMetaType::QLineF, |
130 | Point = QMetaType::QPoint, |
131 | PointF = QMetaType::QPointF, |
132 | #if QT_CONFIG(regularexpression) |
133 | RegularExpression = QMetaType::QRegularExpression, |
134 | #endif |
135 | Hash = QMetaType::QVariantHash, |
136 | #if QT_CONFIG(easingcurve) |
137 | EasingCurve = QMetaType::QEasingCurve, |
138 | #endif |
139 | Uuid = QMetaType::QUuid, |
140 | #if QT_CONFIG(itemmodel) |
141 | ModelIndex = QMetaType::QModelIndex, |
142 | PersistentModelIndex = QMetaType::QPersistentModelIndex, |
143 | #endif |
144 | LastCoreType = QMetaType::LastCoreType, |
145 | |
146 | Font = QMetaType::QFont, |
147 | Pixmap = QMetaType::QPixmap, |
148 | Brush = QMetaType::QBrush, |
149 | Color = QMetaType::QColor, |
150 | Palette = QMetaType::QPalette, |
151 | Image = QMetaType::QImage, |
152 | Polygon = QMetaType::QPolygon, |
153 | Region = QMetaType::QRegion, |
154 | Bitmap = QMetaType::QBitmap, |
155 | Cursor = QMetaType::QCursor, |
156 | #if QT_CONFIG(shortcut) |
157 | KeySequence = QMetaType::QKeySequence, |
158 | #endif |
159 | Pen = QMetaType::QPen, |
160 | TextLength = QMetaType::QTextLength, |
161 | TextFormat = QMetaType::QTextFormat, |
162 | Transform = QMetaType::QTransform, |
163 | Matrix4x4 = QMetaType::QMatrix4x4, |
164 | Vector2D = QMetaType::QVector2D, |
165 | Vector3D = QMetaType::QVector3D, |
166 | Vector4D = QMetaType::QVector4D, |
167 | Quaternion = QMetaType::QQuaternion, |
168 | PolygonF = QMetaType::QPolygonF, |
169 | Icon = QMetaType::QIcon, |
170 | LastGuiType = QMetaType::LastGuiType, |
171 | |
172 | SizePolicy = QMetaType::QSizePolicy, |
173 | |
174 | UserType = QMetaType::User, |
175 | LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type |
176 | }; |
177 | #endif |
178 | QVariant() noexcept : d() {} |
179 | ~QVariant(); |
180 | explicit QVariant(QMetaType type, const void *copy = nullptr); |
181 | QVariant(const QVariant &other); |
182 | |
183 | QVariant(int i); |
184 | QVariant(uint ui); |
185 | QVariant(qlonglong ll); |
186 | QVariant(qulonglong ull); |
187 | QVariant(bool b); |
188 | QVariant(double d); |
189 | QVariant(float f); |
190 | #ifndef QT_NO_CAST_FROM_ASCII |
191 | QT_ASCII_CAST_WARN QVariant(const char *str) |
192 | : QVariant(QString::fromUtf8(str)) |
193 | {} |
194 | #endif |
195 | |
196 | QVariant(const QByteArray &bytearray); |
197 | QVariant(const QBitArray &bitarray); |
198 | QVariant(const QString &string); |
199 | QVariant(QLatin1String string); |
200 | QVariant(const QStringList &stringlist); |
201 | QVariant(QChar qchar); |
202 | QVariant(QDate date); |
203 | QVariant(QTime time); |
204 | QVariant(const QDateTime &datetime); |
205 | QVariant(const QList<QVariant> &list); |
206 | QVariant(const QMap<QString, QVariant> &map); |
207 | QVariant(const QHash<QString, QVariant> &hash); |
208 | #ifndef QT_NO_GEOM_VARIANT |
209 | QVariant(const QSize &size); |
210 | QVariant(const QSizeF &size); |
211 | QVariant(const QPoint &pt); |
212 | QVariant(const QPointF &pt); |
213 | QVariant(const QLine &line); |
214 | QVariant(const QLineF &line); |
215 | QVariant(const QRect &rect); |
216 | QVariant(const QRectF &rect); |
217 | #endif |
218 | QVariant(const QLocale &locale); |
219 | #if QT_CONFIG(regularexpression) |
220 | QVariant(const QRegularExpression &re); |
221 | #endif // QT_CONFIG(regularexpression) |
222 | #if QT_CONFIG(easingcurve) |
223 | QVariant(const QEasingCurve &easing); |
224 | #endif |
225 | QVariant(const QUuid &uuid); |
226 | #ifndef QT_BOOTSTRAPPED |
227 | QVariant(const QUrl &url); |
228 | QVariant(const QJsonValue &jsonValue); |
229 | QVariant(const QJsonObject &jsonObject); |
230 | QVariant(const QJsonArray &jsonArray); |
231 | QVariant(const QJsonDocument &jsonDocument); |
232 | #endif // QT_BOOTSTRAPPED |
233 | #if QT_CONFIG(itemmodel) |
234 | QVariant(const QModelIndex &modelIndex); |
235 | QVariant(const QPersistentModelIndex &modelIndex); |
236 | #endif |
237 | |
238 | QVariant& operator=(const QVariant &other); |
239 | inline QVariant(QVariant &&other) noexcept : d(other.d) |
240 | { other.d = Private(); } |
241 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant) |
242 | |
243 | inline void swap(QVariant &other) noexcept { qSwap(d, other.d); } |
244 | |
245 | int userType() const { return typeId(); } |
246 | int typeId() const { return metaType().id(); } |
247 | |
248 | const char *typeName() const; |
249 | QMetaType metaType() const; |
250 | |
251 | bool canConvert(QMetaType targetType) const |
252 | { return QMetaType::canConvert(d.type(), targetType); } |
253 | bool convert(QMetaType type); |
254 | |
255 | bool canView(QMetaType targetType) const |
256 | { return QMetaType::canView(d.type(), targetType); } |
257 | |
258 | #if QT_DEPRECATED_SINCE(6, 0) |
259 | QT_DEPRECATED_VERSION_6_0 |
260 | bool canConvert(int targetTypeId) const |
261 | { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); } |
262 | QT_DEPRECATED_VERSION_6_0 |
263 | bool convert(int targetTypeId) |
264 | { return convert(QMetaType(targetTypeId)); } |
265 | #endif |
266 | |
267 | inline bool isValid() const; |
268 | bool isNull() const; |
269 | |
270 | void clear(); |
271 | |
272 | void detach(); |
273 | inline bool isDetached() const; |
274 | |
275 | int toInt(bool *ok = nullptr) const; |
276 | uint toUInt(bool *ok = nullptr) const; |
277 | qlonglong toLongLong(bool *ok = nullptr) const; |
278 | qulonglong toULongLong(bool *ok = nullptr) const; |
279 | bool toBool() const; |
280 | double toDouble(bool *ok = nullptr) const; |
281 | float toFloat(bool *ok = nullptr) const; |
282 | qreal toReal(bool *ok = nullptr) const; |
283 | QByteArray toByteArray() const; |
284 | QBitArray toBitArray() const; |
285 | QString toString() const; |
286 | QStringList toStringList() const; |
287 | QChar toChar() const; |
288 | QDate toDate() const; |
289 | QTime toTime() const; |
290 | QDateTime toDateTime() const; |
291 | QList<QVariant> toList() const; |
292 | QMap<QString, QVariant> toMap() const; |
293 | QHash<QString, QVariant> toHash() const; |
294 | |
295 | #ifndef QT_NO_GEOM_VARIANT |
296 | QPoint toPoint() const; |
297 | QPointF toPointF() const; |
298 | QRect toRect() const; |
299 | QSize toSize() const; |
300 | QSizeF toSizeF() const; |
301 | QLine toLine() const; |
302 | QLineF toLineF() const; |
303 | QRectF toRectF() const; |
304 | #endif |
305 | QLocale toLocale() const; |
306 | #if QT_CONFIG(regularexpression) |
307 | QRegularExpression toRegularExpression() const; |
308 | #endif // QT_CONFIG(regularexpression) |
309 | #if QT_CONFIG(easingcurve) |
310 | QEasingCurve toEasingCurve() const; |
311 | #endif |
312 | QUuid toUuid() const; |
313 | #ifndef QT_BOOTSTRAPPED |
314 | QUrl toUrl() const; |
315 | QJsonValue toJsonValue() const; |
316 | QJsonObject toJsonObject() const; |
317 | QJsonArray toJsonArray() const; |
318 | QJsonDocument toJsonDocument() const; |
319 | #endif // QT_BOOTSTRAPPED |
320 | #if QT_CONFIG(itemmodel) |
321 | QModelIndex toModelIndex() const; |
322 | QPersistentModelIndex toPersistentModelIndex() const; |
323 | #endif |
324 | |
325 | #ifndef QT_NO_DATASTREAM |
326 | void load(QDataStream &ds); |
327 | void save(QDataStream &ds) const; |
328 | #endif |
329 | #if QT_DEPRECATED_SINCE(6, 0) |
330 | QT_WARNING_PUSH |
331 | QT_WARNING_DISABLE_DEPRECATED |
332 | QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead." ) |
333 | explicit QVariant(Type type) |
334 | : QVariant(QMetaType(int(type))) |
335 | {} |
336 | QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType()." ) |
337 | Type type() const |
338 | { |
339 | int type = d.typeId(); |
340 | return type >= QMetaType::User ? UserType : static_cast<Type>(type); |
341 | } |
342 | QT_DEPRECATED_VERSION_6_0 |
343 | static const char *typeToName(int typeId) |
344 | { return QMetaType(typeId).name(); } |
345 | QT_DEPRECATED_VERSION_6_0 |
346 | static Type nameToType(const char *name) |
347 | { |
348 | int metaType = QMetaType::fromName(name).id(); |
349 | return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType; |
350 | } |
351 | QT_WARNING_POP |
352 | #endif |
353 | |
354 | void *data(); |
355 | const void *constData() const |
356 | { return d.storage(); } |
357 | inline const void *data() const { return constData(); } |
358 | |
359 | template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> |
360 | void setValue(T &&avalue) |
361 | { |
362 | using VT = std::decay_t<T>; |
363 | QMetaType metaType = QMetaType::fromType<VT>(); |
364 | // If possible we reuse the current QVariant private. |
365 | if (isDetached() && d.type() == metaType) { |
366 | *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue); |
367 | } else { |
368 | *this = QVariant::fromValue<VT>(std::forward<T>(avalue)); |
369 | } |
370 | } |
371 | |
372 | void setValue(const QVariant &avalue) |
373 | { |
374 | *this = avalue; |
375 | } |
376 | |
377 | void setValue(QVariant &&avalue) |
378 | { |
379 | *this = std::move(avalue); |
380 | } |
381 | |
382 | template<typename T> |
383 | inline T value() const |
384 | { return qvariant_cast<T>(*this); } |
385 | |
386 | template<typename T> |
387 | inline T view() |
388 | { |
389 | T t{}; |
390 | QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t); |
391 | return t; |
392 | } |
393 | |
394 | template<typename T> |
395 | #ifndef Q_CLANG_QDOC |
396 | static inline auto fromValue(const T &value) -> |
397 | std::enable_if_t<std::is_copy_constructible_v<T>, QVariant> |
398 | #else |
399 | static inline QVariant fromValue(const T &value) |
400 | #endif |
401 | { |
402 | return QVariant(QMetaType::fromType<T>(), std::addressof(value)); |
403 | } |
404 | |
405 | #if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) |
406 | template<typename... Types> |
407 | static inline QVariant fromStdVariant(const std::variant<Types...> &value) |
408 | { |
409 | if (value.valueless_by_exception()) |
410 | return QVariant(); |
411 | return std::visit([](const auto &arg) { return fromValue(arg); }, value); |
412 | } |
413 | #endif |
414 | |
415 | template<typename T> |
416 | bool canConvert() const |
417 | { return canConvert(QMetaType::fromType<T>()); } |
418 | |
419 | template<typename T> |
420 | bool canView() const |
421 | { return canView(QMetaType::fromType<T>()); } |
422 | |
423 | public: |
424 | struct PrivateShared |
425 | { |
426 | private: |
427 | inline PrivateShared() : ref(1) { } |
428 | public: |
429 | static PrivateShared *create(const QtPrivate::QMetaTypeInterface *type) |
430 | { |
431 | Q_ASSERT(type); |
432 | size_t size = type->size; |
433 | size_t align = type->alignment; |
434 | |
435 | size += sizeof(PrivateShared); |
436 | if (align > sizeof(PrivateShared)) { |
437 | // The alignment is larger than the alignment we can guarantee for the pointer |
438 | // directly following PrivateShared, so we need to allocate some additional |
439 | // memory to be able to fit the object into the available memory with suitable |
440 | // alignment. |
441 | size += align - sizeof(PrivateShared); |
442 | } |
443 | void *data = operator new(size); |
444 | auto *ps = new (data) QVariant::PrivateShared(); |
445 | ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); |
446 | return ps; |
447 | } |
448 | static void free(PrivateShared *p) |
449 | { |
450 | p->~PrivateShared(); |
451 | operator delete(p); |
452 | } |
453 | |
454 | alignas(8) QAtomicInt ref; |
455 | int offset; |
456 | |
457 | const void *data() const |
458 | { return reinterpret_cast<const unsigned char *>(this) + offset; } |
459 | void *data() |
460 | { return reinterpret_cast<unsigned char *>(this) + offset; } |
461 | }; |
462 | struct Private |
463 | { |
464 | static constexpr size_t MaxInternalSize = 3*sizeof(void *); |
465 | template<typename T> |
466 | static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double)); |
467 | static constexpr bool canUseInternalSpace(QtPrivate::QMetaTypeInterface *type) |
468 | { |
469 | Q_ASSERT(type); |
470 | return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType && |
471 | size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double); |
472 | } |
473 | |
474 | union |
475 | { |
476 | uchar data[MaxInternalSize] = {}; |
477 | PrivateShared *shared; |
478 | double _forAlignment; // we want an 8byte alignment on 32bit systems as well |
479 | } data; |
480 | quintptr is_shared : 1; |
481 | quintptr is_null : 1; |
482 | quintptr packedType : sizeof(QMetaType) * 8 - 2; |
483 | |
484 | Private() noexcept : is_shared(false), is_null(true), packedType(0) {} |
485 | explicit Private(QMetaType type) noexcept : is_shared(false), is_null(false) |
486 | { |
487 | quintptr mt = quintptr(type.d_ptr); |
488 | Q_ASSERT((mt & 0x3) == 0); |
489 | packedType = mt >> 2; |
490 | } |
491 | explicit Private(int type) noexcept : Private(QMetaType(type)) {} |
492 | |
493 | const void *storage() const |
494 | { return is_shared ? data.shared->data() : &data.data; } |
495 | |
496 | const void *internalStorage() const |
497 | { Q_ASSERT(is_shared); return &data.data; } |
498 | |
499 | // determine internal storage at compile time |
500 | template<typename T> |
501 | const T &get() const |
502 | { return *static_cast<const T *>(storage()); } |
503 | template<typename T> |
504 | void set(const T &t) |
505 | { *static_cast<T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()) = t; } |
506 | |
507 | inline QMetaType type() const |
508 | { |
509 | return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2)); |
510 | } |
511 | |
512 | inline QtPrivate::QMetaTypeInterface * typeInterface() const |
513 | { |
514 | return reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2); |
515 | } |
516 | |
517 | inline int typeId() const |
518 | { |
519 | return type().id(); |
520 | } |
521 | }; |
522 | public: |
523 | static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs); |
524 | |
525 | private: |
526 | friend inline bool operator==(const QVariant &a, const QVariant &b) |
527 | { return a.equals(b); } |
528 | friend inline bool operator!=(const QVariant &a, const QVariant &b) |
529 | { return !a.equals(b); } |
530 | #ifndef QT_NO_DEBUG_STREAM |
531 | template <typename T> |
532 | friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> { |
533 | return variant.qdebugHelper(debug); |
534 | } |
535 | QDebug qdebugHelper(QDebug) const; |
536 | #endif |
537 | template<typename T> |
538 | friend inline T qvariant_cast(const QVariant &); |
539 | protected: |
540 | Private d; |
541 | void create(int type, const void *copy); |
542 | void create(QMetaType type, const void *copy); |
543 | bool equals(const QVariant &other) const; |
544 | bool convert(int type, void *ptr) const; |
545 | bool view(int type, void *ptr); |
546 | |
547 | private: |
548 | // force compile error, prevent QVariant(bool) to be called |
549 | inline QVariant(void *) = delete; |
550 | // QVariant::Type is marked as \obsolete, but we don't want to |
551 | // provide a constructor from its intended replacement, |
552 | // QMetaType::Type, instead, because the idea behind these |
553 | // constructors is flawed in the first place. But we also don't |
554 | // want QVariant(QMetaType::String) to compile and falsely be an |
555 | // int variant, so delete this constructor: |
556 | QVariant(QMetaType::Type) = delete; |
557 | |
558 | // These constructors don't create QVariants of the type associcated |
559 | // with the enum, as expected, but they would create a QVariant of |
560 | // type int with the value of the enum value. |
561 | // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for |
562 | // example. |
563 | QVariant(Qt::GlobalColor) = delete; |
564 | QVariant(Qt::BrushStyle) = delete; |
565 | QVariant(Qt::PenStyle) = delete; |
566 | QVariant(Qt::CursorShape) = delete; |
567 | #ifdef QT_NO_CAST_FROM_ASCII |
568 | // force compile error when implicit conversion is not wanted |
569 | inline QVariant(const char *) = delete; |
570 | #endif |
571 | public: |
572 | typedef Private DataPtr; |
573 | inline DataPtr &data_ptr() { return d; } |
574 | inline const DataPtr &data_ptr() const { return d; } |
575 | }; |
576 | |
577 | template<> |
578 | inline QVariant QVariant::fromValue(const QVariant &value) |
579 | { |
580 | return value; |
581 | } |
582 | |
583 | #if __has_include(<variant>) && __cplusplus >= 201703L |
584 | template<> |
585 | inline QVariant QVariant::fromValue(const std::monostate &) |
586 | { |
587 | return QVariant(); |
588 | } |
589 | #endif |
590 | |
591 | inline bool QVariant::isValid() const |
592 | { |
593 | return d.type().isValid(); |
594 | } |
595 | |
596 | #ifndef QT_NO_DATASTREAM |
597 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p); |
598 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p); |
599 | |
600 | #if QT_DEPRECATED_SINCE(6, 0) |
601 | QT_WARNING_PUSH |
602 | QT_WARNING_DISABLE_DEPRECATED |
603 | QT_DEPRECATED_VERSION_6_0 |
604 | inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p) |
605 | { |
606 | quint32 u; |
607 | s >> u; |
608 | p = static_cast<QVariant::Type>(u); |
609 | return s; |
610 | } |
611 | QT_DEPRECATED_VERSION_6_0 |
612 | inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p) |
613 | { |
614 | s << static_cast<quint32>(p); |
615 | return s; |
616 | } |
617 | QT_WARNING_POP |
618 | #endif |
619 | |
620 | #endif |
621 | |
622 | inline bool QVariant::isDetached() const |
623 | { return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; } |
624 | |
625 | Q_DECLARE_SHARED(QVariant) |
626 | |
627 | #ifndef QT_MOC |
628 | |
629 | template<typename T> inline T qvariant_cast(const QVariant &v) |
630 | { |
631 | QMetaType targetType = QMetaType::fromType<T>(); |
632 | if (v.d.type() == targetType) |
633 | return v.d.get<T>(); |
634 | if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) { |
635 | using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *; |
636 | QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>(); |
637 | if (v.d.type() == nonConstTargetType) |
638 | return v.d.get<nonConstT>(); |
639 | } |
640 | |
641 | T t{}; |
642 | QMetaType::convert(v.metaType(), v.constData(), targetType, &t); |
643 | return t; |
644 | } |
645 | |
646 | template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) |
647 | { |
648 | if (v.metaType().id() == QMetaType::QVariant) |
649 | return *reinterpret_cast<const QVariant *>(v.constData()); |
650 | return v; |
651 | } |
652 | |
653 | #endif |
654 | |
655 | #ifndef QT_NO_DEBUG_STREAM |
656 | #if QT_DEPRECATED_SINCE(6, 0) |
657 | QT_WARNING_PUSH |
658 | QT_WARNING_DISABLE_DEPRECATED |
659 | QT_DEPRECATED_VERSION_6_0 |
660 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); |
661 | QT_WARNING_POP |
662 | #endif |
663 | #endif |
664 | |
665 | namespace QtPrivate { |
666 | class Q_CORE_EXPORT QVariantTypeCoercer |
667 | { |
668 | public: |
669 | const void *convert(const QVariant &value, const QMetaType &type); |
670 | const void *coerce(const QVariant &value, const QMetaType &type); |
671 | |
672 | private: |
673 | QVariant converted; |
674 | }; |
675 | } |
676 | |
677 | template<typename Pointer> |
678 | class QVariantRef |
679 | { |
680 | private: |
681 | const Pointer *m_pointer = nullptr; |
682 | |
683 | public: |
684 | explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {} |
685 | QVariantRef(const QVariantRef &) = default; |
686 | QVariantRef(QVariantRef &&) = default; |
687 | ~QVariantRef() = default; |
688 | |
689 | operator QVariant() const; |
690 | QVariantRef &operator=(const QVariant &value); |
691 | QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); } |
692 | QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); } |
693 | |
694 | friend void swap(QVariantRef a, QVariantRef b) |
695 | { |
696 | QVariant tmp = a; |
697 | a = b; |
698 | b = std::move(tmp); |
699 | } |
700 | }; |
701 | |
702 | class Q_CORE_EXPORT QVariantConstPointer |
703 | { |
704 | private: |
705 | QVariant m_variant; |
706 | |
707 | public: |
708 | explicit QVariantConstPointer(QVariant variant); |
709 | |
710 | QVariant operator*() const; |
711 | const QVariant *operator->() const; |
712 | }; |
713 | |
714 | template<typename Pointer> |
715 | class QVariantPointer |
716 | { |
717 | private: |
718 | const Pointer *m_pointer = nullptr; |
719 | |
720 | public: |
721 | explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {} |
722 | QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); } |
723 | Pointer operator->() const { return *m_pointer; } |
724 | }; |
725 | |
726 | QT_END_NAMESPACE |
727 | |
728 | #endif // QVARIANT_H |
729 | |