Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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// Qt-Security score:critical reason:data-parser
4
5#include "qcborvalue.h"
6#include "qcborvalue_p.h"
7
8#include "qcborarray.h"
9#include "qcbormap.h"
10
11#include "qjsonarray.h"
12#include "qjsonobject.h"
13#include "qjsondocument.h"
14#include "qjson_p.h"
15
16#include <qmap.h>
17#include <qhash.h>
18
19#include <private/qnumeric_p.h>
20#include <quuid.h>
21
23
24using namespace QtCbor;
25
27
28static QJsonValue fpToJson(double v)
29{
30 return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
31}
32
33static QString simpleTypeString(QCborValue::Type t)
34{
35 int simpleType = t - QCborValue::SimpleType;
36 if (unsigned(simpleType) < 0x100)
37 return QString::fromLatin1("simple(%1)").arg(simpleType);
38
39 // if we got here, we got an unknown type
40 qWarning("QCborValue: found unknown type 0x%x", t);
41 return QString();
42
43}
44
45static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QCborTag encoding)
46{
47 const ByteData *b = d->byteData(idx);
48 if (!b)
49 return QString();
50
51 QByteArray data = QByteArray::fromRawData(b->byte(), b->len);
52 if (encoding == QCborKnownTags::ExpectedBase16)
53 data = data.toHex();
54 else if (encoding == QCborKnownTags::ExpectedBase64)
55 data = data.toBase64();
56 else
57 data = data.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
58
59 return QString::fromLatin1(data);
60}
61
62static QString makeString(const QCborContainerPrivate *d, qsizetype idx,
64
66{
67 qint64 tag = d->elements.at(0).value;
68 const Element &e = d->elements.at(1);
69
70 switch (tag) {
71 case qint64(QCborKnownTags::DateTimeString):
72 case qint64(QCborKnownTags::Url):
73 if (e.type == QCborValue::String)
74 return makeString(d, 1);
75 break;
76
77 case qint64(QCborKnownTags::ExpectedBase64url):
78 case qint64(QCborKnownTags::ExpectedBase64):
79 case qint64(QCborKnownTags::ExpectedBase16):
80 if (e.type == QCborValue::ByteArray)
81 return encodeByteArray(d, 1, QCborTag(tag));
82 break;
83
84 case qint64(QCborKnownTags::Uuid):
85#ifndef QT_BOOTSTRAPPED
86 if (const ByteData *b = d->byteData(e); e.type == QCborValue::ByteArray && b
87 && b->len == sizeof(QUuid))
88 return QUuid::fromRfc4122(b->asByteArrayView()).toString(QUuid::WithoutBraces);
89#endif
90 break;
91 }
92
93 // don't know what to do, bail out
94 return QString();
95}
96
98{
99 QString s;
100 if (!d || d->elements.size() != 2)
101 return s; // invalid (incomplete?) tag state
102
103 s = maybeEncodeTag(d);
104 if (s.isNull()) {
105 // conversion failed, ignore the tag and convert the tagged value
106 s = makeString(d, 1);
107 }
108 return s;
109}
110
111Q_NEVER_INLINE static QString makeString(const QCborContainerPrivate *d, qsizetype idx,
112 ConversionMode mode)
113{
114 const auto &e = d->elements.at(idx);
115
116 switch (e.type) {
117 case QCborValue::Integer:
118 return QString::number(qint64(e.value));
119
120 case QCborValue::Double:
121 return QString::number(e.fpvalue());
122
123 case QCborValue::ByteArray:
124 return mode == ConversionMode::FromVariantToJson
125 ? d->stringAt(idx)
126 : encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
127
128 case QCborValue::String:
129 return d->stringAt(idx);
130
131 case QCborValue::Array:
132 case QCborValue::Map:
133#if defined(QT_BOOTSTRAPPED)
134 Q_UNREACHABLE_RETURN(QString());
135#else
136 return d->valueAt(idx).toDiagnosticNotation(QCborValue::Compact);
137#endif
138
139 case QCborValue::SimpleType:
140 break;
141
142 case QCborValue::False:
143 return QStringLiteral("false");
144
145 case QCborValue::True:
146 return QStringLiteral("true");
147
148 case QCborValue::Null:
149 return QStringLiteral("null");
150
151 case QCborValue::Undefined:
152 return QStringLiteral("undefined");
153
154 case QCborValue::Invalid:
155 return QString();
156
157 case QCborValue::Tag:
158 case QCborValue::DateTime:
159 case QCborValue::Url:
160 case QCborValue::RegularExpression:
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
169static QJsonValue convertToJson(QCborContainerPrivate *d, qsizetype idx,
171
173{
174 qint64 tag = d->elements.at(0).value;
175
176 switch (tag) {
177 case qint64(QCborKnownTags::Url): {
178#ifdef QT_BOOTSTRAPPED
179 break;
180#else
181 // use the fully-encoded URL form
182 Element e = d->elements.at(1);
183 const ByteData *bd = d->byteData(e);
184 if (e.type == QCborValue::String) {
185 if (!bd)
186 return QString();
187 return QUrl::fromEncoded(bd->asByteArrayView()).toString(QUrl::FullyEncoded);
188 }
189 Q_FALLTHROUGH();
190#endif
191 }
192
193 case qint64(QCborKnownTags::DateTimeString):
194 case qint64(QCborKnownTags::ExpectedBase64url):
195 case qint64(QCborKnownTags::ExpectedBase64):
196 case qint64(QCborKnownTags::ExpectedBase16):
197 case qint64(QCborKnownTags::Uuid): {
198 // use the string conversion
199 QString s = maybeEncodeTag(d);
200 if (!s.isNull())
201 return s;
202 }
203 }
204
205 // for all other tags, ignore it and return the converted tagged item
206 return convertToJson(d, 1);
207}
208
209// We need to do this because sub-objects may need conversion.
212{
213 QJsonArray a;
214 if (d) {
215 for (qsizetype idx = 0; idx < d->elements.size(); ++idx)
216 a.append(convertToJson(d, idx, mode));
217 }
218 return a;
219}
220
221// We need to do this because the keys need to be sorted and converted to strings
222// and sub-objects may need recursive conversion.
225{
226 QJsonObject o;
227 if (d) {
228 for (qsizetype idx = 0; idx < d->elements.size(); idx += 2)
229 o.insert(makeString(d, idx), convertToJson(d, idx + 1, mode));
230 }
231 return o;
232}
233
234QJsonValue convertToJson(QCborContainerPrivate *d, qsizetype idx, ConversionMode mode)
235{
236 // encoding the container itself
237 if (idx == -QCborValue::Array)
238 return convertToJsonArray(d, mode);
239 if (idx == -QCborValue::Map)
240 return convertToJsonObject(d, mode);
241 if (idx < 0) {
242 // tag-like type
243 if (!d || d->elements.size() != 2)
244 return QJsonValue::Undefined; // invalid state
245 return convertExtendedTypeToJson(d);
246 }
247
248 // an element in the container
249 const auto &e = d->elements.at(idx);
250 switch (e.type) {
251 case QCborValue::Integer:
252 return QJsonValue(e.value);
253 case QCborValue::ByteArray:
255 const auto value = makeString(d, idx, mode);
256 return value.isEmpty() ? QJsonValue() : QJsonPrivate::Value::fromTrustedCbor(value);
257 }
258 break;
259 case QCborValue::RegularExpression:
261 return QJsonValue();
262 break;
263 case QCborValue::String:
264 case QCborValue::SimpleType:
265 // make string
266 break;
267
268 case QCborValue::Array:
269 case QCborValue::Map:
270 case QCborValue::Tag:
271 case QCborValue::DateTime:
272 case QCborValue::Url:
273 case QCborValue::Uuid:
274 // recurse
275 return convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type,
276 mode);
277
278 case QCborValue::Null:
279 case QCborValue::Undefined:
280 case QCborValue::Invalid:
281 return QJsonValue();
282
283 case QCborValue::False:
284 return false;
285
286 case QCborValue::True:
287 return true;
288
289 case QCborValue::Double:
290 return fpToJson(e.fpvalue());
291 }
292
293 return QJsonPrivate::Value::fromTrustedCbor(makeString(d, idx, mode));
294}
295
296/*!
297 Converts this QCborValue object to an equivalent representation in JSON and
298 returns it as a QJsonValue.
299
300 Please note that CBOR contains a richer and wider type set than JSON, so
301 some information may be lost in this conversion. The following table
302 compares CBOR types to JSON types and indicates whether information may be
303 lost or not.
304
305 \table
306 \header \li CBOR Type \li JSON Type \li Comments
307 \row \li Bool \li Bool \li No data loss possible
308 \row \li Double \li Number \li Infinities and NaN will be converted to Null;
309 no data loss for other values
310 \row \li Integer \li Number \li Data loss possible in the conversion if the
311 integer is larger than 2\sup{53} or smaller
312 than -2\sup{53}.
313 \row \li Null \li Null \li No data loss possible
314 \row \li Undefined \li Null \li Type information lost
315 \row \li String \li String \li No data loss possible
316 \row \li Byte Array \li String \li Converted to a lossless encoding like Base64url,
317 but the distinction between strings and byte
318 arrays is lost
319 \row \li Other simple types \li String \li Type information lost
320 \row \li Array \li Array \li Conversion applies to each contained value
321 \row \li Map \li Object \li Keys are converted to string; values converted
322 according to this table
323 \row \li Tags and extended types \li Special \li The tag number itself is lost and the tagged
324 value is converted to JSON
325 \endtable
326
327 For information on the conversion of CBOR map keys to string, see
328 QCborMap::toJsonObject().
329
330 If this QCborValue contains the undefined value, this function will return
331 an undefined QJsonValue too. Note that JSON does not support undefined
332 values and undefined QJsonValues are an extension to the specification.
333 They cannot be held in a QJsonArray or QJsonObject, but can be returned
334 from functions to indicate a failure. For all other intents and purposes,
335 they are the same as null.
336
337 \section3 Special handling of tags and extended types
338
339 Some tags are handled specially and change the transformation of the tagged
340 value from CBOR to JSON. The following table lists those special cases:
341
342 \table
343 \header \li Tag \li CBOR type \li Transformation
344 \row \li ExpectedBase64url \li Byte array \li Encodes the byte array as Base64url
345 \row \li ExpectedBase64 \li Byte array \li Encodes the byte array as Base64
346 \row \li ExpectedBase16 \li Byte array \li Encodes the byte array as hex
347 \row \li Url \li Url and String \li Uses QUrl::toEncoded() to normalize the
348 encoding to the URL's fully encoded format
349 \row \li Uuid \li Uuid and Byte array \li Uses QUuid::toString() to create
350 the string representation
351 \endtable
352
353 \sa fromJsonValue(), toVariant(), QCborArray::toJsonArray(), QCborMap::toJsonObject()
354 */
355QJsonValue QCborValue::toJsonValue() const
356{
357 if (container)
358 return convertToJson(container, n < 0 ? -type() : n);
359
360 // simple values
361 switch (type()) {
362 case False:
363 return false;
364
365 case Integer:
366 return QJsonPrivate::Value::fromTrustedCbor(*this);
367
368 case True:
369 return true;
370
371 case Null:
372 case Undefined:
373 case Invalid:
374 return QJsonValue();
375
376 case Double:
377 return fpToJson(fp_helper());
378
379 case SimpleType:
380 break;
381
382 case ByteArray:
383 case String:
384 // empty strings
385 return QJsonValue::String;
386
387 case Array:
388 // empty array
389 return QJsonArray();
390
391 case Map:
392 // empty map
393 return QJsonObject();
394
395 case Tag:
396 case DateTime:
397 case Url:
398 case RegularExpression:
399 case Uuid:
400 // Reachable, but invalid in Json
401 return QJsonValue::Undefined;
402 }
403
404 return QJsonPrivate::Value::fromTrustedCbor(simpleTypeString(type()));
405}
406
407#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
408QJsonValue QCborValueRef::toJsonValue() const
409{
410 return convertToJson(d, i);
411}
412#endif
413
414/*!
415 Recursively converts every \l QCborValue element in this array to JSON
416 using QCborValue::toJsonValue() and returns the corresponding QJsonArray
417 composed of those elements.
418
419 Please note that CBOR contains a richer and wider type set than JSON, so
420 some information may be lost in this conversion. For more details on what
421 conversions are applied, see QCborValue::toJsonValue().
422
423 \sa fromJsonArray(), QCborValue::toJsonValue(), QCborMap::toJsonObject(), toVariantList()
424 */
425QJsonArray QCborArray::toJsonArray() const
426{
427 return convertToJsonArray(d.data());
428}
429
430#ifndef QT_NO_VARIANT
432{
433 const auto cborArray = QCborArray::fromVariantList(list);
434 return convertToJsonArray(cborArray.d.data(), ConversionMode::FromVariantToJson);
435}
436#endif // !QT_NO_VARIANT
437
438/*!
439 Recursively converts every \l QCborValue value in this map to JSON using
440 QCborValue::toJsonValue() and creates a string key for all keys that aren't
441 strings, then returns the corresponding QJsonObject composed of those
442 associations.
443
444 Please note that CBOR contains a richer and wider type set than JSON, so
445 some information may be lost in this conversion. For more details on what
446 conversions are applied, see QCborValue::toJsonValue().
447
448 \section3 Map key conversion to string
449
450 JSON objects are defined as having string keys, unlike CBOR, so the
451 conversion of a QCborMap to QJsonObject will imply a step of
452 "stringification" of the key values. The conversion will use the special
453 handling of tags and extended types from above and will also convert the
454 rest of the types as follows:
455
456 \table
457 \header \li Type \li Transformation
458 \row \li Bool \li "true" and "false"
459 \row \li Null \li "null"
460 \row \li Undefined \li "undefined"
461 \row \li Integer \li The decimal string form of the number
462 \row \li Double \li The decimal string form of the number
463 \row \li Byte array \li Unless tagged differently (see above), encoded as
464 Base64url
465 \row \li Array \li Replaced by the compact form of its
466 \l{QCborValue::toDiagnosticNotation()}{Diagnostic notation}
467 \row \li Map \li Replaced by the compact form of its
468 \l{QCborValue::toDiagnosticNotation()}{Diagnostic notation}
469 \row \li Tags and extended types \li Tag number is dropped and the tagged value is converted
470 to string
471 \endtable
472
473 \sa fromJsonObject(), QCborValue::toJsonValue(), QCborArray::toJsonArray(), toVariantMap()
474 */
475QJsonObject QCborMap::toJsonObject() const
476{
477 return convertToJsonObject(d.data());
478}
479
480#ifndef QT_NO_VARIANT
481QJsonObject QJsonPrivate::Variant::toJsonObject(const QVariantMap &map)
482{
483 const auto cborMap = QCborMap::fromVariantMap(map);
484 return convertToJsonObject(cborMap.d.data(), ConversionMode::FromVariantToJson);
485}
486
487/*!
488 Converts this value to a native Qt type and returns the corresponding QVariant.
489
490 The following table lists the mapping performed between \l{Type}{QCborValue
491 types} and \l{QMetaType::Type}{Qt meta types}.
492
493 \table
494 \header \li CBOR Type \li Qt or C++ type \li Notes
495 \row \li Integer \li \l qint64 \li
496 \row \li Double \li \c double \li
497 \row \li Bool \li \c bool \li
498 \row \li Null \li \c std::nullptr_t \li
499 \row \li Undefined \li no type (QVariant()) \li
500 \row \li Byte array \li \l QByteArray \li
501 \row \li String \li \l QString \li
502 \row \li Array \li \l QVariantList \li Recursively converts all values
503 \row \li Map \li \l QVariantMap \li Key types are "stringified"
504 \row \li Other simple types \li \l QCborSimpleType \li
505 \row \li DateTime \li \l QDateTime \li
506 \row \li Url \li \l QUrl \li
507 \row \li RegularExpression \li \l QRegularExpression \li
508 \row \li Uuid \li \l QUuid \li
509 \row \li Other tags \li Special \li The tag is ignored and the tagged
510 value is converted using this
511 function
512 \endtable
513
514 Note that values in both CBOR Maps and Arrays are converted recursively
515 using this function too and placed in QVariantMap and QVariantList instead.
516 You will not find QCborMap and QCborArray stored inside the QVariants.
517
518 QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
519 to QVariantMap will imply a step of "stringification" of the key values.
520 See QCborMap::toJsonObject() for details.
521
522 \sa fromVariant(), toJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap()
523 */
524QVariant QCborValue::toVariant() const
525{
526 switch (type()) {
527 case Integer:
528 return toInteger();
529
530 case Double:
531 return toDouble();
532
533 case SimpleType:
534 break;
535
536 case False:
537 case True:
538 return isTrue();
539
540 case Null:
541 return QVariant::fromValue(nullptr);
542
543 case Undefined:
544 return QVariant();
545
546 case ByteArray:
547 return toByteArray();
548
549 case String:
550 return toString();
551
552 case Array:
553 return toArray().toVariantList();
554
555 case Map:
556 return toMap().toVariantMap();
557
558 case Tag:
559 // ignore tags
560 return taggedValue().toVariant();
561
562#if QT_CONFIG(datestring)
563 case DateTime:
564 return toDateTime();
565#endif
566
567#ifndef QT_BOOTSTRAPPED
568 case Url:
569 return toUrl();
570
571# if QT_CONFIG(regularexpression)
572 case RegularExpression:
573 return toRegularExpression();
574# endif
575
576 case Uuid:
577 return toUuid();
578#endif
579
580 case Invalid:
581 return QVariant();
582
583 default:
584 break;
585 }
586
587 if (isSimpleType())
588 return QVariant::fromValue(toSimpleType());
589
590 Q_UNREACHABLE_RETURN(QVariant());
591}
592#endif // !QT_NO_VARIANT
593
594/*!
595 Converts the JSON value contained in \a v into its corresponding CBOR value
596 and returns it. There is no data loss in converting from JSON to CBOR, as
597 the CBOR type set is richer than JSON's. Additionally, values converted to
598 CBOR using this function can be converted back to JSON using toJsonValue()
599 with no data loss.
600
601 The following table lists the mapping of JSON types to CBOR types:
602
603 \table
604 \header \li JSON Type \li CBOR Type
605 \row \li Bool \li Bool
606 \row \li Number \li Integer (if the number has no fraction and is in the \l qint64
607 range) or Double
608 \row \li String \li String
609 \row \li Array \li Array
610 \row \li Object \li Map
611 \row \li Null \li Null
612 \endtable
613
614 \l QJsonValue can also be undefined, indicating a previous operation that
615 failed to complete (for example, searching for a key not present in an
616 object). Undefined values are not JSON types and may not appear in JSON
617 arrays and objects, but this function does return the QCborValue undefined
618 value if the corresponding QJsonValue is undefined.
619
620 \sa toJsonValue(), fromVariant(), QCborArray::fromJsonArray(), QCborMap::fromJsonObject()
621 */
622QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
623{
624 switch (v.type()) {
625 case QJsonValue::Bool:
626 return v.toBool();
627 case QJsonValue::Double: {
628 if (v.value.t == Integer)
629 return v.toInteger();
630 return v.toDouble();
631 }
632 case QJsonValue::String:
633 return v.toString();
634 case QJsonValue::Array:
635 return QCborArray::fromJsonArray(v.toArray());
636 case QJsonValue::Object:
637 return QCborMap::fromJsonObject(v.toObject());
638 case QJsonValue::Null:
639 return nullptr;
640 case QJsonValue::Undefined:
641 break;
642 }
643 return QCborValue();
644}
645
646#ifndef QT_NO_VARIANT
647static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
648{
649 // Handle strings and byte arrays directly, to avoid creating a temporary
650 // dummy container to hold their data.
651 int type = variant.metaType().id();
652 if (type == QMetaType::QString) {
653 d->append(variant.toString());
654 } else if (type == QMetaType::QByteArray) {
655 QByteArray ba = variant.toByteArray();
656 d->appendByteData(ba.constData(), ba.size(), QCborValue::ByteArray);
657 } else {
658 // For everything else, use the function below.
659 d->append(QCborValue::fromVariant(variant));
660 }
661}
662
663/*!
664 Converts the QVariant \a variant into QCborValue and returns it.
665
666 QVariants may contain a large list of different meta types, many of which
667 have no corresponding representation in CBOR. That includes all
668 user-defined meta types. When preparing transmission using CBOR, it is
669 suggested to encode carefully each value to prevent loss of representation.
670
671 The following table lists the conversion this function will apply:
672
673 \table
674 \header \li Qt (C++) type \li CBOR type
675 \row \li invalid (QVariant()) \li Undefined
676 \row \li \c bool \li Bool
677 \row \li \c std::nullptr_t \li Null
678 \row \li \c short, \c ushort, \c int, \c uint, \l qint64 \li Integer
679 \row \li \l quint64 \li Integer, or Double if outside the range of qint64
680 \row \li \c float, \c double \li Double
681 \row \li \l QByteArray \li ByteArray
682 \row \li \l QDateTime \li DateTime
683 \row \li \l QCborSimpleType \li Simple type
684 \row \li \l QJsonArray \li Array, converted using QCborArray::formJsonArray()
685 \row \li \l QJsonDocument \li Array or Map
686 \row \li \l QJsonObject \li Map, converted using QCborMap::fromJsonObject()
687 \row \li \l QJsonValue \li converted using fromJsonValue()
688 \row \li \l QRegularExpression \li RegularExpression
689 \row \li \l QString \li String
690 \row \li \l QStringList \li Array
691 \row \li \l QVariantHash \li Map
692 \row \li \l QVariantList \li Array
693 \row \li \l QVariantMap \li Map
694 \row \li \l QUrl \li Url
695 \row \li \l QUuid \li Uuid
696 \endtable
697
698 If QVariant::isNull() returns true, a null QCborValue is returned or
699 inserted into the list or object, regardless of the type carried by
700 QVariant. Note the behavior change in Qt 6.0 affecting QVariant::isNull()
701 also affects this function.
702
703 For other types not listed above, a conversion to string will be attempted,
704 usually but not always by calling QVariant::toString(). If the conversion
705 fails the value is replaced by an Undefined CBOR value. Note that
706 QVariant::toString() is also lossy for the majority of types.
707
708 Please note that the conversions via QVariant::toString() are subject to
709 change at any time. Both QVariant and QCborValue may be extended in the
710 future to support more types, which will result in a change in how this
711 function performs conversions.
712
713 \sa toVariant(), fromJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap(), QJsonValue::fromVariant()
714 */
715QCborValue QCborValue::fromVariant(const QVariant &variant)
716{
717 switch (variant.metaType().id()) {
718 case QMetaType::UnknownType:
719 return {};
720 case QMetaType::Nullptr:
721 return nullptr;
722 case QMetaType::Bool:
723 return variant.toBool();
724 case QMetaType::Short:
725 case QMetaType::UShort:
726 case QMetaType::Int:
727 case QMetaType::LongLong:
728 case QMetaType::Long:
729 case QMetaType::UInt:
730 return variant.toLongLong();
731 case QMetaType::ULong:
732 case QMetaType::ULongLong:
733 if (variant.toULongLong() <= static_cast<uint64_t>(std::numeric_limits<qint64>::max()))
734 return variant.toLongLong();
735 Q_FALLTHROUGH();
736 case QMetaType::Float16:
737 case QMetaType::Float:
738 case QMetaType::Double:
739 return variant.toDouble();
740 case QMetaType::QString:
741 return variant.toString();
742 case QMetaType::QStringList:
743 return QCborArray::fromStringList(variant.toStringList());
744 case QMetaType::QByteArray:
745 return variant.toByteArray();
746#if QT_CONFIG(datestring)
747 case QMetaType::QDateTime:
748 return QCborValue(variant.toDateTime());
749#endif
750#ifndef QT_BOOTSTRAPPED
751 case QMetaType::QUrl:
752 return QCborValue(variant.toUrl());
753 case QMetaType::QUuid:
754 return QCborValue(variant.toUuid());
755#endif
756 case QMetaType::QVariantList:
757 return QCborArray::fromVariantList(variant.toList());
758 case QMetaType::QVariantMap:
759 return QCborMap::fromVariantMap(variant.toMap());
760 case QMetaType::QVariantHash:
761 return QCborMap::fromVariantHash(variant.toHash());
762#ifndef QT_BOOTSTRAPPED
763#if QT_CONFIG(regularexpression)
764 case QMetaType::QRegularExpression:
765 return QCborValue(variant.toRegularExpression());
766#endif
767 case QMetaType::QJsonValue:
768 return fromJsonValue(variant.toJsonValue());
769 case QMetaType::QJsonObject:
770 return QCborMap::fromJsonObject(variant.toJsonObject());
771 case QMetaType::QJsonArray:
772 return QCborArray::fromJsonArray(variant.toJsonArray());
773 case QMetaType::QJsonDocument: {
774 QJsonDocument doc = variant.toJsonDocument();
775 if (doc.isArray())
776 return QCborArray::fromJsonArray(doc.array());
777 return QCborMap::fromJsonObject(doc.object());
778 }
779 case QMetaType::QCborValue:
780 return qvariant_cast<QCborValue>(variant);
781 case QMetaType::QCborArray:
782 return qvariant_cast<QCborArray>(variant);
783 case QMetaType::QCborMap:
784 return qvariant_cast<QCborMap>(variant);
785 case QMetaType::QCborSimpleType:
786 return qvariant_cast<QCborSimpleType>(variant);
787#endif
788 default:
789 break;
790 }
791
792 if (variant.isNull())
793 return QCborValue(nullptr);
794
795 QString string = variant.toString();
796 if (string.isNull())
797 return QCborValue(); // undefined
798 return string;
799}
800
801/*!
802 Recursively converts each \l QCborValue in this array using
803 QCborValue::toVariant() and returns the QVariantList composed of the
804 converted items.
805
806 Conversion to \l QVariant is not completely lossless. Please see the
807 documentation in QCborValue::toVariant() for more information.
808
809 \sa fromVariantList(), fromStringList(), toJsonArray(),
810 QCborValue::toVariant(), QCborMap::toVariantMap()
811 */
812QVariantList QCborArray::toVariantList() const
813{
814 QVariantList retval;
815 retval.reserve(size());
816 for (qsizetype i = 0; i < size(); ++i)
817 retval.append(d->valueAt(i).toVariant());
818 return retval;
819}
820
821/*!
822 Returns a QCborArray containing all the strings found in the \a list list.
823
824 \sa fromVariantList(), fromJsonArray()
825 */
826QCborArray QCborArray::fromStringList(const QStringList &list)
827{
828 QCborArray a;
829 a.detach(list.size());
830 for (const QString &s : list)
831 a.d->append(s);
832 return a;
833}
834
835/*!
836 Converts all the items in the \a list to CBOR using
837 QCborValue::fromVariant() and returns the array composed of those elements.
838
839 Conversion from \l QVariant is not completely lossless. Please see the
840 documentation in QCborValue::fromVariant() for more information.
841
842 \sa toVariantList(), fromStringList(), fromJsonArray(), QCborMap::fromVariantMap()
843 */
844QCborArray QCborArray::fromVariantList(const QVariantList &list)
845{
846 QCborArray a;
847 a.detach(list.size());
848 for (const QVariant &v : list)
849 appendVariant(a.d.data(), v);
850 return a;
851}
852#endif // !QT_NO_VARIANT
853
854/*!
855 Converts all JSON items found in the \a array array to CBOR using
856 QCborValue::fromJson(), and returns the CBOR array composed of those
857 elements.
858
859 This conversion is lossless, as the CBOR type system is a superset of
860 JSON's. Moreover, the array returned by this function can be converted back
861 to the original \a array by using toJsonArray().
862
863 \sa toJsonArray(), toVariantList(), QCborValue::fromJsonValue(), QCborMap::fromJsonObject()
864 */
865QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
866{
867 QCborArray result;
868 result.d = array.a;
869 return result;
870}
871
872/*!
873 \overload
874 \since 6.3
875 */
876QCborArray QCborArray::fromJsonArray(QJsonArray &&array) noexcept
877{
878 QCborArray result;
879 result.d = std::exchange(array.a, {});
880 return result;
881
882}
883
884#ifndef QT_NO_VARIANT
885/*!
886 Converts the CBOR values to QVariant using QCborValue::toVariant() and
887 "stringifies" all the CBOR keys in this map, returning the QVariantMap that
888 results from that association list.
889
890 QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
891 to QVariantMap will imply a step of "stringification" of the key values.
892 See QCborMap::toJsonObject() for details.
893
894 In addition, the conversion to \l QVariant is not completely lossless.
895 Please see the documentation in QCborValue::toVariant() for more
896 information.
897
898 \sa fromVariantMap(), toVariantHash(), toJsonObject(), QCborValue::toVariant(),
899 QCborArray::toVariantList()
900 */
901QVariantMap QCborMap::toVariantMap() const
902{
903 QVariantMap retval;
904 for (qsizetype i = 0; i < 2 * size(); i += 2)
905 retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
906 return retval;
907}
908
909/*!
910 Converts the CBOR values to QVariant using QCborValue::toVariant() and
911 "stringifies" all the CBOR keys in this map, returning the QVariantHash that
912 results from that association list.
913
914 QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
915 to QVariantMap will imply a step of "stringification" of the key values.
916 See QCborMap::toJsonObject() for details.
917
918 In addition, the conversion to \l QVariant is not completely lossless.
919 Please see the documentation in QCborValue::toVariant() for more
920 information.
921
922 \sa fromVariantHash(), toVariantMap(), toJsonObject(), QCborValue::toVariant(),
923 QCborArray::toVariantList()
924 */
925QVariantHash QCborMap::toVariantHash() const
926{
927 QVariantHash retval;
928 retval.reserve(size());
929 for (qsizetype i = 0; i < 2 * size(); i += 2)
930 retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
931 return retval;
932}
933
934/*!
935 Converts all the items in \a map to CBOR using QCborValue::fromVariant()
936 and returns the map composed of those elements.
937
938 Conversion from \l QVariant is not completely lossless. Please see the
939 documentation in QCborValue::fromVariant() for more information.
940
941 \sa toVariantMap(), fromVariantHash(), fromJsonObject(), QCborValue::fromVariant()
942 */
943QCborMap QCborMap::fromVariantMap(const QVariantMap &map)
944{
945 QCborMap m;
946 m.detach(map.size());
947 QCborContainerPrivate *d = m.d.data();
948
949 auto it = map.begin();
950 auto end = map.end();
951 for ( ; it != end; ++it) {
952 d->append(it.key());
953 appendVariant(d, it.value());
954 }
955 return m;
956}
957
958/*!
959 Converts all the items in \a hash to CBOR using QCborValue::fromVariant()
960 and returns the map composed of those elements.
961
962 Conversion from \l QVariant is not completely lossless. Please see the
963 documentation in QCborValue::fromVariant() for more information.
964
965 \sa toVariantHash(), fromVariantMap(), fromJsonObject(), QCborValue::fromVariant()
966 */
967QCborMap QCborMap::fromVariantHash(const QVariantHash &hash)
968{
969 QCborMap m;
970 m.detach(hash.size());
971 QCborContainerPrivate *d = m.d.data();
972
973 auto it = hash.begin();
974 auto end = hash.end();
975 for ( ; it != end; ++it) {
976 d->append(it.key());
977 appendVariant(d, it.value());
978 }
979 return m;
980}
981#endif // !QT_NO_VARIANT
982
983/*!
984 Converts all JSON items found in the \a obj object to CBOR using
985 QCborValue::fromJson(), and returns the map composed of those elements.
986
987 This conversion is lossless, as the CBOR type system is a superset of
988 JSON's. Moreover, the map returned by this function can be converted back
989 to the original \a obj by using toJsonObject().
990
991 \sa toJsonObject(), toVariantMap(), QCborValue::fromJsonValue(), QCborArray::fromJsonArray()
992 */
993QCborMap QCborMap::fromJsonObject(const QJsonObject &obj)
994{
995 QCborMap result;
996 result.d = obj.o;
997 return result;
998}
999
1000/*!
1001 \overload
1002 \since 6.3
1003 */
1004QCborMap QCborMap::fromJsonObject(QJsonObject &&obj) noexcept
1005{
1006 QCborMap result;
1007 result.d = std::exchange(obj.o, {});
1008 return result;
1009}
1010
1011QT_END_NAMESPACE
const QtCbor::ByteData * byteData(QtCbor::Element e) const
void append(QtCbor::Undefined)
static QJsonArray toJsonArray(const QVariantList &list)
Combined button and popup list for selecting options.
QList< QVariant > QVariantList
Definition qjsonarray.h:16
static QString simpleTypeString(QCborValue::Type t)
Definition qjsoncbor.cpp:33
static QString makeString(const QCborContainerPrivate *d, qsizetype idx, ConversionMode mode=ConversionMode::FromRaw)
static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QCborTag encoding)
Definition qjsoncbor.cpp:45
ConversionMode
Definition qjsoncbor.cpp:26
static QJsonValue convertToJson(QCborContainerPrivate *d, qsizetype idx, ConversionMode mode=ConversionMode::FromRaw)
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:28
static QString encodeTag(const QCborContainerPrivate *d)
Definition qjsoncbor.cpp:97
static QString maybeEncodeTag(const QCborContainerPrivate *d)
Definition qjsoncbor.cpp:65