11#if QT_CONFIG(cborstreamreader)
12#include "qcborstreamreader.h"
15#if QT_CONFIG(cborstreamwriter)
16#include "qcborstreamwriter.h"
19#include <QtCore/qdebug.h>
24#include <private/qnumeric_p.h>
25#include <private/qsimd_p.h>
31QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCborContainerPrivate)
34static constexpr quint64 MaxAcceptableMemoryUse = (
sizeof(
void*) == 4 ? 256 : 1024) * 1024 * 1024;
45Q_DECL_UNUSED
static constexpr quint64 MaximumPreallocatedElementCount =
46 MaxAcceptableMemoryUse / MaximumRecursionDepth /
sizeof(QtCbor::Element) - 1;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
205
206
207
208
209
210
211
212
213
214
215
216
217
218
221
222
223
224
225
226
227
228
229
232
233
234
235
236
237
238
241
242
243
244
245
246
247
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
347
348
349
350
351
352
353
356
357
358
359
360
361
362
363
364
365
368
369
370
371
372
373
374
375
376
377
378
379
382
383
384
385
386
387
388
389
390
391
392
393
396
397
398
399
400
401
402
403
404
405
406
407
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
437
438
439
440
441
442
443
444
445
448
449
450
451
454
455
456
457
458
459
462
463
464
465
466
467
470
471
472
475
476
477
478
479
480
481
482
483
486
487
488
489
490
491
492
495
496
497
498
499
500
501
504
505
506
507
508
509
510
513
514
515
516
517
518
519
522
523
524
525
526
527
528
531
532
533
534
535
536
537
538
539
540
541
542
545
546
547
548
549
550
551
552
555
556
557
558
559
560
561
562
565
566
567
568
569
570
571
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
593
594
595
596
597
598
599
600
601
602
603
604
605
606
609
610
611
612
613
614
615
618
619
620
621
622
623
624
625
626
627
628
629
632
633
634
635
636
637
638
641
642
643
644
645
646
647
650
651
652
653
654
655
656
659
660
661
662
663
664
665
666
669
670
671
672
673
674
675
678
679
680
681
682
683
684
685
686
689
690
691
692
693
694
695
696
697
698
699
700
701
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
724
725
726
727
728
729
730
731
732
735
736
737
738
739
740
741
744
745
746
747
748
749
750
751
752
770 qint64 tag = d->elements.at(0).value;
771 auto &e = d->elements[1];
774 auto replaceByteData = [&](
const char *buf, qsizetype len, Element::ValueFlags f) {
778 e.value = d->addByteData(buf, len);
782#if QT_CONFIG(datestring)
783 case qint64(QCborKnownTags::DateTimeString):
784 case qint64(QCborKnownTags::UnixTime_t): {
786 if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
787 e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
790 dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
791 }
else if (tag == qint64(QCborKnownTags::UnixTime_t)) {
794 if (e.type == QCborValue::Integer) {
795 ok = !qMulOverflow<1000>(e.value, &msecs);
796 }
else if (e.type == QCborValue::Double) {
797 ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs);
800 dt = QDateTime::fromMSecsSinceEpoch(msecs, QTimeZone::UTC);
804 if (QString dtString = dt.toString(Qt::ISODateWithMs); !dtString.isEmpty())
805 return setToExtendedDateTimeType(d, dtString);
810#ifndef QT_BOOTSTRAPPED
811 case qint64(QCborKnownTags::Url):
812 if (e.type == QCborValue::String) {
815 QUrl url(e.flags & Element::StringIsUtf16 ?
817 b->toUtf8String(), QUrl::StrictMode);
819 QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
820 replaceByteData(encoded, encoded.size(), {});
823 return QCborValue::Url;
828#if QT_CONFIG(regularexpression)
829 case quint64(QCborKnownTags::RegularExpression):
830 if (e.type == QCborValue::String) {
832 return QCborValue::RegularExpression;
837 case qint64(QCborKnownTags::Uuid):
838 if (e.type == QCborValue::ByteArray) {
840 char buf[
sizeof(QUuid)] = {};
842 memcpy(buf, b
->byte(), qMin(
sizeof(buf), size_t(b->len)));
843 replaceByteData(buf,
sizeof(buf), {});
845 return QCborValue::Uuid;
851 return QCborValue::Tag;
854#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
855static void writeDoubleToCbor(QCborStreamWriter &writer,
double d, QCborValue::EncodingOptions opt)
858 if (opt & QCborValue::UseFloat) {
859 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
860 return writer.append(std::numeric_limits<qfloat16>::quiet_NaN());
861 return writer.append(std::numeric_limits<
float>::quiet_NaN());
863 return writer.append(qt_qnan());
867 d = d > 0 ? qt_inf() : -qt_inf();
868 }
else if (opt & QCborValue::UseIntegers) {
870 if (convertDoubleTo(d, &i)) {
872 return writer.append(QCborNegativeInteger(i));
873 return writer.append(i);
877 if (opt & QCborValue::UseFloat) {
881 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
882 qfloat16 f16 = qfloat16(f);
884 return writer.append(f16);
887 return writer.append(f);
895static inline int typeOrder(QCborValue::Type e1, QCborValue::Type e2)
897 auto comparable = [](QCborValue::Type type) {
899 return QCborValue::Tag;
902 return comparable(e1) - comparable(e2);
919 for (
const Element &e : std::as_const(priv->elements)) {
921 if ((e.flags & Element::IsContainer) == 0)
923 if (e.container->ref.deref())
925 if (e.container->elements.isEmpty()) {
929 e.container->nextToDelete = pendingContainers;
930 pendingContainers = e.container;
936 appendNestedContainers(
this);
939 while (pendingContainers) {
941 pendingContainers = priv->nextToDelete;
944 priv->nextToDelete = toBeDeleted;
948 appendNestedContainers(priv);
952 while (toBeDeleted) {
954 toBeDeleted = priv->nextToDelete;
959 priv->elements = QList<
Element>();
967 if (usedData > data.size() / 2)
972 QByteArray::size_type newUsedData = 0;
975 for (
auto &e : elements) {
976 if (e.flags & Element::HasByteData) {
977 if (
const ByteData *b = byteData(e))
978 e.value = addByteDataImpl(newData, newUsedData, b->byte(), b->len);
982 usedData = newUsedData;
993 u->elements.reserve(reserved);
998 d->ref.storeRelaxed(0);
1000 for (
auto &e : std::as_const(d->elements)) {
1001 if (e.flags & Element::IsContainer)
1002 e.container->ref.ref();
1010 if (!d || d->ref.loadRelaxed() != 1)
1011 return clone(d, reserved);
1016
1017
1018
1019
1020
1021
1024 Q_ASSERT(index >= 0);
1025 d = detach(d, index + 1);
1027 qsizetype j = d->elements.size();
1045 if (Q_UNLIKELY(
this == value.container)) {
1046 Q_ASSERT(ref.loadRelaxed() >= 2);
1047 if (disp == MoveContainer)
1050 d->elements.detach();
1051 d->ref.storeRelaxed(1);
1054 e.container = value.container;
1056 e.container->ref.ref();
1059 e.type = value.type();
1063 e = value.container->elements.at(value.n);
1066 if (
const ByteData *b = value.container->byteData(value.n)) {
1067 const auto flags = e.flags;
1074 if (
this == value.container) {
1075 const QByteArray valueData = b->toByteArray();
1077 e.value = addByteData(valueData, valueData.size());
1080 e.value = addByteData(b->byte(), b->len);
1087 value.container->deref();
1096 qsizetype len = s.size();
1098 e.value = addByteData(
nullptr, len);
1099 e.type = QCborValue::String;
1103 char *ptr = data.data() + e.value +
sizeof(ByteData);
1104 uchar *l =
reinterpret_cast<uchar *>(ptr);
1105 qt_to_latin1_unchecked(l, s.utf16(), len);
1110 appendByteData(
reinterpret_cast<
const char *>(s.utf16()), s.size() * 2,
1111 QCborValue::String, QtCbor::Element::StringIsUtf16);
1122 if (b->len + qsizetype(
sizeof(*b)) < data.size() / 4) {
1124 container->appendByteData(b
->byte(), b->len, e.type, e.flags);
1125 usedData -= b->len + qsizetype(
sizeof(*b));
1129 container->data = data;
1130 container->elements.reserve(1);
1131 container->elements.append(e);
1134 return makeValue(e.type, 0, container);
1141 Q_ASSERT(ptr != end);
1147 const char16_t c = *ptr++;
1153 }
else if (!QChar::isHighSurrogate(c) || ptr == end) {
1156 return R{QChar::surrogateToUcs4(c, *ptr++), 4};
1164 len += nextUtf32Character(ptr, end).len;
1171 return lhs == rhs ? 0 : 1;
1180 const char16_t *src1 = lhs.utf16();
1181 const char16_t *src2 = rhs.utf16();
1182 const char16_t *end1 = src1 + lhs.size();
1183 const char16_t *end2 = src2 + rhs.size();
1187 auto r1 = nextUtf32Character(src1, end1);
1188 auto r2 = nextUtf32Character(src2, end2);
1191 diff =
int(r1.c) -
int(r2.c);
1192 }
while (src1 < end1 && src2 < end2 && diff == 0);
1195 len1 += stringLengthInUtf8(src1, end1);
1196 len2 += stringLengthInUtf8(src2, end2);
1199 return len1 < len2 ? -1 : 1;
1209 const qsizetype len1 = lhs.size();
1210 const auto src1 =
reinterpret_cast<
const uchar *>(lhs.data());
1211 const char16_t *src2 = rhs.utf16();
1212 const char16_t *
const end2 = src2 + rhs.size();
1221 char16_t uc = *src2++;
1222 int r = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, ptr, src2, end2);
1225 qptrdiff n = ptr - utf8;
1227 if (len1 - idx1 < n)
1229 diff = memcmp(src1 + idx1, utf8, n);
1231 }
while (diff == 0 && idx1 < len1 && src2 < end2);
1235 if ((idx1 == len1) != (src2 == end2)) {
1237 return idx1 == len1 ? -1 : 1;
1242 len2 += stringLengthInUtf8(src2, end2);
1245 return len1 < len2 ? -1 : 1;
1251 return -compareStringsInUtf8(rhs, lhs, mode);
1254QT_WARNING_DISABLE_MSVC(4146)
1259 Q_ASSERT(e1.type == e2.type);
1261 if (e1.type == QCborValue::Integer) {
1272 auto makeSortable = [](qint64 v) {
1273 quint64 u = quint64(v);
1275 return quint64(std::numeric_limits<qint64>::max()) + (-u);
1278 quint64 u1 = makeSortable(e1.value);
1279 quint64 u2 = makeSortable(e2.value);
1286 if (e1.type == QCborValue::Tag || e1.type == QCborValue::Double) {
1288 quint64 u1 = quint64(e1.value);
1289 quint64 u2 = quint64(e2.value);
1291 return u1 < u2 ? -1 : 1;
1304 int cmp = typeOrder(e1.type, e2.type);
1316 auto len1 = b1 ? b1->len : 0;
1317 auto len2 = b2 ? b2->len : 0;
1318 if (len1 == 0 || len2 == 0)
1319 return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
1329 if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16))
1330 return compareStringsInUtf8(b1->asStringView(), b2->asStringView(), mode);
1338 return memcmp(b1->byte(), b2->byte(), size_t(len1)) == 0 ? 0 : 1;
1340 return memcmp(b1->byte(), b2->byte(), size_t(len1));
1342 return len1 < len2 ? -1 : 1;
1346 if (e1.flags & Element::StringIsUtf16)
1347 return compareStringsInUtf8(b1->asStringView(), b2->asUtf8StringView(), mode);
1349 return compareStringsInUtf8(b1->asUtf8StringView(), b2->asStringView(), mode);
1358 auto len1 = c1 ? c1->elements.size() : 0;
1359 auto len2 = c2 ? c2->elements.size() : 0;
1362 return len1 < len2 ? -1 : 1;
1365 for (qsizetype i = 0; i < len1; ++i) {
1366 const Element &e1 = c1->elements.at(i);
1367 const Element &e2 = c2->elements.at(i);
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1407 const QCborValue &rhs)
noexcept
1409 Element e1 = QCborContainerPrivate::elementFromValue(lhs);
1410 Element e2 = QCborContainerPrivate::elementFromValue(rhs);
1411 return compareElementRecursive(lhs.container, e1, rhs.container, e2,
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539int QCborValue::compare(
const QCborValue &other)
const
1541 Element e1 = QCborContainerPrivate::elementFromValue(*
this);
1542 Element e2 = QCborContainerPrivate::elementFromValue(other);
1543 return compareElementRecursive(container, e1, other.container, e2, Comparison::ForOrdering);
1551int QCborArray::compare(
const QCborArray &other)
const noexcept
1553 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1556bool QCborArray::comparesEqual_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1558 if (typeOrder(QCborValue::Array, rhs.type()))
1560 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1564QCborArray::compareThreeWay_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1566 int c = typeOrder(QCborValue::Array, rhs.type());
1568 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1569 return Qt::compareThreeWay(c, 0);
1577int QCborMap::compare(
const QCborMap &other)
const noexcept
1579 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1582bool QCborMap::comparesEqual_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1584 if (typeOrder(QCborValue::Map, rhs.type()))
1586 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1590QCborMap::compareThreeWay_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1592 int c = typeOrder(QCborValue::Map, rhs.type());
1594 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1595 return Qt::compareThreeWay(c, 0);
1598#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
1599static void encodeToCbor(QCborStreamWriter &writer,
const QCborContainerPrivate *d, qsizetype idx,
1600 QCborValue::EncodingOptions opt)
1602 if (idx == -QCborValue::Array || idx == -QCborValue::Map) {
1603 bool isArray = (idx == -QCborValue::Array);
1604 qsizetype len = d ? d->elements.size() : 0;
1606 writer.startArray(quint64(len));
1608 writer.startMap(quint64(len) / 2);
1610 for (idx = 0; idx < len; ++idx)
1611 encodeToCbor(writer, d, idx, opt);
1617 }
else if (idx < 0) {
1618 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1619 if (d->elements.size() != 2) {
1621 qWarning(
"QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
1626 writer.append(QCborTag(d->elements.at(0).value));
1627 encodeToCbor(writer, d, 1, opt);
1629 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1631 auto e = d->elements.at(idx);
1632 const ByteData *b = d->byteData(idx);
1634 case QCborValue::Integer:
1635 return writer.append(qint64(e.value));
1637 case QCborValue::ByteArray:
1639 return writer.appendByteString(b->byte(), b->len);
1640 return writer.appendByteString(
"", 0);
1642 case QCborValue::String:
1644 if (e.flags & Element::StringIsUtf16)
1645 return writer.append(b->asStringView());
1646 return writer.appendTextString(b->byte(), b->len);
1648 return writer.append(QLatin1StringView());
1650 case QCborValue::Array:
1651 case QCborValue::Map:
1652 case QCborValue::Tag:
1654 return encodeToCbor(writer,
1655 e.flags & Element::IsContainer ? e.container :
nullptr,
1656 -qsizetype(e.type), opt);
1658 case QCborValue::SimpleType:
1659 case QCborValue::False:
1660 case QCborValue::True:
1661 case QCborValue::Null:
1662 case QCborValue::Undefined:
1665 case QCborValue::Double:
1666 return writeDoubleToCbor(writer, e.fpvalue(), opt);
1668 case QCborValue::Invalid:
1671 case QCborValue::DateTime:
1672 case QCborValue::Url:
1673 case QCborValue::RegularExpression:
1674 case QCborValue::Uuid:
1676 return encodeToCbor(writer, e.container, -QCborValue::Tag, opt);
1680 int simpleType = e.type - QCborValue::SimpleType;
1681 if (
unsigned(simpleType) < 0x100)
1682 return writer.append(QCborSimpleType(simpleType));
1685 qWarning(
"QCborValue: found unknown type 0x%x", e.type);
1690#if QT_CONFIG(cborstreamreader)
1692static_assert(
int(QCborValue::Integer) ==
int(QCborStreamReader::UnsignedInteger));
1693static_assert(
int(QCborValue::ByteArray) ==
int(QCborStreamReader::ByteArray));
1694static_assert(
int(QCborValue::String) ==
int(QCborStreamReader::String));
1695static_assert(
int(QCborValue::Array) ==
int(QCborStreamReader::Array));
1696static_assert(
int(QCborValue::Map) ==
int(QCborStreamReader::Map));
1697static_assert(
int(QCborValue::Tag) ==
int(QCborStreamReader::Tag));
1699static inline double integerOutOfRange(
const QCborStreamReader &reader)
1701 Q_ASSERT(reader.isInteger());
1702 if (reader.isUnsignedInteger()) {
1703 quint64 v = reader.toUnsignedInteger();
1707 quint64 v = quint64(reader.toNegativeInteger());
1708 if (qint64(v - 1) < 0)
1716static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
1720 switch (reader.type()) {
1721 case QCborStreamReader::UnsignedInteger:
1722 case QCborStreamReader::NegativeInteger:
1723 if (
double d = integerOutOfRange(reader)) {
1724 e.type = QCborValue::Double;
1725 qToUnaligned(d, &e.value);
1727 e.type = QCborValue::Integer;
1728 e.value = reader.toInteger();
1731 case QCborStreamReader::SimpleType:
1732 e.type = QCborValue::Type(quint8(reader.toSimpleType()) + 0x100);
1734 case QCborStreamReader::Float16:
1735 e.type = QCborValue::Double;
1736 qToUnaligned(
double(reader.toFloat16()), &e.value);
1738 case QCborStreamReader::Float:
1739 e.type = QCborValue::Double;
1740 qToUnaligned(
double(reader.toFloat()), &e.value);
1742 case QCborStreamReader::Double:
1743 e.type = QCborValue::Double;
1744 qToUnaligned(reader.toDouble(), &e.value);
1758static qsizetype clampedContainerLength(
const QCborStreamReader &reader)
1760 if (!reader.isLengthKnown())
1762 int mapShift = reader.isMap() ? 1 : 0;
1763 quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
1764 qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
1765 return len << mapShift;
1768static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1770 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1771 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1775 QCborContainerPrivate *d =
nullptr;
1778 QExplicitlySharedDataPointer u(
new QCborContainerPrivate);
1779 if (qsizetype len = clampedContainerLength(reader))
1780 u->elements.reserve(len);
1784 reader.enterContainer();
1785 if (reader.lastError() != QCborError::NoError) {
1786 d->elements.clear();
1790 while (reader.hasNext() && reader.lastError() == QCborError::NoError)
1791 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1793 if (reader.lastError() == QCborError::NoError)
1794 reader.leaveContainer();
1796 d->elements.squeeze();
1801static QCborValue taggedValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1803 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1804 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1805 return QCborValue::Invalid;
1808 auto d =
new QCborContainerPrivate;
1809 d->append(reader.toTag());
1812 if (reader.lastError() == QCborError::NoError) {
1814 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1817 QCborValue::Type type;
1818 if (reader.lastError() == QCborError::NoError) {
1820 type = convertToExtendedType(d);
1823 type = QCborValue::Invalid;
1827 return QCborContainerPrivate::makeValue(type, -1, d);
1831extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
1832inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error)
1834 qt_cbor_stream_set_error(reader.d.get(), error);
1837extern QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data);
1839void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
1841 if (reader.lastError() != QCborError::NoError)
1844 qsizetype rawlen = reader.currentStringChunkSize();
1845 QByteArray::size_type len = rawlen;
1848 if (len != rawlen) {
1850 setErrorInReader(reader, { QCborError::DataTooLarge });
1854 auto resetSize = qScopeGuard([
this, oldSize = data.size()] {
1855 data.resize(oldSize);
1856 if (oldSize < data.capacity() / 2)
1861 e.type = QCborValue::Type(reader.type());
1862 if (len || !reader.isLengthKnown()) {
1865 constexpr size_t EstimatedOverhead = 16;
1866 constexpr size_t MaxMemoryIncrement = 16384;
1867 size_t offset = data.size();
1870 offset +=
sizeof(QtCbor::ByteData) +
alignof(QtCbor::ByteData);
1871 offset &= ~(
alignof(QtCbor::ByteData) - 1);
1872 if (offset > size_t(QByteArray::maxSize())) {
1874 setErrorInReader(reader, { QCborError::DataTooLarge });
1879 size_t newCapacity = offset + len;
1880 if (size_t(len) > MaxMemoryIncrement - EstimatedOverhead) {
1883 newCapacity = offset + MaxMemoryIncrement - EstimatedOverhead;
1885 if (newCapacity > size_t(QByteArray::maxSize())) {
1887 newCapacity = QByteArray::maxSize();
1889 if (newCapacity > size_t(data.capacity()))
1890 data.reserve(newCapacity);
1891 data.resize(offset +
sizeof(QtCbor::ByteData));
1893 e.flags = Element::HasByteData;
1897 bool isAscii = (e.type == QCborValue::String);
1898 QCborStreamReader::StringResultCode status = qt_cbor_append_string_chunk(reader, &data);
1899 while (status == QCborStreamReader::Ok) {
1900 if (e.type == QCborValue::String && len) {
1902 auto utf8result = QUtf8::isValidUtf8(QByteArrayView(data).last(len));
1903 if (!utf8result.isValidUtf8) {
1904 setErrorInReader(reader, { QCborError::InvalidUtf8String });
1907 isAscii = isAscii && utf8result.isValidAscii;
1910 rawlen = reader.currentStringChunkSize();
1912 if (len == rawlen) {
1913 status = qt_cbor_append_string_chunk(reader, &data);
1916 setErrorInReader(reader, { QCborError::DataTooLarge });
1922 if (status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
1923 Q_ASSERT(data.isDetached());
1924 const char *ptr = data.constData() + e.value;
1925 auto b =
new (
const_cast<
char *>(ptr)) ByteData;
1926 b->len = data.size() - e.value -
int(
sizeof(*b));
1931 Q_ASSERT(e.type == QCborValue::String);
1932 e.flags |= Element::StringIsAscii;
1936 if (e.type == QCborValue::String) {
1937 if (Q_UNLIKELY(b->len > QString::maxSize())) {
1938 setErrorInReader(reader, { QCborError::DataTooLarge });
1944 if (status == QCborStreamReader::EndOfString) {
1946 resetSize.dismiss();
1950void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1952 QCborStreamReader::Type t = reader.type();
1954 case QCborStreamReader::UnsignedInteger:
1955 case QCborStreamReader::NegativeInteger:
1956 case QCborStreamReader::SimpleType:
1957 case QCborStreamReader::Float16:
1958 case QCborStreamReader::Float:
1959 case QCborStreamReader::Double:
1960 elements.append(decodeBasicValueFromCbor(reader));
1963 case QCborStreamReader::ByteArray:
1964 case QCborStreamReader::String:
1965 decodeStringFromCbor(reader);
1968 case QCborStreamReader::Array:
1969 case QCborStreamReader::Map:
1970 return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
1971 createContainerFromCbor(reader, remainingRecursionDepth),
1974 case QCborStreamReader::Tag:
1975 return append(taggedValueFromCbor(reader, remainingRecursionDepth));
1977 case QCborStreamReader::Invalid:
1984
1985
1986
1987
1988
1989QCborValue::QCborValue(
const QByteArray &ba)
1990 : n(0), container(
new QCborContainerPrivate), t(ByteArray)
1992 container->appendByteData(ba.constData(), ba.size(), t);
1993 container->ref.storeRelaxed(1);
1997
1998
1999
2000
2001
2002QCborValue::QCborValue(
const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
2005
2006
2007
2008
2009
2010QCborValue::QCborValue(QStringView s)
2011 : n(0), container(
new QCborContainerPrivate), t(String)
2013 container->append(s);
2014 container->ref.storeRelaxed(1);
2018
2019
2020
2021
2022
2023
2024
2025QCborValue::QCborValue(QLatin1StringView s)
2026 : n(0), container(
new QCborContainerPrivate), t(String)
2028 container->append(s);
2029 container->ref.storeRelaxed(1);
2033
2034
2035
2036
2037
2038
2039
2040
2041QCborValue::QCborValue(
const QCborArray &a)
2042 : n(-1), container(a.d.data()), t(Array)
2045 container->ref.ref();
2049
2050
2051
2052
2053
2054
2055
2056
2057QCborValue::QCborValue(
const QCborMap &m)
2058 : n(-1), container(m.d.data()), t(Map)
2061 container->ref.ref();
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074QCborValue::QCborValue(QCborTag tag,
const QCborValue &tv)
2075 : n(-1), container(
new QCborContainerPrivate), t(Tag)
2077 container->ref.storeRelaxed(1);
2078 container->append(tag);
2079 container->append(tv);
2080 t = convertToExtendedType(container);
2084
2085
2086QCborValue::QCborValue(
const QCborValue &other)
noexcept
2087 : n(other.n), container(other.container), t(other.t)
2090 container->ref.ref();
2093#if QT_CONFIG(datestring)
2094static QCborValue::Type setToExtendedDateTimeType(QCborContainerPrivate *d, QStringView text)
2098 d->elements.resize(0);
2099 d->elements.reserve(2);
2101 d->append(QCborTag(QCborKnownTags::DateTimeString));
2102 d->appendAsciiString(text);
2103 return text.isEmpty() ? QCborValue::Tag : QCborValue::DateTime;
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119QCborValue::QCborValue(
const QDateTime &dt)
2120 : n(-1), container(
new QCborContainerPrivate),
2121 t(setToExtendedDateTimeType(container, dt.toString(Qt::ISODateWithMs)))
2123 container->ref.storeRelaxed(1);
2127#ifndef QT_BOOTSTRAPPED
2129
2130
2131
2132
2133
2134
2135
2136
2137QCborValue::QCborValue(
const QUrl &url)
2138 : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
2142 container->elements[1].type = String;
2145#if QT_CONFIG(regularexpression)
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158QCborValue::QCborValue(
const QRegularExpression &rx)
2159 : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
2162 t = RegularExpression;
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176QCborValue::QCborValue(
const QUuid &uuid)
2177 : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
2185
2186
2187
2188
2189
2190
2191
2192
2193void QCborValue::adjustDefaultConstructedExtendedType()
2197 *
this = QCborValue(QCborTag(-1), QCborValue());
2202 *
this = QCborValue(QCborKnownTags::DateTimeString, QString());
2207 *
this = QCborValue(QCborKnownTags::Url, QString());
2209 case RegularExpression:
2212 *
this = QCborValue(QCborKnownTags::RegularExpression, QString());
2217 *
this = QCborValue(QCborKnownTags::Uuid, QByteArray(
sizeof(QUuid),
'\0'));
2238void QCborValue::dispose()
2244
2245
2246QCborValue &QCborValue::operator=(
const QCborValue &other)
noexcept
2249 assignContainer(container, other.container);
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264QCborTag QCborValue::tag(QCborTag defaultValue)
const
2266 return isTag() && container && container->elements.size() == 2 ?
2267 QCborTag(container->elements.at(0).value) : defaultValue;
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280QCborValue QCborValue::taggedValue(
const QCborValue &defaultValue)
const
2282 return isTag() && container && container->elements.size() == 2 ?
2283 container->valueAt(1) : defaultValue;
2287
2288
2289
2290
2291
2292
2293
2294
2295QByteArray QCborValue::toByteArray(
const QByteArray &defaultValue)
const
2297 if (!container || !isByteArray())
2298 return defaultValue;
2301 return container->byteArrayAt(n);
2305
2306
2307
2308
2309
2310
2311
2312
2313QString QCborValue::toString(
const QString &defaultValue)
const
2315 if (!container || !isString())
2316 return defaultValue;
2319 return container->stringAt(n);
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340QAnyStringView QCborValue::toStringView(QAnyStringView defaultValue)
const
2342 if (!container || !isString())
2343 return defaultValue;
2346 return container->anyStringViewAt(n);
2349#if QT_CONFIG(datestring)
2351
2352
2353
2354
2355
2356
2357
2358
2359QDateTime QCborValue::toDateTime(
const QDateTime &defaultValue)
const
2361 if (!container || !isDateTime() || container->elements.size() != 2)
2362 return defaultValue;
2365 const ByteData *byteData = container->byteData(1);
2367 return defaultValue;
2370 Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
2371 return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
2375#ifndef QT_BOOTSTRAPPED
2377
2378
2379
2380
2381
2382
2383
2384QUrl QCborValue::toUrl(
const QUrl &defaultValue)
const
2386 if (!container || !isUrl() || container->elements.size() != 2)
2387 return defaultValue;
2390 const ByteData *byteData = container->byteData(1);
2394 return QUrl::fromEncoded(byteData->asByteArrayView());
2397#if QT_CONFIG(regularexpression)
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408QRegularExpression QCborValue::toRegularExpression(
const QRegularExpression &defaultValue)
const
2410 if (!container || !isRegularExpression() || container->elements.size() != 2)
2411 return defaultValue;
2414 return QRegularExpression(container->stringAt(1));
2419
2420
2421
2422
2423
2424
2425
2426QUuid QCborValue::toUuid(
const QUuid &defaultValue)
const
2428 if (!container || !isUuid() || container->elements.size() != 2)
2429 return defaultValue;
2432 const ByteData *byteData = container->byteData(1);
2434 return defaultValue;
2436 return QUuid::fromRfc4122(byteData->asByteArrayView());
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466QCborArray QCborValue::toArray()
const
2468 return toArray(QCborArray());
2471QCborArray QCborValue::toArray(
const QCborArray &defaultValue)
const
2474 return defaultValue;
2475 QCborContainerPrivate *dd =
nullptr;
2476 Q_ASSERT(n == -1 || container ==
nullptr);
2480 return dd ? QCborArray(*dd) : QCborArray();
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509QCborMap QCborValue::toMap()
const
2511 return toMap(QCborMap());
2514QCborMap QCborValue::toMap(
const QCborMap &defaultValue)
const
2517 return defaultValue;
2518 QCborContainerPrivate *dd =
nullptr;
2519 Q_ASSERT(n == -1 || container ==
nullptr);
2523 return dd ? QCborMap(*dd) : QCborMap();
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538const QCborValue QCborValue::operator[](
const QString &key)
const
2540 return QCborContainerPrivate::findCborMapKey(*
this, qToStringViewIgnoringNull(key));
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557const QCborValue QCborValue::operator[](QLatin1StringView key)
const
2559 return QCborContainerPrivate::findCborMapKey(*
this, key);
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573const QCborValue QCborValue::operator[](qint64 key)
const
2575 if (isArray() && container && quint64(key) < quint64(container->elements.size()))
2576 return container->valueAt(key);
2577 return QCborContainerPrivate::findCborMapKey(*
this, key);
2582 constexpr qint64 LargeKey = 0x10000;
2583 if (t != QCborValue::Array)
2591 qsizetype currentSize = container ? container->elements.size() : 0;
2592 return key <= currentSize;
2596
2597
2600 if (Q_LIKELY(!array || array->elements.isEmpty()))
2604 qWarning(
"Using CBOR array as map forced conversion");
2606 qsizetype size = array->elements.size();
2608 map->elements.resize(size * 2);
2611 auto dst = map->elements.begin();
2612 auto src = array->elements.constBegin();
2613 for (qsizetype i = size - 1; i >= 0; --i) {
2614 Q_ASSERT(src->type != QCborValue::Invalid);
2615 dst[i * 2 + 1] = src[i];
2617 for (qsizetype i = 0; i < size; ++i)
2618 dst[i * 2] = { i, QCborValue::Integer };
2625
2626
2629 auto replace = QCborContainerPrivate::grow(container, index);
2631 if (replace->elements.size() == index)
2634 Q_ASSERT(replace->elements.size() > index);
2635 return assignContainer(container, replace);
2638template <
typename KeyType>
inline QCborValueRef
2639QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
2643 convertArrayToMap(self.container);
2644 else if (!self.isMap())
2645 self = QCborValue(QCborValue::Map);
2646 self.t = QCborValue::Map;
2649 QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
2650 assignContainer(self.container, result.d);
2654template<
typename KeyType> QCborValueRef
2657 auto &e = self.d->elements[self.i];
2660 if (e.type == QCborValue::Array) {
2661 convertArrayToMap(e.container);
2662 }
else if (e.type != QCborValue::Map) {
2664 e.container->deref();
2665 e.container =
nullptr;
2668 e.type = QCborValue::Map;
2670 QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
2671 assignContainer(e.container, result.d);
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688QCborValueRef QCborValue::operator[](
const QString &key)
2690 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708QCborValueRef QCborValue::operator[](QLatin1StringView key)
2710 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729QCborValueRef QCborValue::operator[](qint64 key)
2731 if (shouldArrayRemainArray(key, t, container)) {
2732 container = maybeGrow(container, key);
2733 return { container, qsizetype(key) };
2735 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2738#if QT_CONFIG(cborstreamreader)
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
2762 auto t = reader.type();
2763 if (reader.lastError() != QCborError::NoError)
2764 t = QCborStreamReader::Invalid;
2768 case QCborStreamReader::UnsignedInteger:
2769 case QCborStreamReader::NegativeInteger:
2770 case QCborStreamReader::SimpleType:
2771 case QCborStreamReader::Float16:
2772 case QCborStreamReader::Float:
2773 case QCborStreamReader::Double: {
2774 Element e = decodeBasicValueFromCbor(reader);
2780 case QCborStreamReader::Invalid:
2781 result.t = QCborValue::Invalid;
2785 case QCborStreamReader::ByteArray:
2786 case QCborStreamReader::String:
2788 result.t = reader.isString() ? String : ByteArray;
2789 result.container =
new QCborContainerPrivate;
2790 result.container->ref.ref();
2791 result.container->decodeStringFromCbor(reader);
2795 case QCborStreamReader::Array:
2796 case QCborStreamReader::Map:
2798 result.t = reader.isArray() ? Array : Map;
2799 result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
2803 case QCborStreamReader::Tag:
2804 result = taggedValueFromCbor(reader, MaximumRecursionDepth);
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833QCborValue QCborValue::fromCbor(
const QByteArray &ba, QCborParserError *error)
2835 QCborStreamReader reader(ba);
2836 QCborValue result = fromCbor(reader);
2838 error->error = reader.lastError();
2839 error->offset = reader.currentOffset();
2845
2846
2847
2848
2849
2850
2851
2852
2855#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882QByteArray QCborValue::toCbor(EncodingOptions opt)
const
2885 QCborStreamWriter writer(&result);
2886 toCbor(writer, opt);
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919Q_NEVER_INLINE
void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
const
2921 if (isContainer() || isTag())
2922 return encodeToCbor(writer, container, -type(), opt);
2924 return encodeToCbor(writer, container, n, opt);
2928 return writer.append(toSimpleType());
2932 return writer.append(n);
2935 return writeDoubleToCbor(writer, fp_helper(), opt);
2951 return writer.appendByteString(
"", 0);
2955 return writer.appendTextString(
"", 0);
2966 case RegularExpression:
2974# if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
2975void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
2977 concrete().toCbor(writer, opt);
2982void QCborValueRef::assign(QCborValueRef that,
const QCborValue &other)
2984 that.d->replaceAt(that.i, other);
2987void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
2989 that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
2992void QCborValueRef::assign(QCborValueRef that,
const QCborValueRef other)
2995 that = other.concrete();
3001 if (e.type != QCborValue::False && e.type != QCborValue::True)
3002 return defaultValue;
3003 return e.type == QCborValue::True;
3009 if (e.type == QCborValue::Integer)
3011 if (e.type != QCborValue::Double)
3012 return defaultValue;
3019 QCborValue::Type t = e.type;
3020 if (t == QCborValue::Double)
3022 if (t != QCborValue::Integer)
3023 return defaultValue;
3031 if (e.type != QCborValue::ByteArray)
3032 return defaultValue;
3033 return self
.d->byteArrayAt(self.i);
3039 if (e.type != QCborValue::String)
3040 return defaultValue;
3041 return self
.d->stringAt(self.i);
3047 if (e.type != QCborValue::String)
3048 return defaultValue;
3049 return self
.d->anyStringViewAt(self.i);
3066 return Qt::compareThreeWay(c, 0);
3073 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
3081 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
3083 return Qt::compareThreeWay(c, 0);
3086bool QCborArray::comparesEqual_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
3088 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3089 if (typeOrder(QCborValue::Array, e2.type))
3091 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3095QCborArray::compareThreeWay_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
3097 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3098 int c = typeOrder(QCborValue::Array, e2.type);
3100 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3101 return Qt::compareThreeWay(c, 0);
3104bool QCborMap::comparesEqual_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3106 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3107 if (typeOrder(QCborValue::Array, e2.type))
3109 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3113QCborMap::compareThreeWay_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3115 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3116 int c = typeOrder(QCborValue::Map, e2.type);
3118 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3119 return Qt::compareThreeWay(c, 0);
3124 return self
.d->valueAt(self.i);
3129 return self
.d->elements.at(self.i).type;
3134 const QCborValue item =
d->valueAt(i);
3140 const QCborValue item =
d->valueAt(i);
3146 const QCborValue item =
d->valueAt(i);
3150#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
) && !defined(QT_BOOTSTRAPPED)
3151QCborValue QCborValueRef::concrete(QCborValueRef self)
noexcept
3153 return self.d->valueAt(self.i);
3156QCborValue::Type QCborValueRef::concreteType(QCborValueRef self)
noexcept
3158 return self.d->elements.at(self.i).type;
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175const QCborValue QCborValueRef::operator[](
const QString &key)
const
3177 return QCborValueConstRef::operator[](key);
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196const QCborValue QCborValueRef::operator[](QLatin1StringView key)
const
3198 return QCborValueConstRef::operator[](key);
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213const QCborValue QCborValueRef::operator[](qint64 key)
const
3215 return QCborValueConstRef::operator[](key);
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232QCborValueRef QCborValueRef::operator[](
const QString &key)
3234 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
3254 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273QCborValueRef QCborValueRef::operator[](qint64 key)
3275 auto &e = d->elements[i];
3276 if (shouldArrayRemainArray(key, e.type, e.container)) {
3277 e.container = maybeGrow(e.container, key);
3278 e.flags |= QtCbor::Element::IsContainer;
3279 return { e.container, qsizetype(key) };
3281 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3285inline QCborArray::QCborArray(QCborContainerPrivate &dd)
noexcept
3290inline QCborMap::QCborMap(QCborContainerPrivate &dd)
noexcept
3297 switch (value.type()) {
3298 case QCborValue::Integer:
3299 return qHash(value.toInteger(), seed);
3300 case QCborValue::ByteArray:
3301 return qHash(value.toByteArray(), seed);
3302 case QCborValue::String:
3303 return qHash(value.toString(), seed);
3304 case QCborValue::Array:
3305 return qHash(value.toArray(), seed);
3306 case QCborValue::Map:
3307 return qHash(value.toMap(), seed);
3308 case QCborValue::Tag:
3309 return qHashMulti(seed, value.tag(), value.taggedValue());
3310 case QCborValue::SimpleType:
3312 case QCborValue::False:
3313 return qHash(
false, seed);
3314 case QCborValue::True:
3315 return qHash(
true, seed);
3316 case QCborValue::Null:
3317 return qHash(
nullptr, seed);
3318 case QCborValue::Undefined:
3320 case QCborValue::Double:
3321 return qHash(value.toDouble(), seed);
3322#if QT_CONFIG(datestring)
3323 case QCborValue::DateTime:
3324 return qHash(value.toDateTime(), seed);
3326#ifndef QT_BOOTSTRAPPED
3327 case QCborValue::Url:
3328 return qHash(value.toUrl(), seed);
3329# if QT_CONFIG(regularexpression)
3330 case QCborValue::RegularExpression:
3331 return qHash(value.toRegularExpression(), seed);
3333 case QCborValue::Uuid:
3334 return qHash(value.toUuid(), seed);
3336 case QCborValue::Invalid:
3342 Q_ASSERT(value.isSimpleType());
3343 return qHash(value.toSimpleType(), seed);
3349 case QCborSimpleType::False:
3351 case QCborSimpleType::True:
3353 case QCborSimpleType::Null:
3355 case QCborSimpleType::Undefined:
3365 auto n = std::underlying_type<QCborKnownTags>::type(tag);
3366 if (QCborTag(n) == tag) {
3367 switch (QCborKnownTags(n)) {
3368 case QCborKnownTags::DateTimeString:
3369 return "DateTimeString";
3370 case QCborKnownTags::UnixTime_t:
3371 return "UnixTime_t";
3372 case QCborKnownTags::PositiveBignum:
3373 return "PositiveBignum";
3374 case QCborKnownTags::NegativeBignum:
3375 return "NegativeBignum";
3376 case QCborKnownTags::Decimal:
3378 case QCborKnownTags::Bigfloat:
3380 case QCborKnownTags::COSE_Encrypt0:
3381 return "COSE_Encrypt0";
3382 case QCborKnownTags::COSE_Mac0:
3384 case QCborKnownTags::COSE_Sign1:
3385 return "COSE_Sign1";
3386 case QCborKnownTags::ExpectedBase64url:
3387 return "ExpectedBase64url";
3388 case QCborKnownTags::ExpectedBase64:
3389 return "ExpectedBase64";
3390 case QCborKnownTags::ExpectedBase16:
3391 return "ExpectedBase16";
3392 case QCborKnownTags::EncodedCbor:
3393 return "EncodedCbor";
3394 case QCborKnownTags::Url:
3396 case QCborKnownTags::Base64url:
3398 case QCborKnownTags::Base64:
3400 case QCborKnownTags::RegularExpression:
3401 return "RegularExpression";
3402 case QCborKnownTags::MimeMessage:
3403 return "MimeMessage";
3404 case QCborKnownTags::Uuid:
3406 case QCborKnownTags::COSE_Encrypt:
3407 return "COSE_Encrypt";
3408 case QCborKnownTags::COSE_Mac:
3410 case QCborKnownTags::COSE_Sign:
3412 case QCborKnownTags::Signature:
3419#if !defined(QT_NO_DEBUG_STREAM)
3423 case QCborValue::Integer:
3424 return dbg << v.toInteger();
3425 case QCborValue::ByteArray:
3426 return dbg <<
"QByteArray(" << v.toByteArray() <<
')';
3427 case QCborValue::String:
3428 return dbg << v.toString();
3429 case QCborValue::Array:
3430 return dbg << v.toArray();
3431 case QCborValue::Map:
3432 return dbg << v.toMap();
3433 case QCborValue::Tag: {
3434 QCborTag tag = v.tag();
3435 const char *id = qt_cbor_tag_id(tag);
3437 dbg.nospace() <<
"QCborKnownTags::" << id <<
", ";
3439 dbg.nospace() <<
"QCborTag(" << quint64(tag) <<
"), ";
3440 return dbg << v.taggedValue();
3442 case QCborValue::SimpleType:
3444 case QCborValue::True:
3446 case QCborValue::False:
3447 return dbg <<
false;
3448 case QCborValue::Null:
3449 return dbg <<
"nullptr";
3450 case QCborValue::Undefined:
3452 case QCborValue::Double: {
3454 if (convertDoubleTo(v.toDouble(), &i))
3455 return dbg << i <<
".0";
3457 return dbg << v.toDouble();
3459#if QT_CONFIG(datestring)
3460 case QCborValue::DateTime:
3461 return dbg << v.toDateTime();
3463#ifndef QT_BOOTSTRAPPED
3464 case QCborValue::Url:
3465 return dbg << v.toUrl();
3466#if QT_CONFIG(regularexpression)
3467 case QCborValue::RegularExpression:
3468 return dbg << v.toRegularExpression();
3470 case QCborValue::Uuid:
3471 return dbg << v.toUuid();
3473 case QCborValue::Invalid:
3474 return dbg <<
"<invalid>";
3478 if (v.isSimpleType())
3479 return dbg << v.toSimpleType();
3480 return dbg <<
"<unknown type 0x" << Qt::hex <<
int(v.type()) << Qt::dec <<
'>';
3484 QDebugStateSaver saver(dbg);
3485 dbg.nospace() <<
"QCborValue(";
3486 return debugContents(dbg, v) <<
')';
3491 QDebugStateSaver saver(dbg);
3492 const char *id = qt_cbor_simpletype_id(st);
3494 return dbg.nospace() <<
"QCborSimpleType::" << id;
3496 return dbg.nospace() <<
"QCborSimpleType(" << uint(st) <<
')';
3501 QDebugStateSaver saver(dbg);
3502 const char *id = qt_cbor_tag_id(tag);
3503 dbg.nospace() <<
"QCborTag(";
3505 dbg.nospace() <<
"QCborKnownTags::" << id;
3507 dbg.nospace() << quint64(tag);
3514 QDebugStateSaver saver(dbg);
3515 const char *id = qt_cbor_tag_id(QCborTag(
int(tag)));
3517 return dbg.nospace() <<
"QCborKnownTags::" << id;
3519 return dbg.nospace() <<
"QCborKnownTags(" <<
int(tag) <<
')';
3523#ifndef QT_NO_DATASTREAM
3524#if QT_CONFIG(cborstreamwriter)
3525QDataStream &operator<<(QDataStream &stream,
const QCborValue &value)
3527 stream << QCborValue(value).toCbor();
3532#if QT_CONFIG(cborstreamreader)
3533QDataStream &operator>>(QDataStream &stream, QCborValue &value)
3537 QCborParserError parseError{};
3538 value = QCborValue::fromCbor(buffer, &parseError);
3539 if (parseError.error)
3540 stream.setStatus(QDataStream::ReadCorruptData);
3552#ifndef QT_NO_QOBJECT
3553#include "moc_qcborvalue.cpp"
const QtCbor::ByteData * byteData(QtCbor::Element e) const
static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1, const QCborContainerPrivate *c2, QtCbor::Element e2, QtCbor::Comparison mode) noexcept
QCborContainerPrivate(const QCborContainerPrivate &)=default
static QCborValueRef findOrAddMapKey(QCborValueRef self, KeyType key)
void appendAsciiString(QStringView s)
void appendNonAsciiString(QStringView s)
void append(QtCbor::Undefined)
QCborValue extractAt_complex(QtCbor::Element e)
void replaceAt_complex(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp)
QCborContainerPrivate * d
Combined button and popup list for selecting options.
static int typeOrder(QCborValue::Type e1, QCborValue::Type e2)
static Q_DECL_UNUSED constexpr int MaximumRecursionDepth
Q_CORE_EXPORT const char * qt_cbor_simpletype_id(QCborSimpleType st)
void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len)
static int compareStringsInUtf8(QStringView lhs, QStringView rhs, Comparison mode) noexcept
static bool shouldArrayRemainArray(qint64 key, QCborValue::Type t, QCborContainerPrivate *container)
static auto nextUtf32Character(const char16_t *&ptr, const char16_t *end) noexcept
static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2, Comparison mode) noexcept
static QCborContainerPrivate * assignContainer(QCborContainerPrivate *&d, QCborContainerPrivate *x)
static qsizetype stringLengthInUtf8(const char16_t *ptr, const char16_t *end) noexcept
static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
static QCborValue::Type setToExtendedDateTimeType(QCborContainerPrivate *d, QStringView dtString)
Q_CORE_EXPORT const char * qt_cbor_tag_id(QCborTag tag)
bool comparesEqual(const QCborArray &lhs, const QCborArray &rhs) noexcept
static QCborContainerPrivate * maybeGrow(QCborContainerPrivate *container, qsizetype index)
static QDebug debugContents(QDebug &dbg, const QCborValue &v)
static int compareElementRecursive(const QCborContainerPrivate *c1, const Element &e1, const QCborContainerPrivate *c2, const Element &e2, Comparison mode) noexcept
static void convertArrayToMap(QCborContainerPrivate *&array)
bool comparesEqual(const QCborMap &lhs, const QCborMap &rhs) noexcept
static int compareElementNoData(const Element &e1, const Element &e2) noexcept
QDebug operator<<(QDebug debug, QDir::Filters filters)
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
const char * byte() const