summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r--src/corelib/serialization/qcborarray.cpp26
-rw-r--r--src/corelib/serialization/qcborarray.h7
-rw-r--r--src/corelib/serialization/qcborcommon.h5
-rw-r--r--src/corelib/serialization/qcbormap.cpp19
-rw-r--r--src/corelib/serialization/qcbormap.h14
-rw-r--r--src/corelib/serialization/qcborstream.cpp16
-rw-r--r--src/corelib/serialization/qcborstream.h4
-rw-r--r--src/corelib/serialization/qcborvalue.cpp530
-rw-r--r--src/corelib/serialization/qcborvalue.h28
-rw-r--r--src/corelib/serialization/qdatastream.cpp15
-rw-r--r--src/corelib/serialization/qdatastream.h8
-rw-r--r--src/corelib/serialization/qjson_p.h2
-rw-r--r--src/corelib/serialization/qjsonarray.cpp35
-rw-r--r--src/corelib/serialization/qjsonarray.h7
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp4
-rw-r--r--src/corelib/serialization/qjsondocument.cpp20
-rw-r--r--src/corelib/serialization/qjsondocument.h5
-rw-r--r--src/corelib/serialization/qjsonobject.cpp17
-rw-r--r--src/corelib/serialization/qjsonobject.h5
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp75
-rw-r--r--src/corelib/serialization/qjsonvalue.h8
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp12
-rw-r--r--src/corelib/serialization/qtextstream.cpp6
-rw-r--r--src/corelib/serialization/qxmlstream.cpp8
-rw-r--r--src/corelib/serialization/qxmlstream.g14
25 files changed, 824 insertions, 66 deletions
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index c56536cdb1..ca0156e07d 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -39,6 +39,7 @@
#include "qcborarray.h"
#include "qcborvalue_p.h"
+#include "qdatastream.h"
QT_BEGIN_NAMESPACE
@@ -272,7 +273,7 @@ QCborValue QCborArray::at(qsizetype i) const
not be empty.
QCborValueRef has the exact same API as \l QCborValue, with one important
- difference: if you assign new values to it, this map will be updated with
+ difference: if you assign new values to it, this array will be updated with
that new value.
\sa operator[](), at(), last(), insert(), prepend(), append(),
@@ -286,7 +287,7 @@ QCborValue QCborArray::at(qsizetype i) const
not be empty.
QCborValueRef has the exact same API as \l QCborValue, with one important
- difference: if you assign new values to it, this map will be updated with
+ difference: if you assign new values to it, this array will be updated with
that new value.
\sa operator[](), at(), first(), insert(), prepend(), append(),
@@ -301,7 +302,7 @@ QCborValue QCborArray::at(qsizetype i) const
with undefined entries, until it has an entry at the specified index.
QCborValueRef has the exact same API as \l QCborValue, with one important
- difference: if you assign new values to it, this map will be updated with
+ difference: if you assign new values to it, this array will be updated with
that new value.
\sa at(), first(), last(), insert(), prepend(), append(),
@@ -1218,4 +1219,23 @@ QDebug operator<<(QDebug dbg, const QCborArray &a)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborArray &value)
+{
+ stream << value.toCborValue().toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborArray &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError).toArray();
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index ed0f4912ba..e06544f245 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
class QJsonArray;
+class QDataStream;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborArray
@@ -271,6 +272,7 @@ private:
void detach(qsizetype reserve = 0);
friend QCborValue;
+ friend QCborValueRef;
explicit QCborArray(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -298,6 +300,11 @@ Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborArray &);
+#endif
+
QT_END_NAMESPACE
#endif // QCBORARRAY_H
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index f8278f1649..3dfe50cd09 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -133,6 +133,11 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
#endif
+#if !defined(QT_NO_DEBUG_STREAM)
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
+#endif
+
inline uint qHash(QCborSimpleType tag, uint seed = 0)
{
return qHash(quint8(tag), seed);
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 33f9249993..4b28ca4a2e 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1763,4 +1763,23 @@ QDebug operator<<(QDebug dbg, const QCborMap &m)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborMap &value)
+{
+ stream << value.toCborValue().toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborMap &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError).toMap();
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 3eb2107691..4aea901eef 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -52,6 +52,7 @@ typedef QMap<QString, QVariant> QVariantMap;
template <class Key, class T> class QHash;
typedef QHash<QString, QVariant> QVariantHash;
class QJsonObject;
+class QDataStream;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborMap
@@ -117,6 +118,8 @@ public:
QCborValueRef item; // points to the value
friend class Iterator;
friend class QCborMap;
+ friend class QCborValue;
+ friend class QCborValueRef;
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
@@ -170,7 +173,7 @@ public:
: QCborMap()
{
detach(args.size());
- for (auto pair : args)
+ for (const auto &pair : args)
insert(pair.first, pair.second);
}
~QCborMap();
@@ -322,9 +325,10 @@ public:
QJsonObject toJsonObject() const;
private:
+ friend class QCborValue;
+ friend class QCborValueRef;
void detach(qsizetype reserve = 0);
- friend QCborValue;
explicit QCborMap(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -352,6 +356,12 @@ Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborMap &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborMap &);
+#endif
+
+
QT_END_NAMESPACE
#endif // QCBORMAP_H
diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp
index 87ae316041..078c14a32d 100644
--- a/src/corelib/serialization/qcborstream.cpp
+++ b/src/corelib/serialization/qcborstream.cpp
@@ -44,6 +44,7 @@
#include <qbuffer.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qdatastream.h>
QT_BEGIN_NAMESPACE
@@ -180,6 +181,21 @@ Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
return nullptr;
}
+#if !defined(QT_NO_DATASTREAM)
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
+{
+ return ds << quint8(st);
+}
+
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
+{
+ quint8 v;
+ ds >> v;
+ st = QCborSimpleType(v);
+ return ds;
+}
+#endif
+
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug dbg, QCborSimpleType st)
{
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
index 3b13a309ab..7a451e63ac 100644
--- a/src/corelib/serialization/qcborstream.h
+++ b/src/corelib/serialization/qcborstream.h
@@ -242,8 +242,8 @@ private:
template <typename FP> FP _toFloatingPoint() const noexcept
{
- using UInt = typename QIntegerForSizeof<FP>::Unsigned;
- UInt u = UInt(value64);
+ using UIntFP = typename QIntegerForSizeof<FP>::Unsigned;
+ UIntFP u = UIntFP(value64);
FP f;
memcpy(static_cast<void *>(&f), &u, sizeof(f));
return f;
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 80ef515fd2..288446878c 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -39,7 +39,7 @@
#include "qcborvalue.h"
#include "qcborvalue_p.h"
-
+#include "qdatastream.h"
#include "qcborarray.h"
#include "qcbormap.h"
#include "qcborstream.h"
@@ -108,7 +108,7 @@ QT_BEGIN_NAMESPACE
QCborValue can contain a value of "null", which is not of any specific type.
It resembles the C++ \c {std::nullptr_t} type, whose only possible value is
- \c nullptr. QCborValue has a constructor taking such a type and creates a
+ \nullptr. QCborValue has a constructor taking such a type and creates a
null QCborValue.
Null values are used to indicate that an optional value is not present. In
@@ -128,10 +128,11 @@ QT_BEGIN_NAMESPACE
Such values are completely valid and may appear in CBOR streams, unlike
JSON content and QJsonValue's undefined bit. But like QJsonValue's
- Undefined, it is returned by QCborArray::value() when out of range or
- QCborMap::operator[] when the key is not found in the container. It is not
- possible to tell such a case apart from the value of Undefined, so if that
- is required, check the QCborArray size and use the QCborMap iterator API.
+ Undefined, it is returned by a CBOR container's value() or read-only
+ operator[] for invalid look-ups (index out of range for QCborArray, or key
+ not found for QCborMap). It is not possible to tell such a case apart from
+ the value of Undefined, so if that is required, check the QCborArray size
+ and use the QCborMap iterator API.
\section1 Simple types
@@ -416,7 +417,7 @@ QT_BEGIN_NAMESPACE
using toSimpleType() as well as isSimpleType(st).
CBOR simple types are types that do not have any associated value, like
- C++'s \c{std::nullptr_t} type, whose only possible value is \c nullptr.
+ C++'s \c{std::nullptr_t} type, whose only possible value is \nullptr.
If \a st is \c{QCborSimpleType::Null}, the resulting QCborValue will be of
the \l{Type}{Null} type and similarly for \c{QCborSimpleType::Undefined}.
@@ -457,7 +458,7 @@ QT_BEGIN_NAMESPACE
\fn QCborValue::QCborValue(QCborValue &&other)
\overload
- Moves the contents of the \a other CBorValue object into this one and frees
+ Moves the contents of the \a other QCborValue object into this one and frees
the resources of this one.
*/
@@ -465,7 +466,7 @@ QT_BEGIN_NAMESPACE
\fn QCborValue &&QCborValue::operator=(QCborValue &&other)
\overload
- Moves the contents of the \a other CBorValue object into this one and frees
+ Moves the contents of the \a other QCborValue object into this one and frees
the resources of this one. Returns a reference to this object.
*/
@@ -1986,12 +1987,24 @@ QUuid QCborValue::toUuid(const QUuid &defaultValue) const
return QUuid::fromRfc4122(byteData->asByteArrayView());
}
-QCborArray QCborValue::toArray() const
-{
- return toArray(QCborArray());
-}
+/*!
+ \fn QCborArray QCborValue::toArray() const
+ \fn QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
+
+ Returns the array value stored in this QCborValue, if it is of the array
+ type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborArray.
+
+ \sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
+ */
/*!
+ \fn QCborArray QCborValueRef::toArray() const
+ \fn QCborArray QCborValueRef::toArray(const QCborArray &defaultValue) const
+ \internal
+
Returns the array value stored in this QCborValue, if it is of the array
type. Otherwise, it returns \a defaultValue.
@@ -2000,6 +2013,11 @@ QCborArray QCborValue::toArray() const
\sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
*/
+QCborArray QCborValue::toArray() const
+{
+ return toArray(QCborArray());
+}
+
QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
{
if (!isArray())
@@ -2011,12 +2029,24 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
return dd ? QCborArray(*dd) : defaultValue;
}
-QCborMap QCborValue::toMap() const
-{
- return toMap(QCborMap());
-}
+/*!
+ \fn QCborMap QCborValue::toMap() const
+ \fn QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
+
+ Returns the map value stored in this QCborValue, if it is of the map type.
+ Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborMap.
+
+ \sa isMap(), isArray(), isContainer(), toArray()
+ */
/*!
+ \fn QCborMap QCborValueRef::toMap() const
+ \fn QCborMap QCborValueRef::toMap(const QCborMap &defaultValue) const
+ \internal
+
Returns the map value stored in this QCborValue, if it is of the map type.
Otherwise, it returns \a defaultValue.
@@ -2025,6 +2055,11 @@ QCborMap QCborValue::toMap() const
\sa isMap(), isArray(), isContainer(), toArray()
*/
+QCborMap QCborValue::toMap() const
+{
+ return toMap(QCborMap());
+}
+
QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
{
if (!isMap())
@@ -2077,15 +2112,16 @@ const QCborValue QCborValue::operator[](QLatin1String key) const
}
/*!
+ \overload
+
If this QCborValue is a QCborMap, searches elements for the value whose key
- matches \a key. If this is an array, returns the element whose index is \a
- key. If there's no matching value in the array or map, or if this
+ matches \a key. If this is a QCborArray, returns the element whose index is
+ \a key. If there's no matching value in the array or map, or if this
QCborValue object is not an array or map, returns the undefined value.
\sa operator[], QCborMap::operator[], QCborMap::value(),
QCborMap::find(), QCborArray::operator[], QCborArray::at()
*/
-
const QCborValue QCborValue::operator[](qint64 key) const
{
if (isMap())
@@ -2096,6 +2132,191 @@ const QCborValue QCborValue::operator[](qint64 key) const
}
/*!
+ \internal
+ */
+static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
+{
+ if (array.size())
+ qWarning("Using CBOR array as map forced conversion");
+ QCborMap map;
+ for (qsizetype i = array.size(); i-- > 0; ) {
+ QCborValue entry = array.at(i);
+ // Ignore padding entries that may have been added to grow the array
+ // when inserting past its end:
+ if (!entry.isInvalid())
+ map[i] = entry;
+ }
+ return map;
+}
+
+/*!
+ \internal
+ */
+static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
+{
+ auto replace = QCborContainerPrivate::detach(container, size);
+ Q_ASSERT(replace);
+ if (replace != container) {
+ if (container)
+ container->deref();
+ replace->ref.ref();
+ }
+ return replace;
+}
+
+/*!
+ \internal
+ */
+static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizetype index)
+{
+ auto replace = QCborContainerPrivate::grow(container, index);
+ Q_ASSERT(replace);
+ if (replace != container) {
+ if (container)
+ container->deref();
+ replace->ref.ref();
+ }
+ if (replace->elements.size() == index)
+ replace->append(Undefined());
+ else
+ Q_ASSERT(replace->elements.size() > index);
+ return replace;
+}
+
+/*!
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if this QCborValue was an array, it is first
+ converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
+ with valid \c{array[i]}); otherwise, if it was not a map it will be
+ over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValue::operator[](const QString &key)
+{
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if this QCborValue was an array, it is first
+ converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i,
+ with valid \c{array[i]}); otherwise, if it was not a map it will be
+ over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValue::operator[](QLatin1String key)
+{
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map or array, with the given \a key. When this QCborValue is a
+ QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
+ equivalent to the matching operator[] on that map or array.
+
+ Before returning the reference: if this QCborValue was an array but the key
+ is out of range, the array is first converted to a map (so that \c{map[i]}
+ is \c{array[i]} for each index, \c i, with valid \c{array[i]}); otherwise,
+ if it was not a map it will be over-written with an empty map.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+QCborValueRef QCborValue::operator[](qint64 key)
+{
+ if (isArray() && key >= 0 && key < 0x10000) {
+ container = maybeGrow(container, key);
+ return { container, qsizetype(key) };
+ }
+ if (!isMap())
+ *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
+
+ const qsizetype size = container ? container->elements.size() : 0;
+ Q_ASSERT(!(size & 1));
+ qsizetype index = size + 1;
+ bool found = false;
+ if (container) {
+ QCborMap proxy(*container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ container = maybeDetach(container, size + (found ? 0 : 2));
+ Q_ASSERT(container);
+ if (!found) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(container->elements.size() & 1));
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+}
+
+/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
or array, it will decode all items found in that map or array, until the
@@ -2359,6 +2580,255 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
return self.d->elements.at(self.i).type;
}
+/*!
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If there's no key matching \a key in the map or if
+ this QCborValueRef object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \code
+ value.toMap().value(key);
+ \endcode
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValueRef::operator[](const QString &key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ \overload
+
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If there's no key matching \a key in the map or if
+ this QCborValueRef object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \code
+ value.toMap().value(key);
+ \endcode
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValueRef::operator[](QLatin1String key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ \overload
+
+ If this QCborValueRef refers to a QCborMap, searches elements for the value
+ whose key matches \a key. If this is a QCborArray, returns the element whose
+ index is \a key. If there's no matching value in the array or map, or if
+ this QCborValueRef object is not an array or map, returns the undefined
+ value.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+const QCborValue QCborValueRef::operator[](qint64 key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+/*!
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValueRef refers to a
+ QCborMap, this function is equivalent to the matching operator[] on that
+ map.
+
+ Before returning the reference: if the QCborValue referenced was an array,
+ it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
+ index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
+ will be over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValueRef::operator[](const QString &key)
+{
+ auto &e = d->elements[i];
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map, with the given \a key. When this QCborValue is a QCborMap,
+ this function is equivalent to the matching operator[] on that map.
+
+ Before returning the reference: if the QCborValue referenced was an array,
+ it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each
+ index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it
+ will be over-written with an empty map.
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+QCborValueRef QCborValueRef::operator[](QLatin1String key)
+{
+ auto &e = d->elements[i];
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+/*!
+ \overload
+
+ Returns a QCborValueRef that can be used to read or modify the entry in
+ this, as a map or array, with the given \a key. When this QCborValue is a
+ QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is
+ equivalent to the matching operator[] on that map or array.
+
+ Before returning the reference: if the QCborValue referenced was an array
+ but the key is out of range, the array is first converted to a map (so that
+ \c{map[i]} is \c{array[i]} for each index, \c i, with valid \c{array[i]});
+ otherwise, if it was not a map it will be over-written with an empty map.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+QCborValueRef QCborValueRef::operator[](qint64 key)
+{
+ auto &e = d->elements[i];
+ if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
+ e.container = maybeGrow(e.container, key);
+ return { e.container, qsizetype(key) };
+ }
+ qsizetype size = 0;
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.container) {
+ if (e.type == QCborValue::Array) {
+ QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
+ qSwap(e.container, repack.container);
+ } else if (e.type != QCborValue::Map) {
+ e.container->deref();
+ e.container = nullptr;
+ }
+ }
+ e.type = QCborValue::Map;
+ if (e.container)
+ size = e.container->elements.size();
+ } else {
+ // Stomp any prior e.value, replace with a map (that we'll grow)
+ e.container = nullptr;
+ e.type = QCborValue::Map;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+ Q_ASSERT(!(size & 1));
+
+ qsizetype index = size + 1;
+ bool found = false;
+ if (e.container) {
+ QCborMap proxy(*e.container);
+ auto it = proxy.constFind(key);
+ if (it < proxy.constEnd()) {
+ found = true;
+ index = it.item.i;
+ }
+ }
+
+ e.container = maybeDetach(e.container, size + (found ? 0 : 2));
+ Q_ASSERT(e.container);
+ if (!found) {
+ e.container->append(key);
+ e.container->append(QCborValue());
+ }
+ Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
+ Q_ASSERT(index < e.container->elements.size());
+ return { e.container, index };
+}
+
+
inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
: d(&dd)
{
@@ -2481,6 +2951,26 @@ QDebug operator<<(QDebug dbg, const QCborValue &v)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QCborValue &value)
+{
+ stream << QCborValue(value).toCbor();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QCborValue &value)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QCborParserError parseError{};
+ value = QCborValue::fromCbor(buffer, &parseError);
+ if (parseError.error)
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
+
QT_END_NAMESPACE
#include "qcborarray.cpp"
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index d6ba4e88d8..f542e44c47 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -69,6 +69,7 @@ class QCborArray;
class QCborMap;
class QCborStreamReader;
class QCborStreamWriter;
+class QDataStream;
struct QCborParserError
{
@@ -78,6 +79,7 @@ struct QCborParserError
QString errorString() const { return error.toString(); }
};
+class QCborValueRef;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborValue
{
@@ -242,20 +244,18 @@ public:
#endif
QUuid toUuid(const QUuid &defaultValue = {}) const;
-#ifdef Q_QDOC
- QCborArray toArray(const QCborArray &a = {}) const;
- QCborMap toMap(const QCborMap &m = {}) const;
-#else
// only forward-declared, need split functions
QCborArray toArray() const;
QCborArray toArray(const QCborArray &defaultValue) const;
QCborMap toMap() const;
QCborMap toMap(const QCborMap &defaultValue) const;
-#endif
const QCborValue operator[](const QString &key) const;
const QCborValue operator[](QLatin1String key) const;
const QCborValue operator[](qint64 key) const;
+ QCborValueRef operator[](qint64 key);
+ QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
#if 0 && QT_HAS_INCLUDE(<compare>)
@@ -393,16 +393,18 @@ public:
QUuid toUuid(const QUuid &defaultValue = {}) const
{ return concrete().toUuid(defaultValue); }
-#ifdef Q_QDOC
- QCborArray toArray(const QCborArray &a = {}) const;
- QCborMap toMap(const QCborMap &m = {}) const;
-#else
// only forward-declared, need split functions. Implemented in qcbor{array,map}.h
QCborArray toArray() const;
QCborArray toArray(const QCborArray &a) const;
QCborMap toMap() const;
QCborMap toMap(const QCborMap &m) const;
-#endif
+
+ const QCborValue operator[](const QString &key) const;
+ const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](qint64 key) const;
+ QCborValueRef operator[](qint64 key);
+ QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
@@ -434,6 +436,7 @@ public:
{ return concrete().toDiagnosticNotation(opt); }
private:
+ friend class QCborValue;
friend class QCborArray;
friend class QCborMap;
friend class QCborContainerPrivate;
@@ -465,6 +468,11 @@ Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborValue &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborValue &);
+#endif
+
QT_END_NAMESPACE
#if defined(QT_X11_DEFINES_FOUND)
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 951f6c9736..02c1d1c573 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -368,7 +368,7 @@ QDataStream::~QDataStream()
/*!
\fn QIODevice *QDataStream::device() const
- Returns the I/O device currently set, or 0 if no
+ Returns the I/O device currently set, or \nullptr if no
device is currently set.
\sa setDevice()
@@ -377,7 +377,7 @@ QDataStream::~QDataStream()
/*!
void QDataStream::setDevice(QIODevice *d)
- Sets the I/O device to \a d, which can be 0
+ Sets the I/O device to \a d, which can be \nullptr
to unset to current I/O device.
\sa device()
@@ -392,17 +392,18 @@ void QDataStream::setDevice(QIODevice *d)
dev = d;
}
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
\obsolete
Unsets the I/O device.
- Use setDevice(0) instead.
+ Use setDevice(nullptr) instead.
*/
void QDataStream::unsetDevice()
{
- setDevice(0);
+ setDevice(nullptr);
}
-
+#endif
/*!
\fn bool QDataStream::atEnd() const
@@ -559,6 +560,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_10 Same as Qt_5_6
\value Qt_5_11 Same as Qt_5_6
\value Qt_5_12 Version 18 (Qt 5.12)
+ \value Qt_5_13 Version 19 (Qt 5.13)
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
@@ -1026,8 +1028,7 @@ QDataStream &QDataStream::operator>>(char *&s)
\c{delete []} operator.
The \a l parameter is set to the length of the buffer. If the
- string read is empty, \a l is set to 0 and \a s is set to
- a null pointer.
+ string read is empty, \a l is set to 0 and \a s is set to \nullptr.
The serialization format is a quint32 length specifier first,
then \a l bytes of data.
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index eae0146553..81134f74b0 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -99,10 +99,11 @@ public:
Qt_5_10 = Qt_5_9,
Qt_5_11 = Qt_5_10,
Qt_5_12 = 18,
-#if QT_VERSION >= 0x050d00
+ Qt_5_13 = 19,
+#if QT_VERSION >= 0x050e00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_12
+ Qt_DefaultCompiledVersion = Qt_5_13
};
enum ByteOrder {
@@ -130,7 +131,10 @@ public:
QIODevice *device() const;
void setDevice(QIODevice *);
+#if QT_DEPRECATED_SINCE(5, 13)
+ QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
void unsetDevice();
+#endif
bool atEnd() const;
diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h
index feba1faac6..40b2414e4a 100644
--- a/src/corelib/serialization/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -746,7 +746,7 @@ public:
bool valid() const;
private:
- Q_DISABLE_COPY(Data)
+ Q_DISABLE_COPY_MOVE(Data)
};
}
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 1187bb03a3..f5f02b886a 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -675,6 +675,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa begin(), constEnd()
*/
+/*! \fn QJsonArray::const_iterator QJsonArray::cbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item
+ in the array.
+
+ \sa begin(), cend()
+*/
+
/*! \fn QJsonArray::iterator QJsonArray::end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item
@@ -696,6 +704,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa constBegin(), end()
*/
+/*! \fn QJsonArray::const_iterator QJsonArray::cend() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ item after the last item in the array.
+
+ \sa cbegin(), end()
+*/
+
/*! \fn void QJsonArray::push_back(const QJsonValue &value)
This function is provided for STL compatibility. It is equivalent
@@ -829,7 +845,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
The return value is of type QJsonValueRef, a helper class for QJsonArray
and QJsonObject. When you get an object of type QJsonValueRef, you can
use it as if it were a reference to a QJsonValue. If you assign to it,
- the assignment will apply to the character in the QJsonArray of QJsonObject
+ the assignment will apply to the element in the QJsonArray or QJsonObject
from which you got the reference.
\sa operator+()
@@ -1259,5 +1275,22 @@ QDebug operator<<(QDebug dbg, const QJsonArray &a)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonArray &array)
+{
+ QJsonDocument doc{array};
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonArray &array)
+{
+ QJsonDocument doc;
+ stream >> doc;
+ array = doc.array();
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 5dff4a0aa9..ba346fb848 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -214,9 +214,11 @@ public:
inline iterator begin() { detach2(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
+ inline const_iterator cbegin() const { return const_iterator(this, 0); }
inline iterator end() { detach2(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
+ inline const_iterator cend() const { return const_iterator(this, size()); }
iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; }
iterator erase(iterator it) { removeAt(it.i); return it; }
@@ -271,6 +273,11 @@ Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonArray &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonArray &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONARRAY_H
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index 4603750d11..d6a0c8c48a 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -421,7 +421,7 @@ QJsonArray QCborArray::toJsonArray() const
}
/*!
- Recursively converts every \l QCborValue value in this array to JSON using
+ Recursively converts every \l QCborValue value in this map to JSON using
QCborValue::toJsonValue() and creates a string key for all keys that aren't
strings, then returns the corresponding QJsonObject composed of those
associations.
@@ -826,7 +826,7 @@ QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
{
QCborArray a;
a.detach(array.size());
- for (const QJsonValue v : array) {
+ for (const QJsonValue &v : array) {
if (v.isString())
a.d->append(v.toString());
else
diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 0cd86d3ded..179a87c699 100644
--- a/src/corelib/serialization/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
@@ -47,6 +47,7 @@
#include "qjsonwriter_p.h"
#include "qjsonparser_p.h"
#include "qjson_p.h"
+#include "qdatastream.h"
QT_BEGIN_NAMESPACE
@@ -657,4 +658,23 @@ QDebug operator<<(QDebug dbg, const QJsonDocument &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonDocument &doc)
+{
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonDocument &doc)
+{
+ QByteArray buffer;
+ stream >> buffer;
+ QJsonParseError parseError{};
+ doc = QJsonDocument::fromJson(buffer, &parseError);
+ if (parseError.error && !buffer.isEmpty())
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index b784890c54..a749439b7d 100644
--- a/src/corelib/serialization/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
@@ -172,6 +172,11 @@ Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonDocument)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonDocument &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonDocument &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONDOCUMENT_H
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index 950bec535b..a9f25a119c 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1320,4 +1320,21 @@ QDebug operator<<(QDebug dbg, const QJsonObject &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonObject &object)
+{
+ QJsonDocument doc{object};
+ stream << doc.toJson(QJsonDocument::Compact);
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonObject &object)
+{
+ QJsonDocument doc;
+ stream >> doc;
+ object = doc.object();
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index be42d3747a..80fe6b2f3f 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -268,6 +268,11 @@ Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonObject &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonObject &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONOBJECT_H
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 2c04da4885..1fc610d7c7 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -45,6 +45,7 @@
#include <qvariant.h>
#include <qstringlist.h>
#include <qdebug.h>
+#include "qdatastream.h"
#ifndef QT_BOOTSTRAPPED
# include <qcborarray.h>
@@ -933,4 +934,78 @@ QDebug operator<<(QDebug dbg, const QJsonValue &o)
}
#endif
+#ifndef QT_NO_DATASTREAM
+QDataStream &operator<<(QDataStream &stream, const QJsonValue &v)
+{
+ quint8 type = v.t;
+ stream << type;
+ switch (type) {
+ case QJsonValue::Undefined:
+ case QJsonValue::Null:
+ break;
+ case QJsonValue::Bool:
+ stream << v.toBool();
+ break;
+ case QJsonValue::Double:
+ stream << v.toDouble();
+ break;
+ case QJsonValue::String:
+ stream << v.toString();
+ break;
+ case QJsonValue::Array:
+ stream << v.toArray();
+ break;
+ case QJsonValue::Object:
+ stream << v.toObject();
+ break;
+ }
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QJsonValue &v)
+{
+ quint8 type;
+ stream >> type;
+ switch (type) {
+ case QJsonValue::Undefined:
+ case QJsonValue::Null:
+ v = QJsonValue{QJsonValue::Type(type)};
+ break;
+ case QJsonValue::Bool: {
+ bool b;
+ stream >> b;
+ v = QJsonValue(b);
+ break;
+ } case QJsonValue::Double: {
+ double d;
+ stream >> d;
+ v = QJsonValue{d};
+ break;
+ } case QJsonValue::String: {
+ QString s;
+ stream >> s;
+ v = QJsonValue{s};
+ break;
+ }
+ case QJsonValue::Array: {
+ QJsonArray a;
+ stream >> a;
+ v = QJsonValue{a};
+ break;
+ }
+ case QJsonValue::Object: {
+ QJsonObject o;
+ stream >> o;
+ v = QJsonValue{o};
+ break;
+ }
+ default: {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ v = QJsonValue{QJsonValue::Undefined};
+ }
+ }
+ return stream;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index d8e121524d..0339eb59f7 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -152,6 +152,7 @@ private:
friend class QJsonObject;
friend class QCborValue;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
+ friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v);
void stringDataFromQStringHelper(const QString &string);
@@ -218,7 +219,6 @@ private:
uint index : 31;
};
-#ifndef Q_QDOC
// ### Qt 6: Get rid of these fake pointer classes
class QJsonValuePtr
{
@@ -243,7 +243,6 @@ public:
QJsonValueRef& operator*() { return valueRef; }
QJsonValueRef* operator->() { return &valueRef; }
};
-#endif
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
@@ -253,6 +252,11 @@ Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonValue &);
+#endif
+
QT_END_NAMESPACE
#endif // QJSONVALUE_H
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 32feb41183..012d3bea86 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -59,7 +59,6 @@ static inline uchar hexdig(uint u)
static QByteArray escapedString(const QString &s)
{
- const uchar replacement = '?';
QByteArray ba(s.length(), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
@@ -112,9 +111,14 @@ static QByteArray escapedString(const QString &s)
} else {
*cursor++ = (uchar)u;
}
- } else {
- if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0)
- *cursor++ = replacement;
+ } else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) {
+ // failed to get valid utf8 use JSON escape sequence
+ *cursor++ = '\\';
+ *cursor++ = 'u';
+ *cursor++ = hexdig(u>>12 & 0x0f);
+ *cursor++ = hexdig(u>>8 & 0x0f);
+ *cursor++ = hexdig(u>>4 & 0x0f);
+ *cursor++ = hexdig(u & 0x0f);
}
}
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index fb7b677b2d..c9ba183a50 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -1332,7 +1332,7 @@ void QTextStream::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QTextStream,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice(), string()
*/
@@ -1369,8 +1369,8 @@ void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
}
/*!
- Returns the current string assigned to the QTextStream, or 0 if no
- string has been assigned.
+ Returns the current string assigned to the QTextStream, or
+ \nullptr if no string has been assigned.
\sa setString(), device()
*/
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 827996ee2d..0170be7602 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -223,7 +223,7 @@ QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
The stream reader does \e not take ownership of the resolver. It's
the callers responsibility to ensure that the resolver is valid
during the entire life-time of the stream reader object, or until
- another resolver or 0 is set.
+ another resolver or \nullptr is set.
\sa entityResolver()
*/
@@ -236,7 +236,7 @@ void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
/*!
\since 4.4
- Returns the entity resolver, or 0 if there is no entity resolver.
+ Returns the entity resolver, or \nullptr if there is no entity resolver.
\sa setEntityResolver()
*/
@@ -480,7 +480,7 @@ void QXmlStreamReader::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QXmlStreamReader,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice()
*/
@@ -3315,7 +3315,7 @@ void QXmlStreamWriter::setDevice(QIODevice *device)
/*!
Returns the current device associated with the QXmlStreamWriter,
- or 0 if no device has been assigned.
+ or \nullptr if no device has been assigned.
\sa setDevice()
*/
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 10bfcd491c..e6328a11ac 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -41,6 +41,8 @@
%merged_output qxmlstream_p.h
+%expect 4
+
%token NOTOKEN
%token SPACE " "
%token LANGLE "<"
@@ -144,7 +146,12 @@
%start document
+
+
/.
+
+#include <QtCore/private/qglobal_p.h>
+
template <typename T> class QXmlStreamSimpleStack {
T *data;
int tos, cap;
@@ -155,7 +162,8 @@ public:
inline void reserve(int extraCapacity) {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
- data = reinterpret_cast<T *>(realloc(data, cap * sizeof(T)));
+ void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
+ data = reinterpret_cast<T *>(ptr);
Q_CHECK_PTR(data);
}
}
@@ -753,7 +761,7 @@ bool QXmlStreamReaderPrivate::parse()
state_stack[tos] = 0;
return true;
} else if (act > 0) {
- if (++tos == stack_size-1)
+ if (++tos >= stack_size-1)
reallocateStack();
Value &val = sym_stack[tos];
@@ -890,7 +898,7 @@ doctype_decl ::= langle_bang DOCTYPE qname markup space_opt RANGLE;
/.
case $rule_number:
dtdName = symString(3);
- // fall through
+ Q_FALLTHROUGH();
./
doctype_decl ::= doctype_decl_start external_id space_opt markup space_opt RANGLE;
/.