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 typeId() const { return d.typeId(); } |
246 | int userType() const { return d.typeId(); } |
247 | const char *typeName() const; |
248 | QMetaType metaType() const; |
249 | |
250 | bool canConvert(QMetaType targetType) const |
251 | { return QMetaType::canConvert(d.type(), targetType); } |
252 | bool convert(QMetaType type); |
253 | |
254 | bool canView(QMetaType targetType) const |
255 | { return QMetaType::canView(d.type(), targetType); } |
256 | |
257 | #if QT_DEPRECATED_SINCE(6, 0) |
258 | QT_DEPRECATED_VERSION_6_0 |
259 | bool canConvert(int targetTypeId) const |
260 | { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); } |
261 | QT_DEPRECATED_VERSION_6_0 |
262 | bool convert(int targetTypeId) |
263 | { return convert(QMetaType(targetTypeId)); } |
264 | #endif |
265 | |
266 | inline bool isValid() const; |
267 | bool isNull() const; |
268 | |
269 | void clear(); |
270 | |
271 | void detach(); |
272 | inline bool isDetached() const; |
273 | |
274 | int toInt(bool *ok = nullptr) const; |
275 | uint toUInt(bool *ok = nullptr) const; |
276 | qlonglong toLongLong(bool *ok = nullptr) const; |
277 | qulonglong toULongLong(bool *ok = nullptr) const; |
278 | bool toBool() const; |
279 | double toDouble(bool *ok = nullptr) const; |
280 | float toFloat(bool *ok = nullptr) const; |
281 | qreal toReal(bool *ok = nullptr) const; |
282 | QByteArray toByteArray() const; |
283 | QBitArray toBitArray() const; |
284 | QString toString() const; |
285 | QStringList toStringList() const; |
286 | QChar toChar() const; |
287 | QDate toDate() const; |
288 | QTime toTime() const; |
289 | QDateTime toDateTime() const; |
290 | QList<QVariant> toList() const; |
291 | QMap<QString, QVariant> toMap() const; |
292 | QHash<QString, QVariant> toHash() const; |
293 | |
294 | #ifndef QT_NO_GEOM_VARIANT |
295 | QPoint toPoint() const; |
296 | QPointF toPointF() const; |
297 | QRect toRect() const; |
298 | QSize toSize() const; |
299 | QSizeF toSizeF() const; |
300 | QLine toLine() const; |
301 | QLineF toLineF() const; |
302 | QRectF toRectF() const; |
303 | #endif |
304 | QLocale toLocale() const; |
305 | #if QT_CONFIG(regularexpression) |
306 | QRegularExpression toRegularExpression() const; |
307 | #endif // QT_CONFIG(regularexpression) |
308 | #if QT_CONFIG(easingcurve) |
309 | QEasingCurve toEasingCurve() const; |
310 | #endif |
311 | QUuid toUuid() const; |
312 | #ifndef QT_BOOTSTRAPPED |
313 | QUrl toUrl() const; |
314 | QJsonValue toJsonValue() const; |
315 | QJsonObject toJsonObject() const; |
316 | QJsonArray toJsonArray() const; |
317 | QJsonDocument toJsonDocument() const; |
318 | #endif // QT_BOOTSTRAPPED |
319 | #if QT_CONFIG(itemmodel) |
320 | QModelIndex toModelIndex() const; |
321 | QPersistentModelIndex toPersistentModelIndex() const; |
322 | #endif |
323 | |
324 | #ifndef QT_NO_DATASTREAM |
325 | void load(QDataStream &ds); |
326 | void save(QDataStream &ds) const; |
327 | #endif |
328 | #if QT_DEPRECATED_SINCE(6, 0) |
329 | QT_WARNING_PUSH |
330 | QT_WARNING_DISABLE_DEPRECATED |
331 | QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead." ) |
332 | explicit QVariant(Type type) |
333 | : QVariant(QMetaType(int(type))) |
334 | {} |
335 | QT_DEPRECATED_VERSION_X_6_0("Use metaType()." ) |
336 | Type type() const |
337 | { |
338 | int type = d.typeId(); |
339 | return type >= QMetaType::User ? UserType : static_cast<Type>(type); |
340 | } |
341 | QT_DEPRECATED_VERSION_6_0 |
342 | static const char *typeToName(int typeId) |
343 | { return QMetaType(typeId).name(); } |
344 | QT_DEPRECATED_VERSION_6_0 |
345 | static Type nameToType(const char *name) |
346 | { |
347 | int metaType = QMetaType::fromName(name).id(); |
348 | return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType; |
349 | } |
350 | QT_WARNING_POP |
351 | #endif |
352 | |
353 | void *data(); |
354 | const void *constData() const |
355 | { return d.storage(); } |
356 | inline const void *data() const { return constData(); } |
357 | |
358 | template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>> |
359 | void setValue(T &&avalue) |
360 | { |
361 | using VT = std::decay_t<T>; |
362 | QMetaType metaType = QMetaType::fromType<VT>(); |
363 | // If possible we reuse the current QVariant private. |
364 | if (isDetached() && d.type() == metaType) { |
365 | *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue); |
366 | } else { |
367 | *this = QVariant::fromValue<VT>(std::forward<T>(avalue)); |
368 | } |
369 | } |
370 | |
371 | void setValue(const QVariant &avalue) |
372 | { |
373 | *this = avalue; |
374 | } |
375 | |
376 | void setValue(QVariant &&avalue) |
377 | { |
378 | *this = std::move(avalue); |
379 | } |
380 | |
381 | template<typename T> |
382 | inline T value() const |
383 | { return qvariant_cast<T>(*this); } |
384 | |
385 | template<typename T> |
386 | inline T view() |
387 | { |
388 | T t{}; |
389 | QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t); |
390 | return t; |
391 | } |
392 | |
393 | template<typename T> |
394 | static inline QVariant fromValue(const T &value) |
395 | { |
396 | return QVariant(QMetaType::fromType<T>(), std::addressof(value)); |
397 | } |
398 | |
399 | #if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC) |
400 | template<typename... Types> |
401 | static inline QVariant fromStdVariant(const std::variant<Types...> &value) |
402 | { |
403 | if (value.valueless_by_exception()) |
404 | return QVariant(); |
405 | return std::visit([](const auto &arg) { return fromValue(arg); }, value); |
406 | } |
407 | #endif |
408 | |
409 | template<typename T> |
410 | bool canConvert() const |
411 | { return canConvert(QMetaType::fromType<T>()); } |
412 | |
413 | template<typename T> |
414 | bool canView() const |
415 | { return canView(QMetaType::fromType<T>()); } |
416 | |
417 | public: |
418 | struct PrivateShared |
419 | { |
420 | private: |
421 | inline PrivateShared() : ref(1) { } |
422 | public: |
423 | static PrivateShared *create(QMetaType type) |
424 | { |
425 | size_t size = type.sizeOf(); |
426 | size_t align = type.alignOf(); |
427 | |
428 | size += sizeof(PrivateShared); |
429 | if (align > sizeof(PrivateShared)) { |
430 | // The alignment is larger than the alignment we can guarantee for the pointer |
431 | // directly following PrivateShared, so we need to allocate some additional |
432 | // memory to be able to fit the object into the available memory with suitable |
433 | // alignment. |
434 | size += align - sizeof(PrivateShared); |
435 | } |
436 | void *data = operator new(size); |
437 | auto *ps = new (data) QVariant::PrivateShared(); |
438 | ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); |
439 | return ps; |
440 | } |
441 | static void free(PrivateShared *p) |
442 | { |
443 | p->~PrivateShared(); |
444 | operator delete(p); |
445 | } |
446 | |
447 | alignas(8) QAtomicInt ref; |
448 | int offset; |
449 | |
450 | const void *data() const |
451 | { return reinterpret_cast<const unsigned char *>(this) + offset; } |
452 | void *data() |
453 | { return reinterpret_cast<unsigned char *>(this) + offset; } |
454 | }; |
455 | struct Private |
456 | { |
457 | static constexpr size_t MaxInternalSize = 3*sizeof(void *); |
458 | template<typename T> |
459 | static constexpr bool CanUseInternalSpace = (QTypeInfo<T>::isRelocatable && sizeof(T) <= MaxInternalSize && alignof(T) <= alignof(double)); |
460 | static constexpr bool canUseInternalSpace(QMetaType type) |
461 | { |
462 | return type.flags() & QMetaType::RelocatableType && |
463 | size_t(type.sizeOf()) <= MaxInternalSize && size_t(type.alignOf()) <= alignof(double); |
464 | } |
465 | |
466 | union |
467 | { |
468 | uchar data[MaxInternalSize] = {}; |
469 | PrivateShared *shared; |
470 | double _forAlignment; // we want an 8byte alignment on 32bit systems as well |
471 | } data; |
472 | quintptr is_shared : 1; |
473 | quintptr is_null : 1; |
474 | quintptr packedType : sizeof(QMetaType) * 8 - 2; |
475 | |
476 | Private() noexcept : is_shared(false), is_null(true), packedType(0) {} |
477 | explicit Private(QMetaType type) noexcept : is_shared(false), is_null(false) |
478 | { |
479 | quintptr mt = quintptr(type.d_ptr); |
480 | Q_ASSERT((mt & 0x3) == 0); |
481 | packedType = mt >> 2; |
482 | } |
483 | explicit Private(int type) noexcept : Private(QMetaType(type)) {} |
484 | |
485 | const void *storage() const |
486 | { return is_shared ? data.shared->data() : &data.data; } |
487 | |
488 | const void *internalStorage() const |
489 | { Q_ASSERT(is_shared); return &data.data; } |
490 | |
491 | // determine internal storage at compile time |
492 | template<typename T> |
493 | const T &get() const |
494 | { return *static_cast<const T *>(storage()); } |
495 | template<typename T> |
496 | void set(const T &t) |
497 | { *static_cast<T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()) = t; } |
498 | |
499 | inline QMetaType type() const |
500 | { |
501 | return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2)); |
502 | } |
503 | inline int typeId() const |
504 | { |
505 | return type().id(); |
506 | } |
507 | }; |
508 | public: |
509 | static std::optional<int> compare(const QVariant &lhs, const QVariant &rhs); |
510 | |
511 | private: |
512 | friend inline bool operator==(const QVariant &a, const QVariant &b) |
513 | { return a.equals(b); } |
514 | friend inline bool operator!=(const QVariant &a, const QVariant &b) |
515 | { return !a.equals(b); } |
516 | #ifndef QT_NO_DEBUG_STREAM |
517 | template <typename T> |
518 | friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> { |
519 | return variant.qdebugHelper(debug); |
520 | } |
521 | QDebug qdebugHelper(QDebug) const; |
522 | #endif |
523 | template<typename T> |
524 | friend inline T qvariant_cast(const QVariant &); |
525 | protected: |
526 | Private d; |
527 | void create(int type, const void *copy); |
528 | bool equals(const QVariant &other) const; |
529 | bool convert(int type, void *ptr) const; |
530 | bool view(int type, void *ptr); |
531 | |
532 | private: |
533 | // force compile error, prevent QVariant(bool) to be called |
534 | inline QVariant(void *) = delete; |
535 | // QVariant::Type is marked as \obsolete, but we don't want to |
536 | // provide a constructor from its intended replacement, |
537 | // QMetaType::Type, instead, because the idea behind these |
538 | // constructors is flawed in the first place. But we also don't |
539 | // want QVariant(QMetaType::String) to compile and falsely be an |
540 | // int variant, so delete this constructor: |
541 | QVariant(QMetaType::Type) = delete; |
542 | |
543 | // These constructors don't create QVariants of the type associcated |
544 | // with the enum, as expected, but they would create a QVariant of |
545 | // type int with the value of the enum value. |
546 | // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for |
547 | // example. |
548 | QVariant(Qt::GlobalColor) = delete; |
549 | QVariant(Qt::BrushStyle) = delete; |
550 | QVariant(Qt::PenStyle) = delete; |
551 | QVariant(Qt::CursorShape) = delete; |
552 | #ifdef QT_NO_CAST_FROM_ASCII |
553 | // force compile error when implicit conversion is not wanted |
554 | inline QVariant(const char *) = delete; |
555 | #endif |
556 | public: |
557 | typedef Private DataPtr; |
558 | inline DataPtr &data_ptr() { return d; } |
559 | inline const DataPtr &data_ptr() const { return d; } |
560 | }; |
561 | |
562 | template<> |
563 | inline QVariant QVariant::fromValue(const QVariant &value) |
564 | { |
565 | return value; |
566 | } |
567 | |
568 | #if __has_include(<variant>) && __cplusplus >= 201703L |
569 | template<> |
570 | inline QVariant QVariant::fromValue(const std::monostate &) |
571 | { |
572 | return QVariant(); |
573 | } |
574 | #endif |
575 | |
576 | inline bool QVariant::isValid() const |
577 | { |
578 | return d.type().isValid(); |
579 | } |
580 | |
581 | #ifndef QT_NO_DATASTREAM |
582 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p); |
583 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p); |
584 | |
585 | #if QT_DEPRECATED_SINCE(6, 0) |
586 | QT_WARNING_PUSH |
587 | QT_WARNING_DISABLE_DEPRECATED |
588 | QT_DEPRECATED_VERSION_6_0 |
589 | inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p) |
590 | { |
591 | quint32 u; |
592 | s >> u; |
593 | p = static_cast<QVariant::Type>(u); |
594 | return s; |
595 | } |
596 | QT_DEPRECATED_VERSION_6_0 |
597 | inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p) |
598 | { |
599 | s << static_cast<quint32>(p); |
600 | return s; |
601 | } |
602 | QT_WARNING_POP |
603 | #endif |
604 | |
605 | #endif |
606 | |
607 | inline bool QVariant::isDetached() const |
608 | { return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; } |
609 | |
610 | Q_DECLARE_SHARED(QVariant) |
611 | |
612 | #ifndef QT_MOC |
613 | |
614 | template<typename T> inline T qvariant_cast(const QVariant &v) |
615 | { |
616 | QMetaType targetType = QMetaType::fromType<T>(); |
617 | if (v.d.type() == targetType) |
618 | return v.d.get<T>(); |
619 | if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) { |
620 | using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *; |
621 | QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>(); |
622 | if (v.d.type() == nonConstTargetType) |
623 | return v.d.get<nonConstT>(); |
624 | } |
625 | |
626 | T t{}; |
627 | QMetaType::convert(v.metaType(), v.constData(), targetType, &t); |
628 | return t; |
629 | } |
630 | |
631 | template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) |
632 | { |
633 | if (v.metaType().id() == QMetaType::QVariant) |
634 | return *reinterpret_cast<const QVariant *>(v.constData()); |
635 | return v; |
636 | } |
637 | |
638 | #endif |
639 | |
640 | #ifndef QT_NO_DEBUG_STREAM |
641 | #if QT_DEPRECATED_SINCE(6, 0) |
642 | QT_WARNING_PUSH |
643 | QT_WARNING_DISABLE_DEPRECATED |
644 | QT_DEPRECATED_VERSION_6_0 |
645 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); |
646 | QT_WARNING_POP |
647 | #endif |
648 | #endif |
649 | |
650 | namespace QtPrivate { |
651 | class Q_CORE_EXPORT QVariantTypeCoercer |
652 | { |
653 | public: |
654 | const void *convert(const QVariant &value, const QMetaType &type); |
655 | const void *coerce(const QVariant &value, const QMetaType &type); |
656 | |
657 | private: |
658 | QVariant converted; |
659 | }; |
660 | } |
661 | |
662 | template<typename Pointer> |
663 | class QVariantRef |
664 | { |
665 | private: |
666 | const Pointer *m_pointer = nullptr; |
667 | |
668 | public: |
669 | explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {} |
670 | QVariantRef(const QVariantRef &) = default; |
671 | QVariantRef(QVariantRef &&) = default; |
672 | ~QVariantRef() = default; |
673 | |
674 | operator QVariant() const; |
675 | QVariantRef &operator=(const QVariant &value); |
676 | QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); } |
677 | QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); } |
678 | |
679 | friend void swap(QVariantRef a, QVariantRef b) |
680 | { |
681 | QVariant tmp = a; |
682 | a = b; |
683 | b = std::move(tmp); |
684 | } |
685 | }; |
686 | |
687 | class Q_CORE_EXPORT QVariantConstPointer |
688 | { |
689 | private: |
690 | QVariant m_variant; |
691 | |
692 | public: |
693 | explicit QVariantConstPointer(QVariant variant); |
694 | |
695 | QVariant operator*() const; |
696 | const QVariant *operator->() const; |
697 | }; |
698 | |
699 | template<typename Pointer> |
700 | class QVariantPointer |
701 | { |
702 | private: |
703 | const Pointer *m_pointer = nullptr; |
704 | |
705 | public: |
706 | explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {} |
707 | QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); } |
708 | Pointer operator->() const { return *m_pointer; } |
709 | }; |
710 | |
711 | QT_END_NAMESPACE |
712 | |
713 | #endif // QVARIANT_H |
714 | |