Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcborstreamreader.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcborstreamreader.h"
5
6#define CBOR_NO_ENCODER_API
7#include <private/qcborcommon_p.h>
8
9#include <private/qnumeric_p.h>
10#include <private/qstringconverter_p.h>
11#include <qiodevice.h>
12#include <qdebug.h>
13#include <qstack.h>
14#include <qvarlengtharray.h>
15
17
18static bool qt_cbor_decoder_can_read(void *token, size_t len);
19static void qt_cbor_decoder_advance(void *token, size_t len);
20static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len);
21static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len);
22
23#define CBOR_PARSER_READER_CONTROL 1
24#define CBOR_PARSER_CAN_READ_BYTES_FUNCTION qt_cbor_decoder_can_read
25#define CBOR_PARSER_ADVANCE_BYTES_FUNCTION qt_cbor_decoder_advance
26#define CBOR_PARSER_TRANSFER_STRING_FUNCTION qt_cbor_decoder_transfer_string
27#define CBOR_PARSER_READ_BYTES_FUNCTION qt_cbor_decoder_read
28
30QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
31QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
32
33#include <cborparser.c>
34
36
37static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
38{
39 Q_UNREACHABLE_RETURN(CborErrorInternalError);
40}
41[[maybe_unused]] static CborError cbor_value_get_half_float_as_float(const CborValue *, float *)
42{
43 Q_UNREACHABLE_RETURN(CborErrorInternalError);
44}
45
46// confirm our constants match TinyCBOR's
47static_assert(int(QCborStreamReader::UnsignedInteger) == CborIntegerType);
48static_assert(int(QCborStreamReader::ByteString) == CborByteStringType);
49static_assert(int(QCborStreamReader::TextString) == CborTextStringType);
50static_assert(int(QCborStreamReader::Array) == CborArrayType);
51static_assert(int(QCborStreamReader::Map) == CborMapType);
52static_assert(int(QCborStreamReader::Tag) == CborTagType);
53static_assert(int(QCborStreamReader::SimpleType) == CborSimpleType);
54static_assert(int(QCborStreamReader::HalfFloat) == CborHalfFloatType);
55static_assert(int(QCborStreamReader::Float) == CborFloatType);
56static_assert(int(QCborStreamReader::Double) == CborDoubleType);
57static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
58
516{
517public:
518 enum {
519 // 9 bytes is the maximum size for any integer, floating point or
520 // length in CBOR.
523 };
524
527 QStack<CborValue> containerStack;
528
529 CborParser parser;
530 CborValue currentElement;
532
534 bool corrupt = false;
535
541
546
550
552 {
553 buffer.clear();
554 device = dev;
555 initDecoder();
556 }
557
559 {
561 bufferStart = 0;
562 if (device) {
563 buffer.clear();
564 buffer.reserve(IdealIoBufferSize); // sets the CapacityReserved flag
565 }
566
567 preread();
568 if (CborError err = cbor_parser_init_reader(nullptr, &parser, &currentElement, this))
569 handleError(err);
570 else
572 }
573
574 char *bufferPtr()
575 {
576 Q_ASSERT(buffer.isDetached());
577 return const_cast<char *>(buffer.constData()) + bufferStart;
578 }
579
580 void preread()
581 {
583 // load more, but only if there's more to be read
584 qint64 avail = device->bytesAvailable();
585 Q_ASSERT(avail >= buffer.size());
586 if (avail == buffer.size())
587 return;
588
589 if (bufferStart)
590 device->skip(bufferStart); // skip what we've already parsed
591
592 if (buffer.size() != IdealIoBufferSize)
594
595 bufferStart = 0;
597 if (read < 0)
598 buffer.clear();
599 else if (read != IdealIoBufferSize)
600 buffer.truncate(read);
601 }
602 }
603
604 void handleError(CborError err) noexcept
605 {
606 Q_ASSERT(err);
607
608 // is the error fatal?
609 if (err != CborErrorUnexpectedEOF)
610 corrupt = true;
611
612 lastError = QCborError { QCborError::Code(int(err)) };
613 }
614
616 union {
617 char *ptr;
620 };
621 enum Type { ByteArray = -1, String = -3, Utf8String = -5 };
623
624 ReadStringChunk(char *ptr, qsizetype maxlen) : ptr(ptr), maxlen_or_type(maxlen) {}
627 bool isString() const { return maxlen_or_type == String; }
628 bool isUtf8String() const { return maxlen_or_type == Utf8String; }
629 bool isByteArray() const { return maxlen_or_type == ByteArray; }
630 bool isPlainPointer() const { return maxlen_or_type >= 0; }
631 };
632
634 bool readFullString(ReadStringChunk params);
637 qsizetype readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len);
638 qsizetype readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len);
640};
641
643{
644 d->handleError(CborError(error.c));
645}
646
647static inline bool qt_cbor_decoder_can_read(void *token, size_t len)
648{
650 auto self = static_cast<QCborStreamReaderPrivate *>(token);
651
652 qint64 avail = self->buffer.size() - self->bufferStart;
653 return len <= quint64(avail);
654}
655
656static void qt_cbor_decoder_advance(void *token, size_t len)
657{
659 auto self = static_cast<QCborStreamReaderPrivate *>(token);
660 Q_ASSERT(len <= size_t(self->buffer.size() - self->bufferStart));
661
662 self->bufferStart += int(len);
663 self->preread();
664}
665
666static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len)
667{
668 Q_ASSERT(len == 1 || len == 2 || len == 4 || len == 8);
669 Q_ASSERT(offset == 0 || offset == 1);
670 auto self = static_cast<const QCborStreamReaderPrivate *>(token);
671
672 // we must have pre-read the data
673 Q_ASSERT(len + offset <= size_t(self->buffer.size() - self->bufferStart));
674 return memcpy(userptr, self->buffer.constData() + self->bufferStart + offset, len);
675}
676
677static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len)
678{
679 auto self = static_cast<QCborStreamReaderPrivate *>(token);
680 Q_ASSERT(offset <= size_t(self->buffer.size()));
681 static_assert(sizeof(size_t) >= sizeof(QByteArray::size_type));
682 static_assert(sizeof(size_t) == sizeof(qsizetype));
683
684 // check that we will have enough data from the QIODevice before we advance
685 // (otherwise, we'd lose the length information)
686 qsizetype total;
687 if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
688 || qAddOverflow<qsizetype>(offset, len, &total))
689 return CborErrorDataTooLarge;
690
691 // our string transfer is just saving the offset to the userptr
692 *userptr = reinterpret_cast<void *>(offset);
693
694 qint64 avail = (self->device ? self->device->bytesAvailable() : self->buffer.size()) -
695 self->bufferStart;
696 return total > avail ? CborErrorUnexpectedEOF : CborNoError;
697}
698
700{
701 if (currentElement.flags & CborIteratorFlag_IteratingStringChunks)
702 return true;
703
704 CborError err = cbor_value_begin_string_iteration(&currentElement);
705 if (!err)
706 return true;
707 handleError(err);
708 return false;
709}
710
714inline void QCborStreamReader::preparse()
715{
717 type_ = cbor_value_get_type(&d->currentElement);
718
719 if (type_ == CborInvalidType) {
720 // We may have reached the end.
721 if (d->device && d->containerStack.isEmpty()) {
722 d->buffer.clear();
723 if (d->bufferStart)
724 d->device->skip(d->bufferStart);
725 d->bufferStart = 0;
726 }
727 } else {
728 d->lastError = {};
729 // Undo the type mapping that TinyCBOR does (we have an explicit type
730 // for negative integer and we don't have separate types for Boolean,
731 // Null and Undefined).
732 if (type_ == CborBooleanType || type_ == CborNullType || type_ == CborUndefinedType) {
733 type_ = CborSimpleType;
734 value64 = quint8(d->buffer.at(d->bufferStart)) - CborSimpleType;
735 } else {
736 // Using internal TinyCBOR API!
737 value64 = _cbor_value_extract_int64_helper(&d->currentElement);
738
739 if (cbor_value_is_negative_integer(&d->currentElement))
741 }
742 }
743 } else {
744 type_ = Invalid;
745 }
746}
747
761
772
780 : QCborStreamReader(QByteArray::fromRawData(reinterpret_cast<const char *>(data), len))
781{
782}
783
795
808
815
821{
822 d->setDevice(device);
823 preparse();
824}
825
832{
833 return d->device;
834}
835
842{
843 addData(data.constData(), data.size());
844}
845
865{
866 if (!d->device) {
867 if (len > 0)
868 d->buffer.append(data, len);
869 reparse();
870 } else {
871 qWarning("QCborStreamReader: addData() with device()");
872 }
873}
874
884{
885 d->lastError = {};
886 d->preread();
887 if (CborError err = cbor_value_reparse(&d->currentElement))
888 d->handleError(err);
889 else
890 preparse();
891}
892
903{
904 setDevice(nullptr);
905}
906
921{
922 if (d->device)
923 d->device->reset();
924 d->lastError = {};
925 d->initDecoder();
926 preparse();
927}
928
936{
937 return d->lastError;
938}
939
949{
950 return (d->device ? d->device->pos() : 0) + d->bufferStart;
951}
952
960{
961 return d->containerStack.size();
962}
963
973{
974 if (d->containerStack.isEmpty())
975 return Invalid;
976 return Type(cbor_value_get_type(&std::as_const(d->containerStack).top()));
977}
978
988bool QCborStreamReader::hasNext() const noexcept
989{
990 return cbor_value_is_valid(&d->currentElement) &&
991 !cbor_value_at_end(&d->currentElement);
992}
993
1010bool QCborStreamReader::next(int maxRecursion)
1011{
1013 return false;
1014
1015 if (!hasNext()) {
1016 d->handleError(CborErrorAdvancePastEOF);
1017 } else if (maxRecursion < 0) {
1018 d->handleError(CborErrorNestingTooDeep);
1019 } else if (isContainer()) {
1020 // iterate over each element
1022 while (lastError() == QCborError::NoError && hasNext())
1023 next(maxRecursion - 1);
1026 } else if (isByteArray()) {
1027 char c;
1028 StringResult<qsizetype> r;
1029 do {
1030 r = readStringChunk(&c, 1);
1031 } while (r.status == Ok);
1032 } else if (isString()) {
1033 // we need to use actual readString so we get UTF-8 validation
1034 StringResult<QString> r;
1035 do {
1036 r = readString();
1037 } while (r.status == Ok);
1038 } else {
1039 // fixed types
1040 CborError err = cbor_value_advance_fixed(&d->currentElement);
1041 if (err)
1042 d->handleError(err);
1043 }
1044
1045 preparse();
1046 return d->lastError == QCborError::NoError;
1047}
1048
1068{
1069 return cbor_value_is_length_known(&d->currentElement);
1070}
1071
1082{
1083 CborError err;
1084 switch (type()) {
1085 case String:
1086 case ByteArray:
1087 case Map:
1088 case Array:
1089 if (isLengthKnown())
1090 return value64;
1091 err = CborErrorUnknownLength;
1092 break;
1093
1094 default:
1095 err = CborErrorIllegalType;
1096 break;
1097 }
1098
1099 d->handleError(err);
1100 return quint64(-1);
1101}
1102
1117bool QCborStreamReader::_enterContainer_helper()
1118{
1120 CborError err = cbor_value_enter_container(&d->containerStack.top(), &d->currentElement);
1121 if (!err) {
1122 preparse();
1123 return true;
1124 }
1125 d->handleError(err);
1126 return false;
1127}
1128
1142{
1143 if (d->containerStack.isEmpty()) {
1144 qWarning("QCborStreamReader::leaveContainer: trying to leave top-level element");
1145 return false;
1146 }
1147 if (d->corrupt)
1148 return false;
1149
1150 CborValue container = d->containerStack.pop();
1151 CborError err = cbor_value_leave_container(&container, &d->currentElement);
1152 d->currentElement = container;
1153 if (err) {
1154 d->handleError(err);
1155 return false;
1156 }
1157
1158 preparse();
1159 return true;
1160}
1161
1304
1308
1311QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
1312{
1314 auto r = d->readStringChunk(&result.data);
1315 result.status = r.status;
1316 if (r.status == Error) {
1317 result.data.clear();
1318 } else {
1319 Q_ASSERT(r.data == result.data.size());
1320 if (r.status == EndOfString && lastError() == QCborError::NoError)
1321 preparse();
1322 }
1323
1324 return result;
1325}
1326
1344QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readUtf8String_helper()
1345{
1348 auto r = d->readStringChunk(P{ &result.data, P::Utf8String });
1349 result.status = r.status;
1350 if (r.status == Error) {
1351 result.data.clear();
1352 } else {
1353 Q_ASSERT(r.data == result.data.size());
1354 if (r.status == EndOfString && lastError() == QCborError::NoError)
1355 preparse();
1356 }
1357
1358 return result;
1359}
1360
1374
1378
1381QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
1382{
1384 auto r = d->readStringChunk(&result.data);
1385 result.status = r.status;
1386 if (r.status == Error) {
1387 result.data.clear();
1388 } else {
1389 Q_ASSERT(r.data == result.data.size());
1390 if (r.status == EndOfString && lastError() == QCborError::NoError)
1391 preparse();
1392 }
1393
1394 return result;
1395}
1396
1410qsizetype QCborStreamReader::_currentStringChunkSize() const
1411{
1412 if (!d->ensureStringIteration())
1413 return -1;
1414
1415 size_t len;
1416 CborError err = cbor_value_get_string_chunk_size(&d->currentElement, &len);
1417 if (err == CborErrorNoMoreStringChunks)
1418 return 0; // not a real error
1419 else if (err)
1420 d->handleError(err);
1421 else if (qsizetype(len) < 0)
1422 d->handleError(CborErrorDataTooLarge);
1423 else
1424 return qsizetype(len);
1425 return -1;
1426}
1427
1429{
1430 auto r = readStringChunk(params);
1431 while (r.status == QCborStreamReader::Ok) {
1432 // keep appending
1434 }
1435
1436 bool ok = r.status == QCborStreamReader::EndOfString;
1437 Q_ASSERT(ok == !lastError);
1438 return ok;
1439}
1440
1454
1460
1479bool QCborStreamReader::_readAndAppendToString_helper(QString &dst)
1480{
1481 bool ok = d->readFullString(&dst);
1482 if (ok)
1483 preparse();
1484 return ok;
1485}
1486
1519bool QCborStreamReader::_readAndAppendToUtf8String_helper(QByteArray &dst)
1520{
1522 bool ok = d->readFullString({ &dst, P::Utf8String });
1523 if (ok)
1524 preparse();
1525 return ok;
1526}
1527
1561bool QCborStreamReader::_readAndAppendToByteArray_helper(QByteArray &dst)
1562{
1563 bool ok = d->readFullString(&dst);
1564 if (ok)
1565 preparse();
1566 return ok;
1567}
1568
1599{
1600 auto r = d->readStringChunk({ptr, maxlen});
1601 if (r.status == EndOfString && lastError() == QCborError::NoError)
1602 preparse();
1603 return r;
1604}
1605
1606// used by qcborvalue.cpp
1611
1614{
1615 auto status = reader.d->readStringChunk(data).status;
1616 if (status == QCborStreamReader::EndOfString && reader.lastError() == QCborError::NoError)
1617 reader.preparse();
1618 return status;
1619}
1620
1623{
1624 CborError err;
1625 size_t len;
1626 const void *content = nullptr;
1628 result.data = 0;
1630
1631 lastError = {};
1632 if (!ensureStringIteration())
1633 return result;
1634
1635 // Note: in the current implementation, the call into TinyCBOR below only
1636 // succeeds if we *already* have all the data in memory. That's obvious for
1637 // the case of direct memory (no QIODevice), whereas for QIODevices
1638 // qt_cbor_decoder_transfer_string() enforces that
1639 // QIODevice::bytesAvailable() be bigger than the amount we're about to
1640 // read.
1641 //
1642 // This is an important security gate: if the CBOR stream is corrupt or
1643 // malicious, and has an impossibly large string size, we only go past it
1644 // if the transfer to the destination buffer will succeed (modulo QIODevice
1645 // I/O failures).
1646
1647#if 1
1648 // Using internal TinyCBOR API!
1649 err = _cbor_value_get_string_chunk(&currentElement, &content, &len, &currentElement);
1650#else
1651 // the above is effectively the same as:
1652 if (cbor_value_is_byte_string(&currentElement))
1653 err = cbor_value_get_byte_string_chunk(&currentElement, reinterpret_cast<const uint8_t **>(&content),
1654 &len, &currentElement);
1655 else
1656 err = cbor_value_get_text_string_chunk(&currentElement, reinterpret_cast<const char **>(&content),
1657 &len, &currentElement);
1658#endif
1659
1660 // Range check: using implementation-defined behavior in converting an
1661 // unsigned value out of range of the destination signed type (same as
1662 // "len > size_t(std::numeric_limits<qsizetype>::max())", but generates
1663 // better code with ICC and MSVC).
1664 if (!err && qsizetype(len) < 0)
1665 err = CborErrorDataTooLarge;
1666
1667 if (err) {
1668 if (err == CborErrorNoMoreStringChunks) {
1669 preread();
1670 err = cbor_value_finish_string_iteration(&currentElement);
1672 }
1673 if (err)
1674 handleError(err);
1675 // caller musts call preparse()
1676 return result;
1677 }
1678
1679 qptrdiff offset = qptrdiff(content);
1681 if (device) {
1682 // This first skip can't fail because we've already read this many bytes.
1684 }
1685
1686 if (params.isString()) {
1687 // readString()
1689 } else if (params.isUtf8String()) {
1691 } else {
1692 // readByteArray() or readStringChunk()
1694 }
1695
1696 if (result.data < 0)
1697 return result; // error
1698
1699 // adjust the buffers after we're done reading the string
1700 bufferStart += len;
1701 if (device) {
1702 qsizetype remainingInBuffer = buffer.size() - bufferStart;
1703
1704 if (remainingInBuffer <= 0) {
1705 // We've read from the QIODevice more than what was in the buffer.
1706 buffer.truncate(0);
1707 } else {
1708 // There's still data buffered, but we need to move it around.
1709 char *ptr = buffer.data();
1710 memmove(ptr, ptr + bufferStart, remainingInBuffer);
1711 buffer.truncate(remainingInBuffer);
1712 }
1713
1714 bufferStart = 0;
1715 }
1716
1717 preread();
1719 return result;
1720}
1721
1722inline qsizetype
1724{
1725 qint64 actuallyRead;
1726 qsizetype toRead = qsizetype(len);
1727 qsizetype left = 0; // bytes from the chunk not copied to the user buffer, to discard
1728 char *ptr = nullptr;
1729
1730 if (params.isPlainPointer()) {
1731 left = toRead - params.maxlen_or_type;
1732 if (left < 0)
1733 left = 0; // buffer bigger than string
1734 else
1735 toRead = params.maxlen_or_type; // buffer smaller than string
1736 ptr = params.ptr;
1737 } else if (!params.isString()) {
1738 // See note above on having ensured there is enough incoming data.
1739 auto oldSize = params.array->size();
1740 auto newSize = oldSize;
1741 if (qAddOverflow<decltype(newSize)>(oldSize, toRead, &newSize)) {
1742 handleError(CborErrorDataTooLarge);
1743 return -1;
1744 }
1745 QT_TRY {
1746 params.array->resize(newSize);
1747 } QT_CATCH (const std::bad_alloc &) {
1748 // the distinction between DataTooLarge and OOM is mostly for
1749 // compatibility with Qt 5; in Qt 6, we could consider everything
1750 // to be OOM.
1751 handleError(newSize > QByteArray::max_size() ? CborErrorDataTooLarge: CborErrorOutOfMemory);
1752 return -1;
1753 }
1754
1755 ptr = const_cast<char *>(params.array->constData()) + oldSize;
1756 }
1757
1758 if (device) {
1759 actuallyRead = device->read(ptr, toRead);
1760
1761 if (actuallyRead != toRead) {
1762 actuallyRead = -1;
1763 } else if (left) {
1764 qint64 skipped = device->skip(left);
1765 if (skipped != left)
1766 actuallyRead = -1;
1767 }
1768
1769 if (actuallyRead < 0) {
1770 handleError(CborErrorIO);
1771 return -1;
1772 }
1773 } else {
1774 actuallyRead = toRead;
1775 memcpy(ptr, buffer.constData() + bufferStart, toRead);
1776 }
1777
1778 return actuallyRead;
1779}
1780
1781inline qsizetype
1783{
1784 Q_ASSERT(params.isString());
1785
1786 // See QUtf8::convertToUnicode() a detailed explanation of why this
1787 // conversion uses the same number of words or less.
1788 qsizetype currentSize = params.string->size();
1789 size_t newSize = size_t(utf8len) + size_t(currentSize); // can't overflow
1790 if (utf8len > QString::max_size() || qsizetype(newSize) < 0) {
1791 handleError(CborErrorDataTooLarge);
1792 return -1;
1793 }
1794 QT_TRY {
1795 params.string->resize(qsizetype(newSize));
1796 } QT_CATCH (const std::bad_alloc &) {
1797 handleError(CborErrorOutOfMemory);
1798 return -1;
1799 }
1800
1801 QChar *begin = const_cast<QChar *>(params.string->constData());
1802 QChar *ptr = begin + currentSize;
1804 if (device == nullptr) {
1805 // Easy case: we can decode straight from the buffer we already have
1806 ptr = QUtf8::convertToUnicode(ptr, { buffer.constData() + bufferStart, utf8len }, &cs);
1807 } else {
1808 // read in chunks, to avoid creating large, intermediate buffers
1809 constexpr qsizetype StringChunkSize = 16384;
1810 qsizetype chunkSize = qMin(StringChunkSize, utf8len);
1811 QVarLengthArray<char> chunk(chunkSize);
1812
1814 while (utf8len > 0 && cs.invalidChars == 0) {
1815 qsizetype toRead = qMin(chunkSize, utf8len);
1816 qint64 actuallyRead = device->read(chunk.data(), toRead);
1817 if (actuallyRead == toRead)
1818 ptr = QUtf8::convertToUnicode(ptr, { chunk.data(), toRead }, &cs);
1819
1820 if (actuallyRead != toRead) {
1821 handleError(CborErrorIO);
1822 return -1;
1823 }
1824 utf8len -= toRead;
1825 }
1826 }
1827
1828 if (cs.invalidChars != 0 || cs.remainingChars != 0) {
1829 handleError(CborErrorInvalidUtf8TextString);
1830 return -1;
1831 }
1832
1833 qsizetype size = ptr - begin;
1834 params.string->truncate(ptr - begin);
1835 return size - currentSize; // how many bytes we added
1836}
1837
1838inline qsizetype
1840{
1842 if (result < 0)
1843 return result;
1844
1845 // validate the UTF-8 content we've just read
1846 QByteArrayView chunk = *params.array;
1847 chunk = chunk.last(result);
1848 if (QtPrivate::isValidUtf8(chunk))
1849 return result;
1850
1851 handleError(CborErrorInvalidUtf8TextString);
1852 return -1;
1853}
1854
1856
1857#include "moc_qcborstreamreader.cpp"
IOBluetoothDevice * device
constexpr QByteArrayView last(qsizetype n) const
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size_type
Definition qbytearray.h:459
static constexpr qsizetype max_size() noexcept
Definition qbytearray.h:485
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
Definition qbytearray.h:600
void clear()
Clears the contents of the byte array and makes it null.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStack< CborValue > containerStack
void handleError(CborError err) noexcept
QCborStreamReaderPrivate(QIODevice *device)
QByteArray::size_type bufferStart
qsizetype readStringChunk_byte(ReadStringChunk params, qsizetype len)
bool readFullString(ReadStringChunk params)
qsizetype readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len)
static QCborStreamReader::StringResultCode appendStringChunk(QCborStreamReader &reader, QByteArray *data)
QCborStreamReader::StringResult< qsizetype > readStringChunk(ReadStringChunk params)
qsizetype readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len)
void setDevice(QIODevice *dev)
QCborStreamReaderPrivate(const QByteArray &data)
\inmodule QtCore\reentrant
void setDevice(QIODevice *device)
Sets the source of data to device, resetting the decoder to its initial state.
bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION
Returns true if the length of the current array, map, byte array or string is known (explicit in the ...
QCborError lastError() const
Returns the last error in decoding the stream, if any.
QIODevice * device() const
Returns the QIODevice that was set with either setDevice() or the QCborStreamReader constructor.
void clear()
Clears the decoder state and resets the input source data to an empty byte array.
qint64 currentOffset() const
Returns the offset in the input stream of the item currently being decoded.
bool isByteArray() const
Returns true if the type of the current element is a byte array (that is, if type() returns QCborStre...
bool next(int maxRecursion=10000)
Advance the CBOR stream decoding one element.
void addData(const QByteArray &data)
Adds data to the CBOR stream and reparses the current element.
bool isString() const
Returns true if the type of the current element is a text string (that is, if type() returns QCborStr...
void reset()
Resets the source back to the beginning and clears the decoder state.
QCborStreamReader()
Creates a QCborStreamReader object with no source data.
QCborStreamReader::Type parentContainerType() const
Returns either QCborStreamReader::Array or QCborStreamReader::Map, indicating whether the container t...
bool enterContainer()
Enters the array or map that is the current item and prepares for iterating the elements contained in...
void reparse()
Reparses the current element.
quint64 length() const
Returns the length of the string or byte array, or the number of items in an array or the number,...
StringResult< QString > readString()
Decodes one string chunk from the CBOR string and returns it.
bool hasNext() const noexcept Q_DECL_PURE_FUNCTION
Returns true if there are more items to be decoded in the current container or false of we've reached...
StringResultCode
This enum is returned by readString() and readByteArray() and is used to indicate what the status of ...
StringResult< qsizetype > readStringChunk(char *ptr, qsizetype maxlen)
Reads the current string chunk into the buffer pointed to by ptr, whose size is maxlen.
Type
This enumeration contains all possible CBOR types as decoded by QCborStreamReader.
bool isContainer() const
Returns true if the current element is a container (that is, an array or a map), false if it is anyth...
~QCborStreamReader()
Destroys this QCborStreamReader object and frees any associated resources.
bool leaveContainer()
Leaves the array or map whose items were being processed and positions the decoder at the next item a...
int containerDepth() const
Returns the number of containers that this stream has entered with enterContainer() but not yet left.
\inmodule QtCore
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
qint64 peek(char *data, qint64 maxlen)
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
qint64 skip(qint64 maxSize)
virtual bool reset()
Seeks to the start of input for random-access devices.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void clear()
Definition qlist.h:434
T & top()
Returns a reference to the stack's top item.
Definition qstack.h:19
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
void push(const T &t)
Adds element t to the top of the stack.
Definition qstack.h:17
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1246
static constexpr qsizetype max_size() noexcept
Definition qstring.h:964
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QString str
[2]
short next
Definition keywords.cpp:445
Token token
Definition keywords.cpp:444
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf8(QByteArrayView s) noexcept
QT_WARNING_PUSH static QT_WARNING_POP CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
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 *)
#define Q_NEVER_INLINE
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_MSVC(number)
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
DBusConnection const char DBusError * error
#define QT_CATCH(A)
#define QT_TRY
#define qWarning
Definition qlogging.h:166
static ControlElement< T > * ptr(QWidget *widget)
@ Invalid
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflow(T v1, T v2, T *r)
Definition qnumeric.h:113
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLint left
GLenum type
GLenum GLenum dst
GLenum GLuint GLintptr offset
void ** params
const GLubyte * c
GLenum array
GLuint64EXT * result
[6]
GLenum GLsizei len
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
ptrdiff_t qptrdiff
Definition qtypes.h:164
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
unsigned char quint8
Definition qtypes.h:46
ReturnedValue read(const char *data)
QObject::connect nullptr
\inmodule QtCore \inheaderfile QtCborCommon \reentrant
Definition qcborcommon.h:63
Code
This enum contains the possible error condition codes.
Definition qcborcommon.h:66
ReadStringChunk(QByteArray *array, Type type=ByteArray)
static QChar * convertToUnicode(QChar *buffer, QByteArrayView in) noexcept
Definition moc.h:23