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
769 qint64 tag = d->elements.at(0).value;
770 auto &e = d->elements[1];
773 auto replaceByteData = [&](
const char *buf, qsizetype len, Element::ValueFlags f) {
777 e.value = d->addByteData(buf, len);
781#if QT_CONFIG(datestring)
782 case qint64(QCborKnownTags::DateTimeString):
783 case qint64(QCborKnownTags::UnixTime_t): {
785 if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
786 e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
789 dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
790 }
else if (tag == qint64(QCborKnownTags::UnixTime_t)) {
793 if (e.type == QCborValue::Integer) {
794#if QT_POINTER_SIZE == 8
797 ok = !qMulOverflow(e.value, qint64(1000), &msecs);
799 static const qint64 Limit = std::numeric_limits<qint64>::max() / 1000;
800 ok = (e.value > -Limit && e.value < Limit);
802 msecs = e.value * 1000;
804 }
else if (e.type == QCborValue::Double) {
805 ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs);
808 dt = QDateTime::fromMSecsSinceEpoch(msecs, QTimeZone::UTC);
811 QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
812 if (!text.isEmpty()) {
813 replaceByteData(text, text.size(), Element::StringIsAscii);
814 e.type = QCborValue::String;
815 d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
816 return QCborValue::DateTime;
823#ifndef QT_BOOTSTRAPPED
824 case qint64(QCborKnownTags::Url):
825 if (e.type == QCborValue::String) {
828 QUrl url(e.flags & Element::StringIsUtf16 ?
830 b->toUtf8String(), QUrl::StrictMode);
832 QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
833 replaceByteData(encoded, encoded.size(), {});
836 return QCborValue::Url;
841#if QT_CONFIG(regularexpression)
842 case quint64(QCborKnownTags::RegularExpression):
843 if (e.type == QCborValue::String) {
845 return QCborValue::RegularExpression;
850 case qint64(QCborKnownTags::Uuid):
851 if (e.type == QCborValue::ByteArray) {
853 char buf[
sizeof(QUuid)] = {};
855 memcpy(buf, b
->byte(), qMin(
sizeof(buf), size_t(b->len)));
856 replaceByteData(buf,
sizeof(buf), {});
858 return QCborValue::Uuid;
864 return QCborValue::Tag;
867#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
868static void writeDoubleToCbor(QCborStreamWriter &writer,
double d, QCborValue::EncodingOptions opt)
871 if (opt & QCborValue::UseFloat) {
872 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
873 return writer.append(std::numeric_limits<qfloat16>::quiet_NaN());
874 return writer.append(std::numeric_limits<
float>::quiet_NaN());
876 return writer.append(qt_qnan());
880 d = d > 0 ? qt_inf() : -qt_inf();
881 }
else if (opt & QCborValue::UseIntegers) {
883 if (convertDoubleTo(d, &i)) {
885 return writer.append(QCborNegativeInteger(i));
886 return writer.append(i);
890 if (opt & QCborValue::UseFloat) {
894 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
895 qfloat16 f16 = qfloat16(f);
897 return writer.append(f16);
900 return writer.append(f);
908static inline int typeOrder(QCborValue::Type e1, QCborValue::Type e2)
910 auto comparable = [](QCborValue::Type type) {
912 return QCborValue::Tag;
915 return comparable(e1) - comparable(e2);
921 for (Element &e : elements) {
922 if (e.flags & Element::IsContainer)
923 e.container->deref();
929 if (usedData > data.size() / 2)
934 QByteArray::size_type newUsedData = 0;
937 for (
auto &e : elements) {
938 if (e.flags & Element::HasByteData) {
939 if (
const ByteData *b = byteData(e))
940 e.value = addByteDataImpl(newData, newUsedData, b->byte(), b->len);
944 usedData = newUsedData;
955 u->elements.reserve(reserved);
960 d->ref.storeRelaxed(0);
962 for (
auto &e : std::as_const(d->elements)) {
963 if (e.flags & Element::IsContainer)
964 e.container->ref.ref();
972 if (!d || d->ref.loadRelaxed() != 1)
973 return clone(d, reserved);
978
979
980
981
982
983
986 Q_ASSERT(index >= 0);
987 d = detach(d, index + 1);
989 qsizetype j = d->elements.size();
1007 if (Q_UNLIKELY(
this == value.container)) {
1008 Q_ASSERT(ref.loadRelaxed() >= 2);
1009 if (disp == MoveContainer)
1012 d->elements.detach();
1013 d->ref.storeRelaxed(1);
1016 e.container = value.container;
1018 e.container->ref.ref();
1021 e.type = value.type();
1025 e = value.container->elements.at(value.n);
1028 if (
const ByteData *b = value.container->byteData(value.n)) {
1029 const auto flags = e.flags;
1036 if (
this == value.container) {
1037 const QByteArray valueData = b->toByteArray();
1039 e.value = addByteData(valueData, valueData.size());
1042 e.value = addByteData(b->byte(), b->len);
1049 value.container->deref();
1058 qsizetype len = s.size();
1060 e.value = addByteData(
nullptr, len);
1061 e.type = QCborValue::String;
1065 char *ptr = data.data() + e.value +
sizeof(ByteData);
1066 uchar *l =
reinterpret_cast<uchar *>(ptr);
1067 qt_to_latin1_unchecked(l, s.utf16(), len);
1072 appendByteData(
reinterpret_cast<
const char *>(s.utf16()), s.size() * 2,
1073 QCborValue::String, QtCbor::Element::StringIsUtf16);
1084 if (b->len + qsizetype(
sizeof(*b)) < data.size() / 4) {
1086 container->appendByteData(b
->byte(), b->len, e.type, e.flags);
1087 usedData -= b->len + qsizetype(
sizeof(*b));
1091 container->data = data;
1092 container->elements.reserve(1);
1093 container->elements.append(e);
1096 return makeValue(e.type, 0, container);
1103 Q_ASSERT(ptr != end);
1109 const char16_t c = *ptr++;
1115 }
else if (!QChar::isHighSurrogate(c) || ptr == end) {
1118 return R{QChar::surrogateToUcs4(c, *ptr++), 4};
1126 len += nextUtf32Character(ptr, end).len;
1133 return lhs == rhs ? 0 : 1;
1142 const char16_t *src1 = lhs.utf16();
1143 const char16_t *src2 = rhs.utf16();
1144 const char16_t *end1 = src1 + lhs.size();
1145 const char16_t *end2 = src2 + rhs.size();
1149 auto r1 = nextUtf32Character(src1, end1);
1150 auto r2 = nextUtf32Character(src2, end2);
1153 diff =
int(r1.c) -
int(r2.c);
1154 }
while (src1 < end1 && src2 < end2 && diff == 0);
1157 len1 += stringLengthInUtf8(src1, end1);
1158 len2 += stringLengthInUtf8(src2, end2);
1161 return len1 < len2 ? -1 : 1;
1171 const qsizetype len1 = lhs.size();
1172 const auto src1 =
reinterpret_cast<
const uchar *>(lhs.data());
1173 const char16_t *src2 = rhs.utf16();
1174 const char16_t *
const end2 = src2 + rhs.size();
1183 char16_t uc = *src2++;
1184 int r = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, ptr, src2, end2);
1187 qptrdiff n = ptr - utf8;
1189 if (len1 - idx1 < n)
1191 diff = memcmp(src1 + idx1, utf8, n);
1193 }
while (diff == 0 && idx1 < len1 && src2 < end2);
1197 if ((idx1 == len1) != (src2 == end2)) {
1199 return idx1 == len1 ? -1 : 1;
1204 len2 += stringLengthInUtf8(src2, end2);
1207 return len1 < len2 ? -1 : 1;
1213 return -compareStringsInUtf8(rhs, lhs, mode);
1216QT_WARNING_DISABLE_MSVC(4146)
1221 Q_ASSERT(e1.type == e2.type);
1223 if (e1.type == QCborValue::Integer) {
1234 auto makeSortable = [](qint64 v) {
1235 quint64 u = quint64(v);
1237 return quint64(std::numeric_limits<qint64>::max()) + (-u);
1240 quint64 u1 = makeSortable(e1.value);
1241 quint64 u2 = makeSortable(e2.value);
1248 if (e1.type == QCborValue::Tag || e1.type == QCborValue::Double) {
1250 quint64 u1 = quint64(e1.value);
1251 quint64 u2 = quint64(e2.value);
1253 return u1 < u2 ? -1 : 1;
1266 int cmp = typeOrder(e1.type, e2.type);
1278 auto len1 = b1 ? b1->len : 0;
1279 auto len2 = b2 ? b2->len : 0;
1280 if (len1 == 0 || len2 == 0)
1281 return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
1291 if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16))
1292 return compareStringsInUtf8(b1->asStringView(), b2->asStringView(), mode);
1300 return memcmp(b1->byte(), b2->byte(), size_t(len1)) == 0 ? 0 : 1;
1302 return memcmp(b1->byte(), b2->byte(), size_t(len1));
1304 return len1 < len2 ? -1 : 1;
1308 if (e1.flags & Element::StringIsUtf16)
1309 return compareStringsInUtf8(b1->asStringView(), b2->asUtf8StringView(), mode);
1311 return compareStringsInUtf8(b1->asUtf8StringView(), b2->asStringView(), mode);
1320 auto len1 = c1 ? c1->elements.size() : 0;
1321 auto len2 = c2 ? c2->elements.size() : 0;
1324 return len1 < len2 ? -1 : 1;
1327 for (qsizetype i = 0; i < len1; ++i) {
1328 const Element &e1 = c1->elements.at(i);
1329 const Element &e2 = c2->elements.at(i);
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1369 const QCborValue &rhs)
noexcept
1371 Element e1 = QCborContainerPrivate::elementFromValue(lhs);
1372 Element e2 = QCborContainerPrivate::elementFromValue(rhs);
1373 return compareElementRecursive(lhs.container, e1, rhs.container, e2,
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492int QCborValue::compare(
const QCborValue &other)
const
1494 Element e1 = QCborContainerPrivate::elementFromValue(*
this);
1495 Element e2 = QCborContainerPrivate::elementFromValue(other);
1496 return compareElementRecursive(container, e1, other.container, e2, Comparison::ForOrdering);
1504int QCborArray::compare(
const QCborArray &other)
const noexcept
1506 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1509bool QCborArray::comparesEqual_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1511 if (typeOrder(QCborValue::Array, rhs.type()))
1513 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1517QCborArray::compareThreeWay_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1519 int c = typeOrder(QCborValue::Array, rhs.type());
1521 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1522 return Qt::compareThreeWay(c, 0);
1530int QCborMap::compare(
const QCborMap &other)
const noexcept
1532 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1535bool QCborMap::comparesEqual_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1537 if (typeOrder(QCborValue::Map, rhs.type()))
1539 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1543QCborMap::compareThreeWay_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1545 int c = typeOrder(QCborValue::Map, rhs.type());
1547 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1548 return Qt::compareThreeWay(c, 0);
1551#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
1552static void encodeToCbor(QCborStreamWriter &writer,
const QCborContainerPrivate *d, qsizetype idx,
1553 QCborValue::EncodingOptions opt)
1555 if (idx == -QCborValue::Array || idx == -QCborValue::Map) {
1556 bool isArray = (idx == -QCborValue::Array);
1557 qsizetype len = d ? d->elements.size() : 0;
1559 writer.startArray(quint64(len));
1561 writer.startMap(quint64(len) / 2);
1563 for (idx = 0; idx < len; ++idx)
1564 encodeToCbor(writer, d, idx, opt);
1570 }
else if (idx < 0) {
1571 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1572 if (d->elements.size() != 2) {
1574 qWarning(
"QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
1579 writer.append(QCborTag(d->elements.at(0).value));
1580 encodeToCbor(writer, d, 1, opt);
1582 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1584 auto e = d->elements.at(idx);
1585 const ByteData *b = d->byteData(idx);
1587 case QCborValue::Integer:
1588 return writer.append(qint64(e.value));
1590 case QCborValue::ByteArray:
1592 return writer.appendByteString(b->byte(), b->len);
1593 return writer.appendByteString(
"", 0);
1595 case QCborValue::String:
1597 if (e.flags & Element::StringIsUtf16)
1598 return writer.append(b->asStringView());
1599 return writer.appendTextString(b->byte(), b->len);
1601 return writer.append(QLatin1StringView());
1603 case QCborValue::Array:
1604 case QCborValue::Map:
1605 case QCborValue::Tag:
1607 return encodeToCbor(writer,
1608 e.flags & Element::IsContainer ? e.container :
nullptr,
1609 -qsizetype(e.type), opt);
1611 case QCborValue::SimpleType:
1612 case QCborValue::False:
1613 case QCborValue::True:
1614 case QCborValue::Null:
1615 case QCborValue::Undefined:
1618 case QCborValue::Double:
1619 return writeDoubleToCbor(writer, e.fpvalue(), opt);
1621 case QCborValue::Invalid:
1624 case QCborValue::DateTime:
1625 case QCborValue::Url:
1626 case QCborValue::RegularExpression:
1627 case QCborValue::Uuid:
1629 return encodeToCbor(writer, e.container, -QCborValue::Tag, opt);
1633 int simpleType = e.type - QCborValue::SimpleType;
1634 if (
unsigned(simpleType) < 0x100)
1635 return writer.append(QCborSimpleType(simpleType));
1638 qWarning(
"QCborValue: found unknown type 0x%x", e.type);
1643#if QT_CONFIG(cborstreamreader)
1645static_assert(
int(QCborValue::Integer) ==
int(QCborStreamReader::UnsignedInteger));
1646static_assert(
int(QCborValue::ByteArray) ==
int(QCborStreamReader::ByteArray));
1647static_assert(
int(QCborValue::String) ==
int(QCborStreamReader::String));
1648static_assert(
int(QCborValue::Array) ==
int(QCborStreamReader::Array));
1649static_assert(
int(QCborValue::Map) ==
int(QCborStreamReader::Map));
1650static_assert(
int(QCborValue::Tag) ==
int(QCborStreamReader::Tag));
1652static inline double integerOutOfRange(
const QCborStreamReader &reader)
1654 Q_ASSERT(reader.isInteger());
1655 if (reader.isUnsignedInteger()) {
1656 quint64 v = reader.toUnsignedInteger();
1660 quint64 v = quint64(reader.toNegativeInteger());
1661 if (qint64(v - 1) < 0)
1669static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
1673 switch (reader.type()) {
1674 case QCborStreamReader::UnsignedInteger:
1675 case QCborStreamReader::NegativeInteger:
1676 if (
double d = integerOutOfRange(reader)) {
1677 e.type = QCborValue::Double;
1678 qToUnaligned(d, &e.value);
1680 e.type = QCborValue::Integer;
1681 e.value = reader.toInteger();
1684 case QCborStreamReader::SimpleType:
1685 e.type = QCborValue::Type(quint8(reader.toSimpleType()) + 0x100);
1687 case QCborStreamReader::Float16:
1688 e.type = QCborValue::Double;
1689 qToUnaligned(
double(reader.toFloat16()), &e.value);
1691 case QCborStreamReader::Float:
1692 e.type = QCborValue::Double;
1693 qToUnaligned(
double(reader.toFloat()), &e.value);
1695 case QCborStreamReader::Double:
1696 e.type = QCborValue::Double;
1697 qToUnaligned(reader.toDouble(), &e.value);
1711static qsizetype clampedContainerLength(
const QCborStreamReader &reader)
1713 if (!reader.isLengthKnown())
1715 int mapShift = reader.isMap() ? 1 : 0;
1716 quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
1717 qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
1718 return len << mapShift;
1721static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1723 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1724 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1728 QCborContainerPrivate *d =
nullptr;
1731 QExplicitlySharedDataPointer u(
new QCborContainerPrivate);
1732 if (qsizetype len = clampedContainerLength(reader))
1733 u->elements.reserve(len);
1737 reader.enterContainer();
1738 if (reader.lastError() != QCborError::NoError) {
1739 d->elements.clear();
1743 while (reader.hasNext() && reader.lastError() == QCborError::NoError)
1744 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1746 if (reader.lastError() == QCborError::NoError)
1747 reader.leaveContainer();
1749 d->elements.squeeze();
1754static QCborValue taggedValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1756 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1757 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1758 return QCborValue::Invalid;
1761 auto d =
new QCborContainerPrivate;
1762 d->append(reader.toTag());
1765 if (reader.lastError() == QCborError::NoError) {
1767 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1770 QCborValue::Type type;
1771 if (reader.lastError() == QCborError::NoError) {
1773 type = convertToExtendedType(d);
1776 type = QCborValue::Invalid;
1780 return QCborContainerPrivate::makeValue(type, -1, d);
1784extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
1785inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error)
1787 qt_cbor_stream_set_error(reader.d.get(), error);
1790extern QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data);
1792void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
1794 if (reader.lastError() != QCborError::NoError)
1797 qsizetype rawlen = reader.currentStringChunkSize();
1798 QByteArray::size_type len = rawlen;
1801 if (len != rawlen) {
1803 setErrorInReader(reader, { QCborError::DataTooLarge });
1807 auto resetSize = qScopeGuard([
this, oldSize = data.size()] {
1808 data.resize(oldSize);
1809 if (oldSize < data.capacity() / 2)
1814 e.type = QCborValue::Type(reader.type());
1815 if (len || !reader.isLengthKnown()) {
1818 constexpr size_t EstimatedOverhead = 16;
1819 constexpr size_t MaxMemoryIncrement = 16384;
1820 size_t offset = data.size();
1823 offset +=
sizeof(QtCbor::ByteData) +
alignof(QtCbor::ByteData);
1824 offset &= ~(
alignof(QtCbor::ByteData) - 1);
1825 if (offset > size_t(QByteArray::maxSize())) {
1827 setErrorInReader(reader, { QCborError::DataTooLarge });
1832 size_t newCapacity = offset + len;
1833 if (size_t(len) > MaxMemoryIncrement - EstimatedOverhead) {
1836 newCapacity = offset + MaxMemoryIncrement - EstimatedOverhead;
1838 if (newCapacity > size_t(QByteArray::maxSize())) {
1840 newCapacity = QByteArray::maxSize();
1842 if (newCapacity > size_t(data.capacity()))
1843 data.reserve(newCapacity);
1844 data.resize(offset +
sizeof(QtCbor::ByteData));
1846 e.flags = Element::HasByteData;
1850 bool isAscii = (e.type == QCborValue::String);
1851 QCborStreamReader::StringResultCode status = qt_cbor_append_string_chunk(reader, &data);
1852 while (status == QCborStreamReader::Ok) {
1853 if (e.type == QCborValue::String && len) {
1855 auto utf8result = QUtf8::isValidUtf8(QByteArrayView(data).last(len));
1856 if (!utf8result.isValidUtf8) {
1857 setErrorInReader(reader, { QCborError::InvalidUtf8String });
1860 isAscii = isAscii && utf8result.isValidAscii;
1863 rawlen = reader.currentStringChunkSize();
1865 if (len == rawlen) {
1866 status = qt_cbor_append_string_chunk(reader, &data);
1869 setErrorInReader(reader, { QCborError::DataTooLarge });
1875 if (status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
1876 Q_ASSERT(data.isDetached());
1877 const char *ptr = data.constData() + e.value;
1878 auto b =
new (
const_cast<
char *>(ptr)) ByteData;
1879 b->len = data.size() - e.value -
int(
sizeof(*b));
1884 Q_ASSERT(e.type == QCborValue::String);
1885 e.flags |= Element::StringIsAscii;
1889 if (e.type == QCborValue::String) {
1890 if (Q_UNLIKELY(b->len > QString::maxSize())) {
1891 setErrorInReader(reader, { QCborError::DataTooLarge });
1897 if (status == QCborStreamReader::EndOfString) {
1899 resetSize.dismiss();
1903void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1905 QCborStreamReader::Type t = reader.type();
1907 case QCborStreamReader::UnsignedInteger:
1908 case QCborStreamReader::NegativeInteger:
1909 case QCborStreamReader::SimpleType:
1910 case QCborStreamReader::Float16:
1911 case QCborStreamReader::Float:
1912 case QCborStreamReader::Double:
1913 elements.append(decodeBasicValueFromCbor(reader));
1916 case QCborStreamReader::ByteArray:
1917 case QCborStreamReader::String:
1918 decodeStringFromCbor(reader);
1921 case QCborStreamReader::Array:
1922 case QCborStreamReader::Map:
1923 return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
1924 createContainerFromCbor(reader, remainingRecursionDepth),
1927 case QCborStreamReader::Tag:
1928 return append(taggedValueFromCbor(reader, remainingRecursionDepth));
1930 case QCborStreamReader::Invalid:
1937
1938
1939
1940
1941
1942QCborValue::QCborValue(
const QByteArray &ba)
1943 : n(0), container(
new QCborContainerPrivate), t(ByteArray)
1945 container->appendByteData(ba.constData(), ba.size(), t);
1946 container->ref.storeRelaxed(1);
1950
1951
1952
1953
1954
1955QCborValue::QCborValue(
const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
1958
1959
1960
1961
1962
1963QCborValue::QCborValue(QStringView s)
1964 : n(0), container(
new QCborContainerPrivate), t(String)
1966 container->append(s);
1967 container->ref.storeRelaxed(1);
1971
1972
1973
1974
1975
1976
1977
1978QCborValue::QCborValue(QLatin1StringView s)
1979 : n(0), container(
new QCborContainerPrivate), t(String)
1981 container->append(s);
1982 container->ref.storeRelaxed(1);
1986
1987
1988
1989
1990
1991
1992
1993
1994QCborValue::QCborValue(
const QCborArray &a)
1995 : n(-1), container(a.d.data()), t(Array)
1998 container->ref.ref();
2002
2003
2004
2005
2006
2007
2008
2009
2010QCborValue::QCborValue(
const QCborMap &m)
2011 : n(-1), container(m.d.data()), t(Map)
2014 container->ref.ref();
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027QCborValue::QCborValue(QCborTag tag,
const QCborValue &tv)
2028 : n(-1), container(
new QCborContainerPrivate), t(Tag)
2030 container->ref.storeRelaxed(1);
2031 container->append(tag);
2032 container->append(tv);
2033 t = convertToExtendedType(container);
2037
2038
2039QCborValue::QCborValue(
const QCborValue &other)
noexcept
2040 : n(other.n), container(other.container), t(other.t)
2043 container->ref.ref();
2046#if QT_CONFIG(datestring)
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060QCborValue::QCborValue(
const QDateTime &dt)
2061 : QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs).toLatin1())
2065 container->elements[1].type = String;
2069#ifndef QT_BOOTSTRAPPED
2071
2072
2073
2074
2075
2076
2077
2078
2079QCborValue::QCborValue(
const QUrl &url)
2080 : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
2084 container->elements[1].type = String;
2087#if QT_CONFIG(regularexpression)
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100QCborValue::QCborValue(
const QRegularExpression &rx)
2101 : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
2104 t = RegularExpression;
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118QCborValue::QCborValue(
const QUuid &uuid)
2119 : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
2127void QCborValue::dispose()
2133
2134
2135QCborValue &QCborValue::operator=(
const QCborValue &other)
noexcept
2138 assignContainer(container, other.container);
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153QCborTag QCborValue::tag(QCborTag defaultValue)
const
2155 return isTag() && container && container->elements.size() == 2 ?
2156 QCborTag(container->elements.at(0).value) : defaultValue;
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169QCborValue QCborValue::taggedValue(
const QCborValue &defaultValue)
const
2171 return isTag() && container && container->elements.size() == 2 ?
2172 container->valueAt(1) : defaultValue;
2176
2177
2178
2179
2180
2181
2182
2183
2184QByteArray QCborValue::toByteArray(
const QByteArray &defaultValue)
const
2186 if (!container || !isByteArray())
2187 return defaultValue;
2190 return container->byteArrayAt(n);
2194
2195
2196
2197
2198
2199
2200
2201
2202QString QCborValue::toString(
const QString &defaultValue)
const
2204 if (!container || !isString())
2205 return defaultValue;
2208 return container->stringAt(n);
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229QAnyStringView QCborValue::toStringView(QAnyStringView defaultValue)
const
2231 if (!container || !isString())
2232 return defaultValue;
2235 return container->anyStringViewAt(n);
2238#if QT_CONFIG(datestring)
2240
2241
2242
2243
2244
2245
2246
2247
2248QDateTime QCborValue::toDateTime(
const QDateTime &defaultValue)
const
2250 if (!container || !isDateTime() || container->elements.size() != 2)
2251 return defaultValue;
2254 const ByteData *byteData = container->byteData(1);
2256 return defaultValue;
2259 Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
2260 return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
2264#ifndef QT_BOOTSTRAPPED
2266
2267
2268
2269
2270
2271
2272
2273QUrl QCborValue::toUrl(
const QUrl &defaultValue)
const
2275 if (!container || !isUrl() || container->elements.size() != 2)
2276 return defaultValue;
2279 const ByteData *byteData = container->byteData(1);
2283 return QUrl::fromEncoded(byteData->asByteArrayView());
2286#if QT_CONFIG(regularexpression)
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297QRegularExpression QCborValue::toRegularExpression(
const QRegularExpression &defaultValue)
const
2299 if (!container || !isRegularExpression() || container->elements.size() != 2)
2300 return defaultValue;
2303 return QRegularExpression(container->stringAt(1));
2308
2309
2310
2311
2312
2313
2314
2315QUuid QCborValue::toUuid(
const QUuid &defaultValue)
const
2317 if (!container || !isUuid() || container->elements.size() != 2)
2318 return defaultValue;
2321 const ByteData *byteData = container->byteData(1);
2323 return defaultValue;
2325 return QUuid::fromRfc4122(byteData->asByteArrayView());
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355QCborArray QCborValue::toArray()
const
2357 return toArray(QCborArray());
2360QCborArray QCborValue::toArray(
const QCborArray &defaultValue)
const
2363 return defaultValue;
2364 QCborContainerPrivate *dd =
nullptr;
2365 Q_ASSERT(n == -1 || container ==
nullptr);
2369 return dd ? QCborArray(*dd) : QCborArray();
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398QCborMap QCborValue::toMap()
const
2400 return toMap(QCborMap());
2403QCborMap QCborValue::toMap(
const QCborMap &defaultValue)
const
2406 return defaultValue;
2407 QCborContainerPrivate *dd =
nullptr;
2408 Q_ASSERT(n == -1 || container ==
nullptr);
2412 return dd ? QCborMap(*dd) : QCborMap();
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427const QCborValue QCborValue::operator[](
const QString &key)
const
2429 return QCborContainerPrivate::findCborMapKey(*
this, qToStringViewIgnoringNull(key));
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446const QCborValue QCborValue::operator[](QLatin1StringView key)
const
2448 return QCborContainerPrivate::findCborMapKey(*
this, key);
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462const QCborValue QCborValue::operator[](qint64 key)
const
2464 if (isArray() && container && quint64(key) < quint64(container->elements.size()))
2465 return container->valueAt(key);
2466 return QCborContainerPrivate::findCborMapKey(*
this, key);
2471 constexpr qint64 LargeKey = 0x10000;
2472 if (t != QCborValue::Array)
2480 qsizetype currentSize = container ? container->elements.size() : 0;
2481 return key <= currentSize;
2485
2486
2489 if (Q_LIKELY(!array || array->elements.isEmpty()))
2493 qWarning(
"Using CBOR array as map forced conversion");
2495 qsizetype size = array->elements.size();
2497 map->elements.resize(size * 2);
2500 auto dst = map->elements.begin();
2501 auto src = array->elements.constBegin();
2502 for (qsizetype i = size - 1; i >= 0; --i) {
2503 Q_ASSERT(src->type != QCborValue::Invalid);
2504 dst[i * 2 + 1] = src[i];
2506 for (qsizetype i = 0; i < size; ++i)
2507 dst[i * 2] = { i, QCborValue::Integer };
2514
2515
2518 auto replace = QCborContainerPrivate::grow(container, index);
2520 if (replace->elements.size() == index)
2523 Q_ASSERT(replace->elements.size() > index);
2524 return assignContainer(container, replace);
2527template <
typename KeyType>
inline QCborValueRef
2528QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
2532 convertArrayToMap(self.container);
2533 else if (!self.isMap())
2534 self = QCborValue(QCborValue::Map);
2535 self.t = QCborValue::Map;
2538 QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
2539 assignContainer(self.container, result.d);
2543template<
typename KeyType> QCborValueRef
2546 auto &e = self.d->elements[self.i];
2549 if (e.type == QCborValue::Array) {
2550 convertArrayToMap(e.container);
2551 }
else if (e.type != QCborValue::Map) {
2553 e.container->deref();
2554 e.container =
nullptr;
2557 e.type = QCborValue::Map;
2559 QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
2560 assignContainer(e.container, result.d);
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577QCborValueRef QCborValue::operator[](
const QString &key)
2579 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597QCborValueRef QCborValue::operator[](QLatin1StringView key)
2599 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618QCborValueRef QCborValue::operator[](qint64 key)
2620 if (shouldArrayRemainArray(key, t, container)) {
2621 container = maybeGrow(container, key);
2622 return { container, qsizetype(key) };
2624 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2627#if QT_CONFIG(cborstreamreader)
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
2651 auto t = reader.type();
2652 if (reader.lastError() != QCborError::NoError)
2653 t = QCborStreamReader::Invalid;
2657 case QCborStreamReader::UnsignedInteger:
2658 case QCborStreamReader::NegativeInteger:
2659 case QCborStreamReader::SimpleType:
2660 case QCborStreamReader::Float16:
2661 case QCborStreamReader::Float:
2662 case QCborStreamReader::Double: {
2663 Element e = decodeBasicValueFromCbor(reader);
2669 case QCborStreamReader::Invalid:
2670 result.t = QCborValue::Invalid;
2674 case QCborStreamReader::ByteArray:
2675 case QCborStreamReader::String:
2677 result.t = reader.isString() ? String : ByteArray;
2678 result.container =
new QCborContainerPrivate;
2679 result.container->ref.ref();
2680 result.container->decodeStringFromCbor(reader);
2684 case QCborStreamReader::Array:
2685 case QCborStreamReader::Map:
2687 result.t = reader.isArray() ? Array : Map;
2688 result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
2692 case QCborStreamReader::Tag:
2693 result = taggedValueFromCbor(reader, MaximumRecursionDepth);
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722QCborValue QCborValue::fromCbor(
const QByteArray &ba, QCborParserError *error)
2724 QCborStreamReader reader(ba);
2725 QCborValue result = fromCbor(reader);
2727 error->error = reader.lastError();
2728 error->offset = reader.currentOffset();
2734
2735
2736
2737
2738
2739
2740
2741
2744#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771QByteArray QCborValue::toCbor(EncodingOptions opt)
const
2774 QCborStreamWriter writer(&result);
2775 toCbor(writer, opt);
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808Q_NEVER_INLINE
void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
const
2810 if (isContainer() || isTag())
2811 return encodeToCbor(writer, container, -type(), opt);
2813 return encodeToCbor(writer, container, n, opt);
2817 return writer.append(toSimpleType());
2821 return writer.append(n);
2824 return writeDoubleToCbor(writer, fp_helper(), opt);
2840 return writer.appendByteString(
"", 0);
2844 return writer.appendTextString(
"", 0);
2855 case RegularExpression:
2863# if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
2864void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
2866 concrete().toCbor(writer, opt);
2871void QCborValueRef::assign(QCborValueRef that,
const QCborValue &other)
2873 that.d->replaceAt(that.i, other);
2876void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
2878 that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
2881void QCborValueRef::assign(QCborValueRef that,
const QCborValueRef other)
2884 that = other.concrete();
2890 if (e.type != QCborValue::False && e.type != QCborValue::True)
2891 return defaultValue;
2892 return e.type == QCborValue::True;
2898 if (e.type == QCborValue::Integer)
2900 if (e.type != QCborValue::Double)
2901 return defaultValue;
2908 QCborValue::Type t = e.type;
2909 if (t == QCborValue::Double)
2911 if (t != QCborValue::Integer)
2912 return defaultValue;
2920 if (e.type != QCborValue::ByteArray)
2921 return defaultValue;
2922 return self
.d->byteArrayAt(self.i);
2928 if (e.type != QCborValue::String)
2929 return defaultValue;
2930 return self
.d->stringAt(self.i);
2936 if (e.type != QCborValue::String)
2937 return defaultValue;
2938 return self
.d->anyStringViewAt(self.i);
2955 return Qt::compareThreeWay(c, 0);
2962 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
2970 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
2972 return Qt::compareThreeWay(c, 0);
2975bool QCborArray::comparesEqual_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
2977 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2978 if (typeOrder(QCborValue::Array, e2.type))
2980 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
2984QCborArray::compareThreeWay_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
2986 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2987 int c = typeOrder(QCborValue::Array, e2.type);
2989 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
2990 return Qt::compareThreeWay(c, 0);
2993bool QCborMap::comparesEqual_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
2995 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2996 if (typeOrder(QCborValue::Array, e2.type))
2998 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3002QCborMap::compareThreeWay_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3004 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3005 int c = typeOrder(QCborValue::Map, e2.type);
3007 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3008 return Qt::compareThreeWay(c, 0);
3013 return self
.d->valueAt(self.i);
3018 return self
.d->elements.at(self.i).type;
3023 const QCborValue item =
d->valueAt(i);
3029 const QCborValue item =
d->valueAt(i);
3035 const QCborValue item =
d->valueAt(i);
3039#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
) && !defined(QT_BOOTSTRAPPED)
3040QCborValue QCborValueRef::concrete(QCborValueRef self)
noexcept
3042 return self.d->valueAt(self.i);
3045QCborValue::Type QCborValueRef::concreteType(QCborValueRef self)
noexcept
3047 return self.d->elements.at(self.i).type;
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064const QCborValue QCborValueRef::operator[](
const QString &key)
const
3066 return QCborValueConstRef::operator[](key);
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085const QCborValue QCborValueRef::operator[](QLatin1StringView key)
const
3087 return QCborValueConstRef::operator[](key);
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102const QCborValue QCborValueRef::operator[](qint64 key)
const
3104 return QCborValueConstRef::operator[](key);
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121QCborValueRef QCborValueRef::operator[](
const QString &key)
3123 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
3143 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162QCborValueRef QCborValueRef::operator[](qint64 key)
3164 auto &e = d->elements[i];
3165 if (shouldArrayRemainArray(key, e.type, e.container)) {
3166 e.container = maybeGrow(e.container, key);
3167 e.flags |= QtCbor::Element::IsContainer;
3168 return { e.container, qsizetype(key) };
3170 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3174inline QCborArray::QCborArray(QCborContainerPrivate &dd)
noexcept
3179inline QCborMap::QCborMap(QCborContainerPrivate &dd)
noexcept
3186 switch (value.type()) {
3187 case QCborValue::Integer:
3188 return qHash(value.toInteger(), seed);
3189 case QCborValue::ByteArray:
3190 return qHash(value.toByteArray(), seed);
3191 case QCborValue::String:
3192 return qHash(value.toString(), seed);
3193 case QCborValue::Array:
3194 return qHash(value.toArray(), seed);
3195 case QCborValue::Map:
3196 return qHash(value.toMap(), seed);
3197 case QCborValue::Tag:
3198 return qHashMulti(seed, value.tag(), value.taggedValue());
3199 case QCborValue::SimpleType:
3201 case QCborValue::False:
3202 return qHash(
false, seed);
3203 case QCborValue::True:
3204 return qHash(
true, seed);
3205 case QCborValue::Null:
3206 return qHash(
nullptr, seed);
3207 case QCborValue::Undefined:
3209 case QCborValue::Double:
3210 return qHash(value.toDouble(), seed);
3211#if QT_CONFIG(datestring)
3212 case QCborValue::DateTime:
3213 return qHash(value.toDateTime(), seed);
3215#ifndef QT_BOOTSTRAPPED
3216 case QCborValue::Url:
3217 return qHash(value.toUrl(), seed);
3218# if QT_CONFIG(regularexpression)
3219 case QCborValue::RegularExpression:
3220 return qHash(value.toRegularExpression(), seed);
3222 case QCborValue::Uuid:
3223 return qHash(value.toUuid(), seed);
3225 case QCborValue::Invalid:
3231 Q_ASSERT(value.isSimpleType());
3232 return qHash(value.toSimpleType(), seed);
3238 case QCborSimpleType::False:
3240 case QCborSimpleType::True:
3242 case QCborSimpleType::Null:
3244 case QCborSimpleType::Undefined:
3254 auto n = std::underlying_type<QCborKnownTags>::type(tag);
3255 if (QCborTag(n) == tag) {
3256 switch (QCborKnownTags(n)) {
3257 case QCborKnownTags::DateTimeString:
3258 return "DateTimeString";
3259 case QCborKnownTags::UnixTime_t:
3260 return "UnixTime_t";
3261 case QCborKnownTags::PositiveBignum:
3262 return "PositiveBignum";
3263 case QCborKnownTags::NegativeBignum:
3264 return "NegativeBignum";
3265 case QCborKnownTags::Decimal:
3267 case QCborKnownTags::Bigfloat:
3269 case QCborKnownTags::COSE_Encrypt0:
3270 return "COSE_Encrypt0";
3271 case QCborKnownTags::COSE_Mac0:
3273 case QCborKnownTags::COSE_Sign1:
3274 return "COSE_Sign1";
3275 case QCborKnownTags::ExpectedBase64url:
3276 return "ExpectedBase64url";
3277 case QCborKnownTags::ExpectedBase64:
3278 return "ExpectedBase64";
3279 case QCborKnownTags::ExpectedBase16:
3280 return "ExpectedBase16";
3281 case QCborKnownTags::EncodedCbor:
3282 return "EncodedCbor";
3283 case QCborKnownTags::Url:
3285 case QCborKnownTags::Base64url:
3287 case QCborKnownTags::Base64:
3289 case QCborKnownTags::RegularExpression:
3290 return "RegularExpression";
3291 case QCborKnownTags::MimeMessage:
3292 return "MimeMessage";
3293 case QCborKnownTags::Uuid:
3295 case QCborKnownTags::COSE_Encrypt:
3296 return "COSE_Encrypt";
3297 case QCborKnownTags::COSE_Mac:
3299 case QCborKnownTags::COSE_Sign:
3301 case QCborKnownTags::Signature:
3308#if !defined(QT_NO_DEBUG_STREAM)
3312 case QCborValue::Integer:
3313 return dbg << v.toInteger();
3314 case QCborValue::ByteArray:
3315 return dbg <<
"QByteArray(" << v.toByteArray() <<
')';
3316 case QCborValue::String:
3317 return dbg << v.toString();
3318 case QCborValue::Array:
3319 return dbg << v.toArray();
3320 case QCborValue::Map:
3321 return dbg << v.toMap();
3322 case QCborValue::Tag: {
3323 QCborTag tag = v.tag();
3324 const char *id = qt_cbor_tag_id(tag);
3326 dbg.nospace() <<
"QCborKnownTags::" << id <<
", ";
3328 dbg.nospace() <<
"QCborTag(" << quint64(tag) <<
"), ";
3329 return dbg << v.taggedValue();
3331 case QCborValue::SimpleType:
3333 case QCborValue::True:
3335 case QCborValue::False:
3336 return dbg <<
false;
3337 case QCborValue::Null:
3338 return dbg <<
"nullptr";
3339 case QCborValue::Undefined:
3341 case QCborValue::Double: {
3343 if (convertDoubleTo(v.toDouble(), &i))
3344 return dbg << i <<
".0";
3346 return dbg << v.toDouble();
3348#if QT_CONFIG(datestring)
3349 case QCborValue::DateTime:
3350 return dbg << v.toDateTime();
3352#ifndef QT_BOOTSTRAPPED
3353 case QCborValue::Url:
3354 return dbg << v.toUrl();
3355#if QT_CONFIG(regularexpression)
3356 case QCborValue::RegularExpression:
3357 return dbg << v.toRegularExpression();
3359 case QCborValue::Uuid:
3360 return dbg << v.toUuid();
3362 case QCborValue::Invalid:
3363 return dbg <<
"<invalid>";
3367 if (v.isSimpleType())
3368 return dbg << v.toSimpleType();
3369 return dbg <<
"<unknown type 0x" << Qt::hex <<
int(v.type()) << Qt::dec <<
'>';
3373 QDebugStateSaver saver(dbg);
3374 dbg.nospace() <<
"QCborValue(";
3375 return debugContents(dbg, v) <<
')';
3380 QDebugStateSaver saver(dbg);
3381 const char *id = qt_cbor_simpletype_id(st);
3383 return dbg.nospace() <<
"QCborSimpleType::" << id;
3385 return dbg.nospace() <<
"QCborSimpleType(" << uint(st) <<
')';
3390 QDebugStateSaver saver(dbg);
3391 const char *id = qt_cbor_tag_id(tag);
3392 dbg.nospace() <<
"QCborTag(";
3394 dbg.nospace() <<
"QCborKnownTags::" << id;
3396 dbg.nospace() << quint64(tag);
3403 QDebugStateSaver saver(dbg);
3404 const char *id = qt_cbor_tag_id(QCborTag(
int(tag)));
3406 return dbg.nospace() <<
"QCborKnownTags::" << id;
3408 return dbg.nospace() <<
"QCborKnownTags(" <<
int(tag) <<
')';
3412#ifndef QT_NO_DATASTREAM
3413#if QT_CONFIG(cborstreamwriter)
3414QDataStream &operator<<(QDataStream &stream,
const QCborValue &value)
3416 stream << QCborValue(value).toCbor();
3421#if QT_CONFIG(cborstreamreader)
3422QDataStream &operator>>(QDataStream &stream, QCborValue &value)
3426 QCborParserError parseError{};
3427 value = QCborValue::fromCbor(buffer, &parseError);
3428 if (parseError.error)
3429 stream.setStatus(QDataStream::ReadCorruptData);
3441#ifndef QT_NO_QOBJECT
3442#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)
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 dbg, const QFileInfo &fi)
bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
QDebug operator<<(QDebug debug, QIODevice::OpenMode modes)
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
const char * byte() const