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
985 Q_ASSERT(index >= 0);
986 d = detach(d, index + 1);
988 qsizetype j = d->elements.size();
1006 if (Q_UNLIKELY(
this == value.container)) {
1007 Q_ASSERT(ref.loadRelaxed() >= 2);
1008 if (disp == MoveContainer)
1011 d->elements.detach();
1012 d->ref.storeRelaxed(1);
1015 e.container = value.container;
1017 e.container->ref.ref();
1020 e.type = value.type();
1024 e = value.container->elements.at(value.n);
1027 if (
const ByteData *b = value.container->byteData(value.n)) {
1028 const auto flags = e.flags;
1035 if (
this == value.container) {
1036 const QByteArray valueData = b->toByteArray();
1038 e.value = addByteData(valueData, valueData.size());
1041 e.value = addByteData(b->byte(), b->len);
1048 value.container->deref();
1057 qsizetype len = s.size();
1059 e.value = addByteData(
nullptr, len);
1060 e.type = QCborValue::String;
1064 char *ptr = data.data() + e.value +
sizeof(ByteData);
1065 uchar *l =
reinterpret_cast<uchar *>(ptr);
1066 qt_to_latin1_unchecked(l, s.utf16(), len);
1071 appendByteData(
reinterpret_cast<
const char *>(s.utf16()), s.size() * 2,
1072 QCborValue::String, QtCbor::Element::StringIsUtf16);
1083 if (b->len + qsizetype(
sizeof(*b)) < data.size() / 4) {
1085 container->appendByteData(b
->byte(), b->len, e.type, e.flags);
1086 usedData -= b->len + qsizetype(
sizeof(*b));
1090 container->data = data;
1091 container->elements.reserve(1);
1092 container->elements.append(e);
1095 return makeValue(e.type, 0, container);
1102 Q_ASSERT(ptr != end);
1111 }
else if (!QChar::isHighSurrogate(r.c) || ptr == end) {
1115 r.c = QChar::surrogateToUcs4(r.c, *ptr++);
1125 len += nextUtf32Character(ptr, end).len;
1132 return lhs == rhs ? 0 : 1;
1141 const char16_t *src1 = lhs.utf16();
1142 const char16_t *src2 = rhs.utf16();
1143 const char16_t *end1 = src1 + lhs.size();
1144 const char16_t *end2 = src2 + rhs.size();
1148 auto r1 = nextUtf32Character(src1, end1);
1149 auto r2 = nextUtf32Character(src2, end2);
1152 diff =
int(r1.c) -
int(r2.c);
1153 }
while (src1 < end1 && src2 < end2 && diff == 0);
1156 len1 += stringLengthInUtf8(src1, end1);
1157 len2 += stringLengthInUtf8(src2, end2);
1160 return len1 < len2 ? -1 : 1;
1170 const qsizetype len1 = lhs.size();
1171 const auto src1 =
reinterpret_cast<
const uchar *>(lhs.data());
1172 const char16_t *src2 = rhs.utf16();
1173 const char16_t *
const end2 = src2 + rhs.size();
1182 char16_t uc = *src2++;
1183 int r = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, ptr, src2, end2);
1186 qptrdiff n = ptr - utf8;
1188 if (len1 - idx1 < n)
1190 diff = memcmp(src1 + idx1, utf8, n);
1192 }
while (diff == 0 && idx1 < len1 && src2 < end2);
1196 if ((idx1 == len1) != (src2 == end2)) {
1198 return idx1 == len1 ? -1 : 1;
1203 len2 += stringLengthInUtf8(src2, end2);
1206 return len1 < len2 ? -1 : 1;
1212 return -compareStringsInUtf8(rhs, lhs, mode);
1215QT_WARNING_DISABLE_MSVC(4146)
1220 Q_ASSERT(e1.type == e2.type);
1222 if (e1.type == QCborValue::Integer) {
1233 auto makeSortable = [](qint64 v) {
1234 quint64 u = quint64(v);
1236 return quint64(std::numeric_limits<qint64>::max()) + (-u);
1239 quint64 u1 = makeSortable(e1.value);
1240 quint64 u2 = makeSortable(e2.value);
1247 if (e1.type == QCborValue::Tag || e1.type == QCborValue::Double) {
1249 quint64 u1 = quint64(e1.value);
1250 quint64 u2 = quint64(e2.value);
1252 return u1 < u2 ? -1 : 1;
1265 int cmp = typeOrder(e1.type, e2.type);
1277 auto len1 = b1 ? b1->len : 0;
1278 auto len2 = b2 ? b2->len : 0;
1279 if (len1 == 0 || len2 == 0)
1280 return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
1290 if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16))
1291 return compareStringsInUtf8(b1->asStringView(), b2->asStringView(), mode);
1299 return memcmp(b1->byte(), b2->byte(), size_t(len1)) == 0 ? 0 : 1;
1301 return memcmp(b1->byte(), b2->byte(), size_t(len1));
1303 return len1 < len2 ? -1 : 1;
1307 if (e1.flags & Element::StringIsUtf16)
1308 return compareStringsInUtf8(b1->asStringView(), b2->asUtf8StringView(), mode);
1310 return compareStringsInUtf8(b1->asUtf8StringView(), b2->asStringView(), mode);
1319 auto len1 = c1 ? c1->elements.size() : 0;
1320 auto len2 = c2 ? c2->elements.size() : 0;
1323 return len1 < len2 ? -1 : 1;
1326 for (qsizetype i = 0; i < len1; ++i) {
1327 const Element &e1 = c1->elements.at(i);
1328 const Element &e2 = c2->elements.at(i);
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1368 const QCborValue &rhs)
noexcept
1370 Element e1 = QCborContainerPrivate::elementFromValue(lhs);
1371 Element e2 = QCborContainerPrivate::elementFromValue(rhs);
1372 return compareElementRecursive(lhs.container, e1, rhs.container, e2,
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1431
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
1491int QCborValue::compare(
const QCborValue &other)
const
1493 Element e1 = QCborContainerPrivate::elementFromValue(*
this);
1494 Element e2 = QCborContainerPrivate::elementFromValue(other);
1495 return compareElementRecursive(container, e1, other.container, e2, Comparison::ForOrdering);
1503int QCborArray::compare(
const QCborArray &other)
const noexcept
1505 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1508bool QCborArray::comparesEqual_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1510 if (typeOrder(QCborValue::Array, rhs.type()))
1512 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1516QCborArray::compareThreeWay_helper(
const QCborArray &lhs,
const QCborValue &rhs)
noexcept
1518 int c = typeOrder(QCborValue::Array, rhs.type());
1520 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1521 return Qt::compareThreeWay(c, 0);
1529int QCborMap::compare(
const QCborMap &other)
const noexcept
1531 return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
1534bool QCborMap::comparesEqual_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1536 if (typeOrder(QCborValue::Map, rhs.type()))
1538 return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
1542QCborMap::compareThreeWay_helper(
const QCborMap &lhs,
const QCborValue &rhs)
noexcept
1544 int c = typeOrder(QCborValue::Map, rhs.type());
1546 c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
1547 return Qt::compareThreeWay(c, 0);
1550#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
1551static void encodeToCbor(QCborStreamWriter &writer,
const QCborContainerPrivate *d, qsizetype idx,
1552 QCborValue::EncodingOptions opt)
1554 if (idx == -QCborValue::Array || idx == -QCborValue::Map) {
1555 bool isArray = (idx == -QCborValue::Array);
1556 qsizetype len = d ? d->elements.size() : 0;
1558 writer.startArray(quint64(len));
1560 writer.startMap(quint64(len) / 2);
1562 for (idx = 0; idx < len; ++idx)
1563 encodeToCbor(writer, d, idx, opt);
1569 }
else if (idx < 0) {
1570 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1571 if (d->elements.size() != 2) {
1573 qWarning(
"QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
1578 writer.append(QCborTag(d->elements.at(0).value));
1579 encodeToCbor(writer, d, 1, opt);
1581 Q_ASSERT_X(d !=
nullptr,
"QCborValue",
"Unexpected null container");
1583 auto e = d->elements.at(idx);
1584 const ByteData *b = d->byteData(idx);
1586 case QCborValue::Integer:
1587 return writer.append(qint64(e.value));
1589 case QCborValue::ByteArray:
1591 return writer.appendByteString(b->byte(), b->len);
1592 return writer.appendByteString(
"", 0);
1594 case QCborValue::String:
1596 if (e.flags & Element::StringIsUtf16)
1597 return writer.append(b->asStringView());
1598 return writer.appendTextString(b->byte(), b->len);
1600 return writer.append(QLatin1StringView());
1602 case QCborValue::Array:
1603 case QCborValue::Map:
1604 case QCborValue::Tag:
1606 return encodeToCbor(writer,
1607 e.flags & Element::IsContainer ? e.container :
nullptr,
1608 -qsizetype(e.type), opt);
1610 case QCborValue::SimpleType:
1611 case QCborValue::False:
1612 case QCborValue::True:
1613 case QCborValue::Null:
1614 case QCborValue::Undefined:
1617 case QCborValue::Double:
1618 return writeDoubleToCbor(writer, e.fpvalue(), opt);
1620 case QCborValue::Invalid:
1623 case QCborValue::DateTime:
1624 case QCborValue::Url:
1625 case QCborValue::RegularExpression:
1626 case QCborValue::Uuid:
1628 return encodeToCbor(writer, e.container, -QCborValue::Tag, opt);
1632 int simpleType = e.type - QCborValue::SimpleType;
1633 if (
unsigned(simpleType) < 0x100)
1634 return writer.append(QCborSimpleType(simpleType));
1637 qWarning(
"QCborValue: found unknown type 0x%x", e.type);
1642#if QT_CONFIG(cborstreamreader)
1644static_assert(
int(QCborValue::Integer) ==
int(QCborStreamReader::UnsignedInteger));
1645static_assert(
int(QCborValue::ByteArray) ==
int(QCborStreamReader::ByteArray));
1646static_assert(
int(QCborValue::String) ==
int(QCborStreamReader::String));
1647static_assert(
int(QCborValue::Array) ==
int(QCborStreamReader::Array));
1648static_assert(
int(QCborValue::Map) ==
int(QCborStreamReader::Map));
1649static_assert(
int(QCborValue::Tag) ==
int(QCborStreamReader::Tag));
1651static inline double integerOutOfRange(
const QCborStreamReader &reader)
1653 Q_ASSERT(reader.isInteger());
1654 if (reader.isUnsignedInteger()) {
1655 quint64 v = reader.toUnsignedInteger();
1659 quint64 v = quint64(reader.toNegativeInteger());
1660 if (qint64(v - 1) < 0)
1668static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
1672 switch (reader.type()) {
1673 case QCborStreamReader::UnsignedInteger:
1674 case QCborStreamReader::NegativeInteger:
1675 if (
double d = integerOutOfRange(reader)) {
1676 e.type = QCborValue::Double;
1677 qToUnaligned(d, &e.value);
1679 e.type = QCborValue::Integer;
1680 e.value = reader.toInteger();
1683 case QCborStreamReader::SimpleType:
1684 e.type = QCborValue::Type(quint8(reader.toSimpleType()) + 0x100);
1686 case QCborStreamReader::Float16:
1687 e.type = QCborValue::Double;
1688 qToUnaligned(
double(reader.toFloat16()), &e.value);
1690 case QCborStreamReader::Float:
1691 e.type = QCborValue::Double;
1692 qToUnaligned(
double(reader.toFloat()), &e.value);
1694 case QCborStreamReader::Double:
1695 e.type = QCborValue::Double;
1696 qToUnaligned(reader.toDouble(), &e.value);
1710static qsizetype clampedContainerLength(
const QCborStreamReader &reader)
1712 if (!reader.isLengthKnown())
1714 int mapShift = reader.isMap() ? 1 : 0;
1715 quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
1716 qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
1717 return len << mapShift;
1720static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1722 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1723 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1727 QCborContainerPrivate *d =
nullptr;
1730 QExplicitlySharedDataPointer u(
new QCborContainerPrivate);
1731 if (qsizetype len = clampedContainerLength(reader))
1732 u->elements.reserve(len);
1736 reader.enterContainer();
1737 if (reader.lastError() != QCborError::NoError) {
1738 d->elements.clear();
1742 while (reader.hasNext() && reader.lastError() == QCborError::NoError)
1743 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1745 if (reader.lastError() == QCborError::NoError)
1746 reader.leaveContainer();
1748 d->elements.squeeze();
1753static QCborValue taggedValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1755 if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
1756 QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep });
1757 return QCborValue::Invalid;
1760 auto d =
new QCborContainerPrivate;
1761 d->append(reader.toTag());
1764 if (reader.lastError() == QCborError::NoError) {
1766 d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
1769 QCborValue::Type type;
1770 if (reader.lastError() == QCborError::NoError) {
1772 type = convertToExtendedType(d);
1775 type = QCborValue::Invalid;
1779 return QCborContainerPrivate::makeValue(type, -1, d);
1783extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
1784inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error)
1786 qt_cbor_stream_set_error(reader.d.get(), error);
1789extern QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data);
1791void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
1793 if (reader.lastError() != QCborError::NoError)
1796 qsizetype rawlen = reader.currentStringChunkSize();
1797 QByteArray::size_type len = rawlen;
1800 if (len != rawlen) {
1802 setErrorInReader(reader, { QCborError::DataTooLarge });
1806 auto resetSize = qScopeGuard([
this, oldSize = data.size()] {
1807 data.resize(oldSize);
1808 if (oldSize < data.capacity() / 2)
1813 e.type = QCborValue::Type(reader.type());
1814 if (len || !reader.isLengthKnown()) {
1817 constexpr size_t EstimatedOverhead = 16;
1818 constexpr size_t MaxMemoryIncrement = 16384;
1819 size_t offset = data.size();
1822 offset +=
sizeof(QtCbor::ByteData) +
alignof(QtCbor::ByteData);
1823 offset &= ~(
alignof(QtCbor::ByteData) - 1);
1824 if (offset > size_t(QByteArray::maxSize())) {
1826 setErrorInReader(reader, { QCborError::DataTooLarge });
1831 size_t newCapacity = offset + len;
1832 if (size_t(len) > MaxMemoryIncrement - EstimatedOverhead) {
1835 newCapacity = offset + MaxMemoryIncrement - EstimatedOverhead;
1837 if (newCapacity > size_t(QByteArray::maxSize())) {
1839 newCapacity = QByteArray::maxSize();
1841 if (newCapacity > size_t(data.capacity()))
1842 data.reserve(newCapacity);
1843 data.resize(offset +
sizeof(QtCbor::ByteData));
1845 e.flags = Element::HasByteData;
1849 bool isAscii = (e.type == QCborValue::String);
1850 QCborStreamReader::StringResultCode status = qt_cbor_append_string_chunk(reader, &data);
1851 while (status == QCborStreamReader::Ok) {
1852 if (e.type == QCborValue::String && len) {
1854 auto utf8result = QUtf8::isValidUtf8(QByteArrayView(data).last(len));
1855 if (!utf8result.isValidUtf8) {
1856 setErrorInReader(reader, { QCborError::InvalidUtf8String });
1859 isAscii = isAscii && utf8result.isValidAscii;
1862 rawlen = reader.currentStringChunkSize();
1864 if (len == rawlen) {
1865 status = qt_cbor_append_string_chunk(reader, &data);
1868 setErrorInReader(reader, { QCborError::DataTooLarge });
1874 if (status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
1875 Q_ASSERT(data.isDetached());
1876 const char *ptr = data.constData() + e.value;
1877 auto b =
new (
const_cast<
char *>(ptr)) ByteData;
1878 b->len = data.size() - e.value -
int(
sizeof(*b));
1883 Q_ASSERT(e.type == QCborValue::String);
1884 e.flags |= Element::StringIsAscii;
1888 if (e.type == QCborValue::String) {
1889 if (Q_UNLIKELY(b->len > QString::maxSize())) {
1890 setErrorInReader(reader, { QCborError::DataTooLarge });
1896 if (status == QCborStreamReader::EndOfString) {
1898 resetSize.dismiss();
1902void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader,
int remainingRecursionDepth)
1904 QCborStreamReader::Type t = reader.type();
1906 case QCborStreamReader::UnsignedInteger:
1907 case QCborStreamReader::NegativeInteger:
1908 case QCborStreamReader::SimpleType:
1909 case QCborStreamReader::Float16:
1910 case QCborStreamReader::Float:
1911 case QCborStreamReader::Double:
1912 elements.append(decodeBasicValueFromCbor(reader));
1915 case QCborStreamReader::ByteArray:
1916 case QCborStreamReader::String:
1917 decodeStringFromCbor(reader);
1920 case QCborStreamReader::Array:
1921 case QCborStreamReader::Map:
1922 return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1,
1923 createContainerFromCbor(reader, remainingRecursionDepth),
1926 case QCborStreamReader::Tag:
1927 return append(taggedValueFromCbor(reader, remainingRecursionDepth));
1929 case QCborStreamReader::Invalid:
1936
1937
1938
1939
1940
1941QCborValue::QCborValue(
const QByteArray &ba)
1942 : n(0), container(
new QCborContainerPrivate), t(ByteArray)
1944 container->appendByteData(ba.constData(), ba.size(), t);
1945 container->ref.storeRelaxed(1);
1949
1950
1951
1952
1953
1954QCborValue::QCborValue(
const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
1957
1958
1959
1960
1961
1962QCborValue::QCborValue(QStringView s)
1963 : n(0), container(
new QCborContainerPrivate), t(String)
1965 container->append(s);
1966 container->ref.storeRelaxed(1);
1970
1971
1972
1973
1974
1975
1976
1977QCborValue::QCborValue(QLatin1StringView s)
1978 : n(0), container(
new QCborContainerPrivate), t(String)
1980 container->append(s);
1981 container->ref.storeRelaxed(1);
1985
1986
1987
1988
1989
1990
1991
1992
1993QCborValue::QCborValue(
const QCborArray &a)
1994 : n(-1), container(a.d.data()), t(Array)
1997 container->ref.ref();
2001
2002
2003
2004
2005
2006
2007
2008
2009QCborValue::QCborValue(
const QCborMap &m)
2010 : n(-1), container(m.d.data()), t(Map)
2013 container->ref.ref();
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026QCborValue::QCborValue(QCborTag tag,
const QCborValue &tv)
2027 : n(-1), container(
new QCborContainerPrivate), t(Tag)
2029 container->ref.storeRelaxed(1);
2030 container->append(tag);
2031 container->append(tv);
2032 t = convertToExtendedType(container);
2036
2037
2038QCborValue::QCborValue(
const QCborValue &other)
noexcept
2039 : n(other.n), container(other.container), t(other.t)
2042 container->ref.ref();
2045#if QT_CONFIG(datestring)
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059QCborValue::QCborValue(
const QDateTime &dt)
2060 : QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs).toLatin1())
2064 container->elements[1].type = String;
2068#ifndef QT_BOOTSTRAPPED
2070
2071
2072
2073
2074
2075
2076
2077
2078QCborValue::QCborValue(
const QUrl &url)
2079 : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
2083 container->elements[1].type = String;
2086#if QT_CONFIG(regularexpression)
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099QCborValue::QCborValue(
const QRegularExpression &rx)
2100 : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
2103 t = RegularExpression;
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117QCborValue::QCborValue(
const QUuid &uuid)
2118 : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
2126void QCborValue::dispose()
2132
2133
2134QCborValue &QCborValue::operator=(
const QCborValue &other)
noexcept
2137 assignContainer(container, other.container);
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152QCborTag QCborValue::tag(QCborTag defaultValue)
const
2154 return isTag() && container && container->elements.size() == 2 ?
2155 QCborTag(container->elements.at(0).value) : defaultValue;
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168QCborValue QCborValue::taggedValue(
const QCborValue &defaultValue)
const
2170 return isTag() && container && container->elements.size() == 2 ?
2171 container->valueAt(1) : defaultValue;
2175
2176
2177
2178
2179
2180
2181
2182
2183QByteArray QCborValue::toByteArray(
const QByteArray &defaultValue)
const
2185 if (!container || !isByteArray())
2186 return defaultValue;
2189 return container->byteArrayAt(n);
2193
2194
2195
2196
2197
2198
2199
2200
2201QString QCborValue::toString(
const QString &defaultValue)
const
2203 if (!container || !isString())
2204 return defaultValue;
2207 return container->stringAt(n);
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228QAnyStringView QCborValue::toStringView(QAnyStringView defaultValue)
const
2230 if (!container || !isString())
2231 return defaultValue;
2234 return container->anyStringViewAt(n);
2237#if QT_CONFIG(datestring)
2239
2240
2241
2242
2243
2244
2245
2246
2247QDateTime QCborValue::toDateTime(
const QDateTime &defaultValue)
const
2249 if (!container || !isDateTime() || container->elements.size() != 2)
2250 return defaultValue;
2253 const ByteData *byteData = container->byteData(1);
2255 return defaultValue;
2258 Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
2259 return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
2263#ifndef QT_BOOTSTRAPPED
2265
2266
2267
2268
2269
2270
2271
2272QUrl QCborValue::toUrl(
const QUrl &defaultValue)
const
2274 if (!container || !isUrl() || container->elements.size() != 2)
2275 return defaultValue;
2278 const ByteData *byteData = container->byteData(1);
2282 return QUrl::fromEncoded(byteData->asByteArrayView());
2285#if QT_CONFIG(regularexpression)
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296QRegularExpression QCborValue::toRegularExpression(
const QRegularExpression &defaultValue)
const
2298 if (!container || !isRegularExpression() || container->elements.size() != 2)
2299 return defaultValue;
2302 return QRegularExpression(container->stringAt(1));
2307
2308
2309
2310
2311
2312
2313
2314QUuid QCborValue::toUuid(
const QUuid &defaultValue)
const
2316 if (!container || !isUuid() || container->elements.size() != 2)
2317 return defaultValue;
2320 const ByteData *byteData = container->byteData(1);
2322 return defaultValue;
2324 return QUuid::fromRfc4122(byteData->asByteArrayView());
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354QCborArray QCborValue::toArray()
const
2356 return toArray(QCborArray());
2359QCborArray QCborValue::toArray(
const QCborArray &defaultValue)
const
2362 return defaultValue;
2363 QCborContainerPrivate *dd =
nullptr;
2364 Q_ASSERT(n == -1 || container ==
nullptr);
2368 return dd ? QCborArray(*dd) : QCborArray();
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397QCborMap QCborValue::toMap()
const
2399 return toMap(QCborMap());
2402QCborMap QCborValue::toMap(
const QCborMap &defaultValue)
const
2405 return defaultValue;
2406 QCborContainerPrivate *dd =
nullptr;
2407 Q_ASSERT(n == -1 || container ==
nullptr);
2411 return dd ? QCborMap(*dd) : QCborMap();
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426const QCborValue QCborValue::operator[](
const QString &key)
const
2428 return QCborContainerPrivate::findCborMapKey(*
this, qToStringViewIgnoringNull(key));
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445const QCborValue QCborValue::operator[](QLatin1StringView key)
const
2447 return QCborContainerPrivate::findCborMapKey(*
this, key);
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461const QCborValue QCborValue::operator[](qint64 key)
const
2463 if (isArray() && container && quint64(key) < quint64(container->elements.size()))
2464 return container->valueAt(key);
2465 return QCborContainerPrivate::findCborMapKey(*
this, key);
2470 constexpr qint64 LargeKey = 0x10000;
2471 if (t != QCborValue::Array)
2479 qsizetype currentSize = container ? container->elements.size() : 0;
2480 return key <= currentSize;
2484
2485
2488 if (Q_LIKELY(!array || array->elements.isEmpty()))
2492 qWarning(
"Using CBOR array as map forced conversion");
2494 qsizetype size = array->elements.size();
2496 map->elements.resize(size * 2);
2499 auto dst = map->elements.begin();
2500 auto src = array->elements.constBegin();
2501 for (qsizetype i = size - 1; i >= 0; --i) {
2502 Q_ASSERT(src->type != QCborValue::Invalid);
2503 dst[i * 2 + 1] = src[i];
2505 for (qsizetype i = 0; i < size; ++i)
2506 dst[i * 2] = { i, QCborValue::Integer };
2513
2514
2517 auto replace = QCborContainerPrivate::grow(container, index);
2519 if (replace->elements.size() == index)
2522 Q_ASSERT(replace->elements.size() > index);
2523 return assignContainer(container, replace);
2526template <
typename KeyType>
inline QCborValueRef
2527QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
2531 convertArrayToMap(self.container);
2532 else if (!self.isMap())
2533 self = QCborValue(QCborValue::Map);
2534 self.t = QCborValue::Map;
2537 QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
2538 assignContainer(self.container, result.d);
2542template<
typename KeyType> QCborValueRef
2545 auto &e = self.d->elements[self.i];
2548 if (e.type == QCborValue::Array) {
2549 convertArrayToMap(e.container);
2550 }
else if (e.type != QCborValue::Map) {
2552 e.container->deref();
2553 e.container =
nullptr;
2556 e.type = QCborValue::Map;
2558 QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
2559 assignContainer(e.container, result.d);
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576QCborValueRef QCborValue::operator[](
const QString &key)
2578 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596QCborValueRef QCborValue::operator[](QLatin1StringView key)
2598 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617QCborValueRef QCborValue::operator[](qint64 key)
2619 if (shouldArrayRemainArray(key, t, container)) {
2620 container = maybeGrow(container, key);
2621 return { container, qsizetype(key) };
2623 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
2626#if QT_CONFIG(cborstreamreader)
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
2650 auto t = reader.type();
2651 if (reader.lastError() != QCborError::NoError)
2652 t = QCborStreamReader::Invalid;
2656 case QCborStreamReader::UnsignedInteger:
2657 case QCborStreamReader::NegativeInteger:
2658 case QCborStreamReader::SimpleType:
2659 case QCborStreamReader::Float16:
2660 case QCborStreamReader::Float:
2661 case QCborStreamReader::Double: {
2662 Element e = decodeBasicValueFromCbor(reader);
2668 case QCborStreamReader::Invalid:
2669 result.t = QCborValue::Invalid;
2673 case QCborStreamReader::ByteArray:
2674 case QCborStreamReader::String:
2676 result.t = reader.isString() ? String : ByteArray;
2677 result.container =
new QCborContainerPrivate;
2678 result.container->ref.ref();
2679 result.container->decodeStringFromCbor(reader);
2683 case QCborStreamReader::Array:
2684 case QCborStreamReader::Map:
2686 result.t = reader.isArray() ? Array : Map;
2687 result.container = createContainerFromCbor(reader, MaximumRecursionDepth);
2691 case QCborStreamReader::Tag:
2692 result = taggedValueFromCbor(reader, MaximumRecursionDepth);
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721QCborValue QCborValue::fromCbor(
const QByteArray &ba, QCborParserError *error)
2723 QCborStreamReader reader(ba);
2724 QCborValue result = fromCbor(reader);
2726 error->error = reader.lastError();
2727 error->offset = reader.currentOffset();
2733
2734
2735
2736
2737
2738
2739
2740
2743#if QT_CONFIG(cborstreamwriter) && !defined(QT_BOOTSTRAPPED)
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770QByteArray QCborValue::toCbor(EncodingOptions opt)
const
2773 QCborStreamWriter writer(&result);
2774 toCbor(writer, opt);
2779
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
2807Q_NEVER_INLINE
void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
const
2809 if (isContainer() || isTag())
2810 return encodeToCbor(writer, container, -type(), opt);
2812 return encodeToCbor(writer, container, n, opt);
2816 return writer.append(toSimpleType());
2820 return writer.append(n);
2823 return writeDoubleToCbor(writer, fp_helper(), opt);
2839 return writer.appendByteString(
"", 0);
2843 return writer.appendTextString(
"", 0);
2854 case RegularExpression:
2862# if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
)
2863void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
2865 concrete().toCbor(writer, opt);
2870void QCborValueRef::assign(QCborValueRef that,
const QCborValue &other)
2872 that.d->replaceAt(that.i, other);
2875void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
2877 that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
2880void QCborValueRef::assign(QCborValueRef that,
const QCborValueRef other)
2883 that = other.concrete();
2889 if (e.type != QCborValue::False && e.type != QCborValue::True)
2890 return defaultValue;
2891 return e.type == QCborValue::True;
2897 if (e.type == QCborValue::Integer)
2899 if (e.type != QCborValue::Double)
2900 return defaultValue;
2907 QCborValue::Type t = e.type;
2908 if (t == QCborValue::Double)
2910 if (t != QCborValue::Integer)
2911 return defaultValue;
2919 if (e.type != QCborValue::ByteArray)
2920 return defaultValue;
2921 return self
.d->byteArrayAt(self.i);
2927 if (e.type != QCborValue::String)
2928 return defaultValue;
2929 return self
.d->stringAt(self.i);
2935 if (e.type != QCborValue::String)
2936 return defaultValue;
2937 return self
.d->anyStringViewAt(self.i);
2954 return Qt::compareThreeWay(c, 0);
2961 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
2969 QtCbor::
Element e2 = QCborContainerPrivate::elementFromValue(rhs);
2971 return Qt::compareThreeWay(c, 0);
2974bool QCborArray::comparesEqual_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
2976 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2977 if (typeOrder(QCborValue::Array, e2.type))
2979 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
2983QCborArray::compareThreeWay_helper(
const QCborArray &lhs, QCborValueConstRef rhs)
noexcept
2985 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2986 int c = typeOrder(QCborValue::Array, e2.type);
2988 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
2989 return Qt::compareThreeWay(c, 0);
2992bool QCborMap::comparesEqual_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
2994 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
2995 if (typeOrder(QCborValue::Array, e2.type))
2997 return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
3001QCborMap::compareThreeWay_helper(
const QCborMap &lhs, QCborValueConstRef rhs)
noexcept
3003 QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
3004 int c = typeOrder(QCborValue::Map, e2.type);
3006 c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
3007 return Qt::compareThreeWay(c, 0);
3012 return self
.d->valueAt(self.i);
3017 return self
.d->elements.at(self.i).type;
3022 const QCborValue item = d->valueAt(i);
3028 const QCborValue item = d->valueAt(i);
3034 const QCborValue item = d->valueAt(i);
3038#if QT_VERSION < QT_VERSION_CHECK(7
, 0
, 0
) && !defined(QT_BOOTSTRAPPED)
3039QCborValue QCborValueRef::concrete(QCborValueRef self)
noexcept
3041 return self.d->valueAt(self.i);
3044QCborValue::Type QCborValueRef::concreteType(QCborValueRef self)
noexcept
3046 return self.d->elements.at(self.i).type;
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063const QCborValue QCborValueRef::operator[](
const QString &key)
const
3065 return QCborValueConstRef::operator[](key);
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084const QCborValue QCborValueRef::operator[](QLatin1StringView key)
const
3086 return QCborValueConstRef::operator[](key);
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101const QCborValue QCborValueRef::operator[](qint64 key)
const
3103 return QCborValueConstRef::operator[](key);
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120QCborValueRef QCborValueRef::operator[](
const QString &key)
3122 return QCborContainerPrivate::findOrAddMapKey(*
this, qToStringViewIgnoringNull(key));
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
3142 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161QCborValueRef QCborValueRef::operator[](qint64 key)
3163 auto &e = d->elements[i];
3164 if (shouldArrayRemainArray(key, e.type, e.container)) {
3165 e.container = maybeGrow(e.container, key);
3166 e.flags |= QtCbor::Element::IsContainer;
3167 return { e.container, qsizetype(key) };
3169 return QCborContainerPrivate::findOrAddMapKey(*
this, key);
3173inline QCborArray::QCborArray(QCborContainerPrivate &dd)
noexcept
3178inline QCborMap::QCborMap(QCborContainerPrivate &dd)
noexcept
3185 switch (value.type()) {
3186 case QCborValue::Integer:
3187 return qHash(value.toInteger(), seed);
3188 case QCborValue::ByteArray:
3189 return qHash(value.toByteArray(), seed);
3190 case QCborValue::String:
3191 return qHash(value.toString(), seed);
3192 case QCborValue::Array:
3193 return qHash(value.toArray(), seed);
3194 case QCborValue::Map:
3195 return qHash(value.toMap(), seed);
3196 case QCborValue::Tag:
3197 return qHashMulti(seed, value.tag(), value.taggedValue());
3198 case QCborValue::SimpleType:
3200 case QCborValue::False:
3201 return qHash(
false, seed);
3202 case QCborValue::True:
3203 return qHash(
true, seed);
3204 case QCborValue::Null:
3205 return qHash(
nullptr, seed);
3206 case QCborValue::Undefined:
3208 case QCborValue::Double:
3209 return qHash(value.toDouble(), seed);
3210#if QT_CONFIG(datestring)
3211 case QCborValue::DateTime:
3212 return qHash(value.toDateTime(), seed);
3214#ifndef QT_BOOTSTRAPPED
3215 case QCborValue::Url:
3216 return qHash(value.toUrl(), seed);
3217# if QT_CONFIG(regularexpression)
3218 case QCborValue::RegularExpression:
3219 return qHash(value.toRegularExpression(), seed);
3221 case QCborValue::Uuid:
3222 return qHash(value.toUuid(), seed);
3224 case QCborValue::Invalid:
3230 Q_ASSERT(value.isSimpleType());
3231 return qHash(value.toSimpleType(), seed);
3237 case QCborSimpleType::False:
3239 case QCborSimpleType::True:
3241 case QCborSimpleType::Null:
3243 case QCborSimpleType::Undefined:
3253 auto n = std::underlying_type<QCborKnownTags>::type(tag);
3254 if (QCborTag(n) == tag) {
3255 switch (QCborKnownTags(n)) {
3256 case QCborKnownTags::DateTimeString:
3257 return "DateTimeString";
3258 case QCborKnownTags::UnixTime_t:
3259 return "UnixTime_t";
3260 case QCborKnownTags::PositiveBignum:
3261 return "PositiveBignum";
3262 case QCborKnownTags::NegativeBignum:
3263 return "NegativeBignum";
3264 case QCborKnownTags::Decimal:
3266 case QCborKnownTags::Bigfloat:
3268 case QCborKnownTags::COSE_Encrypt0:
3269 return "COSE_Encrypt0";
3270 case QCborKnownTags::COSE_Mac0:
3272 case QCborKnownTags::COSE_Sign1:
3273 return "COSE_Sign1";
3274 case QCborKnownTags::ExpectedBase64url:
3275 return "ExpectedBase64url";
3276 case QCborKnownTags::ExpectedBase64:
3277 return "ExpectedBase64";
3278 case QCborKnownTags::ExpectedBase16:
3279 return "ExpectedBase16";
3280 case QCborKnownTags::EncodedCbor:
3281 return "EncodedCbor";
3282 case QCborKnownTags::Url:
3284 case QCborKnownTags::Base64url:
3286 case QCborKnownTags::Base64:
3288 case QCborKnownTags::RegularExpression:
3289 return "RegularExpression";
3290 case QCborKnownTags::MimeMessage:
3291 return "MimeMessage";
3292 case QCborKnownTags::Uuid:
3294 case QCborKnownTags::COSE_Encrypt:
3295 return "COSE_Encrypt";
3296 case QCborKnownTags::COSE_Mac:
3298 case QCborKnownTags::COSE_Sign:
3300 case QCborKnownTags::Signature:
3307#if !defined(QT_NO_DEBUG_STREAM)
3311 case QCborValue::Integer:
3312 return dbg << v.toInteger();
3313 case QCborValue::ByteArray:
3314 return dbg <<
"QByteArray(" << v.toByteArray() <<
')';
3315 case QCborValue::String:
3316 return dbg << v.toString();
3317 case QCborValue::Array:
3318 return dbg << v.toArray();
3319 case QCborValue::Map:
3320 return dbg << v.toMap();
3321 case QCborValue::Tag: {
3322 QCborTag tag = v.tag();
3323 const char *id = qt_cbor_tag_id(tag);
3325 dbg.nospace() <<
"QCborKnownTags::" << id <<
", ";
3327 dbg.nospace() <<
"QCborTag(" << quint64(tag) <<
"), ";
3328 return dbg << v.taggedValue();
3330 case QCborValue::SimpleType:
3332 case QCborValue::True:
3334 case QCborValue::False:
3335 return dbg <<
false;
3336 case QCborValue::Null:
3337 return dbg <<
"nullptr";
3338 case QCborValue::Undefined:
3340 case QCborValue::Double: {
3342 if (convertDoubleTo(v.toDouble(), &i))
3343 return dbg << i <<
".0";
3345 return dbg << v.toDouble();
3347#if QT_CONFIG(datestring)
3348 case QCborValue::DateTime:
3349 return dbg << v.toDateTime();
3351#ifndef QT_BOOTSTRAPPED
3352 case QCborValue::Url:
3353 return dbg << v.toUrl();
3354#if QT_CONFIG(regularexpression)
3355 case QCborValue::RegularExpression:
3356 return dbg << v.toRegularExpression();
3358 case QCborValue::Uuid:
3359 return dbg << v.toUuid();
3361 case QCborValue::Invalid:
3362 return dbg <<
"<invalid>";
3366 if (v.isSimpleType())
3367 return dbg << v.toSimpleType();
3368 return dbg <<
"<unknown type 0x" << Qt::hex <<
int(v.type()) << Qt::dec <<
'>';
3372 QDebugStateSaver saver(dbg);
3373 dbg.nospace() <<
"QCborValue(";
3374 return debugContents(dbg, v) <<
')';
3379 QDebugStateSaver saver(dbg);
3380 const char *id = qt_cbor_simpletype_id(st);
3382 return dbg.nospace() <<
"QCborSimpleType::" << id;
3384 return dbg.nospace() <<
"QCborSimpleType(" << uint(st) <<
')';
3389 QDebugStateSaver saver(dbg);
3390 const char *id = qt_cbor_tag_id(tag);
3391 dbg.nospace() <<
"QCborTag(";
3393 dbg.nospace() <<
"QCborKnownTags::" << id;
3395 dbg.nospace() << quint64(tag);
3402 QDebugStateSaver saver(dbg);
3403 const char *id = qt_cbor_tag_id(QCborTag(
int(tag)));
3405 return dbg.nospace() <<
"QCborKnownTags::" << id;
3407 return dbg.nospace() <<
"QCborKnownTags(" <<
int(tag) <<
')';
3411#ifndef QT_NO_DATASTREAM
3412#if QT_CONFIG(cborstreamwriter)
3413QDataStream &operator<<(QDataStream &stream,
const QCborValue &value)
3415 stream << QCborValue(value).toCbor();
3420#if QT_CONFIG(cborstreamreader)
3421QDataStream &operator>>(QDataStream &stream, QCborValue &value)
3425 QCborParserError parseError{};
3426 value = QCborValue::fromCbor(buffer, &parseError);
3427 if (parseError.error)
3428 stream.setStatus(QDataStream::ReadCorruptData);
3440#ifndef QT_NO_QOBJECT
3441#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
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