diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 7ce4f0a92f..994ed88791 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -223,6 +223,98 @@ private: QDataStream::Status oldStatus; }; +template +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 +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 +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 +QDataStream &writeSequentialContainer(QDataStream &s, const Container &c) +{ + s << quint32(c.size()); + for (const typename Container::value_type &t : c) + s << t; + + return s; +} + +template +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 -QDataStream& operator>>(QDataStream& s, QList& l) +inline QDataStream &operator>>(QDataStream &s, QList &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 -QDataStream& operator<<(QDataStream& s, const QList& l) +inline QDataStream &operator<<(QDataStream &s, const QList &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 -QDataStream& operator>>(QDataStream& s, QLinkedList& l) +inline QDataStream &operator>>(QDataStream &s, QLinkedList &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 -QDataStream& operator<<(QDataStream& s, const QLinkedList& l) +inline QDataStream &operator<<(QDataStream &s, const QLinkedList &l) { - s << quint32(l.size()); - typename QLinkedList::ConstIterator it = l.constBegin(); - for(; it != l.constEnd(); ++it) - s << *it; - return s; + return QtPrivate::writeSequentialContainer(s, l); } template -QDataStream& operator>>(QDataStream& s, QVector& v) +inline QDataStream &operator>>(QDataStream &s, QVector &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 -QDataStream& operator<<(QDataStream& s, const QVector& v) +inline QDataStream &operator<<(QDataStream &s, const QVector &v) { - s << quint32(v.size()); - for (typename QVector::const_iterator it = v.begin(); it != v.end(); ++it) - s << *it; - return s; + return QtPrivate::writeSequentialContainer(s, v); } template -QDataStream &operator>>(QDataStream &in, QSet &set) +inline QDataStream &operator>>(QDataStream &s, QSet &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 -QDataStream& operator<<(QDataStream &out, const QSet &set) +inline QDataStream &operator<<(QDataStream &s, const QSet &set) { - out << quint32(set.size()); - typename QSet::const_iterator i = set.constBegin(); - while (i != set.constEnd()) { - out << *i; - ++i; - } - return out; + return QtPrivate::writeSequentialContainer(s, set); } template -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash &hash) +inline QDataStream &operator>>(QDataStream &s, QHash &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 -Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash& hash) +inline QDataStream &operator<<(QDataStream &s, const QHash &hash) { - out << quint32(hash.size()); - typename QHash::ConstIterator it = hash.end(); - typename QHash::ConstIterator begin = hash.begin(); - while (it != begin) { - --it; - out << it.key() << it.value(); - } - return out; -} -#ifdef Q_QDOC -template -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap &map) -#else -template -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap &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 -Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap &map) +inline QDataStream &operator>>(QDataStream &s, QMap &map) { - out << quint32(map.size()); - typename QMap::ConstIterator it = map.end(); - typename QMap::ConstIterator begin = map.begin(); - while (it != begin) { - --it; - out << it.key() << it.value(); - } - return out; + return QtPrivate::readAssociativeContainer(s, map); +} + +template +inline QDataStream &operator<<(QDataStream &s, const QMap &map) +{ + return QtPrivate::writeAssociativeContainer(s, map); } #ifndef QT_NO_DATASTREAM