blob: cfcd89333bf81e3217c3bd96a59e2769046bdfb8 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QDATASTREAM_H
#define QDATASTREAM_H
#include <QtCore/qscopedpointer.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qpair.h>
#ifdef Status
#error qdatastream.h must be included before any header file that defines Status
#endif
QT_BEGIN_NAMESPACE
class qfloat16;
class QByteArray;
class QIODevice;
template <typename T> class QList;
template <typename T> class QVector;
template <typename T> class QSet;
template <class Key, class T> class QHash;
template <class Key, class T> class QMap;
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
class QDataStreamPrivate;
namespace QtPrivate {
class StreamStateSaver;
}
class Q_CORE_EXPORT QDataStream
{
public:
enum Version {
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,
#if QT_VERSION >= 0x050f00
Qt_5_15 = Qt_5_14,
Qt_DefaultCompiledVersion = Qt_5_15
#elif QT_VERSION >= 0x060000
Qt_6_0 = Qt_5_15,
Qt_DefaultCompiledVersion = Qt_6_0
#else
Qt_DefaultCompiledVersion = Qt_5_14
#endif
#if QT_VERSION >= 0x060100
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
};
enum ByteOrder {
BigEndian = QSysInfo::BigEndian,
LittleEndian = QSysInfo::LittleEndian
};
enum Status {
Ok,
ReadPastEnd,
ReadCorruptData,
WriteFailed
};
enum FloatingPointPrecision {
SinglePrecision,
DoublePrecision
};
QDataStream();
explicit QDataStream(QIODevice *);
QDataStream(QByteArray *, QIODevice::OpenMode flags);
QDataStream(const QByteArray &);
~QDataStream();
QIODevice *device() const;
void setDevice(QIODevice *);
#if QT_DEPRECATED_SINCE(5, 13)
QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
void unsetDevice();
#endif
bool atEnd() const;
Status status() const;
void setStatus(Status status);
void resetStatus();
FloatingPointPrecision floatingPointPrecision() const;
void setFloatingPointPrecision(FloatingPointPrecision precision);
ByteOrder byteOrder() const;
void setByteOrder(ByteOrder);
int version() const;
void setVersion(int);
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);
QDataStream &operator>>(qfloat16 &f);
QDataStream &operator>>(float &f);
QDataStream &operator>>(double &f);
QDataStream &operator>>(char *&str);
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; }
QDataStream &operator<<(bool i);
QDataStream &operator<<(qfloat16 f);
QDataStream &operator<<(float f);
QDataStream &operator<<(double f);
QDataStream &operator<<(const char *str);
QDataStream &readBytes(char *&, uint &len);
int readRawData(char *, int len);
QDataStream &writeBytes(const char *, uint len);
int writeRawData(const char *, int len);
int skipRawData(int len);
void startTransaction();
bool commitTransaction();
void rollbackTransaction();
void abortTransaction();
private:
Q_DISABLE_COPY(QDataStream)
QScopedPointer<QDataStreamPrivate> d;
QIODevice *dev;
bool owndev;
bool noswap;
ByteOrder byteorder;
int ver;
Status q_status;
int readBlock(char *data, int len);
friend class QtPrivate::StreamStateSaver;
};
namespace QtPrivate {
class StreamStateSaver
{
public:
inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
{
if (!stream->dev || !stream->dev->isTransactionStarted())
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();
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
/*****************************************************************************
QDataStream inline functions
*****************************************************************************/
inline QIODevice *QDataStream::device() const
{ return dev; }
inline QDataStream::ByteOrder QDataStream::byteOrder() const
{ return byteorder; }
inline int QDataStream::version() const
{ return ver; }
inline void QDataStream::setVersion(int v)
{ ver = v; }
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<<(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.i; }
template <typename Enum>
inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
{ return s >> e.i; }
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator<<(QDataStream &s, const T &t)
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
template <typename T>
inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
{
return QtPrivate::readArrayBasedContainer(s, l);
}
template <typename T>
inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
{
return QtPrivate::writeSequentialContainer(s, l);
}
template<typename T>
inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v)
{
return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
{
return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
{
return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeContainer(s, hash);
}
template <class Key, class T>
inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{
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
template <class T1, class T2>
inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)
{
s >> p.first >> p.second;
return s;
}
template <class T1, class T2>
inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p)
{
s << p.first << p.second;
return s;
}
#endif
#endif // QT_NO_DATASTREAM
QT_END_NAMESPACE
#endif // QDATASTREAM_H