summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization/qdatastream.h
blob: 1dad3badb77518c8afa6a0d8cfa7b282979ca742 (plain)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
// Copyright (C) 2021 The Qt Company Ltd.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#ifndef QDATASTREAM_H#define QDATASTREAM_H#include <QtCore/qchar.h>#include <QtCore/qcontainerfwd.h>#include <QtCore/qiodevicebase.h>#include <QtCore/qnamespace.h>#include <QtCore/qscopedpointer.h>#include <QtCore/qttypetraits.h>#include <iterator>// std::distance(), std::next()#include <memory>#ifdef Status#error qdatastream.h must be included before any header file that defines Status#endif QT_BEGIN_NAMESPACE #if QT_CORE_REMOVED_SINCE(6, 3)class qfloat16;#endifclass QByteArray;class QDataStream;class QIODevice;class QString;#if !defined(QT_NO_DATASTREAM)namespace QtPrivate {class StreamStateSaver;template<typename Container> QDataStream &readArrayBasedContainer(QDataStream &s, Container &c);template<typename Container> QDataStream &readListBasedContainer(QDataStream &s, Container &c);template<typename Container> QDataStream &readAssociativeContainer(QDataStream &s, Container &c);template<typename Container> QDataStream &writeSequentialContainer(QDataStream &s,const Container &c);template<typename Container> QDataStream &writeAssociativeContainer(QDataStream &s,const Container &c);template<typename Container> QDataStream &writeAssociativeMultiContainer(QDataStream &s,const Container &c);}class Q_CORE_EXPORT QDataStream :public QIODeviceBase {public:enum Version QT7_ONLY(: quint8) { Qt_1_0 =1, Qt_2_0 =2, Qt_2_1 =3, Qt_3_0 =4, Qt_3_1 =5, Qt_3_3 =6, Qt_4_0 =7, Qt_4_1 = Qt_4_0, Qt_4_2 =8, Qt_4_3 =9, Qt_4_4 =10, Qt_4_5 =11, Qt_4_6 =12, Qt_4_7 = Qt_4_6, Qt_4_8 = Qt_4_7, Qt_4_9 = Qt_4_8, Qt_5_0 =13, Qt_5_1 =14, Qt_5_2 =15, Qt_5_3 = Qt_5_2, Qt_5_4 =16, Qt_5_5 = Qt_5_4, Qt_5_6 =17, Qt_5_7 = Qt_5_6, Qt_5_8 = Qt_5_7, Qt_5_9 = Qt_5_8, Qt_5_10 = Qt_5_9, Qt_5_11 = Qt_5_10, Qt_5_12 =18, Qt_5_13 =19, Qt_5_14 = Qt_5_13, Qt_5_15 = Qt_5_14, Qt_6_0 =20, Qt_6_1 = Qt_6_0, Qt_6_2 = Qt_6_0, Qt_6_3 = Qt_6_0, Qt_6_4 = Qt_6_0, Qt_6_5 = Qt_6_0, Qt_6_6 =21, Qt_6_7 =22, Qt_6_8 = Qt_6_7, Qt_6_9 = Qt_6_7, Qt_6_10 =23, Qt_DefaultCompiledVersion = Qt_6_10 #if QT_VERSION >= QT_VERSION_CHECK(6, 11, 0)#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion#endif};enum ByteOrder { BigEndian =QSysInfo::BigEndian, LittleEndian =QSysInfo::LittleEndian };enum Status QT7_ONLY(: quint8) { Ok, ReadPastEnd, ReadCorruptData, WriteFailed, SizeLimitExceeded,};enum FloatingPointPrecision QT7_ONLY(: quint8) { SinglePrecision, DoublePrecision };QDataStream();explicitQDataStream(QIODevice *);QDataStream(QByteArray *, OpenMode flags);QDataStream(const QByteArray &);~QDataStream(); QIODevice *device()const;voidsetDevice(QIODevice *);boolatEnd()const;QT_CORE_INLINE_SINCE(6,8) Status status()const;voidsetStatus(Status status);voidresetStatus();QT_CORE_INLINE_SINCE(6,8) FloatingPointPrecision floatingPointPrecision()const;voidsetFloatingPointPrecision(FloatingPointPrecision precision); ByteOrder byteOrder()const;voidsetByteOrder(ByteOrder);intversion()const;voidsetVersion(int); QDataStream &operator>>(char&i); QDataStream &operator>>(qint8 &i); QDataStream &operator>>(quint8 &i); QDataStream &operator>>(qint16 &i); QDataStream &operator>>(quint16 &i); QDataStream &operator>>(qint32 &i);inline QDataStream &operator>>(quint32 &i); QDataStream &operator>>(qint64 &i); QDataStream &operator>>(quint64 &i); QDataStream &operator>>(std::nullptr_t &ptr) { ptr =nullptr;return*this; } QDataStream &operator>>(bool&i);#if QT_CORE_REMOVED_SINCE(6, 3) QDataStream &operator>>(qfloat16 &f);#endif QDataStream &operator>>(float&f); QDataStream &operator>>(double&f); QDataStream &operator>>(char*&str); QDataStream &operator>>(char16_t &c); QDataStream &operator>>(char32_t &c); QDataStream &operator<<(char i); QDataStream &operator<<(qint8 i); QDataStream &operator<<(quint8 i); QDataStream &operator<<(qint16 i); QDataStream &operator<<(quint16 i); QDataStream &operator<<(qint32 i);inline QDataStream &operator<<(quint32 i); QDataStream &operator<<(qint64 i); QDataStream &operator<<(quint64 i); QDataStream &operator<<(std::nullptr_t) {return*this; }#if QT_CORE_REMOVED_SINCE(6, 8) || defined(Q_QDOC) QDataStream &operator<<(bool i);#endif#if !defined(Q_QDOC)// Disable implicit conversions to bool (e.g. for pointers)template<typename T,std::enable_if_t<std::is_same_v<T,bool>,bool> =true> QDataStream &operator<<(T i){return(*this<<qint8(i));}#endif#if QT_CORE_REMOVED_SINCE(6, 3) QDataStream &operator<<(qfloat16 f);#endif QDataStream &operator<<(float f); QDataStream &operator<<(double f); QDataStream &operator<<(const char*str); QDataStream &operator<<(char16_t c); QDataStream &operator<<(char32_t c);#if QT_DEPRECATED_SINCE(6, 11)QT_DEPRECATED_VERSION_X_6_11("Use an overload that takes qint64 length.") QDataStream &readBytes(char*&, uint &len);#endif#if QT_CORE_REMOVED_SINCE(6, 7) QDataStream &writeBytes(const char*, uint len);intskipRawData(int len);intreadRawData(char*,int len);intwriteRawData(const char*,int len);#endif QDataStream &readBytes(char*&, qint64 &len); qint64 readRawData(char*, qint64 len); QDataStream &writeBytes(const char*, qint64 len); qint64 writeRawData(const char*, qint64 len); qint64 skipRawData(qint64 len);voidstartTransaction();boolcommitTransaction();voidrollbackTransaction();voidabortTransaction();boolisDeviceTransactionStarted()const;private:Q_DISABLE_COPY(QDataStream)#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)void*const d =nullptr;#endif QIODevice *dev =nullptr;bool owndev =false;bool noswap =QSysInfo::ByteOrder ==QSysInfo::BigEndian; quint8 fpPrecision =QDataStream::DoublePrecision; quint8 q_status = Ok;#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) ByteOrder byteorder = BigEndian;int ver = Qt_DefaultCompiledVersion;#else Version ver = Qt_DefaultCompiledVersion;#endif quint16 transactionDepth =0;#if QT_CORE_REMOVED_SINCE(6, 7)intreadBlock(char*data,int len);#endif qint64 readBlock(char*data, qint64 len);staticinline qint64 readQSizeType(QDataStream &s);staticinlineboolwriteQSizeType(QDataStream &s, qint64 value);staticconstexpr quint32 NullCode =0xffffffffu;staticconstexpr quint32 ExtendedSize =0xfffffffeu;friend class QtPrivate::StreamStateSaver; Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out,const QString &str); Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QString &str); Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out,const QByteArray &ba); Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QByteArray &ba);template<typename Container>friend QDataStream &QtPrivate::readArrayBasedContainer(QDataStream &s, Container &c);template<typename Container>friend QDataStream &QtPrivate::readListBasedContainer(QDataStream &s, Container &c);template<typename Container>friend QDataStream &QtPrivate::readAssociativeContainer(QDataStream &s, Container &c);template<typename Container>friend QDataStream &QtPrivate::writeSequentialContainer(QDataStream &s,const Container &c);template<typename Container>friend QDataStream &QtPrivate::writeAssociativeContainer(QDataStream &s,const Container &c);template<typename Container>friend QDataStream &QtPrivate::writeAssociativeMultiContainer(QDataStream &s,const Container &c);};namespace QtPrivate {class StreamStateSaver {Q_DISABLE_COPY_MOVE(StreamStateSaver)public: Q_NODISCARD_CTOR explicitStreamStateSaver(QDataStream *s) :stream(s),oldStatus(s->status()){if(!stream->isDeviceTransactionStarted()) stream->resetStatus();}inline~StreamStateSaver(){if(oldStatus !=QDataStream::Ok) { stream->resetStatus(); stream->setStatus(oldStatus);}}private: QDataStream *stream;QDataStream::Status oldStatus;};template<typename Container> QDataStream &readArrayBasedContainer(QDataStream &s, Container &c){ StreamStateSaver stateSaver(&s); c.clear(); qint64 size =QDataStream::readQSizeType(s); qsizetype n = size;if(size != n || size <0) { s.setStatus(QDataStream::SizeLimitExceeded);return s;} c.reserve(n);for(qsizetype 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(); qint64 size =QDataStream::readQSizeType(s); qsizetype n = size;if(size != n || size <0) { s.setStatus(QDataStream::SizeLimitExceeded);return s;}for(qsizetype 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(); qint64 size =QDataStream::readQSizeType(s); qsizetype n = size;if(size != n || size <0) { s.setStatus(QDataStream::SizeLimitExceeded);return s;}for(qsizetype 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.insert(k, t);}return s;}template<typename Container> QDataStream &writeSequentialContainer(QDataStream &s,const Container &c){if(!QDataStream::writeQSizeType(s, c.size()))return s;for(const typename Container::value_type &t : c) s << t;return s;}template<typename Container> QDataStream &writeAssociativeContainer(QDataStream &s,const Container &c){if(!QDataStream::writeQSizeType(s, c.size()))return s;auto it = c.constBegin();auto end = c.constEnd();while(it != end) { s << it.key() << it.value();++it;}return s;}template<typename Container> QDataStream &writeAssociativeMultiContainer(QDataStream &s,const Container &c){if(!QDataStream::writeQSizeType(s, c.size()))return s;auto it = c.constBegin();auto end = c.constEnd();while(it != end) {constauto rangeStart = it++;while(it != end && rangeStart.key() == it.key())++it;const qint64 last =std::distance(rangeStart, it) -1;for(qint64 i = last; i >=0; --i) {auto next =std::next(rangeStart, i); s << next.key() << next.value();}}return s;}}// QtPrivate namespacetemplate<typename ...T>using QDataStreamIfHasOStreamOperators =std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;template<typename Container, typename ...T>using QDataStreamIfHasOStreamOperatorsContainer =std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;template<typename ...T>using QDataStreamIfHasIStreamOperators =std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;template<typename Container, typename ...T>using QDataStreamIfHasIStreamOperatorsContainer =std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;/***************************************************************************** QDataStream inline functions *****************************************************************************/inline QIODevice *QDataStream::device()const{return dev; }#if QT_CORE_INLINE_IMPL_SINCE(6, 8)QDataStream::Status QDataStream::status()const{returnStatus(q_status);}QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision()const{returnFloatingPointPrecision(fpPrecision);}#endif// INLINE_SINCE 6.8inline QDataStream::ByteOrder QDataStream::byteOrder()const{ifconstexpr(QSysInfo::ByteOrder ==QSysInfo::BigEndian)return noswap ? BigEndian : LittleEndian;return noswap ? LittleEndian : BigEndian;}inlineintQDataStream::version()const{return ver; }inlinevoidQDataStream::setVersion(int v){ ver =Version(v); } qint64 QDataStream::readQSizeType(QDataStream &s){ quint32 first; s >> first;if(first == NullCode)return-1;if(first < ExtendedSize || s.version() <QDataStream::Qt_6_7)returnqint64(first); qint64 extendedLen; s >> extendedLen;return extendedLen;}boolQDataStream::writeQSizeType(QDataStream &s, qint64 value){if(value <qint64(ExtendedSize)) { s <<quint32(value);}else if(s.version() >=QDataStream::Qt_6_7) { s << ExtendedSize << value;}else if(value ==qint64(ExtendedSize)) { s << ExtendedSize;}else{ s.setStatus(QDataStream::SizeLimitExceeded);// value is too big for old formatreturn false;}return true;}inline QDataStream &QDataStream::operator>>(char&i){return*this>>reinterpret_cast<qint8&>(i); }inline QDataStream &QDataStream::operator>>(quint8 &i){return*this>>reinterpret_cast<qint8&>(i); }inline QDataStream &QDataStream::operator>>(quint16 &i){return*this>>reinterpret_cast<qint16&>(i); }inline QDataStream &QDataStream::operator>>(quint32 &i){return*this>>reinterpret_cast<qint32&>(i); }inline QDataStream &QDataStream::operator>>(quint64 &i){return*this>>reinterpret_cast<qint64&>(i); }inline QDataStream &QDataStream::operator<<(char i){return*this<<qint8(i); }inline QDataStream &QDataStream::operator<<(quint8 i){return*this<<qint8(i); }inline QDataStream &QDataStream::operator<<(quint16 i){return*this<<qint16(i); }inline QDataStream &QDataStream::operator<<(quint32 i){return*this<<qint32(i); }inline QDataStream &QDataStream::operator<<(quint64 i){return*this<<qint64(i); }template<typename Enum>inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e){return s << e.toInt(); }template<typename Enum>inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e){ typename QFlags<Enum>::Int i; s >> i; e = QFlags<Enum>::fromInt(i);return s;}template<typename T> typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>operator<<(QDataStream &s,const T &t){// std::underlying_type_t<T> may be long or ulong, for which QDataStream// provides no streaming operators. For those, cast to qint64 or quint64.return s << typename QIntegerForSizeof<T>::Unsigned(t);}template<typename T> typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>operator>>(QDataStream &s, T &t){ typename QIntegerForSizeof<T>::Unsigned i; s >> i; t =T(i);return s;} Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, QChar chr); Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QChar &chr);#ifndef Q_QDOCtemplate<typename T>inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T>operator>>(QDataStream &s, QList<T> &v){returnQtPrivate::readArrayBasedContainer(s, v);}template<typename T>inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T>operator<<(QDataStream &s,const QList<T> &v){returnQtPrivate::writeSequentialContainer(s, v);}template<typename T>inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T>operator>>(QDataStream &s, QSet<T> &set){returnQtPrivate::readListBasedContainer(s, set);}template<typename T>inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T>operator<<(QDataStream &s,const QSet<T> &set){returnQtPrivate::writeSequentialContainer(s, set);}template<class Key,class T>inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T>operator>>(QDataStream &s, QHash<Key, T> &hash){returnQtPrivate::readAssociativeContainer(s, hash);}template<class Key,class T>inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T>operator<<(QDataStream &s,const QHash<Key, T> &hash){returnQtPrivate::writeAssociativeContainer(s, hash);}template<class Key,class T>inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T>operator>>(QDataStream &s, QMultiHash<Key, T> &hash){returnQtPrivate::readAssociativeContainer(s, hash);}template<class Key,class T>inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T>operator<<(QDataStream &s,const QMultiHash<Key, T> &hash){returnQtPrivate::writeAssociativeMultiContainer(s, hash);}template<class Key,class T>inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T>operator>>(QDataStream &s, QMap<Key, T> &map){returnQtPrivate::readAssociativeContainer(s, map);}template<class Key,class T>inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T>operator<<(QDataStream &s,const QMap<Key, T> &map){returnQtPrivate::writeAssociativeContainer(s, map);}template<class Key,class T>inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T>operator>>(QDataStream &s, QMultiMap<Key, T> &map){returnQtPrivate::readAssociativeContainer(s, map);}template<class Key,class T>inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T>operator<<(QDataStream &s,const QMultiMap<Key, T> &map){returnQtPrivate::writeAssociativeMultiContainer(s, map);}template<class T1,class T2>inline QDataStreamIfHasIStreamOperators<T1, T2>operator>>(QDataStream& s,std::pair<T1, T2> &p){ s >> p.first >> p.second;return s;}template<class T1,class T2>inline QDataStreamIfHasOStreamOperators<T1, T2>operator<<(QDataStream& s,conststd::pair<T1, T2> &p){ s << p.first << p.second;return s;}#elsetemplate<class T> QDataStream &operator>>(QDataStream &s, QList<T> &l);template<class T> QDataStream &operator<<(QDataStream &s,const QList<T> &l);template<class T> QDataStream &operator>>(QDataStream &s, QSet<T> &set);template<class T> QDataStream &operator<<(QDataStream &s,const QSet<T> &set);template<class Key,class T> QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash);template<class Key,class T> QDataStream &operator<<(QDataStream &s,const QHash<Key, T> &hash);template<class Key,class T> QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash);template<class Key,class T> QDataStream &operator<<(QDataStream &s,const QMultiHash<Key, T> &hash);template<class Key,class T> QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map);template<class Key,class T> QDataStream &operator<<(QDataStream &s,const QMap<Key, T> &map);template<class Key,class T> QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map);template<class Key,class T> QDataStream &operator<<(QDataStream &s,const QMultiMap<Key, T> &map);template<class T1,class T2> QDataStream &operator>>(QDataStream& s,std::pair<T1, T2> &p);template<class T1,class T2> QDataStream &operator<<(QDataStream& s,conststd::pair<T1, T2> &p);#endif// Q_QDOCinline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination){int combined; s >> combined; combination =QKeyCombination::fromCombined(combined);return s;}inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination){return s << combination.toCombined();}#endif// QT_NO_DATASTREAM QT_END_NAMESPACE #endif// QDATASTREAM_H
close