Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdatastream.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qdatastream.h"
5#include "qdatastream_p.h"
6
7#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
8#include "qbuffer.h"
9#include "qfloat16.h"
10#include "qstring.h"
11#include <stdio.h>
12#include <ctype.h>
13#include <stdlib.h>
14#include "qendian.h"
15
17
18constexpr quint32 QDataStream::NullCode;
19constexpr quint32 QDataStream::ExtendedSize;
20
248/*****************************************************************************
249 QDataStream member functions
250 *****************************************************************************/
251
252#define Q_VOID
253
254#undef CHECK_STREAM_PRECOND
255#ifndef QT_NO_DEBUG
256#define CHECK_STREAM_PRECOND(retVal) \
257 if (!dev) { \
258 qWarning("QDataStream: No device"); \
259 return retVal; \
260 }
261#else
262#define CHECK_STREAM_PRECOND(retVal) \
263 if (!dev) { \
264 return retVal; \
265 }
266#endif
267
268#define CHECK_STREAM_WRITE_PRECOND(retVal) \
269 CHECK_STREAM_PRECOND(retVal) \
270 if (q_status != Ok) \
271 return retVal;
272
273#define CHECK_STREAM_TRANSACTION_PRECOND(retVal) \
274 if (transactionDepth == 0) { \
275 qWarning("QDataStream: No transaction in progress"); \
276 return retVal; \
277 }
278
288
296{
297 dev = d; // set device
298}
299
314{
315 QBuffer *buf = new QBuffer(a);
316#ifndef QT_NO_QOBJECT
317 buf->blockSignals(true);
318#endif
319 buf->open(flags);
320 dev = buf;
321 owndev = true;
322}
323
333{
334 QBuffer *buf = new QBuffer;
335#ifndef QT_NO_QOBJECT
336 buf->blockSignals(true);
337#endif
338 buf->setData(a);
340 dev = buf;
341 owndev = true;
342}
343
354{
355 if (owndev)
356 delete dev;
357}
358
359
379{
380 if (owndev) {
381 delete dev;
382 owndev = false;
383 }
384 dev = d;
385}
386
398{
399 return dev ? dev->atEnd() : true;
400}
401
432void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
433{
434 fpPrecision = precision;
435}
436
451{
452 q_status = Ok;
453}
454
463void QDataStream::setStatus(Status status)
464{
465 if (q_status == Ok)
466 q_status = status;
467}
468
491{
492#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
493 // accessed by inline byteOrder() prior to Qt 6.8
494 byteorder = bo;
495#endif
497 noswap = (bo == BigEndian);
498 else
499 noswap = (bo == LittleEndian);
500}
501
502
621{
623
624 if (++transactionDepth == 1) {
625 dev->startTransaction();
626 resetStatus();
627 }
628}
629
651{
653 if (--transactionDepth == 0) {
655
656 if (q_status == ReadPastEnd) {
657 dev->rollbackTransaction();
658 return false;
659 }
660 dev->commitTransaction();
661 }
662 return q_status == Ok;
663}
664
689{
690 setStatus(ReadPastEnd);
691
693 if (--transactionDepth != 0)
694 return;
695
697 if (q_status == ReadPastEnd)
698 dev->rollbackTransaction();
699 else
700 dev->commitTransaction();
701}
702
725{
726 q_status = ReadCorruptData;
727
729 if (--transactionDepth != 0)
730 return;
731
733 dev->commitTransaction();
734}
735
740{
741 return dev && dev->isTransactionStarted();
742}
743
744/*****************************************************************************
745 QDataStream read functions
746 *****************************************************************************/
747
752qint64 QDataStream::readBlock(char *data, qint64 len)
753{
754 // Disable reads on failure in transacted stream
755 if (q_status != Ok && dev->isTransactionStarted())
756 return -1;
757
758 const qint64 readResult = dev->read(data, len);
759 if (readResult != len)
760 setStatus(ReadPastEnd);
761 return readResult;
762}
763
789{
790 i = 0;
792 char c;
793 if (readBlock(&c, 1) == 1)
794 i = qint8(c);
795 return *this;
796}
797
798
815{
816 i = 0;
818 if (readBlock(reinterpret_cast<char *>(&i), 2) != 2) {
819 i = 0;
820 } else {
821 if (!noswap) {
822 i = qbswap(i);
823 }
824 }
825 return *this;
826}
827
828
845{
846 i = 0;
848 if (readBlock(reinterpret_cast<char *>(&i), 4) != 4) {
849 i = 0;
850 } else {
851 if (!noswap) {
852 i = qbswap(i);
853 }
854 }
855 return *this;
856}
857
874{
875 i = qint64(0);
877 if (version() < 6) {
878 quint32 i1, i2;
879 *this >> i2 >> i1;
880 i = ((quint64)i1 << 32) + i2;
881 } else {
882 if (readBlock(reinterpret_cast<char *>(&i), 8) != 8) {
883 i = qint64(0);
884 } else {
885 if (!noswap) {
886 i = qbswap(i);
887 }
888 }
889 }
890 return *this;
891}
892
898{
899 qint8 v;
900 *this >> v;
901 i = !!v;
902 return *this;
903}
904
916{
917 if (version() >= QDataStream::Qt_4_6
918 && floatingPointPrecision() == QDataStream::DoublePrecision) {
919 double d;
920 *this >> d;
921 f = d;
922 return *this;
923 }
924
925 f = 0.0f;
927 if (readBlock(reinterpret_cast<char *>(&f), 4) != 4) {
928 f = 0.0f;
929 } else {
930 if (!noswap) {
931 union {
932 float val1;
933 quint32 val2;
934 } x;
935 x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
936 f = x.val1;
937 }
938 }
939 return *this;
940}
941
953{
954 if (version() >= QDataStream::Qt_4_6
955 && floatingPointPrecision() == QDataStream::SinglePrecision) {
956 float d;
957 *this >> d;
958 f = d;
959 return *this;
960 }
961
962 f = 0.0;
964 if (readBlock(reinterpret_cast<char *>(&f), 8) != 8) {
965 f = 0.0;
966 } else {
967 if (!noswap) {
968 union {
969 double val1;
970 quint64 val2;
971 } x;
972 x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f));
973 f = x.val1;
974 }
975 }
976 return *this;
977}
978
979
996{
997 qint64 len = 0;
998 return readBytes(s, len);
999}
1000
1009{
1010 quint16 u;
1011 *this >> u;
1012 c = char16_t(u);
1013 return *this;
1014}
1015
1024{
1025 quint32 u;
1026 *this >> u;
1027 c = char32_t(u);
1028 return *this;
1029}
1030
1031#if QT_DEPRECATED_SINCE(6, 11)
1032
1033/*
1034 \deprecated [6.11] Use an overload that takes qint64 length instead.
1035*/
1037{
1038 qint64 length = 0;
1040 if (length != qint64(uint(length))) {
1041 setStatus(SizeLimitExceeded); // Cannot store length in l
1042 delete[] s;
1043 l = 0;
1044 return *this;
1045 }
1046 l = uint(length);
1047 return *this;
1048}
1049
1050#endif // QT_DEPRECATED_SINCE(6, 11)
1051
1075{
1076 s = nullptr;
1077 l = 0;
1079
1080 qint64 length = readQSizeType(*this);
1081 if (length == 0)
1082 return *this;
1083
1085 if (length != len || length < 0) {
1086 setStatus(SizeLimitExceeded); // Cannot store len
1087 return *this;
1088 }
1089
1090 qsizetype step = (dev->bytesAvailable() >= len) ? len : 1024 * 1024;
1091 qsizetype allocated = 0;
1092 std::unique_ptr<char[]> curBuf = nullptr;
1093
1094 constexpr qsizetype StepIncreaseThreshold = std::numeric_limits<qsizetype>::max() / 2;
1095 do {
1096 qsizetype blockSize = qMin(step, len - allocated);
1097 const qsizetype n = allocated + blockSize + 1;
1098 if (const auto prevBuf = std::exchange(curBuf, std::make_unique<char[]>(n)))
1099 memcpy(curBuf.get(), prevBuf.get(), allocated);
1100 if (readBlock(curBuf.get() + allocated, blockSize) != blockSize)
1101 return *this;
1102 allocated += blockSize;
1103 if (step <= StepIncreaseThreshold)
1104 step *= 2;
1105 } while (allocated < len);
1106
1107 s = curBuf.release();
1108 s[len] = '\0';
1109 l = len;
1110 return *this;
1111}
1112
1123{
1125 return readBlock(s, len);
1126}
1127
1139/*****************************************************************************
1140 QDataStream write functions
1141 *****************************************************************************/
1142
1167{
1169 if (!dev->putChar(i))
1170 q_status = WriteFailed;
1171 return *this;
1172}
1173
1174
1191{
1193 if (!noswap) {
1194 i = qbswap(i);
1195 }
1196 if (dev->write((char *)&i, sizeof(qint16)) != sizeof(qint16))
1197 q_status = WriteFailed;
1198 return *this;
1199}
1200
1209{
1211 if (!noswap) {
1212 i = qbswap(i);
1213 }
1214 if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
1215 q_status = WriteFailed;
1216 return *this;
1217}
1218
1235{
1237 if (version() < 6) {
1238 quint32 i1 = i & 0xffffffff;
1239 quint32 i2 = i >> 32;
1240 *this << i2 << i1;
1241 } else {
1242 if (!noswap) {
1243 i = qbswap(i);
1244 }
1245 if (dev->write((char *)&i, sizeof(qint64)) != sizeof(qint64))
1246 q_status = WriteFailed;
1247 }
1248 return *this;
1249}
1250
1277{
1278 if (version() >= QDataStream::Qt_4_6
1279 && floatingPointPrecision() == QDataStream::DoublePrecision) {
1280 *this << double(f);
1281 return *this;
1282 }
1283
1285 float g = f; // fixes float-on-stack problem
1286 if (!noswap) {
1287 union {
1288 float val1;
1289 quint32 val2;
1290 } x;
1291 x.val1 = g;
1292 x.val2 = qbswap(x.val2);
1293
1294 if (dev->write((char *)&x.val2, sizeof(float)) != sizeof(float))
1295 q_status = WriteFailed;
1296 return *this;
1297 }
1298
1299 if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
1300 q_status = WriteFailed;
1301 return *this;
1302}
1303
1304
1315{
1316 if (version() >= QDataStream::Qt_4_6
1317 && floatingPointPrecision() == QDataStream::SinglePrecision) {
1318 *this << float(f);
1319 return *this;
1320 }
1321
1323 if (noswap) {
1324 if (dev->write((char *)&f, sizeof(double)) != sizeof(double))
1325 q_status = WriteFailed;
1326 } else {
1327 union {
1328 double val1;
1329 quint64 val2;
1330 } x;
1331 x.val1 = f;
1332 x.val2 = qbswap(x.val2);
1333 if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double))
1334 q_status = WriteFailed;
1335 }
1336 return *this;
1337}
1338
1339
1352{
1353 // Include null terminator, unless s itself is null
1354 const qint64 len = s ? qint64(qstrlen(s)) + 1 : 0;
1355 writeBytes(s, len);
1356 return *this;
1357}
1358
1367{
1368 return *this << qint16(c);
1369}
1370
1379{
1380 return *this << qint32(c);
1381}
1382
1395{
1396 if (len < 0) {
1397 q_status = WriteFailed;
1398 return *this;
1399 }
1401 // Write length then, if any, content
1402 if (writeQSizeType(*this, len) && len > 0)
1403 writeRawData(s, len);
1404 return *this;
1405}
1406
1416{
1418 qint64 ret = dev->write(s, len);
1419 if (ret != len)
1420 q_status = WriteFailed;
1421 return ret;
1422}
1423
1436{
1438 if (q_status != Ok && dev->isTransactionStarted())
1439 return -1;
1440
1441 const qint64 skipResult = dev->skip(len);
1442 if (skipResult != len)
1443 setStatus(ReadPastEnd);
1444 return skipResult;
1445}
1446
1460
1461#endif // QT_NO_DATASTREAM
\inmodule QtCore \reentrant
Definition qbuffer.h:16
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:47
void setFloatingPointPrecision(FloatingPointPrecision precision)
Sets the floating point precision of the data stream to precision.
Status status() const
Returns the status of the data stream.
ByteOrder
The byte order used for reading/writing the data.
Definition qdatastream.h:98
bool commitTransaction()
qint64 readRawData(char *, qint64 len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
Q_CORE_EXPORT friend QDataStream & operator>>(QDataStream &in, QString &str)
Definition qstring.cpp:9601
bool isDeviceTransactionStarted() const
QDataStream & readBytes(char *&, qint64 &len)
~QDataStream()
Destroys the data stream.
void rollbackTransaction()
void resetStatus()
Resets the status of the data stream.
void setDevice(QIODevice *)
void QDataStream::setDevice(QIODevice *d)
void abortTransaction()
FloatingPointPrecision floatingPointPrecision() const
Returns the floating point precision of the data stream.
qint64 skipRawData(qint64 len)
void startTransaction()
qint64 writeRawData(const char *, qint64 len)
Writes len bytes from s to the stream.
QDataStream & writeBytes(const char *, qint64 len)
Writes the length specifier len and the buffer s to the stream and returns a reference to the stream.
QDataStream()
Constructs a data stream that has no I/O device.
bool atEnd() const
Returns true if the I/O device has reached the end position (end of the stream or file) or if there i...
Q_CORE_EXPORT friend QDataStream & operator<<(QDataStream &out, const QString &str)
Definition qstring.cpp:9570
int version() const
Returns the version number of the data serialization format.
void setStatus(Status status)
Sets the status of the data stream to the status given.
void setByteOrder(ByteOrder)
Sets the serialization byte order to bo.
\inmodule QtCore \reentrant
Definition qiodevice.h:34
bool putChar(char c)
Writes the character c to the device.
void rollbackTransaction()
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
void startTransaction()
qint64 skip(qint64 maxSize)
bool isTransactionStarted() const
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
void commitTransaction()
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
bool blockSignals(bool b) noexcept
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition qobject.cpp:1585
@ BigEndian
Definition qsysinfo.h:29
@ ByteOrder
Definition qsysinfo.h:34
Combined button and popup list for selecting options.
const int blockSize
@ Ok
Definition qbezier.cpp:173
size_t qstrlen(const char *str)
#define CHECK_STREAM_WRITE_PRECOND(retVal)
#define CHECK_STREAM_PRECOND(retVal)
#define CHECK_STREAM_TRANSACTION_PRECOND(retVal)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
constexpr T qbswap(T source)
Definition qendian.h:103
#define Q_VOID
Definition qiodevice.cpp:45
return ret
QT_BEGIN_NAMESPACE constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:19
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLboolean GLboolean g
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLenum GLsizei len
GLenum GLint GLint * precision
unsigned int quint32
Definition qtypes.h:50
short qint16
Definition qtypes.h:47
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45