QDataStream: refactor (de)serialization of containers

- Introduce templates to (de)serialize the different types of
  containers;
- Unify the naming of parameters;
- Fix style issues.

Change-Id: Ie096b7c0846a280a32282c5427f4836e6a8eefed
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Alex Trotsenko 2016-08-11 21:14:11 +03:00
parent ed928cee12
commit bafad505a0

View File

@ -223,6 +223,98 @@ private:
QDataStream::Status oldStatus;
};
template <typename Container>
QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
{
StreamStateSaver stateSaver(&s);
c.clear();
quint32 n;
s >> n;
c.reserve(n);
for (quint32 i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
c.clear();
break;
}
c.append(t);
}
return s;
}
template <typename Container>
QDataStream &readListBasedContainer(QDataStream &s, Container &c)
{
StreamStateSaver stateSaver(&s);
c.clear();
quint32 n;
s >> n;
for (quint32 i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
c.clear();
break;
}
c << t;
}
return s;
}
template <typename Container>
QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
{
StreamStateSaver stateSaver(&s);
c.clear();
quint32 n;
s >> n;
for (quint32 i = 0; i < n; ++i) {
typename Container::key_type k;
typename Container::mapped_type t;
s >> k >> t;
if (s.status() != QDataStream::Ok) {
c.clear();
break;
}
c.insertMulti(k, t);
}
return s;
}
template <typename Container>
QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
{
s << quint32(c.size());
for (const typename Container::value_type &t : c)
s << t;
return s;
}
template <typename Container>
QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
{
s << quint32(c.size());
// 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) {
--it;
s << it.key() << it.value();
}
return s;
}
} // QtPrivate namespace
/*****************************************************************************
@ -266,209 +358,75 @@ inline QDataStream &QDataStream::operator<<(quint64 i)
{ return *this << qint64(i); }
template <typename T>
QDataStream& operator>>(QDataStream& s, QList<T>& l)
inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
{
QtPrivate::StreamStateSaver stateSaver(&s);
l.clear();
quint32 c;
s >> c;
l.reserve(c);
for(quint32 i = 0; i < c; ++i)
{
T t;
s >> t;
if (s.status() != QDataStream::Ok) {
l.clear();
break;
}
l.append(t);
}
return s;
return QtPrivate::readArrayBasedContainer(s, l);
}
template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
{
s << quint32(l.size());
for (int i = 0; i < l.size(); ++i)
s << l.at(i);
return s;
return QtPrivate::writeSequentialContainer(s, l);
}
template <typename T>
QDataStream& operator>>(QDataStream& s, QLinkedList<T>& l)
inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
{
QtPrivate::StreamStateSaver stateSaver(&s);
l.clear();
quint32 c;
s >> c;
for(quint32 i = 0; i < c; ++i)
{
T t;
s >> t;
if (s.status() != QDataStream::Ok) {
l.clear();
break;
}
l.append(t);
}
return s;
return QtPrivate::readListBasedContainer(s, l);
}
template <typename T>
QDataStream& operator<<(QDataStream& s, const QLinkedList<T>& l)
inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
{
s << quint32(l.size());
typename QLinkedList<T>::ConstIterator it = l.constBegin();
for(; it != l.constEnd(); ++it)
s << *it;
return s;
return QtPrivate::writeSequentialContainer(s, l);
}
template<typename T>
QDataStream& operator>>(QDataStream& s, QVector<T>& v)
inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
QtPrivate::StreamStateSaver stateSaver(&s);
v.clear();
quint32 c;
s >> c;
v.resize(c);
for(quint32 i = 0; i < c; ++i) {
T t;
s >> t;
if (s.status() != QDataStream::Ok) {
v.clear();
break;
}
v[i] = t;
}
return s;
return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
QDataStream& operator<<(QDataStream& s, const QVector<T>& v)
inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v)
{
s << quint32(v.size());
for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
s << *it;
return s;
return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
QDataStream &operator>>(QDataStream &in, QSet<T> &set)
inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
{
QtPrivate::StreamStateSaver stateSaver(&in);
set.clear();
quint32 c;
in >> c;
for (quint32 i = 0; i < c; ++i) {
T t;
in >> t;
if (in.status() != QDataStream::Ok) {
set.clear();
break;
}
set << t;
}
return in;
return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
QDataStream& operator<<(QDataStream &out, const QSet<T> &set)
inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
{
out << quint32(set.size());
typename QSet<T>::const_iterator i = set.constBegin();
while (i != set.constEnd()) {
out << *i;
++i;
}
return out;
return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash)
inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
{
QtPrivate::StreamStateSaver stateSaver(&in);
hash.clear();
quint32 n;
in >> n;
for (quint32 i = 0; i < n; ++i) {
if (in.status() != QDataStream::Ok)
break;
Key k;
T t;
in >> k >> t;
hash.insertMulti(k, t);
}
if (in.status() != QDataStream::Ok)
hash.clear();
return in;
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
out << quint32(hash.size());
typename QHash<Key, T>::ConstIterator it = hash.end();
typename QHash<Key, T>::ConstIterator begin = hash.begin();
while (it != begin) {
--it;
out << it.key() << it.value();
}
return out;
}
#ifdef Q_QDOC
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
#else
template <class aKey, class aT>
Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &map)
#endif
{
QtPrivate::StreamStateSaver stateSaver(&in);
map.clear();
quint32 n;
in >> n;
map.detach();
for (quint32 i = 0; i < n; ++i) {
if (in.status() != QDataStream::Ok)
break;
aKey key;
aT value;
in >> key >> value;
map.insertMulti(key, value);
}
if (in.status() != QDataStream::Ok)
map.clear();
return in;
return QtPrivate::writeAssociativeContainer(s, hash);
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{
out << quint32(map.size());
typename QMap<Key, T>::ConstIterator it = map.end();
typename QMap<Key, T>::ConstIterator begin = map.begin();
while (it != begin) {
--it;
out << it.key() << it.value();
}
return out;
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
{
return QtPrivate::writeAssociativeContainer(s, map);
}
#ifndef QT_NO_DATASTREAM