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 <simon.hausmann@qt.io>
This commit is contained in:
Lars Knoll 2020-01-17 14:40:32 +01:00
parent 10afe69c16
commit 4681f1fc2c
2 changed files with 99 additions and 24 deletions

View File

@ -296,10 +296,7 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
c.clear(); c.clear();
break; break;
} }
QT_WARNING_PUSH c.insert(k, t);
QT_WARNING_DISABLE_DEPRECATED
c.insertMulti(k, t);
QT_WARNING_POP
} }
return s; return s;
@ -319,19 +316,20 @@ template <typename Container>
QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
{ {
s << quint32(c.size()); s << quint32(c.size());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && QT_DEPRECATED_SINCE(5, 15) auto it = c.constBegin();
// Deserialization should occur in the reverse order. auto end = c.constEnd();
// Otherwise, value() will return the least recently inserted while (it != end) {
// 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
s << it.key() << it.value(); s << it.key() << it.value();
#else ++it;
}
return s;
}
template <typename Container>
QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
{
s << quint32(c.size());
auto it = c.constBegin(); auto it = c.constBegin();
auto end = c.constEnd(); auto end = c.constEnd();
while (it != end) { while (it != end) {
@ -343,7 +341,6 @@ QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
auto next = std::next(rangeStart, i); auto next = std::next(rangeStart, i);
s << next.key() << next.value(); s << next.key() << next.value();
} }
#endif
} }
return s; return s;
@ -440,11 +437,24 @@ inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
} }
template <class Key, class T> template <class Key, class T>
inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash) inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{ {
return QtPrivate::writeAssociativeContainer(s, hash); return QtPrivate::writeAssociativeContainer(s, hash);
} }
template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
inline QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeMultiContainer(s, hash);
}
template <class Key, class T> template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map) inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{ {
@ -457,6 +467,18 @@ inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
return QtPrivate::writeAssociativeContainer(s, map); return QtPrivate::writeAssociativeContainer(s, map);
} }
template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
inline QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
{
return QtPrivate::writeAssociativeMultiContainer(s, map);
}
#ifndef QT_NO_DATASTREAM #ifndef QT_NO_DATASTREAM
template <class T1, class T2> template <class T1, class T2>
inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p) inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)

View File

@ -121,6 +121,9 @@ private slots:
void stream_Map_data(); void stream_Map_data();
void stream_Map(); void stream_Map();
void stream_MultiMap_data();
void stream_MultiMap();
void stream_Hash_data(); void stream_Hash_data();
void stream_Hash(); void stream_Hash();
@ -233,6 +236,7 @@ private:
void writeQRegularExpression(QDataStream *dev); void writeQRegularExpression(QDataStream *dev);
#endif #endif
void writeMap(QDataStream* dev); void writeMap(QDataStream* dev);
void writeMultiMap(QDataStream* dev);
void writeHash(QDataStream* dev); void writeHash(QDataStream* dev);
void writeMultiHash(QDataStream* dev); void writeMultiHash(QDataStream* dev);
void writeqint64(QDataStream *s); void writeqint64(QDataStream *s);
@ -266,6 +270,7 @@ private:
void readQRegularExpression(QDataStream *s); void readQRegularExpression(QDataStream *s);
#endif #endif
void readMap(QDataStream *s); void readMap(QDataStream *s);
void readMultiMap(QDataStream *s);
void readHash(QDataStream *s); void readHash(QDataStream *s);
void readMultiHash(QDataStream *s); void readMultiHash(QDataStream *s);
void readqint64(QDataStream *s); void readqint64(QDataStream *s);
@ -655,16 +660,10 @@ static Map MapData(int index)
map.insert(2, "bbb"); map.insert(2, "bbb");
map.insert(3, "cccccc"); map.insert(3, "cccccc");
break; 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; return map;
} }
#define MAX_MAP_DATA 3 #define MAX_MAP_DATA 2
void tst_QDataStream::stream_Map_data() void tst_QDataStream::stream_Map_data()
{ {
@ -694,6 +693,60 @@ void tst_QDataStream::readMap(QDataStream *s)
QCOMPARE(S, test); QCOMPARE(S, test);
} }
typedef QMultiMap<int, QString> 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<int, QString> Hash; typedef QHash<int, QString> Hash;