From 4681f1fc2cfabb64b6b4f1095e2d4f44d0cee903 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 17 Jan 2020 14:40:32 +0100 Subject: [PATCH] Separate streaming of QHash and QMultiHash/QMap and QMultiMap Those classes will not have relations anymore in Qt6, so they need separate streaming operators. Writing of multi maps/hashes requires some additional care so that restoring keeps the order of how iteme have been inserted. Change-Id: If41d0c5c24962764a2cb81bd2de9e2fadf1a2b63 Reviewed-by: Simon Hausmann --- src/corelib/serialization/qdatastream.h | 56 +++++++++++----- .../qdatastream/tst_qdatastream.cpp | 67 +++++++++++++++++-- 2 files changed, 99 insertions(+), 24 deletions(-) diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index b7c16018d53..270267e29e0 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -296,10 +296,7 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c) c.clear(); break; } -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - c.insertMulti(k, t); -QT_WARNING_POP + c.insert(k, t); } return s; @@ -319,19 +316,20 @@ template QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) { s << quint32(c.size()); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && QT_DEPRECATED_SINCE(5, 15) - // Deserialization should occur in the reverse order. - // Otherwise, value() will return the least recently inserted - // value instead of the most recently inserted one. - auto it = c.constEnd(); - auto begin = c.constBegin(); - while (it != begin) { - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - --it; - QT_WARNING_POP + auto it = c.constBegin(); + auto end = c.constEnd(); + while (it != end) { s << it.key() << it.value(); -#else + ++it; + } + + return s; +} + +template +QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c) +{ + s << quint32(c.size()); auto it = c.constBegin(); auto end = c.constEnd(); while (it != end) { @@ -343,7 +341,6 @@ QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) auto next = std::next(rangeStart, i); s << next.key() << next.value(); } -#endif } return s; @@ -440,11 +437,24 @@ inline QDataStream &operator>>(QDataStream &s, QHash &hash) } template + inline QDataStream &operator<<(QDataStream &s, const QHash &hash) { return QtPrivate::writeAssociativeContainer(s, hash); } +template +inline QDataStream &operator>>(QDataStream &s, QMultiHash &hash) +{ + return QtPrivate::readAssociativeContainer(s, hash); +} + +template +inline QDataStream &operator<<(QDataStream &s, const QMultiHash &hash) +{ + return QtPrivate::writeAssociativeMultiContainer(s, hash); +} + template inline QDataStream &operator>>(QDataStream &s, QMap &map) { @@ -457,6 +467,18 @@ inline QDataStream &operator<<(QDataStream &s, const QMap &map) return QtPrivate::writeAssociativeContainer(s, map); } +template +inline QDataStream &operator>>(QDataStream &s, QMultiMap &map) +{ + return QtPrivate::readAssociativeContainer(s, map); +} + +template +inline QDataStream &operator<<(QDataStream &s, const QMultiMap &map) +{ + return QtPrivate::writeAssociativeMultiContainer(s, map); +} + #ifndef QT_NO_DATASTREAM template inline QDataStream& operator>>(QDataStream& s, QPair& p) diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index 877de3f95db..d1a77173c3c 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -121,6 +121,9 @@ private slots: void stream_Map_data(); void stream_Map(); + void stream_MultiMap_data(); + void stream_MultiMap(); + void stream_Hash_data(); void stream_Hash(); @@ -233,6 +236,7 @@ private: void writeQRegularExpression(QDataStream *dev); #endif void writeMap(QDataStream* dev); + void writeMultiMap(QDataStream* dev); void writeHash(QDataStream* dev); void writeMultiHash(QDataStream* dev); void writeqint64(QDataStream *s); @@ -266,6 +270,7 @@ private: void readQRegularExpression(QDataStream *s); #endif void readMap(QDataStream *s); + void readMultiMap(QDataStream *s); void readHash(QDataStream *s); void readMultiHash(QDataStream *s); void readqint64(QDataStream *s); @@ -655,16 +660,10 @@ static Map MapData(int index) map.insert(2, "bbb"); map.insert(3, "cccccc"); break; - case 2: - map.insert(1, "a"); - map.insert(2, "one"); - map.insertMulti(2, "two"); - map.insertMulti(2, "three"); - map.insert(3, "cccccc"); } return map; } -#define MAX_MAP_DATA 3 +#define MAX_MAP_DATA 2 void tst_QDataStream::stream_Map_data() { @@ -694,6 +693,60 @@ void tst_QDataStream::readMap(QDataStream *s) QCOMPARE(S, test); } +typedef QMultiMap MultiMap; + +static MultiMap MultiMapData(int index) +{ + MultiMap map; + + switch (index) { + case 0: + default: + break; + case 1: + map.insert(1, "a"); + map.insert(2, "bbb"); + map.insert(3, "cccccc"); + break; + case 2: + map.insert(1, "a"); + map.insert(2, "one"); + map.insert(2, "two"); + map.insert(2, "three"); + map.insert(3, "cccccc"); + } + return map; +} +#define MAX_MULTIMAP_DATA 3 + +void tst_QDataStream::stream_MultiMap_data() +{ + stream_data(MAX_MULTIMAP_DATA); +} + +void tst_QDataStream::stream_MultiMap() +{ + STREAM_IMPL(MultiMap); +} + +void tst_QDataStream::writeMultiMap(QDataStream* s) +{ + MultiMap test(MultiMapData(dataIndex(QTest::currentDataTag()))); + *s << test; + *s << test; +} + +void tst_QDataStream::readMultiMap(QDataStream *s) +{ + MultiMap S; + MultiMap test(MultiMapData(dataIndex(QTest::currentDataTag()))); + + *s >> S; + QCOMPARE(S, test); + *s >> S; + QCOMPARE(S, test); +} + // ************************************ typedef QHash Hash;