7#define CBOR_NO_ENCODER_API
8#include <private/qcborcommon_p.h>
10#include <private/qnumeric_p.h>
11#include <private/qstringconverter_p.h>
15#include <qvarlengtharray.h>
24#define CBOR_PARSER_READER_CONTROL 1
25#define CBOR_PARSER_CAN_READ_BYTES_FUNCTION qt_cbor_decoder_can_read
26#define CBOR_PARSER_ADVANCE_BYTES_FUNCTION qt_cbor_decoder_advance
27#define CBOR_PARSER_TRANSFER_STRING_FUNCTION qt_cbor_decoder_transfer_string
28#define CBOR_PARSER_READ_BYTES_FUNCTION qt_cbor_decoder_read
31QT_WARNING_DISABLE_MSVC(4334)
32QT_WARNING_DISABLE_GCC(
"-Wimplicit-fallthrough")
34#include <cborparser.c>
38static CborError _cbor_value_dup_string(
const CborValue *,
void **, size_t *, CborValue *)
40 Q_UNREACHABLE_RETURN(CborErrorInternalError);
44 Q_UNREACHABLE_RETURN(CborErrorInternalError);
48static_assert(
int(QCborStreamReader::UnsignedInteger) == CborIntegerType);
49static_assert(
int(QCborStreamReader::ByteString) == CborByteStringType);
50static_assert(
int(QCborStreamReader::TextString) == CborTextStringType);
51static_assert(
int(QCborStreamReader::Array) == CborArrayType);
52static_assert(
int(QCborStreamReader::Map) == CborMapType);
53static_assert(
int(QCborStreamReader::Tag) == CborTagType);
54static_assert(
int(QCborStreamReader::SimpleType) == CborSimpleType);
55static_assert(
int(QCborStreamReader::HalfFloat) == CborHalfFloatType);
56static_assert(
int(QCborStreamReader::Float) == CborFloatType);
57static_assert(
int(QCborStreamReader::Double) == CborDoubleType);
58static_assert(
int(QCborStreamReader::Invalid) == CborInvalidType);
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
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
189
190
191
192
193
194
195
196
197
200
201
202
203
204
205
206
207
208
209
212
213
214
215
218
219
220
221
224
225
226
227
228
229
230
231
232
233
236
237
238
239
240
241
242
243
244
245
246
249
250
251
252
253
254
255
256
257
258
259
262
263
264
265
266
267
268
269
272
273
274
275
276
277
278
279
282
283
284
285
286
287
288
289
290
291
292
295
296
297
298
299
300
301
302
305
306
307
308
309
310
311
312
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
372
373
374
375
376
377
378
379
382
383
384
385
386
387
388
389
390
393
394
395
396
397
398
399
400
401
404
405
406
407
408
409
410
411
412
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
432
433
434
435
436
437
438
439
440
441
442
443
444
447
448
449
450
451
452
453
456
457
458
459
460
461
462
465
466
467
468
469
470
471
472
473
474
477
478
479
480
481
482
483
484
485
486
487
490
491
492
493
494
495
496
497
498
499
502
503
504
505
506
507
508
509
510
511
512
513
514
561 containerStack.clear();
565 buffer.reserve(IdealIoBufferSize);
569 if (CborError err = cbor_parser_init_reader(
nullptr, &parser, ¤tElement,
this))
572 lastError = { QCborError::NoError };
577 Q_ASSERT(buffer.isDetached());
578 return const_cast<
char *>(buffer.constBegin()) + bufferStart;
583 if (device && buffer.size() - bufferStart < MaxCborIndividualSize) {
585 qint64 avail =
device->bytesAvailable();
586 Q_ASSERT(avail >= buffer.size());
587 if (avail == buffer.size())
591 device->skip(bufferStart);
593 if (buffer.size() != IdealIoBufferSize)
594 buffer.resize(IdealIoBufferSize);
600 else if (read != IdealIoBufferSize)
601 buffer.truncate(read);
610 if (err != CborErrorUnexpectedEOF)
613 lastError = QCborError { QCborError::Code(
int(err)) };
628 bool isString()
const {
return maxlen_or_type == String; }
645 d->handleError(CborError(error.c));
653 qint64 avail = self->buffer.size() - self->bufferStart;
654 return len <= quint64(avail);
661 Q_ASSERT(len <= size_t(self->buffer.size() - self->bufferStart));
663 self->bufferStart +=
int(len);
669 Q_ASSERT(len == 1 || len == 2 || len == 4 || len == 8);
670 Q_ASSERT(offset == 0 || offset == 1);
674 Q_ASSERT(len + offset <= size_t(self->buffer.size() - self->bufferStart));
675 return memcpy(userptr, self->buffer.constBegin() + self->bufferStart + offset, len);
681 Q_ASSERT(offset <= size_t(self->buffer.size()));
682 static_assert(
sizeof(size_t) >=
sizeof(QByteArray::size_type));
683 static_assert(
sizeof(size_t) ==
sizeof(qsizetype));
688 if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
689 || qAddOverflow<qsizetype>(offset, len, &total))
690 return CborErrorDataTooLarge;
693 *userptr =
reinterpret_cast<
void *>(offset);
695 qint64 avail = (self
->device ? self
->device->bytesAvailable() : self->buffer.size()) -
697 return total > avail ? CborErrorUnexpectedEOF : CborNoError;
702 if (currentElement.flags & CborIteratorFlag_IteratingStringChunks)
705 CborError err = cbor_value_begin_string_iteration(¤tElement);
713
714
715inline void QCborStreamReader::preparse()
717 if (lastError() == QCborError::NoError) {
718 type_ = cbor_value_get_type(&d->currentElement);
720 if (type_ == CborInvalidType) {
722 if (d->device && d->containerStack.isEmpty()) {
725 d->device->skip(d->bufferStart);
733 if (type_ == CborBooleanType || type_ == CborNullType || type_ == CborUndefinedType) {
734 type_ = CborSimpleType;
735 value64 = quint8(d->buffer.at(d->bufferStart)) - CborSimpleType;
738 value64 = _cbor_value_extract_int64_helper(&d->currentElement);
740 if (cbor_value_is_negative_integer(&d->currentElement))
741 type_ = quint8(QCborStreamReader::NegativeInteger);
750
751
752
753
754
755
756
757
758QCborStreamReader::QCborStreamReader()
759 : d(
new QCborStreamReaderPrivate({})), type_(Invalid)
764
765
766
767
768
769QCborStreamReader::QCborStreamReader(
const char *data, qsizetype len)
770 : QCborStreamReader(QByteArray::fromRawData(data, len))
775
776
777
778
779
780QCborStreamReader::QCborStreamReader(
const quint8 *data, qsizetype len)
781 : QCborStreamReader(QByteArray::fromRawData(
reinterpret_cast<
const char *>(data), len))
786
787
788
789
790
791QCborStreamReader::QCborStreamReader(
const QByteArray &data)
792 : d(
new QCborStreamReaderPrivate(data))
798
799
800
801
802
803
804QCborStreamReader::QCborStreamReader(QIODevice *device)
805 : d(
new QCborStreamReaderPrivate(device))
811
812
813QCborStreamReader::~QCborStreamReader()
818
819
820
821void QCborStreamReader::setDevice(QIODevice *device)
823 d->setDevice(device);
828
829
830
831
832QIODevice *QCborStreamReader::device()
const
838
839
840
841
842void QCborStreamReader::addData(
const QByteArray &data)
844 addData(data.constBegin(), data.size());
848
849
850
851
852
853
854
855
858
859
860
861
862
863
864
865void QCborStreamReader::addData(
const char *data, qsizetype len)
869 d->buffer.append(data, len);
872 qWarning(
"QCborStreamReader: addData() with device()");
877
878
879
880
881
882
883
884void QCborStreamReader::reparse()
888 if (CborError err = cbor_value_reparse(&d->currentElement))
895
896
897
898
899
900
901
902
903void QCborStreamReader::clear()
909
910
911
912
913
914
915
916
917
918
919
920
921void QCborStreamReader::reset()
931
932
933
934
935
936QCborError QCborStreamReader::lastError()
const
942
943
944
945
946
947
948
949qint64 QCborStreamReader::currentOffset()
const
951 return (d->device ? d->device->pos() : 0) + d->bufferStart;
955
956
957
958
959
960int QCborStreamReader::containerDepth()
const
962 return d->containerStack.size();
966
967
968
969
970
971
972
973QCborStreamReader::Type QCborStreamReader::parentContainerType()
const
975 if (d->containerStack.isEmpty())
977 return Type(cbor_value_get_type(&std::as_const(d->containerStack).top()));
981
982
983
984
985
986
987
988
989bool QCborStreamReader::hasNext()
const noexcept
991 return cbor_value_is_valid(&d->currentElement) &&
992 !cbor_value_at_end(&d->currentElement);
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011bool QCborStreamReader::next(
int maxRecursion)
1013 if (lastError() != QCborError::NoError)
1017 d->handleError(CborErrorAdvancePastEOF);
1018 }
else if (maxRecursion < 0) {
1019 d->handleError(CborErrorNestingTooDeep);
1020 }
else if (isContainer()) {
1023 while (lastError() == QCborError::NoError && hasNext())
1024 next(maxRecursion - 1);
1025 if (lastError() == QCborError::NoError)
1027 }
else if (isByteArray()) {
1029 StringResult<qsizetype> r;
1031 r = readStringChunk(&c, 1);
1032 }
while (r.status == Ok);
1033 }
else if (isString()) {
1035 StringResult<QString> r;
1038 }
while (r.status == Ok);
1041 CborError err = cbor_value_advance_fixed(&d->currentElement);
1043 d->handleError(err);
1047 return d->lastError == QCborError::NoError;
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068bool QCborStreamReader::isLengthKnown()
const noexcept
1070 return cbor_value_is_length_known(&d->currentElement);
1074
1075
1076
1077
1078
1079
1080
1081
1082quint64 QCborStreamReader::length()
const
1090 if (isLengthKnown())
1092 err = CborErrorUnknownLength;
1096 err = CborErrorIllegalType;
1100 d->handleError(err);
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118bool QCborStreamReader::_enterContainer_helper()
1120 d->containerStack.push(d->currentElement);
1121 CborError err = cbor_value_enter_container(&d->containerStack.top(), &d->currentElement);
1126 d->handleError(err);
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142bool QCborStreamReader::leaveContainer()
1144 if (d->containerStack.isEmpty()) {
1145 qWarning(
"QCborStreamReader::leaveContainer: trying to leave top-level element");
1151 CborValue container = d->containerStack.pop();
1152 CborError err = cbor_value_leave_container(&container, &d->currentElement);
1153 d->currentElement = container;
1155 d->handleError(err);
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
1314 QCborStreamReader::StringResult<QString> result;
1315 auto r = d->readStringChunk(&result.data);
1316 result.status = r.status;
1317 if (r.status == Error) {
1318 result.data.clear();
1320 Q_ASSERT(r.data == result.data.size());
1321 if (r.status == EndOfString && lastError() == QCborError::NoError)
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readUtf8String_helper()
1347 using P = QCborStreamReaderPrivate::ReadStringChunk;
1348 QCborStreamReader::StringResult<QByteArray> result;
1349 auto r = d->readStringChunk(P{ &result.data, P::Utf8String });
1350 result.status = r.status;
1351 if (r.status == Error) {
1352 result.data.clear();
1354 Q_ASSERT(r.data == result.data.size());
1355 if (r.status == EndOfString && lastError() == QCborError::NoError)
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
1384 QCborStreamReader::StringResult<QByteArray> result;
1385 auto r = d->readStringChunk(&result.data);
1386 result.status = r.status;
1387 if (r.status == Error) {
1388 result.data.clear();
1390 Q_ASSERT(r.data == result.data.size());
1391 if (r.status == EndOfString && lastError() == QCborError::NoError)
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411qsizetype QCborStreamReader::_currentStringChunkSize()
const
1413 if (!d->ensureStringIteration())
1417 CborError err = cbor_value_get_string_chunk_size(&d->currentElement, &len);
1418 if (err == CborErrorNoMoreStringChunks)
1421 d->handleError(err);
1422 else if (qsizetype(len) < 0)
1423 d->handleError(CborErrorDataTooLarge);
1425 return qsizetype(len);
1431 auto r = readStringChunk(params);
1432 while (r.status == QCborStreamReader::Ok) {
1434 r = readStringChunk(params);
1437 bool ok = r.status == QCborStreamReader::EndOfString;
1438 Q_ASSERT(ok == !lastError);
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480bool QCborStreamReader::_readAndAppendToString_helper(QString &dst)
1482 bool ok = d->readFullString(&dst);
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520bool QCborStreamReader::_readAndAppendToUtf8String_helper(QByteArray &dst)
1522 using P = QCborStreamReaderPrivate::ReadStringChunk;
1523 bool ok = d->readFullString({ &dst, P::Utf8String });
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562bool QCborStreamReader::_readAndAppendToByteArray_helper(QByteArray &dst)
1564 bool ok = d->readFullString(&dst);
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598QCborStreamReader::StringResult<qsizetype>
1599QCborStreamReader::readStringChunk(
char *ptr, qsizetype maxlen)
1601 auto r = d->readStringChunk({ptr, maxlen});
1602 if (r.status == EndOfString && lastError() == QCborError::NoError)
1610 return QCborStreamReaderPrivate::appendStringChunk(reader, data);
1613inline QCborStreamReader::StringResultCode
1616 auto status = reader.d->readStringChunk(data).status;
1617 if (status == QCborStreamReader::EndOfString && reader.lastError() == QCborError::NoError)
1622Q_NEVER_INLINE QCborStreamReader::StringResult<qsizetype>
1623QCborStreamReaderPrivate::readStringChunk(ReadStringChunk params)
1627 const void *content =
nullptr;
1628 QCborStreamReader::StringResult<qsizetype> result;
1630 result.status = QCborStreamReader::Error;
1633 if (!ensureStringIteration())
1650 err = _cbor_value_get_string_chunk(¤tElement, &content, &len, ¤tElement);
1653 if (cbor_value_is_byte_string(¤tElement))
1654 err = cbor_value_get_byte_string_chunk(¤tElement,
reinterpret_cast<
const uint8_t **>(&content),
1655 &len, ¤tElement);
1657 err = cbor_value_get_text_string_chunk(¤tElement,
reinterpret_cast<
const char **>(&content),
1658 &len, ¤tElement);
1665 if (!err && qsizetype(len) < 0)
1666 err = CborErrorDataTooLarge;
1669 if (err == CborErrorNoMoreStringChunks) {
1671 err = cbor_value_finish_string_iteration(¤tElement);
1672 result.status = QCborStreamReader::EndOfString;
1680 qptrdiff offset = qptrdiff(content);
1681 bufferStart += offset;
1684 device->skip(bufferStart);
1687 if (params.isString()) {
1689 result.data = readStringChunk_unicode(params, qsizetype(len));
1690 }
else if (params.isUtf8String()) {
1691 result.data = readStringChunk_utf8(params, qsizetype(len));
1694 result.data = readStringChunk_byte(params, qsizetype(len));
1697 if (result.data < 0)
1703 qsizetype remainingInBuffer = buffer.size() - bufferStart;
1705 if (remainingInBuffer <= 0) {
1710 char *ptr = buffer.data();
1711 memmove(ptr, ptr + bufferStart, remainingInBuffer);
1712 buffer.truncate(remainingInBuffer);
1719 result.status = QCborStreamReader::Ok;
1726 qint64 actuallyRead;
1727 qsizetype toRead = qsizetype(len);
1729 char *ptr =
nullptr;
1732 left = toRead - params.maxlen_or_type;
1736 toRead = params.maxlen_or_type;
1740 auto oldSize = params.array->size();
1741 auto newSize = oldSize;
1742 if (qAddOverflow<
decltype(newSize)>(oldSize, toRead, &newSize)) {
1743 handleError(CborErrorDataTooLarge);
1747 params.array->resize(newSize);
1748 } QT_CATCH (
const std::bad_alloc &) {
1752 handleError(newSize > QByteArray::maxSize() ? CborErrorDataTooLarge: CborErrorOutOfMemory);
1756 ptr =
const_cast<
char *>(params.array->constBegin()) + oldSize;
1760 actuallyRead = device->read(ptr, toRead);
1762 if (actuallyRead != toRead) {
1765 qint64 skipped = device->skip(left);
1766 if (skipped != left)
1770 if (actuallyRead < 0) {
1771 handleError(CborErrorIO);
1775 actuallyRead = toRead;
1776 memcpy(ptr, buffer.constBegin() + bufferStart, toRead);
1779 return actuallyRead;
1789 qsizetype currentSize = params.string->size();
1790 size_t newSize = size_t(utf8len) + size_t(currentSize);
1791 if (utf8len > QString::maxSize() || qsizetype(newSize) < 0) {
1792 handleError(CborErrorDataTooLarge);
1796 params.string->resize(qsizetype(newSize));
1797 } QT_CATCH (
const std::bad_alloc &) {
1798 handleError(CborErrorOutOfMemory);
1802 QChar *begin =
const_cast<QChar *>(params.string->constBegin());
1803 QChar *ptr = begin + currentSize;
1804 QStringConverter::State cs(QStringConverter::Flag::Stateless);
1807 ptr = QUtf8::convertToUnicode(ptr, { buffer.constBegin() + bufferStart, utf8len }, &cs);
1810 constexpr qsizetype StringChunkSize = 16384;
1811 qsizetype chunkSize = qMin(StringChunkSize, utf8len);
1812 QVarLengthArray<
char> chunk(chunkSize);
1814 cs = { QStringConverter::Flag::ConvertInitialBom };
1815 while (utf8len > 0 && cs.invalidChars == 0) {
1816 qsizetype toRead = qMin(chunkSize, utf8len);
1817 qint64 actuallyRead = device->read(chunk.data(), toRead);
1818 if (actuallyRead == toRead)
1819 ptr = QUtf8::convertToUnicode(ptr, { chunk.data(), toRead }, &cs);
1821 if (actuallyRead != toRead) {
1822 handleError(CborErrorIO);
1829 if (cs.invalidChars != 0 || cs.remainingChars != 0) {
1830 handleError(CborErrorInvalidUtf8TextString);
1834 qsizetype size = ptr - begin;
1835 params.string->truncate(ptr - begin);
1836 return size - currentSize;
1842 qsizetype result = readStringChunk_byte(params, utf8len);
1847 QByteArrayView chunk = *params.array;
1848 chunk = chunk.last(result);
1849 if (QtPrivate::isValidUtf8(chunk))
1852 handleError(CborErrorInvalidUtf8TextString);
1858#include "moc_qcborstreamreader.cpp"
bool ensureStringIteration()
void handleError(CborError err) noexcept
QCborStreamReaderPrivate(QIODevice *device)
QByteArray::size_type bufferStart
qsizetype readStringChunk_byte(ReadStringChunk params, qsizetype len)
bool readFullString(ReadStringChunk params)
QStack< CborValue > containerStack
qsizetype readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len)
~QCborStreamReaderPrivate()
qsizetype readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len)
void setDevice(QIODevice *dev)
QCborStreamReaderPrivate(const QByteArray &data)
static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len)
QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data)
static QT_BEGIN_NAMESPACE bool qt_cbor_decoder_can_read(void *token, size_t len)
void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error)
static void qt_cbor_decoder_advance(void *token, size_t len)
static void * qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len)
static CborError cbor_value_get_half_float_as_float(const CborValue *, float *)
ReadStringChunk(char *ptr, qsizetype maxlen)
bool isPlainPointer() const
ReadStringChunk(QByteArray *array, Type type=ByteArray)
bool isUtf8String() const
ReadStringChunk(QString *str)