1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include <qjsonobject.h>
6#include <qjsonvalue.h>
7#include <qjsonarray.h>
8#include <qjsondocument.h>
9#include <qurl.h>
10#include <quuid.h>
11#include <qvariant.h>
12#include <qstringlist.h>
13#include <qmap.h>
14#include <qhash.h>
15#include <qdebug.h>
16#include "qdatastream.h"
17
18#include <private/qnumeric_p.h>
19#include <private/qcborvalue_p.h>
20
21#include <qcborarray.h>
22#include <qcbormap.h>
23
24#include "qjson_p.h"
25
26QT_BEGIN_NAMESPACE
27
28static QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
29{
30 switch (type) {
31 case QCborValue::Null:
32 return QJsonValue::Null;
33 case QCborValue::True:
34 case QCborValue::False:
35 return QJsonValue::Bool;
36 case QCborValue::Double:
37 case QCborValue::Integer:
38 return QJsonValue::Double;
39 case QCborValue::String:
40 return QJsonValue::String;
41 case QCborValue::Array:
42 return QJsonValue::Array;
43 case QCborValue::Map:
44 return QJsonValue::Object;
45 case QCborValue::Undefined:
46 default:
47 return QJsonValue::Undefined;
48 }
49}
50
51/*!
52 \class QJsonValue
53 \inmodule QtCore
54 \ingroup json
55 \ingroup shared
56 \ingroup qtserialization
57 \reentrant
58 \since 5.0
59
60 \brief The QJsonValue class encapsulates a value in JSON.
61
62 \compares equality
63 \compareswith equality QJsonValueConstRef QJsonValueRef
64 \endcompareswith
65
66 A value in JSON can be one of 6 basic types:
67
68 JSON is a format to store structured data. It has 6 basic data types:
69
70 \list
71 \li bool QJsonValue::Bool
72 \li double QJsonValue::Double
73 \li string QJsonValue::String
74 \li array QJsonValue::Array
75 \li object QJsonValue::Object
76 \li null QJsonValue::Null
77 \endlist
78
79 A value can represent any of the above data types. In addition, QJsonValue has one special
80 flag to represent undefined values. This can be queried with isUndefined().
81
82 The type of the value can be queried with type() or accessors like isBool(), isString(), and so on.
83 Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on.
84
85 Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type
86 conversions. This implies that converting to a type that is not stored in the value will return a default
87 constructed return value.
88
89 \section1 QJsonValueRef
90
91 QJsonValueRef is a helper class for QJsonArray and QJsonObject.
92 When you get an object of type QJsonValueRef, you can
93 use it as if it were a reference to a QJsonValue. If you assign to it,
94 the assignment will apply to the element in the QJsonArray or QJsonObject
95 from which you got the reference.
96
97 The following methods return QJsonValueRef:
98 \list
99 \li \l {QJsonArray}::operator[](qsizetype i)
100 \li \l {QJsonObject}::operator[](const QString & key) const
101 \endlist
102
103 \sa {JSON Support in Qt}, {Saving and Loading a Game}
104*/
105
106/*!
107 Creates a QJsonValue of type \a type.
108
109 The default is to create a Null value.
110 */
111QJsonValue::QJsonValue(Type type)
112{
113 switch (type) {
114 case Null:
115 value = QCborValue::Null;
116 break;
117 case Bool:
118 value = QCborValue::False;
119 break;
120 case Double:
121 value = QCborValue::Double;
122 break;
123 case String:
124 value = QCborValue::String;
125 break;
126 case Array:
127 value = QCborValue::Array;
128 break;
129 case Object:
130 value = QCborValue::Map;
131 break;
132 case Undefined:
133 break;
134 }
135}
136
137/*!
138 Creates a value of type Bool, with value \a b.
139 */
140QJsonValue::QJsonValue(bool b)
141 : value(b)
142{
143}
144
145static inline QCborValue doubleValueHelper(double v)
146{
147 qint64 n = 0;
148 // Convert to integer if the number is an integer and changing wouldn't
149 // introduce additional digit precision not present in the double.
150 if (convertDoubleTo<qint64>(v, value: &n, allow_precision_upgrade: false /* allow_precision_upgrade */))
151 return n;
152 else
153 return v;
154}
155
156/*!
157 Creates a value of type Double, with value \a v.
158 */
159QJsonValue::QJsonValue(double v)
160 : value(doubleValueHelper(v))
161{
162}
163
164/*!
165 \overload
166 Creates a value of type Double, with value \a v.
167 */
168QJsonValue::QJsonValue(int v)
169 : value(v)
170{
171}
172
173/*!
174 \overload
175 Creates a value of type Double, with value \a v.
176 NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992).
177 If you pass in values outside this range expect a loss of precision to occur.
178 */
179QJsonValue::QJsonValue(qint64 v)
180 : value(v)
181{
182}
183
184/*!
185 Creates a value of type String, with value \a s.
186 */
187QJsonValue::QJsonValue(const QString &s)
188 : value(s)
189{
190}
191
192/*!
193 \fn QJsonValue::QJsonValue(const char *s)
194
195 Creates a value of type String with value \a s, assuming
196 UTF-8 encoding of the input.
197
198 You can disable this constructor by defining \c
199 QT_NO_CAST_FROM_ASCII when you compile your applications.
200
201 \since 5.3
202 */
203
204/*!
205 Creates a value of type String, with the Latin-1 string viewed by \a s.
206 */
207QJsonValue::QJsonValue(QLatin1StringView s)
208 : value(s)
209{
210}
211
212/*!
213 Creates a value of type Array, with value \a a.
214 */
215QJsonValue::QJsonValue(const QJsonArray &a)
216 : value(QCborArray::fromJsonArray(array: a))
217{
218}
219
220/*!
221 \overload
222 \since 6.3
223 */
224QJsonValue::QJsonValue(QJsonArray &&a) noexcept
225 : value(QCborArray::fromJsonArray(array: std::move(a)))
226{
227}
228
229/*!
230 Creates a value of type Object, with value \a o.
231 */
232QJsonValue::QJsonValue(const QJsonObject &o)
233 : value(QCborMap::fromJsonObject(o))
234{
235}
236
237/*!
238 \overload
239 \since 6.3
240 */
241QJsonValue::QJsonValue(QJsonObject &&o) noexcept
242 : value(QCborMap::fromJsonObject(o: std::move(o)))
243{
244}
245
246
247/*!
248 Destroys the value.
249 */
250QJsonValue::~QJsonValue() = default;
251
252/*!
253 Creates a copy of \a other.
254 */
255QJsonValue::QJsonValue(const QJsonValue &other) noexcept = default;
256
257/*!
258 Assigns the value stored in \a other to this object.
259 */
260QJsonValue &QJsonValue::operator =(const QJsonValue &other) noexcept
261{
262 QJsonValue copy(other);
263 swap(other&: copy);
264 return *this;
265}
266
267QJsonValue::QJsonValue(QJsonValue &&other) noexcept
268 : value(std::move(other.value))
269{
270 other.value = QCborValue(nullptr);
271}
272
273void QJsonValue::swap(QJsonValue &other) noexcept
274{
275 value.swap(other&: other.value);
276}
277
278/*!
279 \fn QJsonValue::QJsonValue(QJsonValue &&other)
280 \since 5.10
281
282 Move-constructs a QJsonValue from \a other.
283*/
284
285/*!
286 \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other)
287 \since 5.10
288
289 Move-assigns \a other to this value.
290*/
291
292/*!
293 \fn void QJsonValue::swap(QJsonValue &other)
294 \since 5.10
295
296 Swaps the value \a other with this. This operation is very fast and never fails.
297*/
298
299/*!
300 \fn bool QJsonValue::isNull() const
301
302 Returns \c true if the value is null.
303*/
304
305/*!
306 \fn bool QJsonValue::isBool() const
307
308 Returns \c true if the value contains a boolean.
309
310 \sa toBool()
311 */
312
313/*!
314 \fn bool QJsonValue::isDouble() const
315
316 Returns \c true if the value contains a double.
317
318 \sa toDouble()
319 */
320
321/*!
322 \fn bool QJsonValue::isString() const
323
324 Returns \c true if the value contains a string.
325
326 \sa toString()
327 */
328
329/*!
330 \fn bool QJsonValue::isArray() const
331
332 Returns \c true if the value contains an array.
333
334 \sa toArray()
335 */
336
337/*!
338 \fn bool QJsonValue::isObject() const
339
340 Returns \c true if the value contains an object.
341
342 \sa toObject()
343 */
344
345/*!
346 \fn bool QJsonValue::isUndefined() const
347
348 Returns \c true if the value is undefined. This can happen in certain
349 error cases as e.g. accessing a non existing key in a QJsonObject.
350 */
351
352#ifndef QT_NO_VARIANT
353/*!
354 Converts \a variant to a QJsonValue and returns it.
355
356 The conversion will convert QVariant types as follows:
357
358 \table
359 \header
360 \li Source type
361 \li Destination type
362 \row
363 \li
364 \list
365 \li QMetaType::Nullptr
366 \endlist
367 \li QJsonValue::Null
368 \row
369 \li
370 \list
371 \li QMetaType::Bool
372 \endlist
373 \li QJsonValue::Bool
374 \row
375 \li
376 \list
377 \li QMetaType::Int
378 \li QMetaType::UInt
379 \li QMetaType::LongLong
380 \li QMetaType::ULongLong
381 \li QMetaType::Float
382 \li QMetaType::Double
383 \endlist
384 \li QJsonValue::Double
385 \row
386 \li
387 \list
388 \li QMetaType::QString
389 \endlist
390 \li QJsonValue::String
391 \row
392 \li
393 \list
394 \li QMetaType::QStringList
395 \li QMetaType::QVariantList
396 \endlist
397 \li QJsonValue::Array
398 \row
399 \li
400 \list
401 \li QMetaType::QVariantMap
402 \li QMetaType::QVariantHash
403 \endlist
404 \li QJsonValue::Object
405
406 \row
407 \li
408 \list
409 \li QMetaType::QUrl
410 \endlist
411 \li QJsonValue::String. The conversion will use QUrl::toString() with flag
412 QUrl::FullyEncoded, so as to ensure maximum compatibility in parsing the URL
413 \row
414 \li
415 \list
416 \li QMetaType::QUuid
417 \endlist
418 \li QJsonValue::String. Since Qt 5.11, the resulting string will not include braces
419 \row
420 \li
421 \list
422 \li QMetaType::QCborValue
423 \endlist
424 \li Whichever type QCborValue::toJsonValue() returns.
425 \row
426 \li
427 \list
428 \li QMetaType::QCborArray
429 \endlist
430 \li QJsonValue::Array. See QCborValue::toJsonValue() for conversion restrictions.
431 \row
432 \li
433 \list
434 \li QMetaType::QCborMap
435 \endlist
436 \li QJsonValue::Map. See QCborValue::toJsonValue() for conversion restrictions and the
437 "stringification" of map keys.
438 \endtable
439
440 \section2 Loss of information and other types
441
442 QVariant can carry more information than is representable in JSON. If the
443 QVariant is not one of the types above, the conversion is not guaranteed
444 and is subject to change in future versions of Qt, as the UUID one did.
445 Code should strive not to use any other types than those listed above.
446
447 If QVariant::isNull() returns true, a null QJsonValue is returned or
448 inserted into the list or object, regardless of the type carried by
449 QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
450 also affects this function.
451
452 A floating point value that is either an infinity or NaN will be converted
453 to a null JSON value. Since Qt 6.0, QJsonValue can store the full precision
454 of any 64-bit signed integer without loss, but in previous versions values
455 outside the range of ±2^53 may lose precision. Unsigned 64-bit values
456 greater than or equal to 2^63 will either lose precision or alias to
457 negative values, so QMetaType::ULongLong should be avoided.
458
459 For other types not listed above, a conversion to string will be attempted,
460 usually but not always by calling QVariant::toString(). If the conversion
461 fails the value is replaced by a null JSON value. Note that
462 QVariant::toString() is also lossy for the majority of types. For example,
463 if the passed QVariant is representing raw byte array data, it is recommended
464 to pre-encode it to \l {RFC 4686}{Base64} (or
465 another lossless encoding), otherwise a lossy conversion using QString::fromUtf8()
466 will be used.
467
468 Please note that the conversions via QVariant::toString() are subject to
469 change at any time. Both QVariant and QJsonValue may be extended in the
470 future to support more types, which will result in a change in how this
471 function performs conversions.
472
473 \sa toVariant(), QCborValue::fromVariant()
474 */
475QJsonValue QJsonValue::fromVariant(const QVariant &variant)
476{
477 switch (variant.metaType().id()) {
478 case QMetaType::Nullptr:
479 return QJsonValue(Null);
480 case QMetaType::Bool:
481 return QJsonValue(variant.toBool());
482 case QMetaType::Short:
483 case QMetaType::UShort:
484 case QMetaType::Int:
485 case QMetaType::UInt:
486 case QMetaType::LongLong:
487 return QJsonValue(variant.toLongLong());
488 case QMetaType::ULongLong:
489 if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
490 return QJsonValue(variant.toLongLong());
491 Q_FALLTHROUGH();
492 case QMetaType::Float:
493 case QMetaType::Double: {
494 double v = variant.toDouble();
495 return qt_is_finite(d: v) ? QJsonValue(v) : QJsonValue();
496 }
497 case QMetaType::QString:
498 return QJsonValue(variant.toString());
499 case QMetaType::QStringList:
500 return QJsonValue(QJsonArray::fromStringList(list: variant.toStringList()));
501 case QMetaType::QVariantList:
502 return QJsonValue(QJsonArray::fromVariantList(list: variant.toList()));
503 case QMetaType::QVariantMap:
504 return QJsonValue(QJsonObject::fromVariantMap(map: variant.toMap()));
505 case QMetaType::QVariantHash:
506 return QJsonValue(QJsonObject::fromVariantHash(map: variant.toHash()));
507#ifndef QT_BOOTSTRAPPED
508 case QMetaType::QUrl:
509 return QJsonValue(variant.toUrl().toString(options: QUrl::FullyEncoded));
510 case QMetaType::QUuid:
511 return variant.toUuid().toString(mode: QUuid::WithoutBraces);
512 case QMetaType::QJsonValue:
513 return variant.toJsonValue();
514 case QMetaType::QJsonObject:
515 return variant.toJsonObject();
516 case QMetaType::QJsonArray:
517 return variant.toJsonArray();
518 case QMetaType::QJsonDocument: {
519 QJsonDocument doc = variant.toJsonDocument();
520 return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
521 }
522 case QMetaType::QCborValue:
523 return qvariant_cast<QCborValue>(v: variant).toJsonValue();
524 case QMetaType::QCborArray:
525 return qvariant_cast<QCborArray>(v: variant).toJsonArray();
526 case QMetaType::QCborMap:
527 return qvariant_cast<QCborMap>(v: variant).toJsonObject();
528#endif
529 default:
530 break;
531 }
532 QString string = variant.toString();
533 if (string.isEmpty())
534 return QJsonValue();
535 return QJsonValue(string);
536}
537
538/*!
539 Converts the value to a \l {QVariant::}{QVariant()}.
540
541 The QJsonValue types will be converted as follows:
542
543 \value Null QMetaType::Nullptr
544 \value Bool QMetaType::Bool
545 \value Double QMetaType::Double or QMetaType::LongLong
546 \value String QString
547 \value Array QVariantList
548 \value Object QVariantMap
549 \value Undefined \l {QVariant::}{QVariant()}
550
551 \sa fromVariant()
552 */
553QVariant QJsonValue::toVariant() const
554{
555 switch (value.type()) {
556 case QCborValue::True:
557 return true;
558 case QCborValue::False:
559 return false;
560 case QCborValue::Integer:
561 return toInteger();
562 case QCborValue::Double:
563 return toDouble();
564 case QCborValue::String:
565 return toString();
566 case QCborValue::Array:
567 return toArray().toVariantList();
568 case QCborValue::Map:
569 return toObject().toVariantMap();
570 case QCborValue::Null:
571 return QVariant::fromValue(value: nullptr);
572 case QCborValue::Undefined:
573 default:
574 break;
575 }
576 return QVariant();
577}
578
579/*!
580 \enum QJsonValue::Type
581
582 This enum describes the type of the JSON value.
583
584 \value Null A Null value
585 \value Bool A boolean value. Use toBool() to convert to a bool.
586 \value Double A number value. Use toDouble() to convert to a double,
587 or toInteger() to convert to a qint64.
588 \value String A string. Use toString() to convert to a QString.
589 \value Array An array. Use toArray() to convert to a QJsonArray.
590 \value Object An object. Use toObject() to convert to a QJsonObject.
591 \value Undefined The value is undefined. This is usually returned as an
592 error condition, when trying to read an out of bounds value
593 in an array or a non existent key in an object.
594*/
595#endif // !QT_NO_VARIANT
596
597/*!
598 Returns the type of the value.
599
600 \sa QJsonValue::Type
601 */
602QJsonValue::Type QJsonValue::type() const
603{
604 return convertFromCborType(type: value.type());
605}
606
607/*!
608 Converts the value to a bool and returns it.
609
610 If type() is not bool, the \a defaultValue will be returned.
611 */
612bool QJsonValue::toBool(bool defaultValue) const
613{
614 switch (value.type()) {
615 case QCborValue::True:
616 return true;
617 case QCborValue::False:
618 return false;
619 default:
620 return defaultValue;
621 }
622}
623
624/*!
625 \since 5.2
626 Converts the value to an int and returns it.
627
628 If type() is not Double or the value is not a whole number,
629 the \a defaultValue will be returned.
630 */
631int QJsonValue::toInt(int defaultValue) const
632{
633 switch (value.type()) {
634 case QCborValue::Double: {
635 int dblInt;
636 if (convertDoubleTo<int>(v: toDouble(), value: &dblInt))
637 return dblInt;
638 break;
639 }
640 case QCborValue::Integer: {
641 const auto n = value.toInteger();
642 if (qint64(int(n)) == n)
643 return int(n);
644 break;
645 }
646 default:
647 break;
648 }
649 return defaultValue;
650}
651
652/*!
653 \since 6.0
654 Converts the value to an integer and returns it.
655
656 If type() is not Double or the value is not a whole number
657 representable as qint64, the \a defaultValue will be returned.
658 */
659qint64 QJsonValue::toInteger(qint64 defaultValue) const
660{
661 switch (value.type()) {
662 case QCborValue::Integer:
663 return value.toInteger();
664 case QCborValue::Double: {
665 qint64 dblInt;
666 if (convertDoubleTo<qint64>(v: toDouble(), value: &dblInt))
667 return dblInt;
668 break;
669 }
670 default:
671 break;
672 }
673 return defaultValue;
674}
675
676/*!
677 Converts the value to a double and returns it.
678
679 If type() is not Double, the \a defaultValue will be returned.
680 */
681double QJsonValue::toDouble(double defaultValue) const
682{
683 return value.toDouble(defaultValue);
684}
685
686/*!
687 Converts the value to a QString and returns it.
688
689 If type() is not String, the \a defaultValue will be returned.
690 */
691QString QJsonValue::toString(const QString &defaultValue) const
692{
693 return value.toString(defaultValue);
694}
695
696/*!
697 Converts the value to a QString and returns it.
698
699 If type() is not String, a null QString will be returned.
700
701 \sa QString::isNull()
702 */
703QString QJsonValue::toString() const
704{
705 return value.toString();
706}
707
708/*!
709 Converts the value to an array and returns it.
710
711 If type() is not Array, the \a defaultValue will be returned.
712 */
713QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
714{
715 if (!isArray())
716 return defaultValue;
717 QCborContainerPrivate *dd = nullptr;
718 const auto n = QJsonPrivate::Value::valueHelper(v: value);
719 const auto container = QJsonPrivate::Value::container(v: value);
720 Q_ASSERT(n == -1 || container == nullptr);
721 if (n < 0)
722 dd = container;
723 return QJsonArray(dd);
724}
725
726/*!
727 \overload
728
729 Converts the value to an array and returns it.
730
731 If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned.
732 */
733QJsonArray QJsonValue::toArray() const
734{
735 return toArray(defaultValue: QJsonArray());
736}
737
738/*!
739 Converts the value to an object and returns it.
740
741 If type() is not Object, the \a defaultValue will be returned.
742 */
743QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
744{
745 if (!isObject())
746 return defaultValue;
747 QCborContainerPrivate *dd = nullptr;
748 const auto container = QJsonPrivate::Value::container(v: value);
749 const auto n = QJsonPrivate::Value::valueHelper(v: value);
750 Q_ASSERT(n == -1 || container == nullptr);
751 if (n < 0)
752 dd = container;
753 return QJsonObject(dd);
754}
755
756/*!
757 \overload
758
759 Converts the value to an object and returns it.
760
761 If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned.
762*/
763QJsonObject QJsonValue::toObject() const
764{
765 return toObject(defaultValue: QJsonObject());
766}
767
768/*!
769 Returns a QJsonValue representing the value for the key \a key.
770
771 Equivalent to calling toObject().value(key).
772
773 The returned QJsonValue is QJsonValue::Undefined if the key does not exist,
774 or if isObject() is false.
775
776 \since 5.10
777
778 \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject
779 */
780const QJsonValue QJsonValue::operator[](const QString &key) const
781{
782 return (*this)[QStringView(key)];
783}
784
785/*!
786 \overload
787 \since 5.14
788*/
789const QJsonValue QJsonValue::operator[](QStringView key) const
790{
791 if (!isObject())
792 return QJsonValue(QJsonValue::Undefined);
793
794 return toObject().value(key);
795}
796
797/*!
798 \overload
799 \since 5.10
800*/
801const QJsonValue QJsonValue::operator[](QLatin1StringView key) const
802{
803 if (!isObject())
804 return QJsonValue(QJsonValue::Undefined);
805
806 return toObject().value(key);
807}
808
809/*!
810 Returns a QJsonValue representing the value for index \a i.
811
812 Equivalent to calling toArray().at(i).
813
814 The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds,
815 or if isArray() is false.
816
817 \since 5.10
818
819 \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
820 */
821const QJsonValue QJsonValue::operator[](qsizetype i) const
822{
823 if (!isArray())
824 return QJsonValue(QJsonValue::Undefined);
825
826 return toArray().at(i);
827}
828
829/*!
830 \fn bool QJsonValue::operator==(const QJsonValue &lhs, const QJsonValue &rhs)
831
832 Returns \c true if the \a lhs value is equal to \a rhs value, \c false otherwise.
833*/
834bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs)
835{
836 if (lhs.value.type() != rhs.value.type()) {
837 if (lhs.isDouble() && rhs.isDouble()) {
838 // One value Cbor integer, one Cbor double, should interact as doubles.
839 return lhs.toDouble() == rhs.toDouble();
840 }
841 return false;
842 }
843
844 switch (lhs.value.type()) {
845 case QCborValue::Undefined:
846 case QCborValue::Null:
847 case QCborValue::True:
848 case QCborValue::False:
849 break;
850 case QCborValue::Double:
851 return lhs.toDouble() == rhs.toDouble();
852 case QCborValue::Integer:
853 return QJsonPrivate::Value::valueHelper(v: lhs.value)
854 == QJsonPrivate::Value::valueHelper(v: rhs.value);
855 case QCborValue::String:
856 return lhs.toString() == rhs.toString();
857 case QCborValue::Array:
858 return lhs.toArray() == rhs.toArray();
859 case QCborValue::Map:
860 return lhs.toObject() == rhs.toObject();
861 default:
862 return false;
863 }
864 return true;
865}
866
867/*!
868 \fn bool QJsonValue::operator!=(const QJsonValue &lhs, const QJsonValue &rhs)
869
870 Returns \c true if the \a lhs value is not equal to \a rhs value, \c false otherwise.
871*/
872
873/*!
874 \class QJsonValueRef
875 \inmodule QtCore
876 \reentrant
877 \brief The QJsonValueRef class is a helper class for QJsonValue.
878
879 \internal
880
881 \ingroup json
882
883 When you get an object of type QJsonValueRef, if you can assign to it,
884 the assignment will apply to the character in the string from
885 which you got the reference. That is its whole purpose in life.
886
887 You can use it exactly in the same way as a reference to a QJsonValue.
888
889 The QJsonValueRef becomes invalid once modifications are made to the
890 string: if you want to keep the character, copy it into a QJsonValue.
891
892 Most of the QJsonValue member functions also exist in QJsonValueRef.
893 However, they are not explicitly documented here.
894*/
895
896void QJsonValueRef::detach()
897{
898#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
899 QCborContainerPrivate *d = QJsonPrivate::Value::container(r: *this);
900 d = QCborContainerPrivate::detach(d, reserved: d->elements.size());
901
902 if (is_object)
903 o->o.reset(ptr: d);
904 else
905 a->a.reset(ptr: d);
906#else
907 d = QCborContainerPrivate::detach(d, d->elements.size());
908#endif
909}
910
911static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
912{
913 QCborContainerPrivate *d = QJsonPrivate::Value::container(r: ref);
914 qsizetype index = QJsonPrivate::Value::indexHelper(r: ref);
915 if (is_object && value.isUndefined()) {
916 d->removeAt(idx: index);
917 d->removeAt(idx: index - 1);
918 } else {
919 d->replaceAt(idx: index, value);
920 }
921
922 return ref;
923}
924
925QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
926{
927 detach();
928 return assignToRef(ref&: *this, value: QCborValue::fromJsonValue(v: val), is_object);
929}
930
931QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
932{
933 // ### optimize more?
934 const QCborContainerPrivate *d = QJsonPrivate::Value::container(r: ref);
935 qsizetype index = QJsonPrivate::Value::indexHelper(r: ref);
936
937 if (d == QJsonPrivate::Value::container(r: *this) &&
938 index == QJsonPrivate::Value::indexHelper(r: *this))
939 return *this; // self assignment
940
941 detach();
942 return assignToRef(ref&: *this, value: d->valueAt(idx: index), is_object);
943}
944
945#ifndef QT_NO_VARIANT
946QVariant QJsonValueConstRef::toVariant() const
947{
948 return concrete(self: *this).toVariant();
949}
950#endif // !QT_NO_VARIANT
951
952QJsonArray QJsonValueConstRef::toArray() const
953{
954 return concrete(self: *this).toArray();
955}
956
957QJsonObject QJsonValueConstRef::toObject() const
958{
959 return concrete(self: *this).toObject();
960}
961
962QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
963{
964 return convertFromCborType(type: QJsonPrivate::Value::elementHelper(r: self).type);
965}
966
967bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
968{
969 auto &e = QJsonPrivate::Value::elementHelper(r: self);
970 if (e.type == QCborValue::False)
971 return false;
972 if (e.type == QCborValue::True)
973 return true;
974 return defaultValue;
975}
976
977qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
978{
979 auto &e = QJsonPrivate::Value::elementHelper(r: self);
980 qint64 v = defaultValue;
981 if (e.type == QCborValue::Double) {
982 // convertDoubleTo modifies the output even on returning false
983 if (!convertDoubleTo<qint64>(v: e.fpvalue(), value: &v))
984 v = defaultValue;
985 } else if (e.type == QCborValue::Integer) {
986 v = e.value;
987 }
988 if (clamp && qint64(int(v)) != v)
989 return defaultValue;
990 return v;
991}
992
993double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
994{
995 auto &e = QJsonPrivate::Value::elementHelper(r: self);
996 if (e.type == QCborValue::Double)
997 return e.fpvalue();
998 if (e.type == QCborValue::Integer)
999 return e.value;
1000 return defaultValue;
1001}
1002
1003QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
1004{
1005 const QCborContainerPrivate *d = QJsonPrivate::Value::container(r: self);
1006 qsizetype index = QJsonPrivate::Value::indexHelper(r: self);
1007 if (d->elements.at(i: index).type != QCborValue::String)
1008 return defaultValue;
1009 return d->stringAt(idx: index);
1010}
1011
1012QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
1013{
1014 const QCborContainerPrivate *d = QJsonPrivate::Value::container(r: self);
1015 qsizetype index = QJsonPrivate::Value::indexHelper(r: self);
1016 return QJsonPrivate::Value::fromTrustedCbor(v: d->valueAt(idx: index));
1017}
1018
1019QString QJsonValueConstRef::objectKey(QJsonValueConstRef self)
1020{
1021 Q_ASSERT(self.is_object);
1022 Q_ASSERT(self.is_object);
1023 const QCborContainerPrivate *d = QJsonPrivate::Value::container(r: self);
1024 qsizetype index = QJsonPrivate::Value::indexHelper(r: self);
1025
1026 Q_ASSERT(d);
1027 Q_ASSERT(index < d->elements.size());
1028 return d->stringAt(idx: index - 1);
1029}
1030
1031#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1032QVariant QJsonValueRef::toVariant() const
1033{
1034 return QJsonValueConstRef::toVariant();
1035}
1036
1037QJsonArray QJsonValueRef::toArray() const
1038{
1039 return QJsonValueConstRef::toArray();
1040}
1041
1042QJsonObject QJsonValueRef::toObject() const
1043{
1044 return QJsonValueConstRef::toObject();
1045}
1046
1047QJsonValue QJsonValueRef::toValue() const
1048{
1049 return concrete(self: *this);
1050}
1051#else
1052QJsonValueRef QJsonValueRef::operator[](qsizetype key)
1053{
1054 if (d->elements.at(index).type != QCborValue::Array)
1055 d->replaceAt(index, QCborValue::Array);
1056
1057 auto &e = d->elements[index];
1058 e.container = QCborContainerPrivate::grow(e.container, key); // detaches
1059 e.flags |= QtCbor::Element::IsContainer;
1060
1061 return QJsonValueRef(e.container, key, false);
1062}
1063
1064QJsonValueRef QJsonValueRef::operator[](QAnyStringView key)
1065{
1066 // must go through QJsonObject because some of the machinery is non-static
1067 // member or file-static in qjsonobject.cpp
1068 QJsonObject o = QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index)).toObject();
1069 QJsonValueRef ret = key.visit([&](auto v) {
1070 if constexpr (std::is_same_v<decltype(v), QUtf8StringView>)
1071 return o[QString::fromUtf8(v)];
1072 else
1073 return o[v];
1074 });
1075
1076 // ### did the QJsonObject::operator[] above detach?
1077 QCborContainerPrivate *x = o.o.take();
1078 Q_ASSERT(x->ref.loadRelaxed() == 1);
1079
1080 auto &e = d->elements[index];
1081 if (e.flags & QtCbor::Element::IsContainer && e.container != x)
1082 o.o.reset(e.container); // might not an object!
1083
1084 e.flags |= QtCbor::Element::IsContainer;
1085 e.container = x;
1086
1087 return ret;
1088}
1089#endif
1090
1091size_t qHash(const QJsonValue &value, size_t seed)
1092{
1093 switch (value.type()) {
1094 case QJsonValue::Null:
1095 return qHash(nullptr, seed);
1096 case QJsonValue::Bool:
1097 return qHash(t: value.toBool(), seed);
1098 case QJsonValue::Double:
1099 return qHash(key: value.toDouble(), seed);
1100 case QJsonValue::String:
1101 return qHash(key: value.toString(), seed);
1102 case QJsonValue::Array:
1103 return qHash(array: value.toArray(), seed);
1104 case QJsonValue::Object:
1105 return qHash(object: value.toObject(), seed);
1106 case QJsonValue::Undefined:
1107 return seed;
1108 }
1109 Q_UNREACHABLE_RETURN(0);
1110}
1111
1112#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
1113QDebug operator<<(QDebug dbg, const QJsonValue &o)
1114{
1115 QDebugStateSaver saver(dbg);
1116 switch (o.value.type()) {
1117 case QCborValue::Undefined:
1118 dbg << "QJsonValue(undefined)";
1119 break;
1120 case QCborValue::Null:
1121 dbg << "QJsonValue(null)";
1122 break;
1123 case QCborValue::True:
1124 case QCborValue::False:
1125 dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')';
1126 break;
1127 case QCborValue::Integer:
1128 dbg.nospace() << "QJsonValue(double, " << o.toInteger() << ')';
1129 break;
1130 case QCborValue::Double:
1131 dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')';
1132 break;
1133 case QCborValue::String:
1134 dbg.nospace() << "QJsonValue(string, " << o.toString() << ')';
1135 break;
1136 case QCborValue::Array:
1137 dbg.nospace() << "QJsonValue(array, ";
1138 dbg << o.toArray();
1139 dbg << ')';
1140 break;
1141 case QCborValue::Map:
1142 dbg.nospace() << "QJsonValue(object, ";
1143 dbg << o.toObject();
1144 dbg << ')';
1145 break;
1146 default:
1147 Q_UNREACHABLE();
1148 }
1149 return dbg;
1150}
1151#endif
1152
1153#ifndef QT_NO_DATASTREAM
1154QDataStream &operator<<(QDataStream &stream, const QJsonValue &v)
1155{
1156 quint8 type = v.type();
1157 stream << type;
1158 switch (type) {
1159 case QJsonValue::Undefined:
1160 case QJsonValue::Null:
1161 break;
1162 case QJsonValue::Bool:
1163 stream << v.toBool();
1164 break;
1165 case QJsonValue::Double:
1166 stream << v.toDouble();
1167 break;
1168 case QJsonValue::String:
1169 stream << v.toString();
1170 break;
1171 case QJsonValue::Array:
1172 stream << v.toArray();
1173 break;
1174 case QJsonValue::Object:
1175 stream << v.toObject();
1176 break;
1177 }
1178 return stream;
1179}
1180
1181QDataStream &operator>>(QDataStream &stream, QJsonValue &v)
1182{
1183 quint8 type;
1184 stream >> type;
1185 switch (type) {
1186 case QJsonValue::Undefined:
1187 case QJsonValue::Null:
1188 v = QJsonValue{QJsonValue::Type(type)};
1189 break;
1190 case QJsonValue::Bool: {
1191 bool b;
1192 stream >> b;
1193 v = QJsonValue(b);
1194 break;
1195 } case QJsonValue::Double: {
1196 double d;
1197 stream >> d;
1198 v = QJsonValue{d};
1199 break;
1200 } case QJsonValue::String: {
1201 QString s;
1202 stream >> s;
1203 v = QJsonValue{s};
1204 break;
1205 }
1206 case QJsonValue::Array: {
1207 QJsonArray a;
1208 stream >> a;
1209 v = QJsonValue{a};
1210 break;
1211 }
1212 case QJsonValue::Object: {
1213 QJsonObject o;
1214 stream >> o;
1215 v = QJsonValue{o};
1216 break;
1217 }
1218 default: {
1219 stream.setStatus(QDataStream::ReadCorruptData);
1220 v = QJsonValue{QJsonValue::Undefined};
1221 }
1222 }
1223 return stream;
1224}
1225#endif
1226
1227QT_END_NAMESPACE
1228

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/corelib/serialization/qjsonvalue.cpp