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