QtBase  v6.3.1
qdatastream.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qdatastream.h"
41 #include "qdatastream_p.h"
42 
43 #if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
44 #include "qbuffer.h"
45 #include "qfloat16.h"
46 #include "qstring.h"
47 #include <stdio.h>
48 #include <ctype.h>
49 #include <stdlib.h>
50 #include "qendian.h"
51 
53 
241 /*****************************************************************************
242  QDataStream member functions
243  *****************************************************************************/
244 
245 #define Q_VOID
246 
247 #undef CHECK_STREAM_PRECOND
248 #ifndef QT_NO_DEBUG
249 #define CHECK_STREAM_PRECOND(retVal) \
250  if (!dev) { \
251  qWarning("QDataStream: No device"); \
252  return retVal; \
253  }
254 #else
255 #define CHECK_STREAM_PRECOND(retVal) \
256  if (!dev) { \
257  return retVal; \
258  }
259 #endif
260 
261 #define CHECK_STREAM_WRITE_PRECOND(retVal) \
262  CHECK_STREAM_PRECOND(retVal) \
263  if (q_status != Ok) \
264  return retVal;
265 
266 #define CHECK_STREAM_TRANSACTION_PRECOND(retVal) \
267  if (!d || d->transactionDepth == 0) { \
268  qWarning("QDataStream: No transaction in progress"); \
269  return retVal; \
270  }
271 
279 {
280  dev = nullptr;
281  owndev = false;
282  byteorder = BigEndian;
285  q_status = Ok;
286 }
287 
295 {
296  dev = d; // set device
297  owndev = false;
298  byteorder = BigEndian; // default byte order
301  q_status = Ok;
302 }
303 
318 {
319  QBuffer *buf = new QBuffer(a);
320 #ifndef QT_NO_QOBJECT
321  buf->blockSignals(true);
322 #endif
323  buf->open(flags);
324  dev = buf;
325  owndev = true;
326  byteorder = BigEndian;
329  q_status = Ok;
330 }
331 
341 {
342  QBuffer *buf = new QBuffer;
343 #ifndef QT_NO_QOBJECT
344  buf->blockSignals(true);
345 #endif
346  buf->setData(a);
347  buf->open(QIODevice::ReadOnly);
348  dev = buf;
349  owndev = true;
350  byteorder = BigEndian;
353  q_status = Ok;
354 }
355 
366 {
367  if (owndev)
368  delete dev;
369 }
370 
371 
391 {
392  if (owndev) {
393  delete dev;
394  owndev = false;
395  }
396  dev = d;
397 }
398 
409 bool QDataStream::atEnd() const
410 {
411  return dev ? dev->atEnd() : true;
412 }
413 
422 {
424 }
425 
447 {
448  if (!d)
449  d.reset(new QDataStreamPrivate());
451 }
452 
460 {
461  return q_status;
462 }
463 
470 {
471  q_status = Ok;
472 }
473 
483 {
484  if (q_status == Ok)
485  q_status = status;
486 }
487 
510 {
511  byteorder = bo;
513  noswap = (byteorder == BigEndian);
514  else
515  noswap = (byteorder == LittleEndian);
516 }
517 
518 
631 {
633 
634  if (!d)
635  d.reset(new QDataStreamPrivate());
636 
637  if (++d->transactionDepth == 1) {
638  dev->startTransaction();
639  resetStatus();
640  }
641 }
642 
664 {
666  if (--d->transactionDepth == 0) {
667  CHECK_STREAM_PRECOND(false)
668 
669  if (q_status == ReadPastEnd) {
670  dev->rollbackTransaction();
671  return false;
672  }
673  dev->commitTransaction();
674  }
675  return q_status == Ok;
676 }
677 
702 {
704 
706  if (--d->transactionDepth != 0)
707  return;
708 
710  if (q_status == ReadPastEnd)
711  dev->rollbackTransaction();
712  else
713  dev->commitTransaction();
714 }
715 
738 {
739  q_status = ReadCorruptData;
740 
742  if (--d->transactionDepth != 0)
743  return;
744 
746  dev->commitTransaction();
747 }
748 
753 {
754  return dev && dev->isTransactionStarted();
755 }
756 
757 /*****************************************************************************
758  QDataStream read functions
759  *****************************************************************************/
760 
765 int QDataStream::readBlock(char *data, int len)
766 {
767  // Disable reads on failure in transacted stream
768  if (q_status != Ok && dev->isTransactionStarted())
769  return -1;
770 
771  const int readResult = dev->read(data, len);
772  if (readResult != len)
774  return readResult;
775 }
776 
802 {
803  i = 0;
804  CHECK_STREAM_PRECOND(*this)
805  char c;
806  if (readBlock(&c, 1) == 1)
807  i = qint8(c);
808  return *this;
809 }
810 
811 
828 {
829  i = 0;
830  CHECK_STREAM_PRECOND(*this)
831  if (readBlock(reinterpret_cast<char *>(&i), 2) != 2) {
832  i = 0;
833  } else {
834  if (!noswap) {
835  i = qbswap(i);
836  }
837  }
838  return *this;
839 }
840 
841 
858 {
859  i = 0;
860  CHECK_STREAM_PRECOND(*this)
861  if (readBlock(reinterpret_cast<char *>(&i), 4) != 4) {
862  i = 0;
863  } else {
864  if (!noswap) {
865  i = qbswap(i);
866  }
867  }
868  return *this;
869 }
870 
887 {
888  i = qint64(0);
889  CHECK_STREAM_PRECOND(*this)
890  if (version() < 6) {
891  quint32 i1, i2;
892  *this >> i2 >> i1;
893  i = ((quint64)i1 << 32) + i2;
894  } else {
895  if (readBlock(reinterpret_cast<char *>(&i), 8) != 8) {
896  i = qint64(0);
897  } else {
898  if (!noswap) {
899  i = qbswap(i);
900  }
901  }
902  }
903  return *this;
904 }
905 
911 {
912  qint8 v;
913  *this >> v;
914  i = !!v;
915  return *this;
916 }
917 
929 {
932  double d;
933  *this >> d;
934  f = d;
935  return *this;
936  }
937 
938  f = 0.0f;
939  CHECK_STREAM_PRECOND(*this)
940  if (readBlock(reinterpret_cast<char *>(&f), 4) != 4) {
941  f = 0.0f;
942  } else {
943  if (!noswap) {
944  union {
945  float val1;
946  quint32 val2;
947  } x;
948  x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
949  f = x.val1;
950  }
951  }
952  return *this;
953 }
954 
966 {
969  float d;
970  *this >> d;
971  f = d;
972  return *this;
973  }
974 
975  f = 0.0;
976  CHECK_STREAM_PRECOND(*this)
977  if (readBlock(reinterpret_cast<char *>(&f), 8) != 8) {
978  f = 0.0;
979  } else {
980  if (!noswap) {
981  union {
982  double val1;
983  quint64 val2;
984  } x;
985  x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f));
986  f = x.val1;
987  }
988  }
989  return *this;
990 }
991 
992 
1008 {
1009  uint len = 0;
1010  return readBytes(s, len);
1011 }
1012 
1021 {
1022  quint16 u;
1023  *this >> u;
1024  c = char16_t(u);
1025  return *this;
1026 }
1027 
1036 {
1037  quint32 u;
1038  *this >> u;
1039  c = char32_t(u);
1040  return *this;
1041 }
1042 
1060 {
1061  s = nullptr;
1062  l = 0;
1063  CHECK_STREAM_PRECOND(*this)
1064 
1065  quint32 len;
1066  *this >> len;
1067  if (len == 0)
1068  return *this;
1069 
1070  const quint32 Step = 1024 * 1024;
1071  quint32 allocated = 0;
1072  char *prevBuf = nullptr;
1073  char *curBuf = nullptr;
1074 
1075  do {
1076  int blockSize = qMin(Step, len - allocated);
1077  prevBuf = curBuf;
1078  curBuf = new char[allocated + blockSize + 1];
1079  if (prevBuf) {
1080  memcpy(curBuf, prevBuf, allocated);
1081  delete [] prevBuf;
1082  }
1083  if (readBlock(curBuf + allocated, blockSize) != blockSize) {
1084  delete [] curBuf;
1085  return *this;
1086  }
1087  allocated += blockSize;
1088  } while (allocated < len);
1089 
1090  s = curBuf;
1091  s[len] = '\0';
1092  l = (uint)len;
1093  return *this;
1094 }
1095 
1106 {
1108  return readBlock(s, len);
1109 }
1110 
1122 /*****************************************************************************
1123  QDataStream write functions
1124  *****************************************************************************/
1125 
1150 {
1152  if (!dev->putChar(i))
1153  q_status = WriteFailed;
1154  return *this;
1155 }
1156 
1157 
1174 {
1176  if (!noswap) {
1177  i = qbswap(i);
1178  }
1179  if (dev->write((char *)&i, sizeof(qint16)) != sizeof(qint16))
1180  q_status = WriteFailed;
1181  return *this;
1182 }
1183 
1192 {
1194  if (!noswap) {
1195  i = qbswap(i);
1196  }
1197  if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
1198  q_status = WriteFailed;
1199  return *this;
1200 }
1201 
1218 {
1220  if (version() < 6) {
1221  quint32 i1 = i & 0xffffffff;
1222  quint32 i2 = i >> 32;
1223  *this << i2 << i1;
1224  } else {
1225  if (!noswap) {
1226  i = qbswap(i);
1227  }
1228  if (dev->write((char *)&i, sizeof(qint64)) != sizeof(qint64))
1229  q_status = WriteFailed;
1230  }
1231  return *this;
1232 }
1233 
1248 {
1250  if (!dev->putChar(qint8(i)))
1251  q_status = WriteFailed;
1252  return *this;
1253 }
1254 
1265 {
1266  if (version() >= QDataStream::Qt_4_6
1268  *this << double(f);
1269  return *this;
1270  }
1271 
1273  float g = f; // fixes float-on-stack problem
1274  if (!noswap) {
1275  union {
1276  float val1;
1277  quint32 val2;
1278  } x;
1279  x.val1 = g;
1280  x.val2 = qbswap(x.val2);
1281 
1282  if (dev->write((char *)&x.val2, sizeof(float)) != sizeof(float))
1283  q_status = WriteFailed;
1284  return *this;
1285  }
1286 
1287  if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
1288  q_status = WriteFailed;
1289  return *this;
1290 }
1291 
1292 
1303 {
1304  if (version() >= QDataStream::Qt_4_6
1306  *this << float(f);
1307  return *this;
1308  }
1309 
1311  if (noswap) {
1312  if (dev->write((char *)&f, sizeof(double)) != sizeof(double))
1313  q_status = WriteFailed;
1314  } else {
1315  union {
1316  double val1;
1317  quint64 val2;
1318  } x;
1319  x.val1 = f;
1320  x.val2 = qbswap(x.val2);
1321  if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double))
1322  q_status = WriteFailed;
1323  }
1324  return *this;
1325 }
1326 
1327 
1340 {
1341  if (!s) {
1342  *this << (quint32)0;
1343  return *this;
1344  }
1345  int len = int(qstrlen(s)) + 1; // also write null terminator
1346  *this << (quint32)len; // write length specifier
1347  writeRawData(s, len);
1348  return *this;
1349 }
1350 
1359 {
1360  return *this << qint16(c);
1361 }
1362 
1371 {
1372  return *this << qint32(c);
1373 }
1374 
1386 {
1388  *this << (quint32)len; // write length specifier
1389  if (len)
1390  writeRawData(s, len);
1391  return *this;
1392 }
1393 
1394 
1403 int QDataStream::writeRawData(const char *s, int len)
1404 {
1406  int ret = dev->write(s, len);
1407  if (ret != len)
1408  q_status = WriteFailed;
1409  return ret;
1410 }
1411 
1424 {
1426  if (q_status != Ok && dev->isTransactionStarted())
1427  return -1;
1428 
1429  const int skipResult = dev->skip(len);
1430  if (skipResult != len)
1432  return skipResult;
1433 }
1434 
1448 
1449 #endif // QT_NO_DATASTREAM
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:52
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
QDataStream & operator>>(char &i)
Definition: qdatastream.h:388
void setFloatingPointPrecision(FloatingPointPrecision precision)
int readRawData(char *, int len)
@ Qt_DefaultCompiledVersion
Definition: qdatastream.h:105
bool commitTransaction()
QDataStream & readBytes(char *&, uint &len)
bool isDeviceTransactionStarted() const
int skipRawData(int len)
int writeRawData(const char *, int len)
void rollbackTransaction()
QDataStream & writeBytes(const char *, uint len)
void resetStatus()
void setDevice(QIODevice *)
void abortTransaction()
Status status() const
FloatingPointPrecision floatingPointPrecision() const
void startTransaction()
bool atEnd() const
int version() const
Definition: qdatastream.h:382
void setStatus(Status status)
QDataStream & operator<<(char i)
Definition: qdatastream.h:403
void setByteOrder(ByteOrder)
QDataStream::FloatingPointPrecision floatingPointPrecision
Definition: qdatastream_p.h:66
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:70
bool putChar(char c)
Definition: qiodevice.cpp:1850
void rollbackTransaction()
Definition: qiodevice.cpp:1648
qint64 write(const char *data, qint64 len)
Definition: qiodevice.cpp:1681
void startTransaction()
Definition: qiodevice.cpp:1603
qint64 skip(qint64 maxSize)
Definition: qiodevice.cpp:1981
bool isTransactionStarted() const
Definition: qiodevice.cpp:1669
virtual bool atEnd() const
Definition: qiodevice.cpp:952
void commitTransaction()
Definition: qiodevice.cpp:1624
qint64 read(char *data, qint64 maxlen)
Definition: qiodevice.cpp:1030
bool blockSignals(bool b) noexcept
Definition: qobject.cpp:1514
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
@ BigEndian
Definition: qsysinfo.h:61
@ ByteOrder
Definition: qsysinfo.h:66
const int blockSize
size_t qstrlen(const char *str)
#define CHECK_STREAM_WRITE_PRECOND(retVal)
#define CHECK_STREAM_PRECOND(retVal)
#define CHECK_STREAM_TRANSACTION_PRECOND(retVal)
#define Q_VOID
constexpr T qbswap(T source)
Definition: qendian.h:135
unsigned int quint32
Definition: qglobal.h:288
short qint16
Definition: qglobal.h:285
unsigned short quint16
Definition: qglobal.h:286
int qint32
Definition: qglobal.h:287
unsigned long long quint64
Definition: qglobal.h:299
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition: qglobal.h:283
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLfloat GLfloat f
GLenum GLuint GLenum GLsizei const GLchar * buf
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLboolean GLboolean g
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLsizei len
Definition: qopenglext.h:3292
GLdouble s
[6]
Definition: qopenglext.h:235
GLenum GLint GLint * precision
Definition: qopenglext.h:1890