/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtCore module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "qdatastream.h" | |
#include "qdatastream_p.h" | |
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED) | |
#include "qbuffer.h" | |
#include "qstring.h" | |
#include <stdio.h> | |
#include <ctype.h> | |
#include <stdlib.h> | |
#include "qendian.h" | |
QT_BEGIN_NAMESPACE | |
/*! | |
\class QDataStream | |
\reentrant | |
\brief The QDataStream class provides serialization of binary data | |
to a QIODevice. | |
\ingroup io | |
A data stream is a binary stream of encoded information which is | |
100% independent of the host computer's operating system, CPU or | |
byte order. For example, a data stream that is written by a PC | |
under Windows can be read by a Sun SPARC running Solaris. | |
You can also use a data stream to read/write \l{raw}{raw | |
unencoded binary data}. If you want a "parsing" input stream, see | |
QTextStream. | |
The QDataStream class implements the serialization of C++'s basic | |
data types, like \c char, \c short, \c int, \c{char *}, etc. | |
Serialization of more complex data is accomplished by breaking up | |
the data into primitive units. | |
A data stream cooperates closely with a QIODevice. A QIODevice | |
represents an input/output medium one can read data from and write | |
data to. The QFile class is an example of an I/O device. | |
Example (write binary data to a stream): | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 0 | |
Example (read binary data from a stream): | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 1 | |
Each item written to the stream is written in a predefined binary | |
format that varies depending on the item's type. Supported Qt | |
types include QBrush, QColor, QDateTime, QFont, QPixmap, QString, | |
QVariant and many others. For the complete list of all Qt types | |
supporting data streaming see \l{Serializing Qt Data Types}. | |
For integers it is best to always cast to a Qt integer type for | |
writing, and to read back into the same Qt integer type. This | |
ensures that you get integers of the size you want and insulates | |
you from compiler and platform differences. | |
To take one example, a \c{char *} string is written as a 32-bit | |
integer equal to the length of the string including the '\\0' byte, | |
followed by all the characters of the string including the | |
'\\0' byte. When reading a \c{char *} string, 4 bytes are read to | |
create the 32-bit length value, then that many characters for the | |
\c {char *} string including the '\\0' terminator are read. | |
The initial I/O device is usually set in the constructor, but can be | |
changed with setDevice(). If you've reached the end of the data | |
(or if there is no I/O device set) atEnd() will return true. | |
\section1 Versioning | |
QDataStream's binary format has evolved since Qt 1.0, and is | |
likely to continue evolving to reflect changes done in Qt. When | |
inputting or outputting complex types, it's very important to | |
make sure that the same version of the stream (version()) is used | |
for reading and writing. If you need both forward and backward | |
compatibility, you can hardcode the version number in the | |
application: | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 2 | |
If you are producing a new binary data format, such as a file | |
format for documents created by your application, you could use a | |
QDataStream to write the data in a portable format. Typically, you | |
would write a brief header containing a magic string and a version | |
number to give yourself room for future expansion. For example: | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 3 | |
Then read it in with: | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 4 | |
You can select which byte order to use when serializing data. The | |
default setting is big endian (MSB first). Changing it to little | |
endian breaks the portability (unless the reader also changes to | |
little endian). We recommend keeping this setting unless you have | |
special requirements. | |
\target raw | |
\section1 Reading and writing raw binary data | |
You may wish to read/write your own raw binary data to/from the | |
data stream directly. Data may be read from the stream into a | |
preallocated \c{char *} using readRawData(). Similarly data can be | |
written to the stream using writeRawData(). Note that any | |
encoding/decoding of the data must be done by you. | |
A similar pair of functions is readBytes() and writeBytes(). These | |
differ from their \e raw counterparts as follows: readBytes() | |
reads a quint32 which is taken to be the length of the data to be | |
read, then that number of bytes is read into the preallocated | |
\c{char *}; writeBytes() writes a quint32 containing the length of the | |
data, followed by the data. Note that any encoding/decoding of | |
the data (apart from the length quint32) must be done by you. | |
\section1 Reading and writing Qt collection classes | |
The Qt container classes can also be serialized to a QDataStream. | |
These include QList, QLinkedList, QVector, QSet, QHash, and QMap. | |
The stream operators are declared as non-members of the classes. | |
\target Serializing Qt Classes | |
\section1 Reading and writing other Qt classes. | |
In addition to the overloaded stream operators documented here, | |
any Qt classes that you might want to serialize to a QDataStream | |
will have appropriate stream operators declared as non-member of | |
the class: | |
\code | |
QDataStream &operator<<(QDataStream &, const QXxx &); | |
QDataStream &operator>>(QDataStream &, QXxx &); | |
\endcode | |
For example, here are the stream operators declared as non-members | |
of the QImage class: | |
\code | |
QDataStream & operator<< (QDataStream& stream, const QImage& image); | |
QDataStream & operator>> (QDataStream& stream, QImage& image); | |
\endcode | |
To see if your favorite Qt class has similar stream operators | |
defined, check the \bold {Related Non-Members} section of the | |
class's documentation page. | |
\sa QTextStream QVariant | |
*/ | |
/*! | |
\enum QDataStream::ByteOrder | |
The byte order used for reading/writing the data. | |
\value BigEndian Most significant byte first (the default) | |
\value LittleEndian Least significant byte first | |
*/ | |
/*! | |
\enum QDataStream::FloatingPointPrecision | |
The precision of floating point numbers used for reading/writing the data. This will only have | |
an effect if the version of the data stream is Qt_4_6 or higher. | |
\warning The floating point precision must be set to the same value on the object that writes | |
and the object that reads the data stream. | |
\value SinglePrecision All floating point numbers in the data stream have 32-bit precision. | |
\value DoublePrecision All floating point numbers in the data stream have 64-bit precision. | |
\sa setFloatingPointPrecision(), floatingPointPrecision() | |
*/ | |
/*! | |
\enum QDataStream::Status | |
This enum describes the current status of the data stream. | |
\value Ok The data stream is operating normally. | |
\value ReadPastEnd The data stream has read past the end of the | |
data in the underlying device. | |
\value ReadCorruptData The data stream has read corrupt data. | |
*/ | |
/***************************************************************************** | |
QDataStream member functions | |
*****************************************************************************/ | |
#undef CHECK_STREAM_PRECOND | |
#ifndef QT_NO_DEBUG | |
#define CHECK_STREAM_PRECOND(retVal) \ | |
if (!dev) { \ | |
qWarning("QDataStream: No device"); \ | |
return retVal; \ | |
} | |
#else | |
#define CHECK_STREAM_PRECOND(retVal) \ | |
if (!dev) { \ | |
return retVal; \ | |
} | |
#endif | |
enum { | |
DefaultStreamVersion = QDataStream::Qt_4_6 | |
}; | |
// ### 5.0: when streaming invalid QVariants, just the type should | |
// be written, no "data" after it | |
/*! | |
Constructs a data stream that has no I/O device. | |
\sa setDevice() | |
*/ | |
QDataStream::QDataStream() | |
{ | |
dev = 0; | |
owndev = false; | |
byteorder = BigEndian; | |
ver = DefaultStreamVersion; | |
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; | |
q_status = Ok; | |
} | |
/*! | |
Constructs a data stream that uses the I/O device \a d. | |
\warning If you use QSocket or QSocketDevice as the I/O device \a d | |
for reading data, you must make sure that enough data is available | |
on the socket for the operation to successfully proceed; | |
QDataStream does not have any means to handle or recover from | |
short-reads. | |
\sa setDevice(), device() | |
*/ | |
QDataStream::QDataStream(QIODevice *d) | |
{ | |
dev = d; // set device | |
owndev = false; | |
byteorder = BigEndian; // default byte order | |
ver = DefaultStreamVersion; | |
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; | |
q_status = Ok; | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
\fn QDataStream::QDataStream(QByteArray *array, int mode) | |
\compat | |
Constructs a data stream that operates on the given \a array. The | |
\a mode specifies how the byte array is to be used, and is | |
usually either QIODevice::ReadOnly or QIODevice::WriteOnly. | |
*/ | |
QDataStream::QDataStream(QByteArray *a, int mode) | |
{ | |
QBuffer *buf = new QBuffer(a); | |
#ifndef QT_NO_QOBJECT | |
buf->blockSignals(true); | |
#endif | |
buf->open(QIODevice::OpenMode(mode)); | |
dev = buf; | |
owndev = true; | |
byteorder = BigEndian; | |
ver = DefaultStreamVersion; | |
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; | |
q_status = Ok; | |
} | |
#endif | |
/*! | |
\fn QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode mode) | |
Constructs a data stream that operates on a byte array, \a a. The | |
\a mode describes how the device is to be used. | |
Alternatively, you can use QDataStream(const QByteArray &) if you | |
just want to read from a byte array. | |
Since QByteArray is not a QIODevice subclass, internally a QBuffer | |
is created to wrap the byte array. | |
*/ | |
QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags) | |
{ | |
QBuffer *buf = new QBuffer(a); | |
#ifndef QT_NO_QOBJECT | |
buf->blockSignals(true); | |
#endif | |
buf->open(flags); | |
dev = buf; | |
owndev = true; | |
byteorder = BigEndian; | |
ver = DefaultStreamVersion; | |
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; | |
q_status = Ok; | |
} | |
/*! | |
Constructs a read-only data stream that operates on byte array \a a. | |
Use QDataStream(QByteArray*, int) if you want to write to a byte | |
array. | |
Since QByteArray is not a QIODevice subclass, internally a QBuffer | |
is created to wrap the byte array. | |
*/ | |
QDataStream::QDataStream(const QByteArray &a) | |
{ | |
QBuffer *buf = new QBuffer; | |
#ifndef QT_NO_QOBJECT | |
buf->blockSignals(true); | |
#endif | |
buf->setData(a); | |
buf->open(QIODevice::ReadOnly); | |
dev = buf; | |
owndev = true; | |
byteorder = BigEndian; | |
ver = DefaultStreamVersion; | |
noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; | |
q_status = Ok; | |
} | |
/*! | |
Destroys the data stream. | |
The destructor will not affect the current I/O device, unless it is | |
an internal I/O device (e.g. a QBuffer) processing a QByteArray | |
passed in the \e constructor, in which case the internal I/O device | |
is destroyed. | |
*/ | |
QDataStream::~QDataStream() | |
{ | |
if (owndev) | |
delete dev; | |
} | |
/*! | |
\fn QIODevice *QDataStream::device() const | |
Returns the I/O device currently set, or 0 if no | |
device is currently set. | |
\sa setDevice() | |
*/ | |
/*! | |
void QDataStream::setDevice(QIODevice *d) | |
Sets the I/O device to \a d, which can be 0 | |
to unset to current I/O device. | |
\sa device() | |
*/ | |
void QDataStream::setDevice(QIODevice *d) | |
{ | |
if (owndev) { | |
delete dev; | |
owndev = false; | |
} | |
dev = d; | |
} | |
/*! | |
\obsolete | |
Unsets the I/O device. | |
Use setDevice(0) instead. | |
*/ | |
void QDataStream::unsetDevice() | |
{ | |
setDevice(0); | |
} | |
/*! | |
\fn bool QDataStream::atEnd() const | |
Returns true if the I/O device has reached the end position (end of | |
the stream or file) or if there is no I/O device set; otherwise | |
returns false. | |
\sa QIODevice::atEnd() | |
*/ | |
bool QDataStream::atEnd() const | |
{ | |
return dev ? dev->atEnd() : true; | |
} | |
/*! | |
Returns the floating point precision of the data stream. | |
\since 4.6 | |
\sa FloatingPointPrecision setFloatingPointPrecision() | |
*/ | |
QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const | |
{ | |
return d == 0 ? QDataStream::DoublePrecision : d->floatingPointPrecision; | |
} | |
/*! | |
Sets the floating point precision of the data stream to \a precision. If the floating point precision is | |
DoublePrecision and the version of the data stream is Qt_4_6 or higher, all floating point | |
numbers will be written and read with 64-bit precision. If the floating point precision is | |
SinglePrecision and the version is Qt_4_6 or higher, all floating point numbers will be written | |
and read with 32-bit precision. | |
For versions prior to Qt_4_6, the precision of floating point numbers in the data stream depends | |
on the stream operator called. | |
The default is DoublePrecision. | |
\warning This property must be set to the same value on the object that writes and the object | |
that reads the data stream. | |
\since 4.6 | |
*/ | |
void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision) | |
{ | |
if (d == 0) | |
d.reset(new QDataStreamPrivate()); | |
d->floatingPointPrecision = precision; | |
} | |
/*! | |
Returns the status of the data stream. | |
\sa Status setStatus() resetStatus() | |
*/ | |
QDataStream::Status QDataStream::status() const | |
{ | |
return q_status; | |
} | |
/*! | |
Resets the status of the data stream. | |
\sa Status status() setStatus() | |
*/ | |
void QDataStream::resetStatus() | |
{ | |
q_status = Ok; | |
} | |
/*! | |
Sets the status of the data stream to the \a status given. | |
\sa Status status() resetStatus() | |
*/ | |
void QDataStream::setStatus(Status status) | |
{ | |
if (q_status == Ok) | |
q_status = status; | |
} | |
/*!\fn bool QDataStream::eof() const | |
Use atEnd() instead. | |
*/ | |
/*! | |
\fn int QDataStream::byteOrder() const | |
Returns the current byte order setting -- either BigEndian or | |
LittleEndian. | |
\sa setByteOrder() | |
*/ | |
/*! | |
Sets the serialization byte order to \a bo. | |
The \a bo parameter can be QDataStream::BigEndian or | |
QDataStream::LittleEndian. | |
The default setting is big endian. We recommend leaving this | |
setting unless you have special requirements. | |
\sa byteOrder() | |
*/ | |
void QDataStream::setByteOrder(ByteOrder bo) | |
{ | |
byteorder = bo; | |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) | |
noswap = (byteorder == BigEndian); | |
else | |
noswap = (byteorder == LittleEndian); | |
} | |
/*! | |
\fn bool QDataStream::isPrintableData() const | |
In Qt 4, this function always returns false. | |
\sa setPrintableData() | |
*/ | |
/*! | |
\fn void QDataStream::setPrintableData(bool enable) | |
In Qt 3, this function enabled output in a human-readable | |
format if \a enable was false. | |
In Qt 4, QDataStream no longer provides a human-readable output. | |
This function does nothing. | |
*/ | |
/*! | |
\enum QDataStream::Version | |
This enum provides symbolic synonyms for the data serialization | |
format version numbers. | |
\value Qt_1_0 Version 1 (Qt 1.x) | |
\value Qt_2_0 Version 2 (Qt 2.0) | |
\value Qt_2_1 Version 3 (Qt 2.1, 2.2, 2.3) | |
\value Qt_3_0 Version 4 (Qt 3.0) | |
\value Qt_3_1 Version 5 (Qt 3.1, 3.2) | |
\value Qt_3_3 Version 6 (Qt 3.3) | |
\value Qt_4_0 Version 7 (Qt 4.0, Qt 4.1) | |
\value Qt_4_1 Version 7 (Qt 4.0, Qt 4.1) | |
\value Qt_4_2 Version 8 (Qt 4.2) | |
\value Qt_4_3 Version 9 (Qt 4.3) | |
\value Qt_4_4 Version 10 (Qt 4.4) | |
\value Qt_4_5 Version 11 (Qt 4.5) | |
\value Qt_4_6 Version 12 (Qt 4.6) | |
\value Qt_4_7 Same as Qt_4_6. | |
\sa setVersion(), version() | |
*/ | |
/*! | |
\fn int QDataStream::version() const | |
Returns the version number of the data serialization format. | |
\sa setVersion(), Version | |
*/ | |
/*! | |
\fn void QDataStream::setVersion(int v) | |
Sets the version number of the data serialization format to \a v. | |
You don't \e have to set a version if you are using the current | |
version of Qt, but for your own custom binary formats we | |
recommend that you do; see \l{Versioning} in the Detailed | |
Description. | |
To accommodate new functionality, the datastream serialization | |
format of some Qt classes has changed in some versions of Qt. If | |
you want to read data that was created by an earlier version of | |
Qt, or write data that can be read by a program that was compiled | |
with an earlier version of Qt, use this function to modify the | |
serialization format used by QDataStream. | |
\table | |
\header \i Qt Version \i QDataStream Version | |
\row \i Qt 4.6 \i 12 | |
\row \i Qt 4.5 \i 11 | |
\row \i Qt 4.4 \i 10 | |
\row \i Qt 4.3 \i 9 | |
\row \i Qt 4.2 \i 8 | |
\row \i Qt 4.0, 4.1 \i 7 | |
\row \i Qt 3.3 \i 6 | |
\row \i Qt 3.1, 3.2 \i 5 | |
\row \i Qt 3.0 \i 4 | |
\row \i Qt 2.1, 2.2, 2.3 \i 3 | |
\row \i Qt 2.0 \i 2 | |
\row \i Qt 1.x \i 1 | |
\endtable | |
The \l Version enum provides symbolic constants for the different | |
versions of Qt. For example: | |
\snippet doc/src/snippets/code/src_corelib_io_qdatastream.cpp 5 | |
\sa version(), Version | |
*/ | |
/***************************************************************************** | |
QDataStream read functions | |
*****************************************************************************/ | |
/*! | |
\fn QDataStream &QDataStream::operator>>(quint8 &i) | |
\overload | |
Reads an unsigned byte from the stream into \a i, and returns a | |
reference to the stream. | |
*/ | |
/*! | |
Reads a signed byte from the stream into \a i, and returns a | |
reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator>>(qint8 &i) | |
{ | |
i = 0; | |
CHECK_STREAM_PRECOND(*this) | |
char c; | |
if (!dev->getChar(&c)) | |
setStatus(ReadPastEnd); | |
else | |
i = qint8(c); | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator>>(quint16 &i) | |
\overload | |
Reads an unsigned 16-bit integer from the stream into \a i, and | |
returns a reference to the stream. | |
*/ | |
/*! | |
\overload | |
Reads a signed 16-bit integer from the stream into \a i, and | |
returns a reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator>>(qint16 &i) | |
{ | |
i = 0; | |
CHECK_STREAM_PRECOND(*this) | |
if (dev->read((char *)&i, 2) != 2) { | |
i = 0; | |
setStatus(ReadPastEnd); | |
} else { | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
} | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator>>(quint32 &i) | |
\overload | |
Reads an unsigned 32-bit integer from the stream into \a i, and | |
returns a reference to the stream. | |
*/ | |
/*! | |
\overload | |
Reads a signed 32-bit integer from the stream into \a i, and | |
returns a reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator>>(qint32 &i) | |
{ | |
i = 0; | |
CHECK_STREAM_PRECOND(*this) | |
if (dev->read((char *)&i, 4) != 4) { | |
i = 0; | |
setStatus(ReadPastEnd); | |
} else { | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
} | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator>>(quint64 &i) | |
\overload | |
Reads an unsigned 64-bit integer from the stream, into \a i, and | |
returns a reference to the stream. | |
*/ | |
/*! | |
\overload | |
Reads a signed 64-bit integer from the stream into \a i, and | |
returns a reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator>>(qint64 &i) | |
{ | |
i = qint64(0); | |
CHECK_STREAM_PRECOND(*this) | |
if (version() < 6) { | |
quint32 i1, i2; | |
*this >> i2 >> i1; | |
i = ((quint64)i1 << 32) + i2; | |
} else { | |
if (dev->read((char *)&i, 8) != 8) { | |
i = qint64(0); | |
setStatus(ReadPastEnd); | |
} else { | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
} | |
} | |
return *this; | |
} | |
/*! | |
Reads a boolean value from the stream into \a i. Returns a | |
reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator>>(bool &i) | |
{ | |
qint8 v; | |
*this >> v; | |
i = !!v; | |
return *this; | |
} | |
/*! | |
\overload | |
Reads a floating point number from the stream into \a f, | |
using the standard IEEE 754 format. Returns a reference to the | |
stream. | |
\sa setFloatingPointPrecision() | |
*/ | |
QDataStream &QDataStream::operator>>(float &f) | |
{ | |
if (version() >= QDataStream::Qt_4_6 | |
&& floatingPointPrecision() == QDataStream::DoublePrecision) { | |
double d; | |
*this >> d; | |
f = d; | |
return *this; | |
} | |
f = 0.0f; | |
CHECK_STREAM_PRECOND(*this) | |
if (dev->read((char *)&f, 4) != 4) { | |
f = 0.0f; | |
setStatus(ReadPastEnd); | |
} else { | |
if (!noswap) { | |
union { | |
float val1; | |
quint32 val2; | |
} x; | |
x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f)); | |
f = x.val1; | |
} | |
} | |
return *this; | |
} | |
#if defined(Q_DOUBLE_FORMAT) | |
#define Q_DF(x) Q_DOUBLE_FORMAT[(x)] - '0' | |
#endif | |
/*! | |
\overload | |
Reads a floating point number from the stream into \a f, | |
using the standard IEEE 754 format. Returns a reference to the | |
stream. | |
\sa setFloatingPointPrecision() | |
*/ | |
QDataStream &QDataStream::operator>>(double &f) | |
{ | |
if (version() >= QDataStream::Qt_4_6 | |
&& floatingPointPrecision() == QDataStream::SinglePrecision) { | |
float d; | |
*this >> d; | |
f = d; | |
return *this; | |
} | |
f = 0.0; | |
CHECK_STREAM_PRECOND(*this) | |
#ifndef Q_DOUBLE_FORMAT | |
if (dev->read((char *)&f, 8) != 8) { | |
f = 0.0; | |
setStatus(ReadPastEnd); | |
} else { | |
if (!noswap) { | |
union { | |
double val1; | |
quint64 val2; | |
} x; | |
x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f)); | |
f = x.val1; | |
} | |
} | |
#else | |
//non-standard floating point format | |
union { | |
double val1; | |
char val2[8]; | |
} x; | |
char *p = x.val2; | |
char b[8]; | |
if (dev->read(b, 8) == 8) { | |
if (noswap) { | |
*p++ = b[Q_DF(0)]; | |
*p++ = b[Q_DF(1)]; | |
*p++ = b[Q_DF(2)]; | |
*p++ = b[Q_DF(3)]; | |
*p++ = b[Q_DF(4)]; | |
*p++ = b[Q_DF(5)]; | |
*p++ = b[Q_DF(6)]; | |
*p = b[Q_DF(7)]; | |
} else { | |
*p++ = b[Q_DF(7)]; | |
*p++ = b[Q_DF(6)]; | |
*p++ = b[Q_DF(5)]; | |
*p++ = b[Q_DF(4)]; | |
*p++ = b[Q_DF(3)]; | |
*p++ = b[Q_DF(2)]; | |
*p++ = b[Q_DF(1)]; | |
*p = b[Q_DF(0)]; | |
} | |
f = x.val1; | |
} else { | |
setStatus(ReadPastEnd); | |
} | |
#endif | |
return *this; | |
} | |
/*! | |
\overload | |
Reads the '\0'-terminated string \a s from the stream and returns | |
a reference to the stream. | |
Space for the string is allocated using \c new -- the caller must | |
destroy it with \c{delete[]}. | |
*/ | |
QDataStream &QDataStream::operator>>(char *&s) | |
{ | |
uint len = 0; | |
return readBytes(s, len); | |
} | |
/*! | |
Reads the buffer \a s from the stream and returns a reference to | |
the stream. | |
The buffer \a s is allocated using \c new. Destroy it with the \c | |
delete[] operator. | |
The \a l parameter is set to the length of the buffer. If the | |
string read is empty, \a l is set to 0 and \a s is set to | |
a null pointer. | |
The serialization format is a quint32 length specifier first, | |
then \a l bytes of data. | |
\sa readRawData(), writeBytes() | |
*/ | |
QDataStream &QDataStream::readBytes(char *&s, uint &l) | |
{ | |
s = 0; | |
l = 0; | |
CHECK_STREAM_PRECOND(*this) | |
quint32 len; | |
*this >> len; | |
if (len == 0) | |
return *this; | |
const quint32 Step = 1024 * 1024; | |
quint32 allocated = 0; | |
char *prevBuf = 0; | |
char *curBuf = 0; | |
do { | |
int blockSize = qMin(Step, len - allocated); | |
prevBuf = curBuf; | |
curBuf = new char[allocated + blockSize + 1]; | |
if (prevBuf) { | |
memcpy(curBuf, prevBuf, allocated); | |
delete [] prevBuf; | |
} | |
if (dev->read(curBuf + allocated, blockSize) != blockSize) { | |
delete [] curBuf; | |
setStatus(ReadPastEnd); | |
return *this; | |
} | |
allocated += blockSize; | |
} while (allocated < len); | |
s = curBuf; | |
s[len] = '\0'; | |
l = (uint)len; | |
return *this; | |
} | |
/*! | |
Reads at most \a len bytes from the stream into \a s and returns the number of | |
bytes read. If an error occurs, this function returns -1. | |
The buffer \a s must be preallocated. The data is \e not encoded. | |
\sa readBytes(), QIODevice::read(), writeRawData() | |
*/ | |
int QDataStream::readRawData(char *s, int len) | |
{ | |
CHECK_STREAM_PRECOND(-1) | |
return dev->read(s, len); | |
} | |
/***************************************************************************** | |
QDataStream write functions | |
*****************************************************************************/ | |
/*! | |
\fn QDataStream &QDataStream::operator<<(quint8 i) | |
\overload | |
Writes an unsigned byte, \a i, to the stream and returns a | |
reference to the stream. | |
*/ | |
/*! | |
Writes a signed byte, \a i, to the stream and returns a reference | |
to the stream. | |
*/ | |
QDataStream &QDataStream::operator<<(qint8 i) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
dev->putChar(i); | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator<<(quint16 i) | |
\overload | |
Writes an unsigned 16-bit integer, \a i, to the stream and returns | |
a reference to the stream. | |
*/ | |
/*! | |
\overload | |
Writes a signed 16-bit integer, \a i, to the stream and returns a | |
reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator<<(qint16 i) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
dev->write((char *)&i, sizeof(qint16)); | |
return *this; | |
} | |
/*! | |
\overload | |
Writes a signed 32-bit integer, \a i, to the stream and returns a | |
reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator<<(qint32 i) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
dev->write((char *)&i, sizeof(qint32)); | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator<<(quint64 i) | |
\overload | |
Writes an unsigned 64-bit integer, \a i, to the stream and returns a | |
reference to the stream. | |
*/ | |
/*! | |
\overload | |
Writes a signed 64-bit integer, \a i, to the stream and returns a | |
reference to the stream. | |
*/ | |
QDataStream &QDataStream::operator<<(qint64 i) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
if (version() < 6) { | |
quint32 i1 = i & 0xffffffff; | |
quint32 i2 = i >> 32; | |
*this << i2 << i1; | |
} else { | |
if (!noswap) { | |
i = qbswap(i); | |
} | |
dev->write((char *)&i, sizeof(qint64)); | |
} | |
return *this; | |
} | |
/*! | |
\fn QDataStream &QDataStream::operator<<(quint32 i) | |
\overload | |
Writes an unsigned integer, \a i, to the stream as a 32-bit | |
unsigned integer (quint32). Returns a reference to the stream. | |
*/ | |
/*! | |
Writes a boolean value, \a i, to the stream. Returns a reference | |
to the stream. | |
*/ | |
QDataStream &QDataStream::operator<<(bool i) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
dev->putChar(qint8(i)); | |
return *this; | |
} | |
/*! | |
\overload | |
Writes a floating point number, \a f, to the stream using | |
the standard IEEE 754 format. Returns a reference to the stream. | |
\sa setFloatingPointPrecision() | |
*/ | |
QDataStream &QDataStream::operator<<(float f) | |
{ | |
if (version() >= QDataStream::Qt_4_6 | |
&& floatingPointPrecision() == QDataStream::DoublePrecision) { | |
*this << double(f); | |
return *this; | |
} | |
CHECK_STREAM_PRECOND(*this) | |
float g = f; // fixes float-on-stack problem | |
if (!noswap) { | |
union { | |
float val1; | |
quint32 val2; | |
} x; | |
x.val1 = g; | |
x.val2 = qbswap(x.val2); | |
g = x.val1; | |
} | |
dev->write((char *)&g, sizeof(float)); | |
return *this; | |
} | |
/*! | |
\overload | |
Writes a floating point number, \a f, to the stream using | |
the standard IEEE 754 format. Returns a reference to the stream. | |
\sa setFloatingPointPrecision() | |
*/ | |
QDataStream &QDataStream::operator<<(double f) | |
{ | |
if (version() >= QDataStream::Qt_4_6 | |
&& floatingPointPrecision() == QDataStream::SinglePrecision) { | |
*this << float(f); | |
return *this; | |
} | |
CHECK_STREAM_PRECOND(*this) | |
#ifndef Q_DOUBLE_FORMAT | |
if (noswap) { | |
dev->write((char *)&f, sizeof(double)); | |
} else { | |
union { | |
double val1; | |
quint64 val2; | |
} x; | |
x.val1 = f; | |
x.val2 = qbswap(x.val2); | |
dev->write((char *)&x.val2, sizeof(double)); | |
} | |
#else | |
union { | |
double val1; | |
char val2[8]; | |
} x; | |
x.val1 = f; | |
char *p = x.val2; | |
char b[8]; | |
if (noswap) { | |
b[Q_DF(0)] = *p++; | |
b[Q_DF(1)] = *p++; | |
b[Q_DF(2)] = *p++; | |
b[Q_DF(3)] = *p++; | |
b[Q_DF(4)] = *p++; | |
b[Q_DF(5)] = *p++; | |
b[Q_DF(6)] = *p++; | |
b[Q_DF(7)] = *p; | |
} else { | |
b[Q_DF(7)] = *p++; | |
b[Q_DF(6)] = *p++; | |
b[Q_DF(5)] = *p++; | |
b[Q_DF(4)] = *p++; | |
b[Q_DF(3)] = *p++; | |
b[Q_DF(2)] = *p++; | |
b[Q_DF(1)] = *p++; | |
b[Q_DF(0)] = *p; | |
} | |
dev->write(b, 8); | |
#endif | |
return *this; | |
} | |
/*! | |
\overload | |
Writes the '\0'-terminated string \a s to the stream and returns a | |
reference to the stream. | |
The string is serialized using writeBytes(). | |
*/ | |
QDataStream &QDataStream::operator<<(const char *s) | |
{ | |
if (!s) { | |
*this << (quint32)0; | |
return *this; | |
} | |
uint len = qstrlen(s) + 1; // also write null terminator | |
*this << (quint32)len; // write length specifier | |
writeRawData(s, len); | |
return *this; | |
} | |
/*! | |
Writes the length specifier \a len and the buffer \a s to the | |
stream and returns a reference to the stream. | |
The \a len is serialized as a quint32, followed by \a len bytes | |
from \a s. Note that the data is \e not encoded. | |
\sa writeRawData(), readBytes() | |
*/ | |
QDataStream &QDataStream::writeBytes(const char *s, uint len) | |
{ | |
CHECK_STREAM_PRECOND(*this) | |
*this << (quint32)len; // write length specifier | |
if (len) | |
writeRawData(s, len); | |
return *this; | |
} | |
/*! | |
Writes \a len bytes from \a s to the stream. Returns the | |
number of bytes actually written, or -1 on error. | |
The data is \e not encoded. | |
\sa writeBytes(), QIODevice::write(), readRawData() | |
*/ | |
int QDataStream::writeRawData(const char *s, int len) | |
{ | |
CHECK_STREAM_PRECOND(-1) | |
return dev->write(s, len); | |
} | |
/*! | |
\since 4.1 | |
Skips \a len bytes from the device. Returns the number of bytes | |
actually skipped, or -1 on error. | |
This is equivalent to calling readRawData() on a buffer of length | |
\a len and ignoring the buffer. | |
\sa QIODevice::seek() | |
*/ | |
int QDataStream::skipRawData(int len) | |
{ | |
CHECK_STREAM_PRECOND(-1) | |
if (dev->isSequential()) { | |
char buf[4096]; | |
int sumRead = 0; | |
while (len > 0) { | |
int blockSize = qMin(len, (int)sizeof(buf)); | |
int n = dev->read(buf, blockSize); | |
if (n == -1) | |
return -1; | |
if (n == 0) | |
return sumRead; | |
sumRead += n; | |
len -= blockSize; | |
} | |
return sumRead; | |
} else { | |
qint64 pos = dev->pos(); | |
qint64 size = dev->size(); | |
if (pos + len > size) | |
len = size - pos; | |
if (!dev->seek(pos + len)) | |
return -1; | |
return len; | |
} | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
\fn QDataStream &QDataStream::readRawBytes(char *str, uint len) | |
Use readRawData() instead. | |
*/ | |
/*! | |
\fn QDataStream &QDataStream::writeRawBytes(const char *str, uint len) | |
Use writeRawData() instead. | |
*/ | |
#endif | |
QT_END_NAMESPACE | |
#endif // QT_NO_DATASTREAM |