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
620{
622
623 if (++transactionDepth == 1) {
624 dev->startTransaction();
625 resetStatus();
626 }
627}
628
650{
652 if (--transactionDepth == 0) {
654
655 if (q_status == ReadPastEnd) {
656 dev->rollbackTransaction();
657 return false;
658 }
659 dev->commitTransaction();
660 }
661 return q_status == Ok;
662}
663
688{
689 setStatus(ReadPastEnd);
690
692 if (--transactionDepth != 0)
693 return;
694
696 if (q_status == ReadPastEnd)
697 dev->rollbackTransaction();
698 else
699 dev->commitTransaction();
700}
701
724{
725 q_status = ReadCorruptData;
726
728 if (--transactionDepth != 0)
729 return;
730
732 dev->commitTransaction();
733}
734
739{
740 return dev && dev->isTransactionStarted();
741}
742
743/*****************************************************************************
744 QDataStream read functions
745 *****************************************************************************/
746
751qint64 QDataStream::readBlock(char *data, qint64 len)
752{
753 // Disable reads on failure in transacted stream
754 if (q_status != Ok && dev->isTransactionStarted())
755 return -1;
756
757 const qint64 readResult = dev->read(data, len);
758 if (readResult != len)
759 setStatus(ReadPastEnd);
760 return readResult;
761}
762
788{
789 i = 0;
791 char c;
792 if (readBlock(&c, 1) == 1)
793 i = qint8(c);
794 return *this;
795}
796
797
814{
815 i = 0;
817 if (readBlock(reinterpret_cast<char *>(&i), 2) != 2) {
818 i = 0;
819 } else {
820 if (!noswap) {
821 i = qbswap(i);
822 }
823 }
824 return *this;
825}
826
827
844{
845 i = 0;
847 if (readBlock(reinterpret_cast<char *>(&i), 4) != 4) {
848 i = 0;
849 } else {
850 if (!noswap) {
851 i = qbswap(i);
852 }
853 }
854 return *this;
855}
856
873{
874 i = qint64(0);
876 if (version() < 6) {
877 quint32 i1, i2;
878 *this >> i2 >> i1;
879 i = ((quint64)i1 << 32) + i2;
880 } else {
881 if (readBlock(reinterpret_cast<char *>(&i), 8) != 8) {
882 i = qint64(0);
883 } else {
884 if (!noswap) {
885 i = qbswap(i);
886 }
887 }
888 }
889 return *this;
890}
891
897{
898 qint8 v;
899 *this >> v;
900 i = !!v;
901 return *this;
902}
903
915{
916 if (version() >= QDataStream::Qt_4_6
917 && floatingPointPrecision() == QDataStream::DoublePrecision) {
918 double d;
919 *this >> d;
920 f = d;
921 return *this;
922 }
923
924 f = 0.0f;
926 if (readBlock(reinterpret_cast<char *>(&f), 4) != 4) {
927 f = 0.0f;
928 } else {
929 if (!noswap) {
930 union {
931 float val1;
932 quint32 val2;
933 } x;
934 x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
935 f = x.val1;
936 }
937 }
938 return *this;
939}
940
952{
953 if (version() >= QDataStream::Qt_4_6
954 && floatingPointPrecision() == QDataStream::SinglePrecision) {
955 float d;
956 *this >> d;
957 f = d;
958 return *this;
959 }
960
961 f = 0.0;
963 if (readBlock(reinterpret_cast<char *>(&f), 8) != 8) {
964 f = 0.0;
965 } else {
966 if (!noswap) {
967 union {
968 double val1;
969 quint64 val2;
970 } x;
971 x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f));
972 f = x.val1;
973 }
974 }
975 return *this;
976}
977
978
995{
996 qint64 len = 0;
997 return readBytes(s, len);
998}
999
1008{
1009 quint16 u;
1010 *this >> u;
1011 c = char16_t(u);
1012 return *this;
1013}
1014
1023{
1024 quint32 u;
1025 *this >> u;
1026 c = char32_t(u);
1027 return *this;
1028}
1029
1030#if QT_DEPRECATED_SINCE(6, 11)
1031
1032/*
1033 \deprecated [6.11] Use an overload that takes qint64 length instead.
1034*/
1036{
1037 qint64 length = 0;
1039 if (length != qint64(uint(length))) {
1040 setStatus(SizeLimitExceeded); // Cannot store length in l
1041 delete[] s;
1042 l = 0;
1043 return *this;
1044 }
1045 l = uint(length);
1046 return *this;
1047}
1048
1049#endif // QT_DEPRECATED_SINCE(6, 11)
1050
1074{
1075 s = nullptr;
1076 l = 0;
1078
1079 qint64 length = readQSizeType(*this);
1080 if (length == 0)
1081 return *this;
1082
1084 if (length != len || length < 0) {
1085 setStatus(SizeLimitExceeded); // Cannot store len
1086 return *this;
1087 }
1088
1089 qsizetype step = (dev->bytesAvailable() >= len) ? len : 1024 * 1024;
1090 qsizetype allocated = 0;
1091 std::unique_ptr<char[]> curBuf = nullptr;
1092
1093 constexpr qsizetype StepIncreaseThreshold = std::numeric_limits<qsizetype>::max() / 2;
1094 do {
1095 qsizetype blockSize = qMin(step, len - allocated);
1096 const qsizetype n = allocated + blockSize + 1;
1097 if (const auto prevBuf = std::exchange(curBuf, std::make_unique<char[]>(n)))
1098 memcpy(curBuf.get(), prevBuf.get(), allocated);
1099 if (readBlock(curBuf.get() + allocated, blockSize) != blockSize)
1100 return *this;
1101 allocated += blockSize;
1102 if (step <= StepIncreaseThreshold)
1103 step *= 2;
1104 } while (allocated < len);
1105
1106 s = curBuf.release();
1107 s[len] = '\0';
1108 l = len;
1109 return *this;
1110}
1111
1122{
1124 return readBlock(s, len);
1125}
1126
1138/*****************************************************************************
1139 QDataStream write functions
1140 *****************************************************************************/
1141
1166{
1168 if (!dev->putChar(i))
1169 q_status = WriteFailed;
1170 return *this;
1171}
1172
1173
1190{
1192 if (!noswap) {
1193 i = qbswap(i);
1194 }
1195 if (dev->write((char *)&i, sizeof(qint16)) != sizeof(qint16))
1196 q_status = WriteFailed;
1197 return *this;
1198}
1199
1208{
1210 if (!noswap) {
1211 i = qbswap(i);
1212 }
1213 if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
1214 q_status = WriteFailed;
1215 return *this;
1216}
1217
1234{
1236 if (version() < 6) {
1237 quint32 i1 = i & 0xffffffff;
1238 quint32 i2 = i >> 32;
1239 *this << i2 << i1;
1240 } else {
1241 if (!noswap) {
1242 i = qbswap(i);
1243 }
1244 if (dev->write((char *)&i, sizeof(qint64)) != sizeof(qint64))
1245 q_status = WriteFailed;
1246 }
1247 return *this;
1248}
1249
1276{
1277 if (version() >= QDataStream::Qt_4_6
1278 && floatingPointPrecision() == QDataStream::DoublePrecision) {
1279 *this << double(f);
1280 return *this;
1281 }
1282
1284 float g = f; // fixes float-on-stack problem
1285 if (!noswap) {
1286 union {
1287 float val1;
1288 quint32 val2;
1289 } x;
1290 x.val1 = g;
1291 x.val2 = qbswap(x.val2);
1292
1293 if (dev->write((char *)&x.val2, sizeof(float)) != sizeof(float))
1294 q_status = WriteFailed;
1295 return *this;
1296 }
1297
1298 if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
1299 q_status = WriteFailed;
1300 return *this;
1301}
1302
1303
1314{
1315 if (version() >= QDataStream::Qt_4_6
1316 && floatingPointPrecision() == QDataStream::SinglePrecision) {
1317 *this << float(f);
1318 return *this;
1319 }
1320
1322 if (noswap) {
1323 if (dev->write((char *)&f, sizeof(double)) != sizeof(double))
1324 q_status = WriteFailed;
1325 } else {
1326 union {
1327 double val1;
1328 quint64 val2;
1329 } x;
1330 x.val1 = f;
1331 x.val2 = qbswap(x.val2);
1332 if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double))
1333 q_status = WriteFailed;
1334 }
1335 return *this;
1336}
1337
1338
1351{
1352 // Include null terminator, unless s itself is null
1353 const qint64 len = s ? qint64(qstrlen(s)) + 1 : 0;
1354 writeBytes(s, len);
1355 return *this;
1356}
1357
1366{
1367 return *this << qint16(c);
1368}
1369
1378{
1379 return *this << qint32(c);
1380}
1381
1394{
1395 if (len < 0) {
1396 q_status = WriteFailed;
1397 return *this;
1398 }
1400 // Write length then, if any, content
1401 if (writeQSizeType(*this, len) && len > 0)
1402 writeRawData(s, len);
1403 return *this;
1404}
1405
1415{
1417 qint64 ret = dev->write(s, len);
1418 if (ret != len)
1419 q_status = WriteFailed;
1420 return ret;
1421}
1422
1435{
1437 if (q_status != Ok && dev->isTransactionStarted())
1438 return -1;
1439
1440 const qint64 skipResult = dev->skip(len);
1441 if (skipResult != len)
1442 setStatus(ReadPastEnd);
1443 return skipResult;
1444}
1445
1459
1460#endif // QT_NO_DATASTREAM
\inmodule QtCore \reentrant
Definition qbuffer.h:16
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:46
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:96
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:9589
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:9558
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
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
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