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
qcborstreamwriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 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 "qcborstreamwriter.h"
5
6#define CBOR_NO_PARSER_API
7#include <private/qcborcommon_p.h>
8
9#include <private/qnumeric_p.h>
10#include <private/qstringconverter_p.h>
11#include <qbuffer.h>
12#include <qdebug.h>
13#include <qstack.h>
14#include <qvarlengtharray.h>
15
17
18static CborError qt_cbor_encoder_write_callback(void *token, const void *data, size_t len, CborEncoderAppendType);
19#define CBOR_ENCODER_WRITER_CONTROL 1
20#define CBOR_ENCODER_WRITE_FUNCTION qt_cbor_encoder_write_callback
21#define CBOR_ENCODER_NO_CHECK_USER
22
24QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
25
26#include <cborencoder.c>
27
29
30// silence compilers that complain about this being a static function declared
31// but never defined
32[[maybe_unused]] static CborError cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
33{
34 Q_UNREACHABLE_RETURN(CborErrorInternalError);
35}
36
37[[maybe_unused]] static CborError cbor_encode_float_as_half_float(CborEncoder *, float)
38{
39 Q_UNREACHABLE_RETURN(CborErrorInternalError);
40}
41
43
184{
185public:
186 static constexpr quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
187
189 CborEncoder encoder;
190 QStack<CborEncoder> containerStack;
191 bool deleteDevice = false;
192
194 : device(device)
195 {
196 cbor_encoder_init_writer(&encoder, qt_cbor_encoder_write_callback, this);
197 }
198
200 {
201 if (deleteDevice)
202 delete device;
203 }
204
205 template <typename... Args> void executeAppend(CborError (*f)(CborEncoder *, Args...), Args... args)
206 {
207 f(&encoder, std::forward<Args>(args)...);
208 }
209
210 void createContainer(CborError (*f)(CborEncoder *, CborEncoder *, size_t), quint64 len = IndefiniteLength)
211 {
212 static_assert(size_t(IndefiniteLength) == CborIndefiniteLength);
213 if (sizeof(len) != sizeof(size_t) && len != IndefiniteLength) {
214 if (Q_UNLIKELY(len >= CborIndefiniteLength)) {
215 // TinyCBOR can't do this in 32-bit mode
216 qWarning("QCborStreamWriter: container of size %llu is too big for a 32-bit build; "
217 "will use indeterminate length instead", len);
218 len = CborIndefiniteLength;
219 }
220 }
221
224 }
225
227 {
228 if (containerStack.isEmpty()) {
229 qWarning("QCborStreamWriter: closing map or array that wasn't open");
230 return false;
231 }
232
233 CborEncoder container = containerStack.pop();
234 CborError err = cbor_encoder_close_container(&container, &encoder);
235 encoder = container;
236
237 if (Q_UNLIKELY(err)) {
238 if (err == CborErrorTooFewItems)
239 qWarning("QCborStreamWriter: not enough items added to array or map");
240 else if (err == CborErrorTooManyItems)
241 qWarning("QCborStreamWriter: too many items added to array or map");
242 return false;
243 }
244
245 return true;
246 }
247};
248
249static CborError qt_cbor_encoder_write_callback(void *self, const void *data, size_t len, CborEncoderAppendType)
250{
251 auto that = static_cast<QCborStreamWriterPrivate *>(self);
252 if (!that->device)
253 return CborNoError;
254 qint64 written = that->device->write(static_cast<const char *>(data), len);
255 return (written == qsizetype(len) ? CborNoError : CborErrorIO);
256}
257
279
298
309
317{
318 if (d->deleteDevice)
319 delete d->device;
320 d->device = device;
321 d->deleteDevice = false;
322}
323
335{
336 return d->device;
337}
338
351{
352 d->executeAppend(cbor_encode_uint, uint64_t(u));
353}
354
368{
369 d->executeAppend(cbor_encode_int, int64_t(i));
370}
371
392{
393 d->executeAppend(cbor_encode_negative_int, uint64_t(n));
394}
395
437{
438 // We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
439 // common subset (US-ASCII).
440 if (QtPrivate::isAscii(str)) {
441 // it is plain US-ASCII
442 appendTextString(str.latin1(), str.size());
443 } else {
444 // non-ASCII, convert:
445 QVarLengthArray<char> utf8(str.size() * 2); // each L1 char gives at most two U8 units
446 const qsizetype written = QUtf8::convertFromLatin1(utf8.data(), str) - utf8.data();
447 appendTextString(utf8.data(), written);
448 }
449}
450
465{
466 QByteArray utf8 = str.toUtf8();
467 appendTextString(utf8.constData(), utf8.size());
468}
469
484{
485 d->executeAppend(cbor_encode_tag, CborTag(tag));
486}
487
520{
521 d->executeAppend(cbor_encode_simple_value, uint8_t(st));
522}
523
524#ifndef QT_BOOTSTRAPPED
538{
539 d->executeAppend(cbor_encode_half_float, static_cast<const void *>(&f));
540}
541#endif // QT_BOOTSTRAPPED
542
556{
557 d->executeAppend(cbor_encode_float, f);
558}
559
581{
582 this->d->executeAppend(cbor_encode_double, d);
583}
584
599{
600 d->executeAppend(cbor_encode_byte_string, reinterpret_cast<const uint8_t *>(data), size_t(len));
601}
602
619{
620 d->executeAppend(cbor_encode_text_string, utf8, size_t(len));
621}
622
709{
710 d->createContainer(cbor_encoder_create_array);
711}
712
741{
742 d->createContainer(cbor_encoder_create_array, count);
743}
744
760{
761 return d->closeContainer();
762}
763
783{
784 d->createContainer(cbor_encoder_create_map);
785}
786
815{
816 d->createContainer(cbor_encoder_create_map, count);
817}
818
834{
835 return d->closeContainer();
836}
837
839
840#undef CBOR_ENCODER_WRITER_CONTROL
841#undef CBOR_ENCODER_WRITE_FUNCTION
842#undef CBOR_ENCODER_NO_CHECK_USER
IOBluetoothDevice * device
\inmodule QtCore \reentrant
Definition qbuffer.h:16
\inmodule QtCore
Definition qbytearray.h:57
void executeAppend(CborError(*f)(CborEncoder *, Args...), Args... args)
QCborStreamWriterPrivate(QIODevice *device)
QStack< CborEncoder > containerStack
static constexpr quint64 IndefiniteLength
void createContainer(CborError(*f)(CborEncoder *, CborEncoder *, size_t), quint64 len=IndefiniteLength)
void setDevice(QIODevice *device)
Replaces the device or byte array that this QCborStreamWriter object is writing to with device.
~QCborStreamWriter()
Destroys this QCborStreamWriter object and frees any resources associated.
bool endMap()
Terminates the map started by either overload of startMap() and returns true if the correct number of...
void startMap()
Starts a CBOR Map with indeterminate length in the CBOR stream.
void appendTextString(const char *utf8, qsizetype len)
Appends len bytes of text starting from utf8 to the stream, creating a CBOR Text String value.
void appendByteString(const char *data, qsizetype len)
Appends len bytes of data starting from data to the stream, creating a CBOR Byte String value.
QCborStreamWriter(QIODevice *device)
Creates a QCborStreamWriter object that will write the stream to device.
void startArray()
Starts a CBOR Array with indeterminate length in the CBOR stream.
void append(quint64 u)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool endArray()
Terminates the array started by either overload of startArray() and returns true if the correct numbe...
QIODevice * device() const
Returns the QIODevice that this QCborStreamWriter object is writing to.
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
bool isEmpty() const noexcept
Definition qlist.h:401
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
\inmodule QtCore
Definition qstringview.h:78
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QByteArray toUtf8() const &
Definition qstring.h:634
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
Definition qfloat16.h:47
QString str
[2]
Token token
Definition keywords.cpp:444
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1StringView s) noexcept
Definition qstring.cpp:850
QCborTag
Definition qcborcommon.h:30
QCborSimpleType
Definition qcborcommon.h:23
QCborNegativeInteger
QT_WARNING_PUSH static QT_WARNING_POP CborError cbor_encoder_close_container_checked(CborEncoder *, const CborEncoder *)
static QT_BEGIN_NAMESPACE CborError qt_cbor_encoder_write_callback(void *token, const void *data, size_t len, CborEncoderAppendType)
static CborError cbor_encode_float_as_half_float(CborEncoder *, float)
#define Q_UNLIKELY(x)
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_MSVC(number)
#define QT_WARNING_PUSH
AudioChannelLayoutTag tag
#define qWarning
Definition qlogging.h:166
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLfloat n
GLenum GLsizei len
@ Q_PRIMITIVE_TYPE
Definition qtypeinfo.h:157
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
QJSValueList args
static Q_CORE_EXPORT char * convertFromLatin1(char *out, QLatin1StringView in)