Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcborvalue_p.h
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#ifndef QCBORVALUE_P_H
5#define QCBORVALUE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API.
12// This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qcborvalue.h"
19
20#if QT_CONFIG(cborstreamreader)
21# include "qcborstreamreader.h"
22#endif
23
24#include <private/qglobal_p.h>
25#include <private/qstringconverter_p.h>
26
27#include <math.h>
28
30
31namespace QtCbor {
32struct Undefined {};
33struct Element
34{
36 IsContainer = 0x0001,
37 HasByteData = 0x0002,
38 StringIsUtf16 = 0x0004,
39 StringIsAscii = 0x0008
40 };
41 Q_DECLARE_FLAGS(ValueFlags, ValueFlag)
42
43 union {
46 };
48 ValueFlags flags = {};
49
51 : value(v), type(t), flags(f)
52 {}
53
56 {}
57
58 double fpvalue() const
59 {
60 double d;
61 memcpy(&d, &value, sizeof(d));
62 return d;
63 }
64};
65Q_DECLARE_OPERATORS_FOR_FLAGS(Element::ValueFlags)
66static_assert(sizeof(Element) == 16);
67
69{
71
72 const char *byte() const { return reinterpret_cast<const char *>(this + 1); }
73 char *byte() { return reinterpret_cast<char *>(this + 1); }
74 const QChar *utf16() const { return reinterpret_cast<const QChar *>(this + 1); }
75 QChar *utf16() { return reinterpret_cast<QChar *>(this + 1); }
76
77 QByteArray toByteArray() const { return QByteArray(byte(), len); }
78 QString toString() const { return QString(utf16(), len / 2); }
79 QString toUtf8String() const { return QString::fromUtf8(byte(), len); }
80
82 QLatin1StringView asLatin1() const { return {byte(), len}; }
84 QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
86};
87static_assert(std::is_trivial<ByteData>::value);
88static_assert(std::is_standard_layout<ByteData>::value);
89} // namespace QtCbor
90
92
94{
97
98public:
100
104
105 void deref() { if (!ref.deref()) delete this; }
106 void compact(qsizetype reserved);
110
111 qptrdiff addByteData(const char *block, qsizetype len)
112 {
113 // This function does not do overflow checking, since the len parameter
114 // is expected to be trusted. There's another version of this function
115 // in decodeStringFromCbor(), which checks.
116
117 qptrdiff offset = data.size();
118
119 // align offset
120 offset += alignof(QtCbor::ByteData) - 1;
121 offset &= ~(alignof(QtCbor::ByteData) - 1);
122
124
126 data.resize(offset + increment);
127
128 char *ptr = data.begin() + offset;
129 auto b = new (ptr) QtCbor::ByteData;
130 b->len = len;
131 if (block)
132 memcpy(b->byte(), block, len);
133
134 return offset;
135 }
136
138 {
139 if ((e.flags & QtCbor::Element::HasByteData) == 0)
140 return nullptr;
141
142 size_t offset = size_t(e.value);
143 Q_ASSERT((offset % alignof(QtCbor::ByteData)) == 0);
144 Q_ASSERT(offset + sizeof(QtCbor::ByteData) <= size_t(data.size()));
145
146 auto b = reinterpret_cast<const QtCbor::ByteData *>(data.constData() + offset);
147 Q_ASSERT(offset + sizeof(*b) + size_t(b->len) <= size_t(data.size()));
148 return b;
149 }
151 {
152 return byteData(elements.at(idx));
153 }
154
156 {
157 const QtCbor::Element &e = elements.at(idx);
158 if (e.type != type || (e.flags & QtCbor::Element::IsContainer) == 0)
159 return nullptr;
160 return e.container;
161 }
162
165 {
166 if (value.container)
167 return replaceAt_complex(e, value, disp);
168
169 e = { value.value_helper(), value.type() };
170 if (value.isContainer())
171 e.container = nullptr;
172 }
174 {
175 QtCbor::Element &e = elements[idx];
176 if (e.flags & QtCbor::Element::IsContainer) {
177 e.container->deref();
178 e.container = nullptr;
179 e.flags = {};
180 } else if (auto b = byteData(e)) {
181 usedData -= b->len + sizeof(QtCbor::ByteData);
182 }
183 replaceAt_internal(e, value, disp);
184 }
186 {
187 replaceAt_internal(*elements.insert(elements.begin() + int(idx), {}), value, disp);
188 }
189
191 {
193 }
195 {
197 }
199 {
201 }
203 QtCbor::Element::ValueFlags extraFlags = {})
204 {
206 QtCbor::Element::HasByteData | extraFlags));
207 }
210 {
212 }
214 {
216 }
218 {
219 if (!QtPrivate::isAscii(s))
220 return append(QString(s));
221
222 // US-ASCII is a subset of UTF-8, so we can keep in 8-bit
223 appendByteData(s.latin1(), s.size(), QCborValue::String,
225 }
227
228 void append(const QString &s)
229 {
231 }
232
234 {
237 else
238 appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
240 }
241 void append(const QCborValue &v)
242 {
244 }
245
247 {
248 const auto &e = elements.at(idx);
249 const auto data = byteData(e);
250 if (!data)
251 return QByteArray();
252 return data->toByteArray();
253 }
255 {
256 const auto &e = elements.at(idx);
257 const auto data = byteData(e);
258 if (!data)
259 return QString();
261 return data->toString();
263 return data->asLatin1();
264 return data->toUtf8String();
265 }
266
267 static void resetValue(QCborValue &v)
268 {
269 v.container = nullptr;
270 }
271
274 {
276 result.n = n;
277 result.container = d;
278 if (d && disp == CopyContainer)
279 d->ref.ref();
280 return result;
281 }
282
284 {
285 const auto &e = elements.at(idx);
286
287 if (e.flags & QtCbor::Element::IsContainer) {
288 if (e.type == QCborValue::Tag && e.container->elements.size() != 2) {
289 // invalid tags can be created due to incomplete parsing
290 return makeValue(QCborValue::Invalid, 0, nullptr);
291 }
292 return makeValue(e.type, -1, e.container);
293 } else if (e.flags & QtCbor::Element::HasByteData) {
294 return makeValue(e.type, idx, const_cast<QCborContainerPrivate *>(this));
295 }
296 return makeValue(e.type, e.value);
297 }
300 {
302 qSwap(e, elements[idx]);
303
304 if (e.flags & QtCbor::Element::IsContainer) {
305 if (e.type == QCborValue::Tag && e.container->elements.size() != 2) {
306 // invalid tags can be created due to incomplete parsing
307 e.container->deref();
308 return makeValue(QCborValue::Invalid, 0, nullptr);
309 }
310 return makeValue(e.type, -1, e.container, MoveContainer);
311 } else if (e.flags & QtCbor::Element::HasByteData) {
312 return extractAt_complex(e);
313 }
314 return makeValue(e.type, e.value);
315 }
316
318 {
319 if (value.n >= 0 && value.container)
320 return value.container->elements.at(value.n);
321
323 e.value = value.n;
324 e.type = value.t;
325 if (value.container) {
326 e.container = value.container;
328 }
329 return e;
330 }
331
333 {
334 return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
335 }
336
338 {
339 return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
340 }
341
342 template<typename String>
343 int stringCompareElement(const QtCbor::Element &e, String s) const
344 {
345 if (e.type != QCborValue::String)
346 return int(e.type) - int(QCborValue::String);
347
348 const QtCbor::ByteData *b = byteData(e);
349 if (!b)
350 return s.isEmpty() ? 0 : -1;
351
353 return QtPrivate::compareStrings(b->asStringView(), s);
354 return compareUtf8(b, s);
355 }
356
357 template<typename String>
358 bool stringEqualsElement(const QtCbor::Element &e, String s) const
359 {
360 return stringCompareElement(e, s) == 0;
361 }
362
363 template<typename String>
364 bool stringEqualsElement(qsizetype idx, String s) const
365 {
366 return stringEqualsElement(elements.at(idx), s);
367 }
368
372 {
373 auto &e1 = elements.at(idx);
374 auto e2 = elementFromValue(value);
375 return compareElement_helper(this, e1, value.container, e2);
376 }
377
379 {
380 replaceAt(idx, {});
381 elements.remove(idx);
382 }
383
384 // doesn't apply to JSON
385 template <typename KeyType> QCborValueConstRef findCborMapKey(KeyType key)
386 {
387 qsizetype i = 0;
388 for ( ; i < elements.size(); i += 2) {
389 const auto &e = elements.at(i);
390 bool equals;
391 if constexpr (std::is_same_v<std::decay_t<KeyType>, QCborValue>) {
392 equals = (compareElement(i, key) == 0);
393 } else if constexpr (std::is_integral_v<KeyType>) {
394 equals = (e.type == QCborValue::Integer && e.value == key);
395 } else {
396 // assume it's a string
397 equals = stringEqualsElement(i, key);
398 }
399 if (equals)
400 break;
401 }
402 return { this, i + 1 };
403 }
404 template <typename KeyType> static QCborValue findCborMapKey(const QCborValue &self, KeyType key)
405 {
406 if (self.isMap() && self.container) {
407 qsizetype idx = self.container->findCborMapKey(key).i;
408 if (idx < self.container->elements.size())
409 return self.container->valueAt(idx);
410 }
411 return QCborValue();
412 }
413 template <typename KeyType> static QCborValueRef
415 {
416 qsizetype size = 0;
417 qsizetype index = size + 1;
418 if (container) {
419 size = container->elements.size();
420 index = container->findCborMapKey<KeyType>(key).i; // returns size + 1 if not found
421 }
422 Q_ASSERT(index & 1);
423 Q_ASSERT((size & 1) == 0);
424
425 container = detach(container, qMax(index + 1, size));
426 Q_ASSERT(container);
427 Q_ASSERT((container->elements.size() & 1) == 0);
428
429 if (index >= size) {
430 container->append(key);
431 container->append(QCborValue());
432 }
433 Q_ASSERT(index < container->elements.size());
434 return { container, index };
435 }
436 template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborMap &map, KeyType key);
437 template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValue &self, KeyType key);
438 template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValueRef self, KeyType key);
439
440#if QT_CONFIG(cborstreamreader)
441 void decodeValueFromCbor(QCborStreamReader &reader, int remainingStackDepth);
442 void decodeStringFromCbor(QCborStreamReader &reader);
443 static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
444#endif
445};
446
448
449#endif // QCBORVALUE_P_H
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size_type
Definition qbytearray.h:444
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
QString stringAt(qsizetype idx) const
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp=CopyContainer)
QByteArray::size_type usedData
const QtCbor::ByteData * byteData(QtCbor::Element e) const
static int compareUtf8(const QtCbor::ByteData *b, QStringView s)
void replaceAt_internal(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp)
void append(QStringView s)
void appendUtf8String(const char *str, qsizetype len)
void append(const QString &s)
void append(const QCborValue &v)
const QtCbor::ByteData * byteData(qsizetype idx) const
void appendByteData(const char *data, qsizetype len, QCborValue::Type type, QtCbor::Element::ValueFlags extraFlags={})
static QCborContainerPrivate * grow(QCborContainerPrivate *d, qsizetype index)
Prepare for an insertion at position index.
static QCborContainerPrivate * detach(QCborContainerPrivate *d, qsizetype reserved)
bool stringEqualsElement(const QtCbor::Element &e, String s) const
void removeAt(qsizetype idx)
static int compareUtf8(const QtCbor::ByteData *b, QLatin1StringView s)
void append(QLatin1StringView s)
QCborValueConstRef findCborMapKey(KeyType key)
void replaceAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp=CopyContainer)
QList< QtCbor::Element > elements
void append(QCborTag tag)
void compact(qsizetype reserved)
void appendAsciiString(const char *str, qsizetype len)
QCborValue extractAt(qsizetype idx)
int stringCompareElement(const QtCbor::Element &e, String s) const
void append(QtCbor::Undefined)
QByteArray byteArrayAt(qsizetype idx) const
QCborContainerPrivate * containerAt(qsizetype idx, QCborValue::Type type) const
static QCborValue makeValue(QCborValue::Type type, qint64 n, QCborContainerPrivate *d=nullptr, ContainerDisposition disp=CopyContainer)
static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1, const QCborContainerPrivate *c2, QtCbor::Element e2)
static QCborValueRef findOrAddMapKey(QCborContainerPrivate *container, KeyType key)
QCborValue extractAt_complex(QtCbor::Element e)
void appendAsciiString(const QString &s)
int compareElement(qsizetype idx, const QCborValue &value) const
qptrdiff addByteData(const char *block, qsizetype len)
static QtCbor::Element elementFromValue(const QCborValue &value)
void replaceAt_complex(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp)
static void resetValue(QCborValue &v)
static QCborValue findCborMapKey(const QCborValue &self, KeyType key)
bool stringEqualsElement(qsizetype idx, String s) const
QCborValue valueAt(qsizetype idx) const
void append(qint64 value)
static QCborContainerPrivate * clone(QCborContainerPrivate *d, qsizetype reserved=-1)
\inmodule QtCore\reentrant
Definition qcbormap.h:21
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
Definition qcborvalue.h:50
Type
This enum represents the QCborValue type.
Definition qcborvalue.h:73
\inmodule QtCore
Definition qchar.h:48
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:471
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
iterator begin()
Definition qlist.h:608
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qshareddata.h:19
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
static QString fromRawData(const QChar *, qsizetype size)
Constructs a QString that uses the first size Unicode characters in the array unicode.
Definition qstring.cpp:9242
QString str
[2]
QMap< QString, QString > map
[6]
qSwap(pi, e)
double e
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1StringView s) noexcept
Definition qstring.cpp:860
QCborTag
Definition qcborcommon.h:30
AudioChannelLayoutTag tag
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLfloat GLfloat f
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint ref
GLfloat n
GLenum GLsizei len
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QBasicUtf8StringView< false > QUtf8StringView
Definition qstringfwd.h:46
QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
@ Q_PRIMITIVE_TYPE
Definition qtypeinfo.h:144
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:163
unsigned int quint32
Definition qtypes.h:45
ptrdiff_t qptrdiff
Definition qtypes.h:69
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
QtConcurrent::task([]{ qDebug("Hello, world!");}).spawn(FutureResult void increment(QPromise< int > &promise, int i)
[10]
MyCustomStruct c2
\inmodule QtCore \inheaderfile QtCborCommon \reentrant
Definition qcborcommon.h:63
static int compareUtf8(QByteArrayView utf8, QStringView utf16, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
QString toUtf8String() const
QStringView asStringView() const
QUtf8StringView asUtf8StringView() const
QLatin1StringView asLatin1() const
QString asQStringRaw() const
const QChar * utf16() const
QString toString() const
const char * byte() const
QByteArray::size_type len
QByteArray asByteArrayView() const
QByteArray toByteArray() const
double fpvalue() const
Element(qint64 v=0, QCborValue::Type t=QCborValue::Undefined, ValueFlags f={})
Element(QCborContainerPrivate *d, QCborValue::Type t, ValueFlags f={})
QCborValue::Type type
QCborContainerPrivate * container