Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qjsoncbor.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcborvalue.h"
5#include "qcborvalue_p.h"
6
7#include "qcborarray.h"
8#include "qcbormap.h"
9
10#include "qjsonarray.h"
11#include "qjsonobject.h"
12#include "qjsondocument.h"
13#include "qjson_p.h"
14
15#include <qmap.h>
16#include <qhash.h>
17
18#include <private/qnumeric_p.h>
19#include <quuid.h>
20
22
23using namespace QtCbor;
24
26
27static QJsonValue fpToJson(double v)
28{
29 return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
30}
31
33{
34 int simpleType = t - QCborValue::SimpleType;
35 if (unsigned(simpleType) < 0x100)
36 return QString::fromLatin1("simple(%1)").arg(simpleType);
37
38 // if we got here, we got an unknown type
39 qWarning("QCborValue: found unknown type 0x%x", t);
40 return QString();
41
42}
43
45{
46 const ByteData *b = d->byteData(idx);
47 if (!b)
48 return QString();
49
50 QByteArray data = QByteArray::fromRawData(b->byte(), b->len);
51 if (encoding == QCborKnownTags::ExpectedBase16)
52 data = data.toHex();
53 else if (encoding == QCborKnownTags::ExpectedBase64)
54 data = data.toBase64();
55 else
57
58 return QString::fromLatin1(data, data.size());
59}
60
63
65{
66 qint64 tag = d->elements.at(0).value;
67 const Element &e = d->elements.at(1);
68
69 switch (tag) {
72 if (e.type == QCborValue::String)
73 return makeString(d, 1);
74 break;
75
79 if (e.type == QCborValue::ByteArray)
80 return encodeByteArray(d, 1, QCborTag(tag));
81 break;
82
84#ifndef QT_BOOTSTRAPPED
85 if (const ByteData *b = d->byteData(e); e.type == QCborValue::ByteArray && b
86 && b->len == sizeof(QUuid))
87 return QUuid::fromRfc4122(b->asByteArrayView()).toString(QUuid::WithoutBraces);
88#endif
89 break;
90 }
91
92 // don't know what to do, bail out
93 return QString();
94}
95
97{
98 QString s;
99 if (!d || d->elements.size() != 2)
100 return s; // invalid (incomplete?) tag state
101
102 s = maybeEncodeTag(d);
103 if (s.isNull()) {
104 // conversion failed, ignore the tag and convert the tagged value
105 s = makeString(d, 1);
106 }
107 return s;
108}
109
112{
113 const auto &e = d->elements.at(idx);
114
115 switch (e.type) {
117 return QString::number(qint64(e.value));
118
120 return QString::number(e.fpvalue());
121
124 ? d->stringAt(idx)
126
128 return d->stringAt(idx);
129
131 case QCborValue::Map:
132#if defined(QT_JSON_READONLY) || defined(QT_BOOTSTRAPPED)
133 qFatal("Writing JSON is disabled.");
134 return QString();
135#else
136 return d->valueAt(idx).toDiagnosticNotation(QCborValue::Compact);
137#endif
138
140 break;
141
143 return QStringLiteral("false");
144
145 case QCborValue::True:
146 return QStringLiteral("true");
147
148 case QCborValue::Null:
149 return QStringLiteral("null");
150
152 return QStringLiteral("undefined");
153
155 return QString();
156
157 case QCborValue::Tag:
159 case QCborValue::Url:
161 case QCborValue::Uuid:
162 return encodeTag(e.flags & Element::IsContainer ? e.container : nullptr);
163 }
164
165 // maybe it's a simple type
166 return simpleTypeString(e.type);
167}
168
171
173{
174 qint64 tag = d->elements.at(0).value;
175
176 switch (tag) {
178#ifdef QT_BOOTSTRAPPED
179 break;
180#else
181 // use the fully-encoded URL form
182 if (d->elements.at(1).type == QCborValue::String)
183 return QUrl::fromEncoded(d->byteData(1)->asByteArrayView()).toString(QUrl::FullyEncoded);
185#endif
186
192 // use the string conversion
194 if (!s.isNull())
195 return s;
196 }
197 }
198
199 // for all other tags, ignore it and return the converted tagged item
200 return qt_convertToJson(d, 1);
201}
202
203// We need to do this because sub-objects may need conversion.
206{
208 if (d) {
209 for (qsizetype idx = 0; idx < d->elements.size(); ++idx)
210 a.append(qt_convertToJson(d, idx, mode));
211 }
212 return a;
213}
214
215// We need to do this because the keys need to be sorted and converted to strings
216// and sub-objects may need recursive conversion.
219{
221 if (d) {
222 for (qsizetype idx = 0; idx < d->elements.size(); idx += 2)
223 o.insert(makeString(d, idx), qt_convertToJson(d, idx + 1, mode));
224 }
225 return o;
226}
227
229{
230 // encoding the container itself
231 if (idx == -QCborValue::Array)
232 return convertToJsonArray(d, mode);
233 if (idx == -QCborValue::Map)
234 return convertToJsonObject(d, mode);
235 if (idx < 0) {
236 // tag-like type
237 if (!d || d->elements.size() != 2)
238 return QJsonValue::Undefined; // invalid state
240 }
241
242 // an element in the container
243 const auto &e = d->elements.at(idx);
244 switch (e.type) {
246 return QJsonValue(e.value);
249 const auto value = makeString(d, idx, mode);
251 }
252 break;
255 return QJsonValue();
256 break;
259 // make string
260 break;
261
263 case QCborValue::Map:
264 case QCborValue::Tag:
266 case QCborValue::Url:
267 case QCborValue::Uuid:
268 // recurse
269 return qt_convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type,
270 mode);
271
272 case QCborValue::Null:
275 return QJsonValue();
276
278 return false;
279
280 case QCborValue::True:
281 return true;
282
284 return fpToJson(e.fpvalue());
285 }
286
288}
289
350{
351 if (container)
352 return qt_convertToJson(container, n < 0 ? -type() : n);
353
354 // simple values
355 switch (type()) {
356 case False:
357 return false;
358
359 case Integer:
361
362 case True:
363 return true;
364
365 case Null:
366 case Undefined:
367 case Invalid:
368 return QJsonValue();
369
370 case Double:
371 return fpToJson(fp_helper());
372
373 case SimpleType:
374 break;
375
376 case ByteArray:
377 case String:
378 // empty strings
379 return QJsonValue::String;
380
381 case Array:
382 // empty array
383 return QJsonArray();
384
385 case Map:
386 // empty map
387 return QJsonObject();
388
389 case Tag:
390 case DateTime:
391 case Url:
393 case Uuid:
394 // Reachable, but invalid in Json
396 }
397
399}
400
401#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
402QJsonValue QCborValueRef::toJsonValue() const
403{
404 return qt_convertToJson(d, i);
405}
406#endif
407
420{
421 return convertToJsonArray(d.data());
422}
423
425{
426 const auto cborArray = QCborArray::fromVariantList(list);
427 return convertToJsonArray(cborArray.d.data(), ConversionMode::FromVariantToJson);
428}
429
468{
469 return convertToJsonObject(d.data());
470}
471
473{
474 const auto cborMap = QCborMap::fromVariantMap(map);
476}
477
516{
517 switch (type()) {
518 case Integer:
519 return toInteger();
520
521 case Double:
522 return toDouble();
523
524 case SimpleType:
525 break;
526
527 case False:
528 case True:
529 return isTrue();
530
531 case Null:
532 return QVariant::fromValue(nullptr);
533
534 case Undefined:
535 return QVariant();
536
537 case ByteArray:
538 return toByteArray();
539
540 case String:
541 return toString();
542
543 case Array:
544 return toArray().toVariantList();
545
546 case Map:
547 return toMap().toVariantMap();
548
549 case Tag:
550 // ignore tags
551 return taggedValue().toVariant();
552
553 case DateTime:
554 return toDateTime();
555
556#ifndef QT_BOOTSTRAPPED
557 case Url:
558 return toUrl();
559
560# if QT_CONFIG(regularexpression)
562 return toRegularExpression();
563# endif
564
565 case Uuid:
566 return toUuid();
567#endif
568
569 case Invalid:
570 return QVariant();
571
572 default:
573 break;
574 }
575
576 if (isSimpleType())
577 return QVariant::fromValue(toSimpleType());
578
579 Q_UNREACHABLE_RETURN(QVariant());
580}
581
611{
612 switch (v.type()) {
613 case QJsonValue::Bool:
614 return v.toBool();
615 case QJsonValue::Double: {
616 if (v.value.t == Integer)
617 return v.toInteger();
618 return v.toDouble();
619 }
621 return v.toString();
623 return QCborArray::fromJsonArray(v.toArray());
625 return QCborMap::fromJsonObject(v.toObject());
626 case QJsonValue::Null:
627 return nullptr;
629 break;
630 }
631 return QCborValue();
632}
633
635{
636 // Handle strings and byte arrays directly, to avoid creating a temporary
637 // dummy container to hold their data.
638 int type = variant.metaType().id();
639 if (type == QMetaType::QString) {
640 d->append(variant.toString());
641 } else if (type == QMetaType::QByteArray) {
643 d->appendByteData(ba.constData(), ba.size(), QCborValue::ByteArray);
644 } else {
645 // For everything else, use the function below.
647 }
648}
649
703{
704 switch (variant.metaType().id()) {
706 return {};
707 case QMetaType::Nullptr:
708 return nullptr;
709 case QMetaType::Bool:
710 return variant.toBool();
711 case QMetaType::Short:
712 case QMetaType::UShort:
713 case QMetaType::Int:
714 case QMetaType::LongLong:
715 case QMetaType::UInt:
716 return variant.toLongLong();
717 case QMetaType::ULongLong:
718 if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
719 return variant.toLongLong();
721 case QMetaType::Float:
722 case QMetaType::Double:
723 return variant.toDouble();
724 case QMetaType::QString:
725 return variant.toString();
726 case QMetaType::QStringList:
728 case QMetaType::QByteArray:
729 return variant.toByteArray();
730 case QMetaType::QDateTime:
731 return QCborValue(variant.toDateTime());
732#ifndef QT_BOOTSTRAPPED
733 case QMetaType::QUrl:
734 return QCborValue(variant.toUrl());
735 case QMetaType::QUuid:
736 return QCborValue(variant.toUuid());
737#endif
738 case QMetaType::QVariantList:
740 case QMetaType::QVariantMap:
742 case QMetaType::QVariantHash:
744#ifndef QT_BOOTSTRAPPED
745#if QT_CONFIG(regularexpression)
746 case QMetaType::QRegularExpression:
747 return QCborValue(variant.toRegularExpression());
748#endif
749 case QMetaType::QJsonValue:
750 return fromJsonValue(variant.toJsonValue());
751 case QMetaType::QJsonObject:
753 case QMetaType::QJsonArray:
755 case QMetaType::QJsonDocument: {
757 if (doc.isArray())
758 return QCborArray::fromJsonArray(doc.array());
759 return QCborMap::fromJsonObject(doc.object());
760 }
761 case QMetaType::QCborValue:
762 return qvariant_cast<QCborValue>(variant);
763 case QMetaType::QCborArray:
764 return qvariant_cast<QCborArray>(variant);
765 case QMetaType::QCborMap:
766 return qvariant_cast<QCborMap>(variant);
767 case QMetaType::QCborSimpleType:
768 return qvariant_cast<QCborSimpleType>(variant);
769#endif
770 default:
771 break;
772 }
773
774 if (variant.isNull())
775 return QCborValue(nullptr);
776
777 QString string = variant.toString();
778 if (string.isNull())
779 return QCborValue(); // undefined
780 return string;
781}
782
795{
796 QVariantList retval;
797 retval.reserve(size());
798 for (qsizetype i = 0; i < size(); ++i)
799 retval.append(d->valueAt(i).toVariant());
800 return retval;
801}
802
809{
811 a.detach(list.size());
812 for (const QString &s : list)
813 a.d->append(s);
814 return a;
815}
816
827{
829 a.detach(list.size());
830 for (const QVariant &v : list)
831 appendVariant(a.d.data(), v);
832 return a;
833}
834
847{
849 result.d = array.a;
850 return result;
851}
852
858{
860 result.d = std::exchange(array.a, {});
861 return result;
862
863}
864
882{
883 QVariantMap retval;
884 for (qsizetype i = 0; i < 2 * size(); i += 2)
885 retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
886 return retval;
887}
888
906{
907 QVariantHash retval;
908 retval.reserve(size());
909 for (qsizetype i = 0; i < 2 * size(); i += 2)
910 retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
911 return retval;
912}
913
924{
925 QCborMap m;
926 m.detach(map.size());
927 QCborContainerPrivate *d = m.d.data();
928
929 auto it = map.begin();
930 auto end = map.end();
931 for ( ; it != end; ++it) {
932 d->append(it.key());
933 appendVariant(d, it.value());
934 }
935 return m;
936}
937
948{
949 QCborMap m;
950 m.detach(hash.size());
951 QCborContainerPrivate *d = m.d.data();
952
953 auto it = hash.begin();
954 auto end = hash.end();
955 for ( ; it != end; ++it) {
956 d->append(it.key());
957 appendVariant(d, it.value());
958 }
959 return m;
960}
961
973{
975 result.d = obj.o;
976 return result;
977}
978
984{
986 result.d = std::exchange(obj.o, {});
987 return result;
988}
989
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
@ Base64UrlEncoding
Definition qbytearray.h:74
@ OmitTrailingEquals
Definition qbytearray.h:77
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
\inmodule QtCore\reentrant
Definition qcborarray.h:20
QVariantList toVariantList() const
Recursively converts each \l QCborValue in this array using QCborValue::toVariant() and returns the Q...
static QCborArray fromJsonArray(const QJsonArray &array)
Converts all JSON items found in the array array to CBOR using QCborValue::fromJson(),...
QJsonArray toJsonArray() const
Recursively converts every \l QCborValue element in this array to JSON using QCborValue::toJsonValue(...
static QCborArray fromStringList(const QStringList &list)
Returns a QCborArray containing all the strings found in the list list.
static QCborArray fromVariantList(const QVariantList &list)
Converts all the items in the list to CBOR using QCborValue::fromVariant() and returns the array comp...
\inmodule QtCore\reentrant
Definition qcbormap.h:21
QVariantMap toVariantMap() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
QVariantHash toVariantHash() const
Converts the CBOR values to QVariant using QCborValue::toVariant() and "stringifies" all the CBOR key...
QJsonObject toJsonObject() const
Recursively converts every \l QCborValue value in this map to JSON using QCborValue::toJsonValue() an...
static QCborMap fromJsonObject(const QJsonObject &o)
Converts all JSON items found in the obj object to CBOR using QCborValue::fromJson(),...
static QCborMap fromVariantMap(const QVariantMap &map)
Converts all the items in map to CBOR using QCborValue::fromVariant() and returns the map composed of...
static QCborMap fromVariantHash(const QVariantHash &hash)
Converts all the items in hash to CBOR using QCborValue::fromVariant() and returns the map composed o...
\inmodule QtCore\reentrant
Definition qcborvalue.h:50
static QCborValue fromVariant(const QVariant &variant)
Converts the QVariant variant into QCborValue and returns it.
QVariant toVariant() const
Converts this value to a native Qt type and returns the corresponding QVariant.
QJsonValue toJsonValue() const
Converts this QCborValue object to an equivalent representation in JSON and returns it as a QJsonValu...
Type
This enum represents the QCborValue type.
Definition qcborvalue.h:73
@ RegularExpression
Definition qcborvalue.h:93
Type type() const
Returns the type of this QCborValue.
Definition qcborvalue.h:157
static QCborValue fromJsonValue(const QJsonValue &v)
Converts the JSON value contained in v into its corresponding CBOR value and returns it.
T * data() const noexcept
Returns a pointer to the shared data object.
void reserve(qsizetype size)
Ensures that the QHash's internal hash table has space to store at least size items without having to...
Definition qhash.h:929
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
bool isArray() const
Returns true if the document contains an array.
QJsonArray array() const
Returns the QJsonArray contained in the document.
QJsonObject object() const
Returns the QJsonObject contained in the document.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
static QJsonValue fromTrustedCbor(const QCborValue &v)
Definition qjson_p.h:200
static QJsonObject toJsonObject(const QVariantMap &map)
static QJsonArray toJsonArray(const QVariantList &list)
\inmodule QtCore\reentrant
Definition qjsonvalue.h:24
qsizetype size() const noexcept
Definition qlist.h:386
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
iterator begin()
Definition qmap.h:597
iterator end()
Definition qmap.h:601
size_type size() const
Definition qmap.h:266
int id(int=0) const
Definition qmetatype.h:454
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
@ FullyEncoded
Definition qurl.h:129
static QUrl fromEncoded(QByteArrayView input, ParsingMode mode=TolerantMode)
Parses input and returns the corresponding QUrl.
Definition qurl.cpp:2985
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
\inmodule QtCore
Definition quuid.h:31
@ WithoutBraces
Definition quuid.h:54
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:602
static QUuid fromRfc4122(QByteArrayView) noexcept
Creates a QUuid object from the binary representation of the UUID, as specified by RFC 4122 section 4...
Definition quuid.cpp:547
\inmodule QtCore
Definition qvariant.h:64
QDateTime toDateTime() const
Returns the variant as a QDateTime if the variant has userType() \l QMetaType::QDateTime,...
QJsonValue toJsonValue() const
double toDouble(bool *ok=nullptr) const
Returns the variant as a double if the variant has userType() \l QMetaType::Double,...
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has userType() \l QMetaType::QVariantList.
QMap< QString, QVariant > toMap() const
Returns the variant as a QVariantMap if the variant has type() \l QMetaType::QVariantMap.
qlonglong toLongLong(bool *ok=nullptr) const
Returns the variant as a long long int if the variant has userType() \l QMetaType::LongLong,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QJsonArray toJsonArray() const
QHash< QString, QVariant > toHash() const
Returns the variant as a QHash<QString, QVariant> if the variant has type() \l QMetaType::QVariantHas...
bool isNull() const
Returns true if this is a null variant, false otherwise.
QJsonDocument toJsonDocument() const
QJsonObject toJsonObject() const
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QUuid toUuid() const
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
QMetaType metaType() const
qulonglong toULongLong(bool *ok=nullptr) const
Returns the variant as an unsigned long long int if the variant has type() \l QMetaType::ULongLong,...
QStringList toStringList() const
Returns the variant as a QStringList if the variant has userType() \l QMetaType::QStringList,...
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
double e
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QCborTag
Definition qcborcommon.h:30
#define Q_FALLTHROUGH()
#define Q_NEVER_INLINE
AudioChannelLayoutTag tag
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QString simpleTypeString(QCborValue::Type t)
Definition qjsoncbor.cpp:32
static QString makeString(const QCborContainerPrivate *d, qsizetype idx, ConversionMode mode=ConversionMode::FromRaw)
static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx, ConversionMode mode=ConversionMode::FromRaw)
static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QCborTag encoding)
Definition qjsoncbor.cpp:44
ConversionMode
Definition qjsoncbor.cpp:25
static QJsonArray convertToJsonArray(QCborContainerPrivate *d, ConversionMode mode=ConversionMode::FromRaw)
static QJsonValue convertExtendedTypeToJson(QCborContainerPrivate *d)
static QJsonObject convertToJsonObject(QCborContainerPrivate *d, ConversionMode mode=ConversionMode::FromRaw)
static QJsonValue fpToJson(double v)
Definition qjsoncbor.cpp:27
static QString encodeTag(const QCborContainerPrivate *d)
Definition qjsoncbor.cpp:96
static QString maybeEncodeTag(const QCborContainerPrivate *d)
Definition qjsoncbor.cpp:64
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
@ Invalid
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
Definition qnumeric_p.h:111
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLenum mode
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
GLhandleARB obj
[2]
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define QStringLiteral(str)
Tag
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
QList< QPair< QString, QString > > Map
static double toDouble(Value v)
QList< int > list
[14]
QByteArray ba
[0]
QVariant variant
[1]
value toMap().value(key)
[3]
value isSimpleType(QCborSimpleType(12))
[1]
char * toString(const MyType &t)
[31]