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;
1926#if Q_CC_GNU >= 1600
&& Q_CC_GNU < 1700
1927 QT_WARNING_DISABLE_GCC(
"-Warray-bounds")
1929 auto b =
new (
const_cast<
char *>(ptr)) ByteData;
1931 b->len = data.size() - e.value -
int(
sizeof(*b));
1936 Q_ASSERT(e.type == QCborValue::String);
1937 e.flags |= Element::StringIsAscii;
1941 if (e.type == QCborValue::String) {
1942 if (Q_UNLIKELY(b->len > QString::maxSize())) {
1943 setErrorInReader(reader, { QCborError::DataTooLarge });
1949 if (status == QCborStreamReader::EndOfString) {
1951 resetSize.dismiss();
1955void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1957 QCborStreamReader::Type t = reader.type();
1959 case QCborStreamReader::UnsignedInteger:
1960 case QCborStreamReader::NegativeInteger:
1961 case QCborStreamReader::SimpleType:
1962 case QCborStreamReader::Float16:
1963 case QCborStreamReader::Float:
1964 case QCborStreamReader::Double:
1965 elements.append(decodeBasicValueFromCbor(reader));
1968 case QCborStreamReader::ByteArray:
1969 case QCborStreamReader::String:
1970 decodeStringFromCbor(reader);
1973 case QCborStreamReader::Array:
1974 case QCborStreamReader::Map:
1975 return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
1976 createContainerFromCbor(reader, remainingRecursionDepth),
1979 case QCborStreamReader::Tag:
1980 return append(taggedValueFromCbor(reader, remainingRecursionDepth));
1982 case QCborStreamReader::Invalid:
1989
1990
1991
1992
1993
1994QCborValue::QCborValue(
const QByteArray &ba)
1995 : n(0), container(
new QCborContainerPrivate), t(ByteArray)
1997 container->appendByteData(ba.constData(), ba.size(), t);
1998 container->ref.storeRelaxed(1);
2002
2003
2004
2005
2006
2007QCborValue::QCborValue(
const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
2010
2011
2012
2013
2014
2015QCborValue::QCborValue(QStringView s)
2016 : n(0), container(
new QCborContainerPrivate), t(String)
2018 container->append(s);
2019 container->ref.storeRelaxed(1);
2023
2024
2025
2026
2027
2028
2029
2030QCborValue::QCborValue(QLatin1StringView s)
2031 : n(0), container(
new QCborContainerPrivate), t(String)
2033 container->append(s);
2034 container->ref.storeRelaxed(1);
2038
2039
2040
2041
2042
2043
2044
2045
2046QCborValue::QCborValue(
const QCborArray &a)
2047 : n(-1), container(a.d.data()), t(Array)
2050 container->ref.ref();
2054
2055
2056
2057
2058
2059
2060
2061
2062QCborValue::QCborValue(
const QCborMap &m)
2063 : n(-1), container(m.d.data()), t(Map)
2066 container->ref.ref();
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079QCborValue::QCborValue(QCborTag tag,
const QCborValue &tv)
2080 : n(-1), container(
new QCborContainerPrivate), t(Tag)
2082 container->ref.storeRelaxed(1);
2083 container->append(tag);
2084 container->append(tv);
2085 t = convertToExtendedType(container);
2089
2090
2091QCborValue::QCborValue(
const QCborValue &other)
noexcept
2092 : n(other.n), container(other.container), t(other.t)
2095 container->ref.ref();
2098#if QT_CONFIG(datestring)
2099static QCborValue::Type setToExtendedDateTimeType(QCborContainerPrivate *d, QStringView text)
2103 d->elements.resize(0);
2104 d->elements.reserve(2);
2106 d->append(QCborTag(QCborKnownTags::DateTimeString));
2107 d->appendAsciiString(text);
2108 return text.isEmpty() ? QCborValue::Tag : QCborValue::DateTime;
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124QCborValue::QCborValue(
const QDateTime &dt)
2125 : n(-1), container(
new QCborContainerPrivate),
2126 t(setToExtendedDateTimeType(container, dt.toString(Qt::ISODateWithMs)))
2128 container->ref.storeRelaxed(1);
2132#ifndef QT_BOOTSTRAPPED
2134
2135
2136
2137
2138
2139
2140
2141
2142QCborValue::QCborValue(
const QUrl &url)
2143 : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
2147 container->elements[1].type = String;
2150#if QT_CONFIG(regularexpression)
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163QCborValue::QCborValue(
const QRegularExpression &rx)
2164 : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
2167 t = RegularExpression;
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181QCborValue::QCborValue(
const QUuid &uuid)
2182 : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
2190
2191
2192
2193
2194
2195
2196
2197
2198void QCborValue::adjustDefaultConstructedExtendedType()
2202 *
this = QCborValue(QCborTag(-1), QCborValue());
2207 *
this = QCborValue(QCborKnownTags::DateTimeString, QString());
2212 *
this = QCborValue(QCborKnownTags::Url, QString());
2214 case RegularExpression:
2217 *
this = QCborValue(QCborKnownTags::RegularExpression, QString());
2222 *
this = QCborValue(QCborKnownTags::Uuid, QByteArray(
sizeof(QUuid),
'\0'));
2243void QCborValue::dispose()
2249
2250
2251QCborValue &QCborValue::operator=(
const QCborValue &other)
noexcept
2254 assignContainer(container, other.container);
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269QCborTag QCborValue::tag(QCborTag defaultValue)
const
2271 return isTag() && container && container->elements.size() == 2 ?
2272 QCborTag(container->elements.at(0).value) : defaultValue;
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285QCborValue QCborValue::taggedValue(
const QCborValue &defaultValue)
const
2287 return isTag() && container && container->elements.size() == 2 ?
2288 container->valueAt(1) : defaultValue;
2292
2293
2294
2295
2296
2297
2298
2299
2300QByteArray QCborValue::toByteArray(
const QByteArray &defaultValue)
const
2302 if (!container || !isByteArray())
2303 return defaultValue;
2306 return container->byteArrayAt(n);
2310
2311
2312
2313
2314
2315
2316
2317
2318QString QCborValue::toString(
const QString &defaultValue)
const
2320 if (!container || !isString())
2321 return defaultValue;
2324 return container->stringAt(n);
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345QAnyStringView QCborValue::toStringView(QAnyStringView defaultValue)
const
2347 if (!container || !isString())
2348 return defaultValue;
2351 return container->anyStringViewAt(n);
2354#if QT_CONFIG(datestring)
2356
2357
2358
2359
2360
2361
2362
2363
2364QDateTime QCborValue::toDateTime(
const QDateTime &defaultValue)
const
2366 if (!container || !isDateTime() || container->elements.size() != 2)
2367 return defaultValue;
2370 const ByteData *byteData = container->byteData(1);
2372 return defaultValue;
2375 Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
2376 return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
2380#ifndef QT_BOOTSTRAPPED
2382
2383
2384
2385
2386
2387
2388
2389QUrl QCborValue::toUrl(
const QUrl &defaultValue)
const
2391 if (!container || !isUrl() || container->elements.size() != 2)
2392 return defaultValue;
2395 const ByteData *byteData = container->byteData(1);
2399 return QUrl::fromEncoded(byteData->asByteArrayView());
2402#if QT_CONFIG(regularexpression)
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413QRegularExpression QCborValue::toRegularExpression(
const QRegularExpression &defaultValue)
const
2415 if (!container || !isRegularExpression() || container->elements.size() != 2)
2416 return defaultValue;
2419 return QRegularExpression(container->stringAt(1));
2424
2425
2426
2427
2428
2429
2430
2431QUuid QCborValue::toUuid(
const QUuid &defaultValue)
const
2433 if (!container || !isUuid() || container->elements.size() != 2)
2434 return defaultValue;
2437 const ByteData *byteData = container->byteData(1);
2439 return defaultValue;
2441 return QUuid::fromRfc4122(byteData->asByteArrayView());
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471QCborArray QCborValue::toArray()
const
2473 return toArray(QCborArray());
2476QCborArray QCborValue::toArray(
const QCborArray &defaultValue)
const
2479 return defaultValue;
2480 QCborContainerPrivate *dd =
nullptr;
2481 Q_ASSERT(n == -1 || container ==
nullptr);
2485 return dd ? QCborArray(*dd) : QCborArray();
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514QCborMap QCborValue::toMap()
const
2516 return toMap(QCborMap());
2519QCborMap QCborValue::toMap(
const QCborMap &defaultValue)
const
2522 return defaultValue;
2523 QCborContainerPrivate *dd =
nullptr;
2524 Q_ASSERT(n == -1 || container ==
nullptr);
2528 return dd ? QCborMap(*dd) : QCborMap();
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543const QCborValue QCborValue::operator[](
const QString &key)
const
2545 return QCborContainerPrivate::findCborMapKey(*
this, qToStringViewIgnoringNull(key));
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562const QCborValue QCborValue::operator[](QLatin1StringView key)
const
2564 return QCborContainerPrivate::findCborMapKey(*
this, key);
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578const QCborValue QCborValue::operator[](qint64 key)
const
2580 if (isArray() && container && quint64(key) < quint64(container->elements.size()))
2581 return container->valueAt(key);
2582 return QCborContainerPrivate::findCborMapKey(*
this, key);
2587 constexpr qint64 LargeKey = 0x10000;
2588 if (t != QCborValue::Array)
2596 qsizetype currentSize = container ? container->elements.size() : 0;
2597 return key <= currentSize;
2601
2602
2605 if (Q_LIKELY(!array || array->elements.isEmpty()))
2609 qWarning(
"Using CBOR array as map forced conversion");
2611 qsizetype size = array->elements.size();
2613 map->elements.resize(size * 2);
2616 auto dst = map->elements.begin();
2617 auto src = array->elements.constBegin();
2618 for (qsizetype i = size - 1; i >= 0; --i) {
2619 Q_ASSERT(src->type != QCborValue::Invalid);
2620 dst[i * 2 + 1] = src[i];
2622 for (qsizetype i = 0; i < size; ++i)
2623 dst[i * 2] = { i, QCborValue::Integer };
2630
2631
2634 auto replace = QCborContainerPrivate::grow(container, index);
2636 if (replace->elements.size() == index)
2639 Q_ASSERT(replace->elements.size() > index);
2640 return assignContainer(container, replace);
2643template <
typename KeyType>
inline QCborValueRef
2644QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
2648 convertArrayToMap(self.container);
2649 else if (!self.isMap())
2650 self = QCborValue(QCborValue::Map);
2651 self.t = QCborValue::Map;
2654 QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
2655 assignContainer(self.container, result.d);
2659template<
typename KeyType> QCborValueRef
2662 auto &e = self.d->elements[self.i];
2665 if (e.type == QCborValue::Array) {
2666 convertArrayToMap(e.container);
2667 }
else if (e.type != QCborValue::Map) {
2669 e.container->deref();
2670 e.container =
nullptr;
2673 e.type = QCborValue::Map;
2675 QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
2676 assignContainer(e.container, result.d);
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693QCborValueRef QCborValue::operator[](
const QString &key)
2695 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713QCborValueRef QCborValue::operator[](QLatin1StringView key)
2715 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734QCborValueRef QCborValue::operator[](qint64 key)
2736 if (shouldArrayRemainArray(key, t, container)) {
2737 container = maybeGrow(container, key);
2738 return { container, qsizetype(key) };
2740 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2743#if QT_CONFIG(cborstreamreader)
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
2767 auto t = reader.type();
2768 if (reader.lastError() != QCborError::NoError)
2769 t = QCborStreamReader::Invalid;
2773 case QCborStreamReader::UnsignedInteger:
2774 case QCborStreamReader::NegativeInteger:
2775 case QCborStreamReader::SimpleType:
2776 case QCborStreamReader::Float16:
2777 case QCborStreamReader::Float:
2778 case QCborStreamReader::Double: {
2779 Element e = decodeBasicValueFromCbor(reader);
2785 case QCborStreamReader::Invalid:
2786 result.t = QCborValue::Invalid;
2790 case QCborStreamReader::ByteArray:
2791 case QCborStreamReader::String:
2793 result.t = reader.isString() ? String : ByteArray;
2794 result.container =
new QCborContainerPrivate;
2795 result.container->ref.ref();
2796 result.container->decodeStringFromCbor(reader);
2800 case QCborStreamReader::Array:
2801 case QCborStreamReader::Map:
2803 result.t = reader.isArray() ? Array : Map;
2804 result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
2808 case QCborStreamReader::Tag:
2809 result = taggedValueFromCbor(reader, MaximumRecursionDepth);
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838QCborValue QCborValue::fromCbor(
const QByteArray &ba, QCborParserError *error)
2840 QCborStreamReader reader(ba);
2841 QCborValue result = fromCbor(reader);
2843 error->error = reader.lastError();
2844 error->offset = reader.currentOffset();
2850
2851
2852
2853
2854
2855
2856
2857
2860#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887QByteArray QCborValue::toCbor(EncodingOptions opt)
const
2890 QCborStreamWriter writer(&result);
2891 toCbor(writer, opt);
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924Q_NEVER_INLINE
void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
const
2926 if (isContainer() || isTag())
2927 return encodeToCbor(writer, container, -type(), opt);
2929 return encodeToCbor(writer, container, n, opt);
2933 return writer.append(toSimpleType());
2937 return writer.append(n);
2940 return writeDoubleToCbor(writer, fp_helper(), opt);
2956 return writer.appendByteString(
"", 0);
2960 return writer.appendTextString(
"", 0);
2971 case RegularExpression:
2979# if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
2980void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
2982 concrete().toCbor(writer, opt);
2987void QCborValueRef::assign(QCborValueRef that,
const QCborValue &other)
2989 that.d->replaceAt(that.i, other);
2992void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
2994 that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
2997void QCborValueRef::assign(QCborValueRef that,
const QCborValueRef other)
3000 that = other.concrete();
3006 if (e.type != QCborValue::False && e.type != QCborValue::True)
3007 return defaultValue;
3008 return e.type == QCborValue::True;
3014 if (e.type == QCborValue::Integer)
3016 if (e.type != QCborValue::Double)
3017 return defaultValue;
3024 QCborValue::Type t = e.type;
3025 if (t == QCborValue::Double)
3027 if (t != QCborValue::Integer)
3028 return defaultValue;
3036 if (e.type != QCborValue::ByteArray)
3037 return defaultValue;
3038 return self
.d->byteArrayAt(self.i);
3044 if (e.type != QCborValue::String)
3045 return defaultValue;
3046 return self
.d->stringAt(self.i);
3052 if (e.type != QCborValue::String)
3053 return defaultValue;
3054 return self
.d->anyStringViewAt(self.i);
3071 return Qt::compareThreeWay(c, 0);
3078 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
3086 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
3088 return Qt::compareThreeWay(c, 0);
3091bool QCborArray::comparesEqual_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
3093 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3094 if (typeOrder(QCborValue::Array, e2.type))
3096 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3100QCborArray::compareThreeWay_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
3102 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3103 int c = typeOrder(QCborValue::Array, e2.type);
3105 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3106 return Qt::compareThreeWay(c, 0);
3109bool QCborMap::comparesEqual_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3111 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3112 if (typeOrder(QCborValue::Array, e2.type))
3114 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3118QCborMap::compareThreeWay_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3120 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3121 int c = typeOrder(QCborValue::Map, e2.type);
3123 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3124 return Qt::compareThreeWay(c, 0);
3129 return self
.d->valueAt(self.i);
3134 return self
.d->elements.at(self.i).type;
3139 const QCborValue item =
d->valueAt(i);
3145 const QCborValue item =
d->valueAt(i);
3151 const QCborValue item =
d->valueAt(i);
3155#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
) && !defined(QT_BOOTSTRAPPED)
3156QCborValue QCborValueRef::concrete(QCborValueRef self)
noexcept
3158 return self.d->valueAt(self.i);
3161QCborValue::Type QCborValueRef::concreteType(QCborValueRef self)
noexcept
3163 return self.d->elements.at(self.i).type;
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180const QCborValue QCborValueRef::operator[](
const QString &key)
const
3182 return QCborValueConstRef::operator[](key);
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201const QCborValue QCborValueRef::operator[](QLatin1StringView key)
const
3203 return QCborValueConstRef::operator[](key);
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218const QCborValue QCborValueRef::operator[](qint64 key)
const
3220 return QCborValueConstRef::operator[](key);
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237QCborValueRef QCborValueRef::operator[](
const QString &key)
3239 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
3259 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278QCborValueRef QCborValueRef::operator[](qint64 key)
3280 auto &e = d->elements[i];
3281 if (shouldArrayRemainArray(key, e.type, e.container)) {
3282 e.container = maybeGrow(e.container, key);
3283 e.flags |= QtCbor::Element::IsContainer;
3284 return { e.container, qsizetype(key) };
3286 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3290inline QCborArray::QCborArray(QCborContainerPrivate &dd)
noexcept
3295inline QCborMap::QCborMap(QCborContainerPrivate &dd)
noexcept
3302 switch (value.type()) {
3303 case QCborValue::Integer:
3304 return qHash(value.toInteger(), seed);
3305 case QCborValue::ByteArray:
3306 return qHash(value.toByteArray(), seed);
3307 case QCborValue::String:
3308 return qHash(value.toString(), seed);
3309 case QCborValue::Array:
3310 return qHash(value.toArray(), seed);
3311 case QCborValue::Map:
3312 return qHash(value.toMap(), seed);
3313 case QCborValue::Tag:
3314 return qHashMulti(seed, value.tag(), value.taggedValue());
3315 case QCborValue::SimpleType:
3317 case QCborValue::False:
3318 return qHash(
false, seed);
3319 case QCborValue::True:
3320 return qHash(
true, seed);
3321 case QCborValue::Null:
3322 return qHash(
nullptr, seed);
3323 case QCborValue::Undefined:
3325 case QCborValue::Double:
3326 return qHash(value.toDouble(), seed);
3327#if QT_CONFIG(datestring)
3328 case QCborValue::DateTime:
3329 return qHash(value.toDateTime(), seed);
3331#ifndef QT_BOOTSTRAPPED
3332 case QCborValue::Url:
3333 return qHash(value.toUrl(), seed);
3334# if QT_CONFIG(regularexpression)
3335 case QCborValue::RegularExpression:
3336 return qHash(value.toRegularExpression(), seed);
3338 case QCborValue::Uuid:
3339 return qHash(value.toUuid(), seed);
3341 case QCborValue::Invalid:
3347 Q_ASSERT(value.isSimpleType());
3348 return qHash(value.toSimpleType(), seed);
3354 case QCborSimpleType::False:
3356 case QCborSimpleType::True:
3358 case QCborSimpleType::Null:
3360 case QCborSimpleType::Undefined:
3370 auto n = std::underlying_type<QCborKnownTags>::type(tag);
3371 if (QCborTag(n) == tag) {
3372 switch (QCborKnownTags(n)) {
3373 case QCborKnownTags::DateTimeString:
3374 return "DateTimeString";
3375 case QCborKnownTags::UnixTime_t:
3376 return "UnixTime_t";
3377 case QCborKnownTags::PositiveBignum:
3378 return "PositiveBignum";
3379 case QCborKnownTags::NegativeBignum:
3380 return "NegativeBignum";
3381 case QCborKnownTags::Decimal:
3383 case QCborKnownTags::Bigfloat:
3385 case QCborKnownTags::COSE_Encrypt0:
3386 return "COSE_Encrypt0";
3387 case QCborKnownTags::COSE_Mac0:
3389 case QCborKnownTags::COSE_Sign1:
3390 return "COSE_Sign1";
3391 case QCborKnownTags::ExpectedBase64url:
3392 return "ExpectedBase64url";
3393 case QCborKnownTags::ExpectedBase64:
3394 return "ExpectedBase64";
3395 case QCborKnownTags::ExpectedBase16:
3396 return "ExpectedBase16";
3397 case QCborKnownTags::EncodedCbor:
3398 return "EncodedCbor";
3399 case QCborKnownTags::Url:
3401 case QCborKnownTags::Base64url:
3403 case QCborKnownTags::Base64:
3405 case QCborKnownTags::RegularExpression:
3406 return "RegularExpression";
3407 case QCborKnownTags::MimeMessage:
3408 return "MimeMessage";
3409 case QCborKnownTags::Uuid:
3411 case QCborKnownTags::COSE_Encrypt:
3412 return "COSE_Encrypt";
3413 case QCborKnownTags::COSE_Mac:
3415 case QCborKnownTags::COSE_Sign:
3417 case QCborKnownTags::Signature:
3424#if !defined(QT_NO_DEBUG_STREAM)
3428 case QCborValue::Integer:
3429 return dbg << v.toInteger();
3430 case QCborValue::ByteArray:
3431 return dbg <<
"QByteArray(" << v.toByteArray() <<
')';
3432 case QCborValue::String:
3433 return dbg << v.toString();
3434 case QCborValue::Array:
3435 return dbg << v.toArray();
3436 case QCborValue::Map:
3437 return dbg << v.toMap();
3438 case QCborValue::Tag: {
3439 QCborTag tag = v.tag();
3440 const char *id = qt_cbor_tag_id(tag);
3442 dbg.nospace() <<
"QCborKnownTags::" << id <<
", ";
3444 dbg.nospace() <<
"QCborTag(" << quint64(tag) <<
"), ";
3445 return dbg << v.taggedValue();
3447 case QCborValue::SimpleType:
3449 case QCborValue::True:
3451 case QCborValue::False:
3452 return dbg <<
false;
3453 case QCborValue::Null:
3454 return dbg <<
"nullptr";
3455 case QCborValue::Undefined:
3457 case QCborValue::Double: {
3459 if (convertDoubleTo(v.toDouble(), &i))
3460 return dbg << i <<
".0";
3462 return dbg << v.toDouble();
3464#if QT_CONFIG(datestring)
3465 case QCborValue::DateTime:
3466 return dbg << v.toDateTime();
3468#ifndef QT_BOOTSTRAPPED
3469 case QCborValue::Url:
3470 return dbg << v.toUrl();
3471#if QT_CONFIG(regularexpression)
3472 case QCborValue::RegularExpression:
3473 return dbg << v.toRegularExpression();
3475 case QCborValue::Uuid:
3476 return dbg << v.toUuid();
3478 case QCborValue::Invalid:
3479 return dbg <<
"<invalid>";
3483 if (v.isSimpleType())
3484 return dbg << v.toSimpleType();
3485 return dbg <<
"<unknown type 0x" << Qt::hex <<
int(v.type()) << Qt::dec <<
'>';
3489 QDebugStateSaver saver(dbg);
3490 dbg.nospace() <<
"QCborValue(";
3491 return debugContents(dbg, v) <<
')';
3496 QDebugStateSaver saver(dbg);
3497 const char *id = qt_cbor_simpletype_id(st);
3499 return dbg.nospace() <<
"QCborSimpleType::" << id;
3501 return dbg.nospace() <<
"QCborSimpleType(" << uint(st) <<
')';
3506 QDebugStateSaver saver(dbg);
3507 const char *id = qt_cbor_tag_id(tag);
3508 dbg.nospace() <<
"QCborTag(";
3510 dbg.nospace() <<
"QCborKnownTags::" << id;
3512 dbg.nospace() << quint64(tag);
3519 QDebugStateSaver saver(dbg);
3520 const char *id = qt_cbor_tag_id(QCborTag(
int(tag)));
3522 return dbg.nospace() <<
"QCborKnownTags::" << id;
3524 return dbg.nospace() <<
"QCborKnownTags(" <<
int(tag) <<
')';
3534#ifndef QT_NO_DATASTREAM
3535#if QT_CONFIG(cborstreamwriter)
3536QDataStream &operator<<(QDataStream &stream,
const QCborValue &value)
3538 stream << QCborValue(value).toCbor();
3543#if QT_CONFIG(cborstreamreader)
3544QDataStream &operator>>(QDataStream &stream, QCborValue &value)
3548 QCborParserError parseError{};
3549 value = QCborValue::fromCbor(buffer, &parseError);
3550 if (parseError.error)
3551 stream.setStatus(QDataStream::ReadCorruptData);
3563#ifndef QT_NO_QOBJECT
3564#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