1/****************************************************************************
2**
3** Copyright (C) 2018 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcborvalue.h"
41#include "qcborvalue_p.h"
42#include "qdatastream.h"
43#include "qcborarray.h"
44#include "qcbormap.h"
45#include "qcborstream.h"
46
47#include <qendian.h>
48#include <qlocale.h>
49#include <private/qnumeric_p.h>
50#include <private/qsimd_p.h>
51
52#include <new>
53
54QT_BEGIN_NAMESPACE
55
56/*!
57 \class QCborValue
58 \inmodule QtCore
59 \ingroup cbor
60 \reentrant
61 \since 5.12
62
63 \brief The QCborValue class encapsulates a value in CBOR.
64
65 This class can be used to hold one of the many types available in CBOR.
66 CBOR is the Concise Binary Object Representation, a very compact form of
67 binary data encoding that is a superset of JSON. It was created by the IETF
68 Constrained RESTful Environments (CoRE) WG, which has used it in many
69 new RFCs. It is meant to be used alongside the
70 \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
71
72 CBOR has three groups of built-in types:
73
74 \list
75 \li Basic types: integers, floating point (double), boolean, null, etc.
76 \li String-like types: strings and byte arrays
77 \li Containers: arrays and maps
78 \endlist
79
80 Additionally, CBOR supports a form of type extensibility by associating a
81 "tag" to one of the above types to convey more information. For example, a
82 UUID is represented by a tag and a byte array containing the 16 bytes of
83 the UUID content. QCborValue supports creating and decoding several of those
84 extended types directly with Qt classes (like QUuid).
85
86 For the complete list, see \l QCborValue::Type. The type of a QCborValue can
87 be queried using type() or one of the "isXxxx" functions.
88
89 \section1 Extended types and tagged values
90
91 A tagged value is a normal QCborValue that is paired with a number that
92 is its tag. See \l QCborKnownTags for more information on what tags are in
93 the API as well as the full, official list. Such combinations form extended
94 types.
95
96 QCborValue has support for certain extended types in the API, like URL
97 (with \l QUrl) and UUID (with \l QUuid). Other extended types not supported
98 in the API are represented by a QCborValue of \l {Type}{Tag} type. The tag
99 can later be retrieved by tag() and the tagged value using taggedValue().
100
101 In order to support future compatibility, QCborValues containing extended
102 Qt types compare equal to the tag type of the same contents. In other
103 words, the following expression is true:
104
105 \snippet code/src_corelib_serialization_qcborvalue.cpp 0
106
107 \section1 Undefined and null values
108
109 QCborValue can contain a value of "null", which is not of any specific type.
110 It resembles the C++ \c {std::nullptr_t} type, whose only possible value is
111 \nullptr. QCborValue has a constructor taking such a type and creates a
112 null QCborValue.
113
114 Null values are used to indicate that an optional value is not present. In
115 that aspect, it is similar to the C++ Standard Library type \c
116 {std::optional} when that is disengaged. Unlike the C++ type, CBOR nulls
117 are simply of type "Null" and it is not possible to determine what concrete
118 type it is replacing.
119
120 QCborValue can also be of the undefined type, which represents a value of
121 "undefined". In fact, that is what the QCborValue default constructor
122 creates.
123
124 Undefined values are different from null values. While nulls are used to
125 indicate an optional value that is not provided, Undefined is usually
126 used to indicate that an expected value could not be provided, usually due
127 to an error or a precondition that could not be satisfied.
128
129 Such values are completely valid and may appear in CBOR streams, unlike
130 JSON content and QJsonValue's undefined bit. But like QJsonValue's
131 Undefined, it is returned by a CBOR container's value() or read-only
132 operator[] for invalid look-ups (index out of range for QCborArray, or key
133 not found for QCborMap). It is not possible to tell such a case apart from
134 the value of Undefined, so if that is required, check the QCborArray size
135 and use the QCborMap iterator API.
136
137 \section1 Simple types
138
139 CBOR supports additional simple types that, like Null and Undefined, carry
140 no other value. They are called interchangeably "Simple Types" and "Simple
141 Values". CBOR encodes booleans as two distinct types (one for \c true and
142 one for \c false), but QCborValue has a convenience API for them.
143
144 There are currently no other defined CBOR simple types. QCborValue supports
145 them simply by their number with API like isSimpleType() and
146 toSimpleType(), available for compatibility with future specifications
147 before the Qt API can be updated. Their use before such a specification is
148 discouraged, as other CBOR implementations may not support them fully.
149
150 \section1 CBOR support
151
152 QCborValue supports all CBOR features required to create canonical and
153 strict streams. It implements almost all of the features specified in \l
154 {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
155
156 The following table lists the CBOR features that QCborValue supports.
157
158 \table
159 \header \li Feature \li Support
160 \row \li Unsigned numbers \li Yes (\l qint64 range)
161 \row \li Negative numbers \li Yes (\l qint64 range)
162 \row \li Byte strings \li Yes
163 \row \li Text strings \li Yes
164 \row \li Chunked strings \li See below
165 \row \li Tags \li Yes (arbitrary)
166 \row \li Booleans \li Yes
167 \row \li Null \li Yes
168 \row \li Undefined \li Yes
169 \row \li Arbitrary simple values \li Yes
170 \row \li Half-precision float (16-bit) \li Yes
171 \row \li Single-precision float (32-bit) \li Yes
172 \row \li Double-precision float (64-bit) \li Yes
173 \row \li Infinities and NaN floating point \li Yes
174 \row \li Determinate-length arrays and maps \li Yes
175 \row \li Indeterminate-length arrays and maps \li Yes
176 \row \li Map key types other than strings and integers \li Yes (arbitrary)
177 \endtable
178
179 Integers in QCborValue are limited to the range of the \l qint64 type. That
180 is, from -9,223,372,036,854,775,808 (-2\sup{63}) to
181 9,223,372,036,854,775,807 (2\sup{63} - 1). CBOR itself can represent integer
182 values outside of this range, which QCborValue does not support. When
183 decoding a stream using fromCbor() containing one of those values,
184 QCborValue will convert automatically to \l {Type}{Double}, but that may
185 lose up to 11 bits of precision.
186
187 fromCbor() is able to decode chunked strings, but will always merge the
188 chunks together into a single QCborValue. For that reason, it always writes
189 non-chunked strings when using toCbor() (which is required by the Canonical
190 format anyway).
191
192 QCborValue will always convert half- and single-precision floating point
193 values in the CBOR stream to double-precision. The toCbor() function can
194 take a parameter indicating to recreate them.
195
196 \section1 QCborValueRef
197
198 QCborValueRef is a helper class for QCborArray and QCborMap. It is the type
199 you get when using one of the mutating APIs in those classes. Unlike
200 QCborValue, new values can be assigned to that class. When that is done, the
201 array or map it refers to will be modified with the new value. In all other
202 aspects, its API is identical to QCborValue.
203
204 \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter
205 QJsonValue, QJsonDocument
206 */
207
208/*!
209 \class QCborParserError
210 \inmodule QtCore
211 \ingroup cbor
212 \reentrant
213 \since 5.12
214
215 \brief The QCborParserError is used by QCborValue to report a parsing error.
216
217 This class is used by \l {QCborValue::fromCbor(const QByteArray &ba,
218 QCborParserError *error)} to report a parser error and the byte offset
219 where the error was detected.
220
221 \sa QCborValue, QCborError
222 */
223
224/*!
225 \variable QCborParserError::offset
226
227 This field contains the offset from the beginning of the data where the
228 error was detected. The offset should point to the beginning of the item
229 that contained the error, even if the error itself was elsewhere (for
230 example, for UTF-8 decoding issues).
231
232 \sa QCborValue::fromCbor()
233 */
234
235/*!
236 \variable QCborParserError::error
237
238 This field contains the error code that indicates what decoding problem was
239 found.
240
241 \sa QCborValue::fromCbor()
242 */
243
244/*!
245 \fn QString QCborParserError::errorString() const
246
247 Returns a string representation of the error code. This string is not
248 translated.
249
250 \sa QCborError::toString(), QCborValue::fromCbor()
251 */
252
253/*!
254 \enum QCborValue::EncodingOption
255
256 This enum is used in the options argument to toCbor(), modifying the
257 behavior of the encoder.
258
259 \omitvalue SortKeysInMaps
260 \value NoTransformation (Default) Performs no transformations.
261 \value UseFloat Tells the encoder to use IEEE 754 single-precision floating point
262 (that is, \c float) whenever possible.
263 \value UseFloat16 Tells the encoder to use IEEE 754 half-precision floating point
264 (that is, \c qfloat16), whenever possible. Implies \c UseFloat.
265 \value UseIntegers Tells the encoder to use integers whenever a value of type \l
266 {Type}{Double} contains an integer.
267
268 The use of \c UseFloat16 is required to encode the stream in Canonical
269 Format, but is not otherwise necessary.
270
271 \sa toCbor()
272 */
273
274/*!
275 \enum QCborValue::DiagnosticNotationOption
276
277 This enum is used in the option argument to toDiagnosticNotation(), to
278 modify the output format.
279
280 \value Compact Does not use any line-breaks, producing a compact representation.
281 \value LineWrapped Uses line-breaks, one QCborValue per line.
282 \value ExtendedFormat Uses some different options to represent values, not found in
283 RFC 7049. Those options are subject to change.
284
285 Currently, \c ExtendedFormat will change how byte arrays are represented.
286 Without it, they are always hex-encoded and without spaces. With it,
287 QCborValue::toCbor() will either use hex with spaces, base64 or base64url
288 encoding, depending on the context.
289
290 \sa toDiagnosticNotation()
291 */
292
293/*!
294 \enum QCborValue::Type
295
296 This enum represents the QCborValue type. It is returned by the type()
297 function.
298
299 The CBOR built-in types are:
300
301 \value Integer \c qint64: An integer value
302 \value ByteArray \l QByteArray: a byte array ("byte string")
303 \value String \l QString: a Unicode string ("text string")
304 \value Array \l QCborArray: an array of QCborValues
305 \value Map \l QCborMap: an associative container of QCborValues
306 \value SimpleType \l QCborSimpleType: one of several simple types/values
307 \value False \c bool: the simple type for value \c false
308 \value True \c bool: the simple type for value \c true
309 \value Null \c std::nullptr_t: the simple type for the null value
310 \value Undefined (no type) the simple type for the undefined value
311 \value Double \c double: a double-precision floating point
312 \value Invalid Not a valid value, this usually indicates a CBOR decoding error
313
314 Additionally, QCborValue can represent extended types:
315
316 \value Tag An unknown or unrecognized extended type, represented by its
317 tag (a \l QCborTag) and the tagged value (a QCborValue)
318 \value DateTime \l QDateTime: a date and time stamp
319 \value Url \l QUrl: a URL or URI
320 \value RegularExpression \l QRegularExpression: the pattern of a regular expression
321 \value Uuid \l QUuid: a UUID
322
323 \sa type()
324 */
325
326/*!
327 \fn QCborValue::QCborValue()
328
329 Creates a QCborValue of the \l {Type}{Undefined} type.
330
331 CBOR undefined values are used to indicate missing information, usually as
332 a result of a previous operation that did not complete as expected. They
333 are also used by the QCborArray and QCborMap API to indicate the searched
334 item was not found.
335
336 Undefined values are represented by the \l {QCborSimpleType}{Undefined
337 simple type}. Because of that, QCborValues with undefined values will also
338 return true for isSimpleType() and
339 \c{isSimpleType(QCborSimpleType::Undefined)}.
340
341 Undefined values are different from null values.
342
343 QCborValue objects with undefined values are also different from invalid
344 QCborValue objects. The API will not create invalid QCborValues, but they
345 may exist as a result of a parsing error.
346
347 \sa isUndefined(), isNull(), isSimpleType()
348 */
349
350/*!
351 \fn QCborValue::QCborValue(Type t_)
352
353 Creates a QCborValue of type \a t_. The value associated with such a type
354 (if any) will be default constructed.
355
356 \sa type()
357 */
358
359/*!
360 \fn QCborValue::QCborValue(std::nullptr_t)
361
362 Creates a QCborValue of the \l {Type}{Null} type.
363
364 CBOR null values are used to indicate optional values that were not
365 provided. They are distinct from undefined values, in that null values are
366 usually not the result of an earlier error or problem.
367
368 \sa isNull(), isUndefined(), isSimpleType()
369 */
370
371/*!
372 \fn QCborValue::QCborValue(bool b)
373
374 Creates a QCborValue with boolean value \a b. The value can later be
375 retrieved using toBool().
376
377 Internally, CBOR booleans are represented by a pair of types, one for true
378 and one for false. For that reason, boolean QCborValues will return true
379 for isSimpleType() and one of \c{isSimpleType(QCborSimpleType::False)} or
380 \c{isSimpleType(QCborSimpleType::True)}.
381
382 \sa toBool(), isBool(), isTrue(), isFalse(), isSimpleType()
383 */
384
385/*!
386 \fn QCborValue::QCborValue(qint64 i)
387
388 Creates a QCborValue with integer value \a i. The value can later be
389 retrieved using toInteger().
390
391 CBOR integer values are distinct from floating point values. Therefore,
392 QCborValue objects with integers will compare differently to QCborValue
393 objects containing floating-point, even if the values contained in the
394 objects are equivalent.
395
396 \sa toInteger(), isInteger(), isDouble()
397 */
398
399/*!
400 \fn QCborValue::QCborValue(double d)
401
402 Creates a QCborValue with floating point value \a d. The value can later be
403 retrieved using toDouble().
404
405 CBOR floating point values are distinct from integer values. Therefore,
406 QCborValue objects with integers will compare differently to QCborValue
407 objects containing floating-point, even if the values contained in the
408 objects are equivalent.
409
410 \sa toDouble(), isDouble(), isInteger()
411 */
412
413/*!
414 \fn QCborValue::QCborValue(QCborSimpleType st)
415
416 Creates a QCborValue of simple type \a st. The type can later later be retrieved
417 using toSimpleType() as well as isSimpleType(st).
418
419 CBOR simple types are types that do not have any associated value, like
420 C++'s \c{std::nullptr_t} type, whose only possible value is \nullptr.
421
422 If \a st is \c{QCborSimpleType::Null}, the resulting QCborValue will be of
423 the \l{Type}{Null} type and similarly for \c{QCborSimpleType::Undefined}.
424 If \a st is \c{QCborSimpleType::False} or \c{QCborSimpleType::True}, the
425 created QCborValue will be a boolean containing a value of false or true,
426 respectively.
427
428 This function can be used with simple types not defined in the API. For
429 example, to create a QCborValue with simple type 12, one could write:
430
431 \snippet code/src_corelib_serialization_qcborvalue.cpp 1
432
433 Simple types should not be used until a specification for them has been
434 published, since other implementations may not support them properly.
435 Simple type values 24 to 31 are reserved and must not be used.
436
437 isSimpleType(), isNull(), isUndefined(), isTrue(), isFalse()
438 */
439
440/*!
441 \fn QCborValue::QCborValue(QCborKnownTags tag, const QCborValue &taggedValue)
442 \overload
443
444 Creates a QCborValue for the extended type represented by the tag value \a
445 tag, tagging value \a taggedValue. The tag can later be retrieved using
446 tag() and the tagged value using taggedValue().
447
448 \sa isTag(), tag(), taggedValue(), QCborKnownTags
449 */
450
451/*!
452 \fn QCborValue::~QCborValue()
453
454 Disposes of the current QCborValue object and frees any associated resources.
455 */
456
457/*!
458 \fn QCborValue::QCborValue(QCborValue &&other)
459 \overload
460
461 Moves the contents of the \a other QCborValue object into this one and frees
462 the resources of this one.
463 */
464
465/*!
466 \fn QCborValue &&QCborValue::operator=(QCborValue &&other)
467 \overload
468
469 Moves the contents of the \a other QCborValue object into this one and frees
470 the resources of this one. Returns a reference to this object.
471 */
472
473/*!
474 \fn void QCborValue::swap(QCborValue &other)
475
476 Swaps the contents of this QCborValue object and \a other.
477 */
478
479/*!
480 \fn QCborValue::Type QCborValue::type() const
481
482 Returns the type of this QCborValue. The type can also later be retrieved by one
483 of the "isXxx" functions.
484
485 \sa isInteger(), isByteArray(), isString(), isArray(), isMap(),
486 isTag(), isFalse(), isTrue(), isBool(), isNull(), isUndefined, isDouble(),
487 isDateTime(), isUrl(), isRegularExpression(), isUuid()
488 */
489
490/*!
491 \fn bool QCborValue::isInteger() const
492
493 Returns true if this QCborValue is of the integer type. The integer value
494 can be retrieved using toInteger().
495
496 \sa type(), toInteger()
497 */
498
499/*!
500 \fn bool QCborValue::isByteArray() const
501
502 Returns true if this QCborValue is of the byte array type. The byte array
503 value can be retrieved using toByteArray().
504
505 \sa type(), toByteArray()
506 */
507
508/*!
509 \fn bool QCborValue::isString() const
510
511 Returns true if this QCborValue is of the string type. The string value
512 can be retrieved using toString().
513
514 \sa type(), toString()
515 */
516
517/*!
518 \fn bool QCborValue::isArray() const
519
520 Returns true if this QCborValue is of the array type. The array value can
521 be retrieved using toArray().
522
523 \sa type(), toArray()
524 */
525
526/*!
527 \fn bool QCborValue::isMap() const
528
529 Returns true if this QCborValue is of the map type. The map value can be
530 retrieved using toMap().
531
532 \sa type(), toMap()
533 */
534
535/*!
536 \fn bool QCborValue::isTag() const
537
538 Returns true if this QCborValue is of the tag type. The tag value can be
539 retrieved using tag() and the tagged value using taggedValue().
540
541 This function also returns true for extended types that the API
542 recognizes. For code that handles extended types directly before the Qt API
543 is updated to support them, it is possible to recreate the tag + tagged
544 value pair by using taggedValue().
545
546 \sa type(), tag(), taggedValue(), taggedValue()
547 */
548
549/*!
550 \fn bool QCborValue::isFalse() const
551
552 Returns true if this QCborValue is a boolean with false value. This
553 function exists because, internally, CBOR booleans are stored as two
554 separate types, one for true and one for false.
555
556 \sa type(), isBool(), isTrue(), toBool()
557 */
558
559/*!
560 \fn bool QCborValue::isTrue() const
561
562 Returns true if this QCborValue is a boolean with true value. This
563 function exists because, internally, CBOR booleans are stored as two
564 separate types, one for false and one for true.
565
566 \sa type(), isBool(), isFalse(), toBool()
567 */
568
569/*!
570 \fn bool QCborValue::isBool() const
571
572 Returns true if this QCborValue is a boolean. The value can be retrieved
573 using toBool().
574
575 \sa type(), toBool(), isTrue(), isFalse()
576 */
577
578/*!
579 \fn bool QCborValue::isUndefined() const
580
581 Returns true if this QCborValue is of the undefined type.
582
583 CBOR undefined values are used to indicate missing information, usually as
584 a result of a previous operation that did not complete as expected. They
585 are also used by the QCborArray and QCborMap API to indicate the searched
586 item was not found.
587
588 Undefined values are distinct from null values.
589
590 QCborValue objects with undefined values are also different from invalid
591 QCborValue objects. The API will not create invalid QCborValues, but they
592 may exist as a result of a parsing error.
593
594 \sa type(), isNull(), isInvalid()
595 */
596
597/*!
598 \fn bool QCborValue::isNull() const
599
600 Returns true if this QCborValue is of the null type.
601
602 CBOR null values are used to indicate optional values that were not
603 provided. They are distinct from undefined values, in that null values are
604 usually not the result of an earlier error or problem.
605
606 Null values are distinct from undefined values and from invalid QCborValue
607 objects. The API will not create invalid QCborValues, but they may exist as
608 a result of a parsing error.
609
610 \sa type(), isUndefined(), isInvalid()
611 */
612
613/*!
614 \fn bool QCborValue::isDouble() const
615
616 Returns true if this QCborValue is of the floating-point type. The value
617 can be retrieved using toDouble().
618
619 \sa type(), toDouble()
620 */
621
622/*!
623 \fn bool QCborValue::isDateTime() const
624
625 Returns true if this QCborValue is of the date/time type. The value can be
626 retrieved using toDateTime(). Date/times are extended types that use the
627 tag \l{QCborKnownTags}{DateTime}.
628
629 Additionally, when decoding from a CBOR stream, QCborValue will interpret
630 tags of value \l{QCborKnownTags}{UnixTime_t} and convert them to the
631 equivalent date/time.
632
633 \sa type(), toDateTime()
634 */
635
636/*!
637 \fn bool QCborValue::isUrl() const
638
639 Returns true if this QCborValue is of the URL type. The URL value
640 can be retrieved using toUrl().
641
642 \sa type(), toUrl()
643 */
644
645/*!
646 \fn bool QCborValue::isRegularExpression() const
647
648 Returns true if this QCborValue contains a regular expression's pattern.
649 The pattern can be retrieved using toRegularExpression().
650
651 \sa type(), toRegularExpression()
652 */
653
654/*!
655 \fn bool QCborValue::isUuid() const
656
657 Returns true if this QCborValue contains a UUID. The value can be retrieved
658 using toUuid().
659
660 \sa type(), toUuid()
661 */
662
663/*!
664 \fn bool QCborValue::isInvalid() const
665
666 Returns true if this QCborValue is not of any valid type. Invalid
667 QCborValues are distinct from those with undefined values and they usually
668 represent a decoding error.
669
670 \sa isUndefined(), isNull()
671 */
672
673/*!
674 \fn bool QCborValue::isContainer() const
675
676 This convenience function returns true if the QCborValue is either an array
677 or a map.
678
679 \sa isArray(), isMap()
680 */
681
682/*!
683 \fn bool QCborValue::isSimpleType() const
684
685 Returns true if this QCborValue is of one of the CBOR simple types. The
686 type itself can later be retrieved using type(), even for types that don't have an
687 enumeration in the API. They can also be checked with the
688 \l{isSimpleType(QCborSimpleType)} overload.
689
690 \sa QCborSimpleType, isSimpleType(QCborSimpleType), toSimpleType()
691 */
692
693/*!
694 \fn bool QCborValue::isSimpleType(QCborSimpleType st) const
695 \overload
696
697 Returns true if this QCborValue is of a simple type and toSimpleType()
698 would return \a st, false otherwise. This function can be used to check for
699 any CBOR simple type, even those for which there is no enumeration in the
700 API. For example, for the simple type of value 12, you could write:
701
702 \snippet code/src_corelib_serialization_qcborvalue.cpp 2
703
704 \sa QCborValue::QCborValue(QCborSimpleType), isSimpleType(), isFalse(),
705 isTrue(), isNull, isUndefined(), toSimpleType()
706 */
707
708/*!
709 \fn QCborSimpleType QCborValue::toSimpleType(QCborSimpleType defaultValue) const
710
711 Returns the simple type this QCborValue is of, if it is a simple type. If
712 it is not a simple type, it returns \a defaultValue.
713
714 The following types are simple types and this function will return the
715 listed values:
716
717 \table
718 \row \li QCborValue::False \li QCborSimpleType::False
719 \row \li QCborValue::True \li QCborSimpleType::True
720 \row \li QCborValue::Null \li QCborSimpleType::Null
721 \row \li QCborValue::Undefined \li QCborSimpleType::Undefined
722 \endtable
723
724 \sa type(), isSimpleType(), isBool(), isTrue(), isFalse(), isTrue(),
725 isNull(), isUndefined()
726 */
727
728/*!
729 \fn qint64 QCborValue::toInteger(qint64 defaultValue) const
730
731 Returns the integer value stored in this QCborValue, if it is of the
732 integer type. If it is of the Double type, this function returns the
733 floating point value converted to integer. In any other case, it returns \a
734 defaultValue.
735
736 \sa isInteger(), isDouble(), toDouble()
737 */
738
739/*!
740 \fn bool QCborValue::toBool(bool defaultValue) const
741
742 Returns the boolean value stored in this QCborValue, if it is of a boolean
743 type. Otherwise, it returns \a defaultValue.
744
745 \sa isBool(), isTrue(), isFalse()
746 */
747
748/*!
749 \fn double QCborValue::toDouble(double defaultValue) const
750
751 Returns the floating point value stored in this QCborValue, if it is of the
752 Double type. If it is of the Integer type, this function returns the
753 integer value converted to double. In any other case, it returns \a
754 defaultValue.
755
756 \sa isDouble(), isInteger(), toInteger()
757 */
758
759using namespace QtCbor;
760
761// in qcborstream.cpp
762extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
763
764static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
765{
766 if (qt_is_nan(d)) {
767 if (opt & QCborValue::UseFloat16) {
768 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
769 return writer.append(std::numeric_limits<qfloat16>::quiet_NaN());
770 return writer.append(std::numeric_limits<float>::quiet_NaN());
771 }
772 return writer.append(qt_qnan());
773 }
774
775 if (qt_is_inf(d)) {
776 d = d > 0 ? qt_inf() : -qt_inf();
777 } else if (opt & QCborValue::UseIntegers) {
778 quint64 i;
779 if (convertDoubleTo(d, &i)) {
780 if (d < 0)
781 return writer.append(QCborNegativeInteger(i));
782 return writer.append(i);
783 }
784 }
785
786 if (opt & QCborValue::UseFloat16) {
787 float f = float(d);
788 if (f == d) {
789 // no data loss, we could use float
790 if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
791 qfloat16 f16 = f;
792 if (f16 == f)
793 return writer.append(f16);
794 }
795
796 return writer.append(f);
797 }
798 }
799
800 writer.append(d);
801}
802
803static inline int typeOrder(Element e1, Element e2)
804{
805 auto comparable = [](Element e) {
806 if (e.type >= 0x10000) // see QCborValue::isTag_helper()
807 return QCborValue::Tag;
808 return e.type;
809 };
810 return comparable(e1) - comparable(e2);
811}
812
813QCborContainerPrivate::~QCborContainerPrivate()
814{
815 // delete our elements
816 for (Element &e : elements) {
817 if (e.flags & Element::IsContainer)
818 e.container->deref();
819 }
820}
821
822void QCborContainerPrivate::compact(qsizetype reserved)
823{
824 if (usedData > data.size() / 2)
825 return;
826
827 // 50% savings if we recreate the byte data
828 // ### TBD
829 Q_UNUSED(reserved);
830}
831
832QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qsizetype reserved)
833{
834 if (!d) {
835 d = new QCborContainerPrivate;
836 } else {
837 d = new QCborContainerPrivate(*d);
838 if (reserved >= 0) {
839 d->elements.reserve(reserved);
840 d->compact(reserved);
841 }
842 for (auto &e : qAsConst(d->elements)) {
843 if (e.flags & Element::IsContainer)
844 e.container->ref.ref();
845 }
846 }
847 return d;
848}
849
850QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, qsizetype reserved)
851{
852 if (!d || d->ref.loadRelaxed() != 1)
853 return clone(d, reserved);
854 return d;
855}
856
857/*!
858 Prepare for an insertion at position \a index
859
860 Detaches and ensures there are at least index entries in the array, padding
861 with Undefined as needed.
862*/
863QCborContainerPrivate *QCborContainerPrivate::grow(QCborContainerPrivate *d, qsizetype index)
864{
865 Q_ASSERT(index >= 0);
866 d = detach(d, index + 1);
867 Q_ASSERT(d);
868 int j = d->elements.size();
869 while (j < index)
870 d->append(Undefined());
871 return d;
872}
873
874// Copies or moves \a value into element at position \a e. If \a disp is
875// CopyContainer, then this function increases the reference count of the
876// container, but otherwise leaves it unmodified. If \a disp is MoveContainer,
877// then it transfers ownership (move semantics) and the caller must set
878// value.container back to nullptr.
879void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &value, ContainerDisposition disp)
880{
881 if (value.n < 0) {
882 // This QCborValue is an array, map, or tagged value (container points
883 // to itself).
884
885 // detect self-assignment
886 if (Q_UNLIKELY(this == value.container)) {
887 Q_ASSERT(ref.loadRelaxed() >= 2);
888 if (disp == MoveContainer)
889 ref.deref(); // not deref() because it can't drop to 0
890 QCborContainerPrivate *d = QCborContainerPrivate::clone(this);
891 d->elements.detach();
892 d->ref.storeRelaxed(1);
893 e.container = d;
894 } else {
895 e.container = value.container;
896 if (disp == CopyContainer)
897 e.container->ref.ref();
898 }
899
900 e.type = value.type();
901 e.flags = Element::IsContainer;
902 } else {
903 // String data, copy contents
904 e = value.container->elements.at(value.n);
905
906 // Copy string data, if any
907 if (const ByteData *b = value.container->byteData(value.n))
908 e.value = addByteData(b->byte(), b->len);
909
910 if (disp == MoveContainer)
911 value.container->deref();
912 }
913}
914
915// in qstring.cpp
916void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
917
918Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(const QString &s)
919{
920 qsizetype len = s.size();
921 QtCbor::Element e;
922 e.value = addByteData(nullptr, len);
923 e.type = QCborValue::String;
924 e.flags = Element::HasByteData | Element::StringIsAscii;
925 elements.append(e);
926
927 char *ptr = data.data() + e.value + sizeof(ByteData);
928 uchar *l = reinterpret_cast<uchar *>(ptr);
929 const ushort *uc = (const ushort *)s.unicode();
930 qt_to_latin1_unchecked(l, uc, len);
931}
932
933QCborValue QCborContainerPrivate::extractAt_complex(Element e)
934{
935 // create a new container for the returned value, containing the byte data
936 // from this element, if it's worth it
937 Q_ASSERT(e.flags & Element::HasByteData);
938 auto b = byteData(e);
939 auto container = new QCborContainerPrivate;
940
941 if (b->len + qsizetype(sizeof(*b)) < data.size() / 4) {
942 // make a shallow copy of the byte data
943 container->appendByteData(b->byte(), b->len, e.type, e.flags);
944 usedData -= b->len + qsizetype(sizeof(*b));
945 compact(elements.size());
946 } else {
947 // just share with the original byte data
948 container->data = data;
949 container->elements.reserve(1);
950 container->elements.append(e);
951 }
952
953 return makeValue(e.type, 0, container);
954}
955
956QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
957static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2);
958static int compareElementNoData(const Element &e1, const Element &e2)
959{
960 Q_ASSERT(e1.type == e2.type);
961
962 if (e1.type == QCborValue::Integer) {
963 // CBOR sorting order is 0, 1, 2, ..., INT64_MAX, -1, -2, -3, ... INT64_MIN
964 // So we transform:
965 // 0 -> 0
966 // 1 -> 1
967 // INT64_MAX -> INT64_MAX
968 // -1 -> INT64_MAX + 1 = INT64_MAX - (-1)
969 // -2 -> INT64_MAX + 2 = INT64_MAX - (-2)
970 // INT64_MIN -> UINT64_MAX = INT64_MAX - INT64_MIN
971 // Note how the unsigned arithmethic is well defined in C++ (it's
972 // always performed modulo 2^64).
973 auto makeSortable = [](qint64 v) {
974 quint64 u = quint64(v);
975 if (v < 0)
976 return quint64(std::numeric_limits<qint64>::max()) + (-u);
977 return u;
978 };
979 quint64 u1 = makeSortable(e1.value);
980 quint64 u2 = makeSortable(e2.value);
981 if (u1 < u2)
982 return -1;
983 if (u1 > u2)
984 return 1;
985 }
986
987 if (e1.type == QCborValue::Tag || e1.type == QCborValue::Double) {
988 // Perform unsigned comparisons for the tag value and floating point
989 quint64 u1 = quint64(e1.value);
990 quint64 u2 = quint64(e2.value);
991 if (u1 != u2)
992 return u1 < u2 ? -1 : 1;
993 }
994
995 // Any other type is equal at this point:
996 // - simple types carry no value
997 // - empty strings, arrays and maps
998 return 0;
999}
1000
1001static int compareElementRecursive(const QCborContainerPrivate *c1, const Element &e1,
1002 const QCborContainerPrivate *c2, const Element &e2)
1003{
1004 int cmp = typeOrder(e1, e2);
1005 if (cmp != 0)
1006 return cmp;
1007
1008 if ((e1.flags & Element::IsContainer) || (e2.flags & Element::IsContainer))
1009 return compareContainer(e1.flags & Element::IsContainer ? e1.container : nullptr,
1010 e2.flags & Element::IsContainer ? e2.container : nullptr);
1011
1012 // string data?
1013 const ByteData *b1 = c1 ? c1->byteData(e1) : nullptr;
1014 const ByteData *b2 = c2 ? c2->byteData(e2) : nullptr;
1015 if (b1 || b2) {
1016 auto len1 = b1 ? b1->len : 0;
1017 auto len2 = b2 ? b2->len : 0;
1018
1019 if (e1.flags & Element::StringIsUtf16)
1020 len1 /= 2;
1021 if (e2.flags & Element::StringIsUtf16)
1022 len2 /= 2;
1023 if (len1 == 0 || len2 == 0)
1024 return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
1025
1026 // we definitely have data from this point forward
1027 Q_ASSERT(b1);
1028 Q_ASSERT(b2);
1029
1030 // Officially with CBOR, we sort first the string with the shortest
1031 // UTF-8 length. The length of an ASCII string is the same as its UTF-8
1032 // and UTF-16 ones, but the UTF-8 length of a string is bigger than the
1033 // UTF-16 equivalent. Combinations are:
1034 // 1) UTF-16 and UTF-16
1035 // 2) UTF-16 and UTF-8 <=== this is the problem case
1036 // 3) UTF-16 and US-ASCII
1037 // 4) UTF-8 and UTF-8
1038 // 5) UTF-8 and US-ASCII
1039 // 6) US-ASCII and US-ASCII
1040 if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16)) {
1041 // Case 1: both UTF-16, so lengths are comparable.
1042 // (we can't use memcmp in little-endian machines)
1043 if (len1 == len2)
1044 return QtPrivate::compareStrings(b1->asStringView(), b2->asStringView());
1045 return len1 < len2 ? -1 : 1;
1046 }
1047
1048 if (!(e1.flags & Element::StringIsUtf16) && !(e2.flags & Element::StringIsUtf16)) {
1049 // Cases 4, 5 and 6: neither is UTF-16, so lengths are comparable too
1050 // (this case includes byte arrays too)
1051 if (len1 == len2)
1052 return memcmp(b1->byte(), b2->byte(), size_t(len1));
1053 return len1 < len2 ? -1 : 1;
1054 }
1055
1056 if (!(e1.flags & Element::StringIsAscii) || !(e2.flags & Element::StringIsAscii)) {
1057 // Case 2: one of them is UTF-8 and the other is UTF-16, so lengths
1058 // are NOT comparable. We need to convert to UTF-16 first...
1059 auto string = [](const Element &e, const ByteData *b) {
1060 return e.flags & Element::StringIsUtf16 ? b->asQStringRaw() : b->toUtf8String();
1061 };
1062
1063 QString s1 = string(e1, b1);
1064 QString s2 = string(e2, b2);
1065 if (s1.size() == s2.size())
1066 return s1.compare(s2);
1067 return s1.size() < s2.size() ? -1 : 1;
1068 }
1069
1070 // Case 3 (UTF-16 and US-ASCII) remains, so lengths are comparable again
1071 if (len1 != len2)
1072 return len1 < len2 ? -1 : 1;
1073 if (e1.flags & Element::StringIsUtf16)
1074 return QtPrivate::compareStrings(b1->asStringView(), b2->asLatin1());
1075 return QtPrivate::compareStrings(b1->asLatin1(), b2->asStringView());
1076 }
1077
1078 return compareElementNoData(e1, e2);
1079}
1080
1081static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2)
1082{
1083 auto len1 = c1 ? c1->elements.size() : 0;
1084 auto len2 = c2 ? c2->elements.size() : 0;
1085 if (len1 != len2) {
1086 // sort the shorter container first
1087 return len1 < len2 ? -1 : 1;
1088 }
1089
1090 for (qsizetype i = 0; i < len1; ++i) {
1091 const Element &e1 = c1->elements.at(i);
1092 const Element &e2 = c2->elements.at(i);
1093 int cmp = QCborContainerPrivate::compareElement_helper(c1, e1, c2, e2);
1094 if (cmp)
1095 return cmp;
1096 }
1097
1098 return 0;
1099}
1100
1101inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPrivate *c1, Element e1,
1102 const QCborContainerPrivate *c2, Element e2)
1103{
1104 return compareElementRecursive(c1, e1, c2, e2);
1105}
1106
1107/*!
1108 \fn bool QCborValue::operator==(const QCborValue &other) const
1109
1110 Compares this value and \a other, and returns true if they hold the same
1111 contents, false otherwise. If each QCborValue contains an array or map, the
1112 comparison is recursive to elements contained in them.
1113
1114 For more information on CBOR equality in Qt, see, compare().
1115
1116 \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
1117 operator!=(), operator<()
1118 */
1119
1120/*!
1121 \fn bool QCborValue::operator!=(const QCborValue &other) const
1122
1123 Compares this value and \a other, and returns true if contents differ,
1124 false otherwise. If each QCborValue contains an array or map, the comparison
1125 is recursive to elements contained in them.
1126
1127 For more information on CBOR equality in Qt, see, QCborValue::compare().
1128
1129 \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
1130 operator==(), operator<()
1131 */
1132
1133/*!
1134 \fn bool QCborValue::operator<(const QCborValue &other) const
1135
1136 Compares this value and \a other, and returns true if this value should be
1137 sorted before \a other, false otherwise. If each QCborValue contains an
1138 array or map, the comparison is recursive to elements contained in them.
1139
1140 For more information on CBOR sorting order, see QCborValue::compare().
1141
1142 \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
1143 operator==(), operator!=()
1144 */
1145
1146/*!
1147 Compares this value and \a other, and returns an integer that indicates
1148 whether this value should be sorted prior to (if the result is negative) or
1149 after \a other (if the result is positive). If this function returns 0, the
1150 two values are equal and hold the same contents.
1151
1152 If each QCborValue contains an array or map, the comparison is recursive to
1153 elements contained in them.
1154
1155 \section3 Extended types
1156
1157 QCborValue compares equal a QCborValue containing an extended type, like
1158 \l{Type}{Url} and \l{Type}{Url} and its equivalent tagged representation.
1159 So, for example, the following expression is true:
1160
1161 \snippet code/src_corelib_serialization_qcborvalue.cpp 3
1162
1163 Do note that Qt types like \l QUrl and \l QDateTime will normalize and
1164 otherwise modify their arguments. The expression above is true only because
1165 the string on the right side is the normalized value that the QCborValue on
1166 the left would take. If, for example, the "https" part were uppercase in
1167 both sides, the comparison would fail. For information on normalizations
1168 performed by QCborValue, please consult the documentation of the
1169 constructor taking the Qt type in question.
1170
1171 \section3 Sorting order
1172
1173 Sorting order in CBOR is defined in RFC 7049
1174 {https://tools.ietf.org/html/rfc7049#section-3.9}{section 3.9}, which
1175 discusses the sorting of keys in a map when following the Canonical
1176 encoding. According to the specification, "sorting is performed on the
1177 bytes of the representation of the key data items" and lists as
1178 consequences that:
1179
1180 \list
1181 \li "If two keys have different lengths, the shorter one sorts earlier;"
1182 \li "If two keys have the same length, the one with the lower value in
1183 (byte-wise) lexical order sorts earlier."
1184 \endlist
1185
1186 This results in surprising sorting of QCborValues, where the result of this
1187 function is different from that which would later be retrieved by comparing the
1188 contained elements. For example, the QCborValue containing string "zzz"
1189 sorts before the QCborValue with string "foobar", even though when
1190 comparing as \l{QString::compare()}{QStrings} or
1191 \l{QByteArray}{QByteArrays} the "zzz" sorts after "foobar"
1192 (dictionary order).
1193
1194 The specification does not clearly indicate what sorting order should be
1195 done for values of different types (it says sorting should not pay
1196 "attention to the 3/5 bit splitting for major types"). QCborValue makes the
1197 assumption that types should be sorted too. The numeric values of the
1198 QCborValue::Type enumeration are in that order, with the exception of the
1199 extended types, which compare as their tagged equivalents.
1200
1201 \note Sorting order is preliminary and is subject to change. Applications
1202 should not depend on the order returned by this function for the time
1203 being.
1204
1205 \sa QCborArray::compare(), QCborMap::compare(), operator==()
1206 */
1207int QCborValue::compare(const QCborValue &other) const
1208{
1209 Element e1 = QCborContainerPrivate::elementFromValue(*this);
1210 Element e2 = QCborContainerPrivate::elementFromValue(other);
1211 return compareElementRecursive(container, e1, other.container, e2);
1212}
1213
1214int QCborArray::compare(const QCborArray &other) const noexcept
1215{
1216 return compareContainer(d.data(), other.d.data());
1217}
1218
1219int QCborMap::compare(const QCborMap &other) const noexcept
1220{
1221 return compareContainer(d.data(), other.d.data());
1222}
1223
1224static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate *d, qsizetype idx,
1225 QCborValue::EncodingOptions opt)
1226{
1227 if (idx == -QCborValue::Array || idx == -QCborValue::Map) {
1228 bool isArray = (idx == -QCborValue::Array);
1229 qsizetype len = d ? d->elements.size() : 0;
1230 if (isArray)
1231 writer.startArray(quint64(len));
1232 else
1233 writer.startMap(quint64(len) / 2);
1234
1235 for (idx = 0; idx < len; ++idx)
1236 encodeToCbor(writer, d, idx, opt);
1237
1238 if (isArray)
1239 writer.endArray();
1240 else
1241 writer.endMap();
1242 } else if (idx < 0) {
1243 if (d->elements.size() != 2) {
1244 // invalid state!
1245 qWarning("QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
1246 return;
1247 }
1248
1249 // write the tag and the tagged element
1250 writer.append(QCborTag(d->elements.at(0).value));
1251 encodeToCbor(writer, d, 1, opt);
1252 } else {
1253 // just one element
1254 auto e = d->elements.at(idx);
1255 const ByteData *b = d->byteData(idx);
1256 switch (e.type) {
1257 case QCborValue::Integer:
1258 return writer.append(qint64(e.value));
1259
1260 case QCborValue::ByteArray:
1261 if (b)
1262 return writer.appendByteString(b->byte(), b->len);
1263 return writer.appendByteString("", 0);
1264
1265 case QCborValue::String:
1266 if (b) {
1267 if (e.flags & Element::StringIsUtf16)
1268 return writer.append(b->asStringView());
1269 return writer.appendTextString(b->byte(), b->len);
1270 }
1271 return writer.append(QLatin1String());
1272
1273 case QCborValue::Array:
1274 case QCborValue::Map:
1275 case QCborValue::Tag:
1276 // recurse
1277 return encodeToCbor(writer,
1278 e.flags & Element::IsContainer ? e.container : nullptr,
1279 -qsizetype(e.type), opt);
1280
1281 case QCborValue::SimpleType:
1282 case QCborValue::False:
1283 case QCborValue::True:
1284 case QCborValue::Null:
1285 case QCborValue::Undefined:
1286 break;
1287
1288 case QCborValue::Double:
1289 return writeDoubleToCbor(writer, e.fpvalue(), opt);
1290
1291 case QCborValue::Invalid:
1292 return;
1293
1294 case QCborValue::DateTime:
1295 case QCborValue::Url:
1296 case QCborValue::RegularExpression:
1297 case QCborValue::Uuid:
1298 // recurse as tag
1299 return encodeToCbor(writer, e.container, -QCborValue::Tag, opt);
1300 }
1301
1302 // maybe it's a simple type
1303 int simpleType = e.type - QCborValue::SimpleType;
1304 if (unsigned(simpleType) < 0x100)
1305 return writer.append(QCborSimpleType(simpleType));
1306
1307 // if we got here, we've got an unknown type
1308 qWarning("QCborValue: found unknown type 0x%x", e.type);
1309 }
1310}
1311
1312static inline double integerOutOfRange(const QCborStreamReader &reader)
1313{
1314 Q_ASSERT(reader.isInteger());
1315 if (reader.isUnsignedInteger()) {
1316 quint64 v = reader.toUnsignedInteger();
1317 if (qint64(v) < 0)
1318 return double(v);
1319 } else {
1320 quint64 v = quint64(reader.toNegativeInteger());
1321 if (qint64(v - 1) < 0)
1322 return -double(v);
1323 }
1324
1325 // result is in range
1326 return 0;
1327}
1328
1329static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
1330{
1331 Element e = {};
1332
1333 switch (reader.type()) {
1334 case QCborStreamReader::UnsignedInteger:
1335 case QCborStreamReader::NegativeInteger:
1336 if (double d = integerOutOfRange(reader)) {
1337 e.type = QCborValue::Double;
1338 qToUnaligned(d, &e.value);
1339 } else {
1340 e.type = QCborValue::Integer;
1341 e.value = reader.toInteger();
1342 }
1343 break;
1344 case QCborStreamReader::SimpleType:
1345 e.type = QCborValue::Type(quint8(reader.toSimpleType()) + 0x100);
1346 break;
1347 case QCborStreamReader::Float16:
1348 e.type = QCborValue::Double;
1349 qToUnaligned(double(reader.toFloat16()), &e.value);
1350 break;
1351 case QCborStreamReader::Float:
1352 e.type = QCborValue::Double;
1353 qToUnaligned(double(reader.toFloat()), &e.value);
1354 break;
1355 case QCborStreamReader::Double:
1356 e.type = QCborValue::Double;
1357 qToUnaligned(reader.toDouble(), &e.value);
1358 break;
1359
1360 default:
1361 Q_UNREACHABLE();
1362 }
1363
1364 reader.next();
1365 return e;
1366}
1367
1368static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader)
1369{
1370 auto d = new QCborContainerPrivate;
1371 d->ref.storeRelaxed(1);
1372 d->decodeFromCbor(reader);
1373 return d;
1374}
1375
1376static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
1377{
1378 auto d = new QCborContainerPrivate;
1379 d->append(reader.toTag());
1380 reader.next();
1381
1382 if (reader.lastError() == QCborError::NoError) {
1383 // decode tagged value
1384 d->decodeValueFromCbor(reader);
1385 }
1386
1387 QCborValue::Type type = QCborValue::Tag;
1388 if (reader.lastError() == QCborError::NoError) {
1389 // post-process to create our extended types
1390 qint64 tag = d->elements.at(0).value;
1391 auto &e = d->elements[1];
1392 const ByteData *b = d->byteData(e);
1393
1394 auto replaceByteData = [&](const char *buf, qsizetype len) {
1395 d->data.clear();
1396 d->usedData = 0;
1397 e.flags = Element::HasByteData | Element::StringIsAscii;
1398 e.value = d->addByteData(buf, len);
1399 };
1400
1401 switch (tag) {
1402 case qint64(QCborKnownTags::DateTimeString):
1403 case qint64(QCborKnownTags::UnixTime_t): {
1404 QDateTime dt;
1405 if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
1406 e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
1407 // The data is supposed to be US-ASCII. If it isn't,
1408 // QDateTime::fromString will fail anyway.
1409 dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
1410 } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) {
1411 dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC);
1412 } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) {
1413 dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC);
1414 }
1415 if (dt.isValid()) {
1416 QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
1417 replaceByteData(text, text.size());
1418 e.type = QCborValue::String;
1419 d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
1420 type = QCborValue::DateTime;
1421 }
1422 break;
1423 }
1424
1425 case qint64(QCborKnownTags::Url):
1426 if (e.type == QCborValue::String) {
1427 if (b) {
1428 // normalize to a short (decoded) form, so as to save space
1429 QUrl url(e.flags & Element::StringIsUtf16 ?
1430 b->asQStringRaw() :
1431 b->toUtf8String());
1432 QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
1433 replaceByteData(encoded, encoded.size());
1434 }
1435 type = QCborValue::Url;
1436 }
1437 break;
1438
1439 case quint64(QCborKnownTags::RegularExpression):
1440 if (e.type == QCborValue::String) {
1441 // no normalization is necessary
1442 type = QCborValue::RegularExpression;
1443 }
1444 break;
1445
1446 case qint64(QCborKnownTags::Uuid):
1447 if (e.type == QCborValue::ByteArray) {
1448 // force the size to 16
1449 char buf[sizeof(QUuid)] = {};
1450 if (b)
1451 memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len)));
1452 replaceByteData(buf, sizeof(buf));
1453
1454 type = QCborValue::Uuid;
1455 }
1456 break;
1457 }
1458 } else {
1459 // decoding error
1460 type = QCborValue::Invalid;
1461 }
1462
1463 // note: may return invalid state!
1464 return QCborContainerPrivate::makeValue(type, -1, d);
1465}
1466
1467void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
1468{
1469 auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
1470 // this duplicates a lot of addByteData, but with overflow checking
1471 QByteArray::size_type newSize;
1472 QByteArray::size_type increment = sizeof(QtCbor::ByteData);
1473 QByteArray::size_type alignment = alignof(QtCbor::ByteData);
1474 QByteArray::size_type offset = data.size();
1475
1476 // calculate the increment we want
1477 if (add_overflow(increment, len, &increment))
1478 return -1;
1479
1480 // align offset
1481 if (add_overflow(offset, alignment - 1, &offset))
1482 return -1;
1483 offset &= ~(alignment - 1);
1484
1485 // and calculate the final size
1486 if (add_overflow(offset, increment, &newSize))
1487 return -1;
1488
1489 // since usedData <= data.size(), this can't overflow
1490 usedData += increment;
1491 data.resize(newSize);
1492 return offset;
1493 };
1494 auto dataPtr = [this]() {
1495 // Null happens when we're reading zero bytes.
1496 Q_ASSERT(data.isNull() || data.isDetached());
1497 return const_cast<char *>(data.constData());
1498 };
1499
1500 Element e = {};
1501 e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
1502 if (reader.lastError() != QCborError::NoError)
1503 return;
1504
1505 qsizetype rawlen = reader.currentStringChunkSize();
1506 QByteArray::size_type len = rawlen;
1507 if (rawlen < 0)
1508 return; // error
1509 if (len != rawlen) {
1510 // truncation
1511 qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
1512 return;
1513 }
1514
1515 // allocate space, but only if there will be data
1516 if (len != 0 || !reader.isLengthKnown()) {
1517 e.flags = Element::HasByteData;
1518 e.value = addByteData_local(len);
1519 if (e.value < 0) {
1520 // overflow
1521 qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
1522 return;
1523 }
1524 }
1525
1526 // read chunks
1527 bool isAscii = (e.type == QCborValue::String);
1528 auto r = reader.readStringChunk(dataPtr() + e.value + sizeof(ByteData), len);
1529 while (r.status == QCborStreamReader::Ok) {
1530 if (e.type == QCborValue::String && len) {
1531 // verify UTF-8 string validity
1532 auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
1533 if (!utf8result.isValidUtf8) {
1534 r.status = QCborStreamReader::Error;
1535 qt_cbor_stream_set_error(reader.d.data(), { QCborError::InvalidUtf8String });
1536 break;
1537 }
1538 isAscii = isAscii && utf8result.isValidAscii;
1539 }
1540
1541 // allocate space for the next chunk
1542 rawlen = reader.currentStringChunkSize();
1543 len = rawlen;
1544 if (len == rawlen) {
1545 auto oldSize = data.size();
1546 auto newSize = oldSize;
1547 if (!add_overflow(newSize, len, &newSize)) {
1548 if (newSize != oldSize)
1549 data.resize(newSize);
1550
1551 // read the chunk
1552 r = reader.readStringChunk(dataPtr() + oldSize, len);
1553 continue;
1554 }
1555 }
1556
1557 // error
1558 r.status = QCborStreamReader::Error;
1559 qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
1560 }
1561
1562 if (r.status == QCborStreamReader::Error) {
1563 // There can only be errors if there was data to be read.
1564 Q_ASSERT(e.flags & Element::HasByteData);
1565 data.truncate(e.value);
1566 return;
1567 }
1568
1569 // update size
1570 if (e.flags & Element::HasByteData) {
1571 auto b = new (dataPtr() + e.value) ByteData;
1572 b->len = data.size() - e.value - int(sizeof(*b));
1573 usedData += b->len;
1574
1575 if (isAscii) {
1576 // set the flag if it is US-ASCII only (as it often is)
1577 Q_ASSERT(e.type == QCborValue::String);
1578 e.flags |= Element::StringIsAscii;
1579 }
1580 }
1581
1582 elements.append(e);
1583}
1584
1585void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
1586{
1587 switch (reader.type()) {
1588 case QCborStreamReader::UnsignedInteger:
1589 case QCborStreamReader::NegativeInteger:
1590 case QCborStreamReader::SimpleType:
1591 case QCborStreamReader::Float16:
1592 case QCborStreamReader::Float:
1593 case QCborStreamReader::Double:
1594 elements.append(decodeBasicValueFromCbor(reader));
1595 break;
1596
1597 case QCborStreamReader::ByteArray:
1598 case QCborStreamReader::String:
1599 decodeStringFromCbor(reader);
1600 break;
1601
1602 case QCborStreamReader::Array:
1603 case QCborStreamReader::Map:
1604 case QCborStreamReader::Tag:
1605 return append(QCborValue::fromCbor(reader));
1606
1607 case QCborStreamReader::Invalid:
1608 return; // probably a decode error
1609 }
1610}
1611
1612void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader)
1613{
1614 int mapShift = reader.isMap() ? 1 : 0;
1615 if (reader.isLengthKnown()) {
1616 quint64 len = reader.length();
1617
1618 // Clamp allocation to 1M elements (avoids crashing due to corrupt
1619 // stream or loss of precision when converting from quint64 to
1620 // QVector::size_type).
1621 len = qMin(len, quint64(1024 * 1024 - 1));
1622 elements.reserve(qsizetype(len) << mapShift);
1623 }
1624
1625 reader.enterContainer();
1626 if (reader.lastError() != QCborError::NoError)
1627 return;
1628
1629 while (reader.hasNext() && reader.lastError() == QCborError::NoError)
1630 decodeValueFromCbor(reader);
1631
1632 if (reader.lastError() == QCborError::NoError)
1633 reader.leaveContainer();
1634}
1635
1636/*!
1637 Creates a QCborValue with byte array value \a ba. The value can later be
1638 retrieved using toByteArray().
1639
1640 \sa toByteArray(), isByteArray(), isString()
1641 */
1642QCborValue::QCborValue(const QByteArray &ba)
1643 : n(0), container(new QCborContainerPrivate), t(ByteArray)
1644{
1645 container->appendByteData(ba.constData(), ba.size(), t);
1646 container->ref.storeRelaxed(1);
1647}
1648
1649/*!
1650 Creates a QCborValue with string value \a s. The value can later be
1651 retrieved using toString().
1652
1653 \sa toString(), isString(), isByteArray()
1654 */
1655QCborValue::QCborValue(const QString &s)
1656 : n(0), container(new QCborContainerPrivate), t(String)
1657{
1658 container->append(s);
1659 container->ref.storeRelaxed(1);
1660}
1661
1662/*!
1663 \overload
1664
1665 Creates a QCborValue with string value \a s. The value can later be
1666 retrieved using toString().
1667
1668 \sa toString(), isString(), isByteArray()
1669 */
1670QCborValue::QCborValue(QLatin1String s)
1671 : n(0), container(new QCborContainerPrivate), t(String)
1672{
1673 container->append(s);
1674 container->ref.storeRelaxed(1);
1675}
1676
1677/*!
1678 \fn QCborValue::QCborValue(const QCborArray &a)
1679 \fn QCborValue::QCborValue(QCborArray &&a)
1680
1681 Creates a QCborValue with the array \a a. The array can later be retrieved
1682 using toArray().
1683
1684 \sa toArray(), isArray(), isMap()
1685 */
1686QCborValue::QCborValue(const QCborArray &a)
1687 : n(-1), container(a.d.data()), t(Array)
1688{
1689 if (container)
1690 container->ref.ref();
1691}
1692
1693/*!
1694 \fn QCborValue::QCborValue(const QCborMap &m)
1695 \fn QCborValue::QCborValue(QCborMap &&m)
1696
1697 Creates a QCborValue with the map \a m. The map can later be retrieved
1698 using toMap().
1699
1700 \sa toMap(), isMap(), isArray()
1701 */
1702QCborValue::QCborValue(const QCborMap &m)
1703 : n(-1), container(m.d.data()), t(Map)
1704{
1705 if (container)
1706 container->ref.ref();
1707}
1708
1709/*!
1710 \fn QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
1711 \fn QCborValue::QCborValue(QCborKnownTags t, const QCborValue &tv)
1712
1713 Creates a QCborValue for the extended type represented by the tag value \a
1714 t, tagging value \a tv. The tag can later be retrieved using tag() and
1715 the tagged value using taggedValue().
1716
1717 \sa isTag(), tag(), taggedValue(), QCborKnownTags
1718 */
1719QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
1720 : n(-1), container(new QCborContainerPrivate), t(Tag)
1721{
1722 container->ref.storeRelaxed(1);
1723 container->append(t);
1724 container->append(tv);
1725}
1726
1727/*!
1728 Copies the contents of \a other into this object.
1729 */
1730QCborValue::QCborValue(const QCborValue &other)
1731 : n(other.n), container(other.container), t(other.t)
1732{
1733 if (container)
1734 container->ref.ref();
1735}
1736
1737/*!
1738 Creates a QCborValue object of the date/time extended type and containing
1739 the value represented by \a dt. The value can later be retrieved using
1740 toDateTime().
1741
1742 The CBOR date/time types are extension types using tags: either a string
1743 (in ISO date format) tagged as a \l{QCborKnownTags}{DateTime} or a number
1744 (of seconds since the start of 1970, UTC) tagged as a
1745 \l{QCborKnownTags}{UnixTime_t}. When parsing CBOR streams, QCborValue will
1746 convert \l{QCborKnownTags}{UnixTime_t} to the string-based type.
1747
1748 \sa toDateTime(), isDateTime(), taggedValue()
1749 */
1750QCborValue::QCborValue(const QDateTime &dt)
1751 : QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs).toLatin1())
1752{
1753 // change types
1754 t = DateTime;
1755 container->elements[1].type = String;
1756}
1757
1758/*!
1759 Creates a QCborValue object of the URL extended type and containing the
1760 value represented by \a url. The value can later be retrieved using toUrl().
1761
1762 The CBOR URL type is an extended type represented by a string tagged as an
1763 \l{QCborKnownTags}{Url}.
1764
1765 \sa toUrl(), isUrl(), taggedValue()
1766 */
1767QCborValue::QCborValue(const QUrl &url)
1768 : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
1769{
1770 // change types
1771 t = Url;
1772 container->elements[1].type = String;
1773}
1774
1775#if QT_CONFIG(regularexpression)
1776/*!
1777 Creates a QCborValue object of the regular expression pattern extended type
1778 and containing the value represented by \a rx. The value can later be retrieved
1779 using toRegularExpression().
1780
1781 The CBOR regular expression type is an extended type represented by a
1782 string tagged as an \l{QCborKnownTags}{RegularExpression}. Note that CBOR
1783 regular expressions only store the patterns, so any flags that the
1784 QRegularExpression object may carry will be lost.
1785
1786 \sa toRegularExpression(), isRegularExpression(), taggedValue()
1787 */
1788QCborValue::QCborValue(const QRegularExpression &rx)
1789 : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
1790{
1791 // change type
1792 t = RegularExpression;
1793}
1794#endif // QT_CONFIG(regularexpression)
1795
1796/*!
1797 Creates a QCborValue object of the UUID extended type and containing the
1798 value represented by \a uuid. The value can later be retrieved using
1799 toUuid().
1800
1801 The CBOR UUID type is an extended type represented by a byte array tagged
1802 as an \l{QCborKnownTags}{Uuid}.
1803
1804 \sa toUuid(), isUuid(), taggedValue()
1805 */
1806QCborValue::QCborValue(const QUuid &uuid)
1807 : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
1808{
1809 // change our type
1810 t = Uuid;
1811}
1812
1813// destructor
1814void QCborValue::dispose()
1815{
1816 container->deref();
1817}
1818
1819/*!
1820 Replaces the contents of this QCborObject with a copy of \a other.
1821 */
1822QCborValue &QCborValue::operator=(const QCborValue &other)
1823{
1824 if (other.container)
1825 other.container->ref.ref();
1826 if (container)
1827 container->deref();
1828
1829 n = other.n;
1830 container = other.container;
1831 t = other.t;
1832 return *this;
1833}
1834
1835/*!
1836 Returns the tag of this extended QCborValue object, if it is of the tag
1837 type, \a defaultValue otherwise.
1838
1839 CBOR represents extended types by associating a number (the tag) with a
1840 stored representation. This function returns that number. To retrieve the
1841 representation, use taggedValue().
1842
1843 \sa isTag(), taggedValue(), isDateTime(), isUrl(), isRegularExpression(), isUuid()
1844 */
1845QCborTag QCborValue::tag(QCborTag defaultValue) const
1846{
1847 return isTag() && container && container->elements.size() == 2 ?
1848 QCborTag(container->elements.at(0).value) : defaultValue;
1849}
1850
1851/*!
1852 Returns the tagged value of this extended QCborValue object, if it is of
1853 the tag type, \a defaultValue otherwise.
1854
1855 CBOR represents extended types by associating a number (the tag) with a
1856 stored representation. This function returns that representation. To
1857 retrieve the tag, use tag().
1858
1859 \sa isTag(), tag(), isDateTime(), isUrl(), isRegularExpression(), isUuid()
1860 */
1861QCborValue QCborValue::taggedValue(const QCborValue &defaultValue) const
1862{
1863 return isTag() && container && container->elements.size() == 2 ?
1864 container->valueAt(1) : defaultValue;
1865}
1866
1867/*!
1868 Returns the byte array value stored in this QCborValue, if it is of the byte
1869 array type. Otherwise, it returns \a defaultValue.
1870
1871 Note that this function performs no conversion from other types to
1872 QByteArray.
1873
1874 \sa isByteArray(), isString(), toString()
1875 */
1876QByteArray QCborValue::toByteArray(const QByteArray &defaultValue) const
1877{
1878 if (!container || !isByteArray())
1879 return defaultValue;
1880
1881 Q_ASSERT(n >= 0);
1882 return container->byteArrayAt(n);
1883}
1884
1885/*!
1886 Returns the string value stored in this QCborValue, if it is of the string
1887 type. Otherwise, it returns \a defaultValue.
1888
1889 Note that this function performs no conversion from other types to
1890 QString.
1891
1892 \sa isString(), isByteArray(), toByteArray()
1893 */
1894QString QCborValue::toString(const QString &defaultValue) const
1895{
1896 if (!container || !isString())
1897 return defaultValue;
1898
1899 Q_ASSERT(n >= 0);
1900 return container->stringAt(n);
1901}
1902
1903/*!
1904 Returns the date/time value stored in this QCborValue, if it is of the
1905 date/time extended type. Otherwise, it returns \a defaultValue.
1906
1907 Note that this function performs no conversion from other types to
1908 QDateTime.
1909
1910 \sa isDateTime(), isTag(), taggedValue()
1911 */
1912QDateTime QCborValue::toDateTime(const QDateTime &defaultValue) const
1913{
1914 if (!container || !isDateTime() || container->elements.size() != 2)
1915 return defaultValue;
1916
1917 Q_ASSERT(n == -1);
1918 const ByteData *byteData = container->byteData(1);
1919 if (!byteData)
1920 return defaultValue; // date/times are never empty, so this must be invalid
1921
1922 // Our data must be US-ASCII.
1923 Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
1924 return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
1925}
1926
1927/*!
1928 Returns the URL value stored in this QCborValue, if it is of the URL
1929 extended type. Otherwise, it returns \a defaultValue.
1930
1931 Note that this function performs no conversion from other types to QUrl.
1932
1933 \sa isUrl(), isTag(), taggedValue()
1934 */
1935QUrl QCborValue::toUrl(const QUrl &defaultValue) const
1936{
1937 if (!container || !isUrl() || container->elements.size() != 2)
1938 return defaultValue;
1939
1940 Q_ASSERT(n == -1);
1941 const ByteData *byteData = container->byteData(1);
1942 if (!byteData)
1943 return QUrl(); // valid, empty URL
1944
1945 return QUrl::fromEncoded(byteData->asByteArrayView());
1946}
1947
1948#if QT_CONFIG(regularexpression)
1949/*!
1950 Returns the regular expression value stored in this QCborValue, if it is of
1951 the regular expression pattern extended type. Otherwise, it returns \a
1952 defaultValue.
1953
1954 Note that this function performs no conversion from other types to
1955 QRegularExpression.
1956
1957 \sa isRegularExpression(), isTag(), taggedValue()
1958 */
1959QRegularExpression QCborValue::toRegularExpression(const QRegularExpression &defaultValue) const
1960{
1961 if (!container || !isRegularExpression() || container->elements.size() != 2)
1962 return defaultValue;
1963
1964 Q_ASSERT(n == -1);
1965 return QRegularExpression(container->stringAt(1));
1966}
1967#endif // QT_CONFIG(regularexpression)
1968
1969/*!
1970 Returns the UUID value stored in this QCborValue, if it is of the UUID
1971 extended type. Otherwise, it returns \a defaultValue.
1972
1973 Note that this function performs no conversion from other types to QUuid.
1974
1975 \sa isUuid(), isTag(), taggedValue()
1976 */
1977QUuid QCborValue::toUuid(const QUuid &defaultValue) const
1978{
1979 if (!container || !isUuid() || container->elements.size() != 2)
1980 return defaultValue;
1981
1982 Q_ASSERT(n == -1);
1983 const ByteData *byteData = container->byteData(1);
1984 if (!byteData)
1985 return defaultValue; // UUIDs must always be 16 bytes, so this must be invalid
1986
1987 return QUuid::fromRfc4122(byteData->asByteArrayView());
1988}
1989
1990/*!
1991 \fn QCborArray QCborValue::toArray() const
1992 \fn QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
1993
1994 Returns the array value stored in this QCborValue, if it is of the array
1995 type. Otherwise, it returns \a defaultValue.
1996
1997 Note that this function performs no conversion from other types to
1998 QCborArray.
1999
2000 \sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
2001 */
2002
2003/*!
2004 \fn QCborArray QCborValueRef::toArray() const
2005 \fn QCborArray QCborValueRef::toArray(const QCborArray &defaultValue) const
2006 \internal
2007
2008 Returns the array value stored in this QCborValue, if it is of the array
2009 type. Otherwise, it returns \a defaultValue.
2010
2011 Note that this function performs no conversion from other types to
2012 QCborArray.
2013
2014 \sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
2015 */
2016QCborArray QCborValue::toArray() const
2017{
2018 return toArray(QCborArray());
2019}
2020
2021QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
2022{
2023 if (!isArray())
2024 return defaultValue;
2025 QCborContainerPrivate *dd = nullptr;
2026 Q_ASSERT(n == -1 || container == nullptr);
2027 if (n < 0)
2028 dd = container;
2029 return dd ? QCborArray(*dd) : defaultValue;
2030}
2031
2032/*!
2033 \fn QCborMap QCborValue::toMap() const
2034 \fn QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
2035
2036 Returns the map value stored in this QCborValue, if it is of the map type.
2037 Otherwise, it returns \a defaultValue.
2038
2039 Note that this function performs no conversion from other types to
2040 QCborMap.
2041
2042 \sa isMap(), isArray(), isContainer(), toArray()
2043 */
2044
2045/*!
2046 \fn QCborMap QCborValueRef::toMap() const
2047 \fn QCborMap QCborValueRef::toMap(const QCborMap &defaultValue) const
2048 \internal
2049
2050 Returns the map value stored in this QCborValue, if it is of the map type.
2051 Otherwise, it returns \a defaultValue.
2052
2053 Note that this function performs no conversion from other types to
2054 QCborMap.
2055
2056 \sa isMap(), isArray(), isContainer(), toArray()
2057 */
2058QCborMap QCborValue::toMap() const
2059{
2060 return toMap(QCborMap());
2061}
2062
2063QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
2064{
2065 if (!isMap())
2066 return defaultValue;
2067 QCborContainerPrivate *dd = nullptr;
2068 Q_ASSERT(n == -1 || container == nullptr);
2069 if (n < 0)
2070 dd = container;
2071 return dd ? QCborMap(*dd) : defaultValue;
2072}
2073
2074/*!
2075 If this QCborValue is a QCborMap, searches elements for the value whose key
2076 matches \a key. If there's no key matching \a key in the map or if this
2077 QCborValue object is not a map, returns the undefined value.
2078
2079 This function is equivalent to:
2080
2081 \snippet code/src_corelib_serialization_qcborvalue.cpp 4
2082
2083 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2084 QCborMap::find()
2085 */
2086const QCborValue QCborValue::operator[](const QString &key) const
2087{
2088 if (isMap())
2089 return toMap().value(key);
2090 return QCborValue();
2091}
2092
2093/*!
2094 \overload
2095
2096 If this QCborValue is a QCborMap, searches elements for the value whose key
2097 matches \a key. If there's no key matching \a key in the map or if this
2098 QCborValue object is not a map, returns the undefined value.
2099
2100 This function is equivalent to:
2101
2102 \snippet code/src_corelib_serialization_qcborvalue.cpp 5
2103
2104 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2105 QCborMap::find()
2106 */
2107const QCborValue QCborValue::operator[](QLatin1String key) const
2108{
2109 if (isMap())
2110 return toMap().value(key);
2111 return QCborValue();
2112}
2113
2114/*!
2115 \overload
2116
2117 If this QCborValue is a QCborMap, searches elements for the value whose key
2118 matches \a key. If this is a QCborArray, returns the element whose index is
2119 \a key. If there's no matching value in the array or map, or if this
2120 QCborValue object is not an array or map, returns the undefined value.
2121
2122 \sa operator[], QCborMap::operator[], QCborMap::value(),
2123 QCborMap::find(), QCborArray::operator[], QCborArray::at()
2124 */
2125const QCborValue QCborValue::operator[](qint64 key) const
2126{
2127 if (isMap())
2128 return toMap().value(key);
2129 if (isArray())
2130 return toArray().at(key);
2131 return QCborValue();
2132}
2133
2134/*!
2135 \internal
2136 */
2137static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
2138{
2139 if (array.size())
2140 qWarning("Using CBOR array as map forced conversion");
2141 QCborMap map;
2142 for (qsizetype i = array.size(); i-- > 0; ) {
2143 QCborValue entry = array.at(i);
2144 // Ignore padding entries that may have been added to grow the array
2145 // when inserting past its end:
2146 if (!entry.isInvalid())
2147 map[i] = entry;
2148 }
2149 return map;
2150}
2151
2152/*!
2153 \internal
2154 */
2155static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
2156{
2157 auto replace = QCborContainerPrivate::detach(container, size);
2158 Q_ASSERT(replace);
2159 if (replace != container) {
2160 if (container)
2161 container->deref();
2162 replace->ref.ref();
2163 }
2164 return replace;
2165}
2166
2167/*!
2168 \internal
2169 */
2170static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizetype index)
2171{
2172 auto replace = QCborContainerPrivate::grow(container, index);
2173 Q_ASSERT(replace);
2174 if (replace != container) {
2175 if (container)
2176 container->deref();
2177 replace->ref.ref();
2178 }
2179 if (replace->elements.size() == index)
2180 replace->append(Undefined());
2181 else
2182 Q_ASSERT(replace->elements.size() > index);
2183 return replace;
2184}
2185
2186/*!
2187 Returns a QCborValueRef that can be used to read or modify the entry in
2188 this, as a map, with the given \a key. When this QCborValue is a QCborMap,
2189 this function is equivalent to the matching operator[] on that map.
2190
2191 Before returning the reference: if this QCborValue was an array, it is first
2192 converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
2193 with valid \c{array[i]}); otherwise, if it was not a map it will be
2194 over-written with an empty map.
2195
2196 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2197 QCborMap::find()
2198 */
2199QCborValueRef QCborValue::operator[](const QString &key)
2200{
2201 if (!isMap())
2202 *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
2203
2204 const qsizetype size = container ? container->elements.size() : 0;
2205 qsizetype index = size + 1;
2206 bool found = false;
2207 if (container) {
2208 QCborMap proxy(*container);
2209 auto it = proxy.constFind(key);
2210 if (it < proxy.constEnd()) {
2211 found = true;
2212 index = it.item.i;
2213 }
2214 }
2215
2216 container = maybeDetach(container, size + (found ? 0 : 2));
2217 Q_ASSERT(container);
2218 if (!found) {
2219 container->append(key);
2220 container->append(QCborValue());
2221 }
2222 Q_ASSERT(index & 1 && !(container->elements.size() & 1));
2223 Q_ASSERT(index < container->elements.size());
2224 return { container, index };
2225}
2226
2227/*!
2228 \overload
2229
2230 Returns a QCborValueRef that can be used to read or modify the entry in
2231 this, as a map, with the given \a key. When this QCborValue is a QCborMap,
2232 this function is equivalent to the matching operator[] on that map.
2233
2234 Before returning the reference: if this QCborValue was an array, it is first
2235 converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
2236 with valid \c{array[i]}); otherwise, if it was not a map it will be
2237 over-written with an empty map.
2238
2239 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2240 QCborMap::find()
2241 */
2242QCborValueRef QCborValue::operator[](QLatin1String key)
2243{
2244 if (!isMap())
2245 *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
2246
2247 const qsizetype size = container ? container->elements.size() : 0;
2248 qsizetype index = size + 1;
2249 bool found = false;
2250 if (container) {
2251 QCborMap proxy(*container);
2252 auto it = proxy.constFind(key);
2253 if (it < proxy.constEnd()) {
2254 found = true;
2255 index = it.item.i;
2256 }
2257 }
2258
2259 container = maybeDetach(container, size + (found ? 0 : 2));
2260 Q_ASSERT(container);
2261 if (!found) {
2262 container->append(key);
2263 container->append(QCborValue());
2264 }
2265 Q_ASSERT(index & 1 && !(container->elements.size() & 1));
2266 Q_ASSERT(index < container->elements.size());
2267 return { container, index };
2268}
2269
2270/*!
2271 \overload
2272
2273 Returns a QCborValueRef that can be used to read or modify the entry in
2274 this, as a map or array, with the given \a key. When this QCborValue is a
2275 QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
2276 equivalent to the matching operator[] on that map or array.
2277
2278 Before returning the reference: if this QCborValue was an array but the key
2279 is out of range, the array is first converted to a map (so that \c{map[i]}
2280 is \c{array[i]} for each index, \c i, with valid \c{array[i]}); otherwise,
2281 if it was not a map it will be over-written with an empty map.
2282
2283 \sa operator[], QCborMap::operator[], QCborMap::value(),
2284 QCborMap::find(), QCborArray::operator[], QCborArray::at()
2285 */
2286QCborValueRef QCborValue::operator[](qint64 key)
2287{
2288 if (isArray() && key >= 0 && key < 0x10000) {
2289 container = maybeGrow(container, key);
2290 return { container, qsizetype(key) };
2291 }
2292 if (!isMap())
2293 *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
2294
2295 const qsizetype size = container ? container->elements.size() : 0;
2296 Q_ASSERT(!(size & 1));
2297 qsizetype index = size + 1;
2298 bool found = false;
2299 if (container) {
2300 QCborMap proxy(*container);
2301 auto it = proxy.constFind(key);
2302 if (it < proxy.constEnd()) {
2303 found = true;
2304 index = it.item.i;
2305 }
2306 }
2307
2308 container = maybeDetach(container, size + (found ? 0 : 2));
2309 Q_ASSERT(container);
2310 if (!found) {
2311 container->append(key);
2312 container->append(QCborValue());
2313 }
2314 Q_ASSERT(index & 1 && !(container->elements.size() & 1));
2315 Q_ASSERT(index < container->elements.size());
2316 return { container, index };
2317}
2318
2319/*!
2320 Decodes one item from the CBOR stream found in \a reader and returns the
2321 equivalent representation. This function is recursive: if the item is a map
2322 or array, it will decode all items found in that map or array, until the
2323 outermost object is finished.
2324
2325 This function need not be used on the root element of a \l
2326 QCborStreamReader. For example, the following code illustrates how to skip
2327 the CBOR signature tag from the beginning of a file:
2328
2329 \snippet code/src_corelib_serialization_qcborvalue.cpp 6
2330
2331 The returned value may be partially complete and indistinguishable from a
2332 valid QCborValue even if the decoding failed. To determine if there was an
2333 error, check if \l{QCborStreamReader::lastError()}{reader.lastError()} is
2334 indicating an error condition. This function stops decoding immediately
2335 after the first error.
2336
2337 \sa toCbor(), toDiagnosticNotation(), toVariant(), toJsonValue()
2338 */
2339QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
2340{
2341 QCborValue result;
2342 auto t = reader.type();
2343 if (reader.lastError() != QCborError::NoError)
2344 t = QCborStreamReader::Invalid;
2345
2346 switch (t) {
2347 // basic types, no container needed:
2348 case QCborStreamReader::UnsignedInteger:
2349 case QCborStreamReader::NegativeInteger:
2350 case QCborStreamReader::SimpleType:
2351 case QCborStreamReader::Float16:
2352 case QCborStreamReader::Float:
2353 case QCborStreamReader::Double: {
2354 Element e = decodeBasicValueFromCbor(reader);
2355 result.n = e.value;
2356 result.t = e.type;
2357 break;
2358 }
2359
2360 case QCborStreamReader::Invalid:
2361 result.t = QCborValue::Invalid;
2362 break; // probably a decode error
2363
2364 // strings
2365 case QCborStreamReader::ByteArray:
2366 case QCborStreamReader::String:
2367 result.n = 0;
2368 result.t = reader.isString() ? String : ByteArray;
2369 result.container = new QCborContainerPrivate;
2370 result.container->ref.ref();
2371 result.container->decodeStringFromCbor(reader);
2372 break;
2373
2374 // containers
2375 case QCborStreamReader::Array:
2376 case QCborStreamReader::Map:
2377 result.n = -1;
2378 result.t = reader.isArray() ? Array : Map;
2379 result.container = createContainerFromCbor(reader);
2380 break;
2381
2382 // tag
2383 case QCborStreamReader::Tag:
2384 result = taggedValueFromCbor(reader);
2385 break;
2386 }
2387
2388 return result;
2389}
2390
2391/*!
2392 \overload
2393
2394 Decodes one item from the CBOR stream found in the byte array \a ba and
2395 returns the equivalent representation. This function is recursive: if the
2396 item is a map or array, it will decode all items found in that map or
2397 array, until the outermost object is finished.
2398
2399 This function stores the error state, if any, in the object pointed to by
2400 \a error, along with the offset of where the error occurred. If no error
2401 happened, it stores \l{QCborError}{NoError} in the error state and the
2402 number of bytes that it consumed (that is, it stores the offset for the
2403 first unused byte). Using that information makes it possible to parse
2404 further data that may exist in the same byte array.
2405
2406 The returned value may be partially complete and indistinguishable from a
2407 valid QCborValue even if the decoding failed. To determine if there was an
2408 error, check if there was an error stored in \a error. This function stops
2409 decoding immediately after the first error.
2410
2411 \sa toCbor(), toDiagnosticNotation(), toVariant(), toJsonValue()
2412 */
2413QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error)
2414{
2415 QCborStreamReader reader(ba);
2416 QCborValue result = fromCbor(reader);
2417 if (error) {
2418 error->error = reader.lastError();
2419 error->offset = reader.currentOffset();
2420 }
2421 return result;
2422}
2423
2424/*!
2425 \fn QCborValue QCborValue::fromCbor(const char *data, qsizetype len, QCborParserError *error)
2426 \fn QCborValue QCborValue::fromCbor(const quint8 *data, qsizetype len, QCborParserError *error)
2427 \overload
2428
2429 Converts \a len bytes of \a data to a QByteArray and then calls the
2430 overload of this function that accepts a QByteArray, also passing \a error,
2431 if provided.
2432*/
2433
2434/*!
2435 Encodes this QCborValue object to its CBOR representation, using the
2436 options specified in \a opt, and return the byte array containing that
2437 representation.
2438
2439 This function will not fail, except if this QCborValue or any of the
2440 contained items, if this is a map or array, are invalid. Invalid types are
2441 not produced normally by the API, but can result from decoding errors.
2442
2443 By default, this function performs no transformation on the values in the
2444 QCborValue, writing all floating point directly as double-precision (\c
2445 double) types. If the \l{EncodingOption}{UseFloat} option is specified, it
2446 will use single precision (\c float) for any floating point value for which
2447 there's no loss of precision in using that representation. That includes
2448 infinities and NaN values.
2449
2450 Similarly, if \l{EncodingOption}{UseFloat16} is specified, this function
2451 will try to use half-precision (\c qfloat16) floating point if the
2452 conversion to that results in no loss of precision. This is always true for
2453 infinities and NaN.
2454
2455 If \l{EncodingOption}{UseIntegers} is specified, it will use integers for
2456 any floating point value that contains an actual integer.
2457
2458 \sa fromCbor(), fromVariant(), fromJsonValue()
2459 */
2460QByteArray QCborValue::toCbor(EncodingOptions opt)
2461{
2462 QByteArray result;
2463 QCborStreamWriter writer(&result);
2464 toCbor(writer, opt);
2465 return result;
2466}
2467
2468/*!
2469 \overload
2470
2471 Encodes this QCborValue object to its CBOR representation, using the
2472 options specified in \a opt, to the writer specified by \a writer. The same
2473 writer can be used by multiple QCborValues, for example, in order to encode
2474 different elements in a larger array.
2475
2476 This function will not fail, except if this QCborValue or any of the
2477 contained items, if this is a map or array, are invalid. Invalid types are
2478 not produced normally by the API, but can result from decoding errors.
2479
2480 By default, this function performs no transformation on the values in the
2481 QCborValue, writing all floating point directly as double-precision
2482 (binary64) types. If the \l{EncodingOption}{UseFloat} option is
2483 specified, it will use single precision (binary32) for any floating point
2484 value for which there's no loss of precision in using that representation.
2485 That includes infinities and NaN values.
2486
2487 Similarly, if \l{EncodingOption}{UseFloat16} is specified, this function
2488 will try to use half-precision (binary16) floating point if the conversion
2489 to that results in no loss of precision. This is always true for infinities
2490 and NaN.
2491
2492 If \l{EncodingOption}{UseIntegers} is specified, it will use integers
2493 for any floating point value that contains an actual integer.
2494
2495 \sa fromCbor(), fromVariant(), fromJsonValue()
2496 */
2497Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
2498{
2499 if (isContainer() || isTag())
2500 return encodeToCbor(writer, container, -type(), opt);
2501 if (container)
2502 return encodeToCbor(writer, container, n, opt);
2503
2504 // very simple types
2505 if (isSimpleType())
2506 return writer.append(toSimpleType());
2507
2508 switch (type()) {
2509 case Integer:
2510 return writer.append(n);
2511
2512 case Double:
2513 return writeDoubleToCbor(writer, fp_helper(), opt);
2514
2515 case Invalid:
2516 return;
2517
2518 case SimpleType:
2519 case False:
2520 case True:
2521 case Null:
2522 case Undefined:
2523 // handled by "if (isSimpleType())"
2524 Q_UNREACHABLE();
2525 break;
2526
2527 case ByteArray:
2528 // Byte array with no container is empty
2529 return writer.appendByteString("", 0);
2530
2531 case String:
2532 // String with no container is empty
2533 return writer.appendTextString("", 0);
2534
2535 case Array:
2536 case Map:
2537 case Tag:
2538 // handled by "if (isContainer() || isTag())"
2539 Q_UNREACHABLE();
2540 break;
2541
2542 case DateTime:
2543 case Url:
2544 case RegularExpression:
2545 case Uuid:
2546 // not possible
2547 Q_UNREACHABLE();
2548 break;
2549 }
2550}
2551
2552void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
2553{
2554 concrete().toCbor(writer, opt);
2555}
2556
2557void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
2558{
2559 that.d->replaceAt(that.i, other);
2560}
2561
2562void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
2563{
2564 that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
2565}
2566
2567void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other)
2568{
2569 // ### optimize?
2570 assign(that, other.concrete());
2571}
2572
2573QCborValue QCborValueRef::concrete(QCborValueRef self) noexcept
2574{
2575 return self.d->valueAt(self.i);
2576}
2577
2578QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
2579{
2580 return self.d->elements.at(self.i).type;
2581}
2582
2583/*!
2584 If this QCborValueRef refers to a QCborMap, searches elements for the value
2585 whose key matches \a key. If there's no key matching \a key in the map or if
2586 this QCborValueRef object is not a map, returns the undefined value.
2587
2588 This function is equivalent to:
2589
2590 \code
2591 value.toMap().value(key);
2592 \endcode
2593
2594 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2595 QCborMap::find()
2596 */
2597const QCborValue QCborValueRef::operator[](const QString &key) const
2598{
2599 const QCborValue item = d->valueAt(i);
2600 return item[key];
2601}
2602
2603/*!
2604 \overload
2605
2606 If this QCborValueRef refers to a QCborMap, searches elements for the value
2607 whose key matches \a key. If there's no key matching \a key in the map or if
2608 this QCborValueRef object is not a map, returns the undefined value.
2609
2610 This function is equivalent to:
2611
2612 \code
2613 value.toMap().value(key);
2614 \endcode
2615
2616 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2617 QCborMap::find()
2618 */
2619const QCborValue QCborValueRef::operator[](QLatin1String key) const
2620{
2621 const QCborValue item = d->valueAt(i);
2622 return item[key];
2623}
2624
2625/*!
2626 \overload
2627
2628 If this QCborValueRef refers to a QCborMap, searches elements for the value
2629 whose key matches \a key. If this is a QCborArray, returns the element whose
2630 index is \a key. If there's no matching value in the array or map, or if
2631 this QCborValueRef object is not an array or map, returns the undefined
2632 value.
2633
2634 \sa operator[], QCborMap::operator[], QCborMap::value(),
2635 QCborMap::find(), QCborArray::operator[], QCborArray::at()
2636 */
2637const QCborValue QCborValueRef::operator[](qint64 key) const
2638{
2639 const QCborValue item = d->valueAt(i);
2640 return item[key];
2641}
2642
2643/*!
2644 Returns a QCborValueRef that can be used to read or modify the entry in
2645 this, as a map, with the given \a key. When this QCborValueRef refers to a
2646 QCborMap, this function is equivalent to the matching operator[] on that
2647 map.
2648
2649 Before returning the reference: if the QCborValue referenced was an array,
2650 it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
2651 index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
2652 will be over-written with an empty map.
2653
2654 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2655 QCborMap::find()
2656 */
2657QCborValueRef QCborValueRef::operator[](const QString &key)
2658{
2659 auto &e = d->elements[i];
2660 qsizetype size = 0;
2661 if (e.flags & QtCbor::Element::IsContainer) {
2662 if (e.container) {
2663 if (e.type == QCborValue::Array) {
2664 QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
2665 qSwap(e.container, repack.container);
2666 } else if (e.type != QCborValue::Map) {
2667 e.container->deref();
2668 e.container = nullptr;
2669 }
2670 }
2671 e.type = QCborValue::Map;
2672 if (e.container)
2673 size = e.container->elements.size();
2674 } else {
2675 // Stomp any prior e.value, replace with a map (that we'll grow)
2676 e.container = nullptr;
2677 e.type = QCborValue::Map;
2678 e.flags = QtCbor::Element::IsContainer;
2679 }
2680
2681 qsizetype index = size + 1;
2682 bool found = false;
2683 if (e.container) {
2684 QCborMap proxy(*e.container);
2685 auto it = proxy.constFind(key);
2686 if (it < proxy.constEnd()) {
2687 found = true;
2688 index = it.item.i;
2689 }
2690 }
2691
2692 e.container = maybeDetach(e.container, size + (found ? 0 : 2));
2693 Q_ASSERT(e.container);
2694 if (!found) {
2695 e.container->append(key);
2696 e.container->append(QCborValue());
2697 }
2698 Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
2699 Q_ASSERT(index < e.container->elements.size());
2700 return { e.container, index };
2701}
2702
2703/*!
2704 \overload
2705
2706 Returns a QCborValueRef that can be used to read or modify the entry in
2707 this, as a map, with the given \a key. When this QCborValue is a QCborMap,
2708 this function is equivalent to the matching operator[] on that map.
2709
2710 Before returning the reference: if the QCborValue referenced was an array,
2711 it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
2712 index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
2713 will be over-written with an empty map.
2714
2715 \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
2716 QCborMap::find()
2717 */
2718QCborValueRef QCborValueRef::operator[](QLatin1String key)
2719{
2720 auto &e = d->elements[i];
2721 qsizetype size = 0;
2722 if (e.flags & QtCbor::Element::IsContainer) {
2723 if (e.container) {
2724 if (e.type == QCborValue::Array) {
2725 QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
2726 qSwap(e.container, repack.container);
2727 } else if (e.type != QCborValue::Map) {
2728 e.container->deref();
2729 e.container = nullptr;
2730 }
2731 }
2732 e.type = QCborValue::Map;
2733 if (e.container)
2734 size = e.container->elements.size();
2735 } else {
2736 // Stomp any prior e.value, replace with a map (that we'll grow)
2737 e.container = nullptr;
2738 e.type = QCborValue::Map;
2739 e.flags = QtCbor::Element::IsContainer;
2740 }
2741
2742 qsizetype index = size + 1;
2743 bool found = false;
2744 if (e.container) {
2745 QCborMap proxy(*e.container);
2746 auto it = proxy.constFind(key);
2747 if (it < proxy.constEnd()) {
2748 found = true;
2749 index = it.item.i;
2750 }
2751 }
2752
2753 e.container = maybeDetach(e.container, size + (found ? 0 : 2));
2754 Q_ASSERT(e.container);
2755 if (!found) {
2756 e.container->append(key);
2757 e.container->append(QCborValue());
2758 }
2759 Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
2760 Q_ASSERT(index < e.container->elements.size());
2761 return { e.container, index };
2762}
2763
2764/*!
2765 \overload
2766
2767 Returns a QCborValueRef that can be used to read or modify the entry in
2768 this, as a map or array, with the given \a key. When this QCborValue is a
2769 QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
2770 equivalent to the matching operator[] on that map or array.
2771
2772 Before returning the reference: if the QCborValue referenced was an array
2773 but the key is out of range, the array is first converted to a map (so that
2774 \c{map[i]} is \c{array[i]} for each index, \c i, with valid \c{array[i]});
2775 otherwise, if it was not a map it will be over-written with an empty map.
2776
2777 \sa operator[], QCborMap::operator[], QCborMap::value(),
2778 QCborMap::find(), QCborArray::operator[], QCborArray::at()
2779 */
2780QCborValueRef QCborValueRef::operator[](qint64 key)
2781{
2782 auto &e = d->elements[i];
2783 if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
2784 e.container = maybeGrow(e.container, key);
2785 return { e.container, qsizetype(key) };
2786 }
2787 qsizetype size = 0;
2788 if (e.flags & QtCbor::Element::IsContainer) {
2789 if (e.container) {
2790 if (e.type == QCborValue::Array) {
2791 QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
2792 qSwap(e.container, repack.container);
2793 } else if (e.type != QCborValue::Map) {
2794 e.container->deref();
2795 e.container = nullptr;
2796 }
2797 }
2798 e.type = QCborValue::Map;
2799 if (e.container)
2800 size = e.container->elements.size();
2801 } else {
2802 // Stomp any prior e.value, replace with a map (that we'll grow)
2803 e.container = nullptr;
2804 e.type = QCborValue::Map;
2805 e.flags = QtCbor::Element::IsContainer;
2806 }
2807 Q_ASSERT(!(size & 1));
2808
2809 qsizetype index = size + 1;
2810 bool found = false;
2811 if (e.container) {
2812 QCborMap proxy(*e.container);
2813 auto it = proxy.constFind(key);
2814 if (it < proxy.constEnd()) {
2815 found = true;
2816 index = it.item.i;
2817 }
2818 }
2819
2820 e.container = maybeDetach(e.container, size + (found ? 0 : 2));
2821 Q_ASSERT(e.container);
2822 if (!found) {
2823 e.container->append(key);
2824 e.container->append(QCborValue());
2825 }
2826 Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
2827 Q_ASSERT(index < e.container->elements.size());
2828 return { e.container, index };
2829}
2830
2831
2832inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
2833 : d(&dd)
2834{
2835}
2836
2837inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept
2838 : d(&dd)
2839{
2840}
2841
2842uint qHash(const QCborValue &value, uint seed)
2843{
2844 switch (value.type()) {
2845 case QCborValue::Integer:
2846 return qHash(value.toInteger(), seed);
2847 case QCborValue::ByteArray:
2848 return qHash(value.toByteArray(), seed);
2849 case QCborValue::String:
2850 return qHash(value.toString(), seed);
2851 case QCborValue::Array:
2852 return qHash(value.toArray(), seed);
2853 case QCborValue::Map:
2854 return qHash(value.toMap(), seed);
2855 case QCborValue::Tag: {
2856 QtPrivate::QHashCombine hash;
2857 seed = hash(seed, value.tag());
2858 seed = hash(seed, value.taggedValue());
2859 return seed;
2860 }
2861 case QCborValue::SimpleType:
2862 break;
2863 case QCborValue::False:
2864 return qHash(false, seed);
2865 case QCborValue::True:
2866 return qHash(true, seed);
2867 case QCborValue::Null:
2868 return qHash(nullptr, seed);
2869 case QCborValue::Undefined:
2870 return seed;
2871 case QCborValue::Double:
2872 return qHash(value.toDouble(), seed);
2873 case QCborValue::DateTime:
2874 return qHash(value.toDateTime(), seed);
2875 case QCborValue::Url:
2876 return qHash(value.toUrl(), seed);
2877#if QT_CONFIG(regularexpression)
2878 case QCborValue::RegularExpression:
2879 return qHash(value.toRegularExpression(), seed);
2880#endif
2881 case QCborValue::Uuid:
2882 return qHash(value.toUuid(), seed);
2883 case QCborValue::Invalid:
2884 return seed;
2885 default:
2886 break;
2887 }
2888
2889 Q_ASSERT(value.isSimpleType());
2890 return qHash(value.toSimpleType(), seed);
2891}
2892
2893#if !defined(QT_NO_DEBUG_STREAM)
2894static QDebug debugContents(QDebug &dbg, const QCborValue &v)
2895{
2896 switch (v.type()) {
2897 case QCborValue::Integer:
2898 return dbg << v.toInteger();
2899 case QCborValue::ByteArray:
2900 return dbg << "QByteArray(" << v.toByteArray() << ')';
2901 case QCborValue::String:
2902 return dbg << v.toString();
2903 case QCborValue::Array:
2904 return dbg << v.toArray();
2905 case QCborValue::Map:
2906 return dbg << v.toMap();
2907 case QCborValue::Tag:
2908 dbg << v.tag() << ", ";
2909 return debugContents(dbg, v.taggedValue());
2910 case QCborValue::SimpleType:
2911 break;
2912 case QCborValue::True:
2913 return dbg << true;
2914 case QCborValue::False:
2915 return dbg << false;
2916 case QCborValue::Null:
2917 return dbg << "nullptr";
2918 case QCborValue::Undefined:
2919 return dbg;
2920 case QCborValue::Double: {
2921 qint64 i = qint64(v.toDouble());
2922 if (i == v.toDouble())
2923 return dbg << i << ".0";
2924 else
2925 return dbg << v.toDouble();
2926 }
2927 case QCborValue::DateTime:
2928 return dbg << v.toDateTime();
2929 case QCborValue::Url:
2930 return dbg << v.toUrl();
2931#if QT_CONFIG(regularexpression)
2932 case QCborValue::RegularExpression:
2933 return dbg << v.toRegularExpression();
2934#endif
2935 case QCborValue::Uuid:
2936 return dbg << v.toUuid();
2937 case QCborValue::Invalid:
2938 return dbg << "<invalid>";
2939 default:
2940 break;
2941 }
2942 if (v.isSimpleType())
2943 return dbg << v.toSimpleType();
2944 return dbg << "<unknown type " << Qt::hex << int(v.type()) << Qt::dec << '>';
2945}
2946QDebug operator<<(QDebug dbg, const QCborValue &v)
2947{
2948 QDebugStateSaver saver(dbg);
2949 dbg.nospace() << "QCborValue(";
2950 return debugContents(dbg, v) << ')';
2951}
2952#endif
2953
2954#ifndef QT_NO_DATASTREAM
2955QDataStream &operator<<(QDataStream &stream, const QCborValue &value)
2956{
2957 stream << QCborValue(value).toCbor();
2958 return stream;
2959}
2960
2961QDataStream &operator>>(QDataStream &stream, QCborValue &value)
2962{
2963 QByteArray buffer;
2964 stream >> buffer;
2965 QCborParserError parseError{};
2966 value = QCborValue::fromCbor(buffer, &parseError);
2967 if (parseError.error)
2968 stream.setStatus(QDataStream::ReadCorruptData);
2969 return stream;
2970}
2971#endif
2972
2973
2974QT_END_NAMESPACE
2975
2976#include "qcborarray.cpp"
2977#include "qcbormap.cpp"
2978
2979#include "moc_qcborvalue.cpp"
2980