summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r--src/corelib/serialization/qcborarray.cpp20
-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/qcborvalue.cpp526
-rw-r--r--src/corelib/serialization/qcborvalue.h28
-rw-r--r--src/corelib/serialization/qdatastream.cpp1
-rw-r--r--src/corelib/serialization/qdatastream.h5
-rw-r--r--src/corelib/serialization/qjson_p.h2
-rw-r--r--src/corelib/serialization/qjsonarray.cpp17
-rw-r--r--src/corelib/serialization/qjsonarray.h5
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp2
-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
20 files changed, 761 insertions, 36 deletions
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index c56536cdb1..28ae40f3df 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
@@ -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 d7b81ae324..546f9ffe57 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
@@ -170,6 +171,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/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index e53b6a0326..9e8c98837c 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"
@@ -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
@@ -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.
*/
@@ -1982,12 +1983,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.
@@ -1996,6 +2009,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())
@@ -2007,12 +2025,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.
@@ -2021,6 +2051,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())
@@ -2073,15 +2108,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())
@@ -2092,6 +2128,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
@@ -2355,6 +2576,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)
{
@@ -2469,6 +2939,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 105af1ba73..e6e73e1fb6 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -67,6 +67,7 @@ class QCborArray;
class QCborMap;
class QCborStreamReader;
class QCborStreamWriter;
+class QDataStream;
struct QCborParserError
{
@@ -76,6 +77,7 @@ struct QCborParserError
QString errorString() const { return error.toString(); }
};
+class QCborValueRef;
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborValue
{
@@ -236,20 +238,18 @@ public:
QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const;
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>)
@@ -385,16 +385,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); }
@@ -426,6 +428,7 @@ public:
{ return concrete().toDiagnosticNotation(opt); }
private:
+ friend class QCborValue;
friend class QCborArray;
friend class QCborMap;
friend class QCborContainerPrivate;
@@ -457,6 +460,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..01808ebce6 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -559,6 +559,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()
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index eae0146553..2c874700e4 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 {
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..5ba83c41b9 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -1259,5 +1259,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..0a17951fb7 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -271,6 +271,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 158f1950d0..b4d3b4db18 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -817,7 +817,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