Qt 4.8
qdatastream.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdatastream.h"
43 #include "qdatastream_p.h"
44 
45 #if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
46 #include "qbuffer.h"
47 #include "qstring.h"
48 #include <stdio.h>
49 #include <ctype.h>
50 #include <stdlib.h>
51 #include "qendian.h"
52 
54 
240 /*****************************************************************************
241  QDataStream member functions
242  *****************************************************************************/
243 
244 #undef CHECK_STREAM_PRECOND
245 #ifndef QT_NO_DEBUG
246 #define CHECK_STREAM_PRECOND(retVal) \
247  if (!dev) { \
248  qWarning("QDataStream: No device"); \
249  return retVal; \
250  }
251 #else
252 #define CHECK_STREAM_PRECOND(retVal) \
253  if (!dev) { \
254  return retVal; \
255  }
256 #endif
257 
258 #define CHECK_STREAM_WRITE_PRECOND(retVal) \
259  CHECK_STREAM_PRECOND(retVal) \
260  if (q_status != Ok) \
261  return retVal;
262 
263 enum {
265 };
266 
267 // ### 5.0: when streaming invalid QVariants, just the type should
268 // be written, no "data" after it
269 
277 {
278  dev = 0;
279  owndev = false;
282  noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
283  q_status = Ok;
284 }
285 
299 {
300  dev = d; // set device
301  owndev = false;
302  byteorder = BigEndian; // default byte order
304  noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
305  q_status = Ok;
306 }
307 
308 #ifdef QT3_SUPPORT
309 
318 {
319  QBuffer *buf = new QBuffer(a);
320 #ifndef QT_NO_QOBJECT
321  buf->blockSignals(true);
322 #endif
323  buf->open(QIODevice::OpenMode(mode));
324  dev = buf;
325  owndev = true;
328  noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
329  q_status = Ok;
330 }
331 #endif
332 
346 QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
347 {
348  QBuffer *buf = new QBuffer(a);
349 #ifndef QT_NO_QOBJECT
350  buf->blockSignals(true);
351 #endif
352  buf->open(flags);
353  dev = buf;
354  owndev = true;
357  noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
358  q_status = Ok;
359 }
360 
370 {
371  QBuffer *buf = new QBuffer;
372 #ifndef QT_NO_QOBJECT
373  buf->blockSignals(true);
374 #endif
375  buf->setData(a);
377  dev = buf;
378  owndev = true;
381  noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
382  q_status = Ok;
383 }
384 
395 {
396  if (owndev)
397  delete dev;
398 }
399 
400 
420 {
421  if (owndev) {
422  delete dev;
423  owndev = false;
424  }
425  dev = d;
426 }
427 
438 {
439  setDevice(0);
440 }
441 
442 
456 bool QDataStream::atEnd() const
457 {
458  return dev ? dev->atEnd() : true;
459 }
460 
469 {
471 }
472 
491 {
492  if (d == 0)
493  d.reset(new QDataStreamPrivate());
494  d->floatingPointPrecision = precision;
495 }
496 
504 {
505  return q_status;
506 }
507 
514 {
515  q_status = Ok;
516 }
517 
527 {
528  if (q_status == Ok)
529  q_status = status;
530 }
531 
562 {
563  byteorder = bo;
564  if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
565  noswap = (byteorder == BigEndian);
566  else
568 }
569 
570 
678 /*****************************************************************************
679  QDataStream read functions
680  *****************************************************************************/
681 
699 {
700  i = 0;
701  CHECK_STREAM_PRECOND(*this)
702  char c;
703  if (!dev->getChar(&c))
705  else
706  i = qint8(c);
707  return *this;
708 }
709 
710 
733 {
734  i = 0;
735  CHECK_STREAM_PRECOND(*this)
736  if (dev->read((char *)&i, 2) != 2) {
737  i = 0;
739  } else {
740  if (!noswap) {
741  i = qbswap(i);
742  }
743  }
744  return *this;
745 }
746 
747 
770 {
771  i = 0;
772  CHECK_STREAM_PRECOND(*this)
773  if (dev->read((char *)&i, 4) != 4) {
774  i = 0;
776  } else {
777  if (!noswap) {
778  i = qbswap(i);
779  }
780  }
781  return *this;
782 }
783 
806 {
807  i = qint64(0);
808  CHECK_STREAM_PRECOND(*this)
809  if (version() < 6) {
810  quint32 i1, i2;
811  *this >> i2 >> i1;
812  i = ((quint64)i1 << 32) + i2;
813  } else {
814  if (dev->read((char *)&i, 8) != 8) {
815  i = qint64(0);
817  } else {
818  if (!noswap) {
819  i = qbswap(i);
820  }
821  }
822  }
823  return *this;
824 }
825 
831 {
832  qint8 v;
833  *this >> v;
834  i = !!v;
835  return *this;
836 }
837 
852 {
855  double d;
856  *this >> d;
857  f = d;
858  return *this;
859  }
860 
861  f = 0.0f;
862  CHECK_STREAM_PRECOND(*this)
863  if (dev->read((char *)&f, 4) != 4) {
864  f = 0.0f;
866  } else {
867  if (!noswap) {
868  union {
869  float val1;
870  quint32 val2;
871  } x;
872  x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
873  f = x.val1;
874  }
875  }
876  return *this;
877 }
878 
879 #if defined(Q_DOUBLE_FORMAT)
880 #define Q_DF(x) Q_DOUBLE_FORMAT[(x)] - '0'
881 #endif
882 
897 {
900  float d;
901  *this >> d;
902  f = d;
903  return *this;
904  }
905 
906  f = 0.0;
907  CHECK_STREAM_PRECOND(*this)
908 #ifndef Q_DOUBLE_FORMAT
909  if (dev->read((char *)&f, 8) != 8) {
910  f = 0.0;
912  } else {
913  if (!noswap) {
914  union {
915  double val1;
916  quint64 val2;
917  } x;
918  x.val2 = qbswap(*reinterpret_cast<quint64 *>(&f));
919  f = x.val1;
920  }
921  }
922 #else
923  //non-standard floating point format
924  union {
925  double val1;
926  char val2[8];
927  } x;
928  char *p = x.val2;
929  char b[8];
930  if (dev->read(b, 8) == 8) {
931  if (noswap) {
932  *p++ = b[Q_DF(0)];
933  *p++ = b[Q_DF(1)];
934  *p++ = b[Q_DF(2)];
935  *p++ = b[Q_DF(3)];
936  *p++ = b[Q_DF(4)];
937  *p++ = b[Q_DF(5)];
938  *p++ = b[Q_DF(6)];
939  *p = b[Q_DF(7)];
940  } else {
941  *p++ = b[Q_DF(7)];
942  *p++ = b[Q_DF(6)];
943  *p++ = b[Q_DF(5)];
944  *p++ = b[Q_DF(4)];
945  *p++ = b[Q_DF(3)];
946  *p++ = b[Q_DF(2)];
947  *p++ = b[Q_DF(1)];
948  *p = b[Q_DF(0)];
949  }
950  f = x.val1;
951  } else {
953  }
954 #endif
955  return *this;
956 }
957 
958 
973 {
974  uint len = 0;
975  return readBytes(s, len);
976 }
977 
978 
997 {
998  s = 0;
999  l = 0;
1000  CHECK_STREAM_PRECOND(*this)
1001 
1002  quint32 len;
1003  *this >> len;
1004  if (len == 0)
1005  return *this;
1006 
1007  const quint32 Step = 1024 * 1024;
1008  quint32 allocated = 0;
1009  char *prevBuf = 0;
1010  char *curBuf = 0;
1011 
1012  do {
1013  int blockSize = qMin(Step, len - allocated);
1014  prevBuf = curBuf;
1015  curBuf = new char[allocated + blockSize + 1];
1016  if (prevBuf) {
1017  memcpy(curBuf, prevBuf, allocated);
1018  delete [] prevBuf;
1019  }
1020  if (dev->read(curBuf + allocated, blockSize) != blockSize) {
1021  delete [] curBuf;
1023  return *this;
1024  }
1025  allocated += blockSize;
1026  } while (allocated < len);
1027 
1028  s = curBuf;
1029  s[len] = '\0';
1030  l = (uint)len;
1031  return *this;
1032 }
1033 
1043 int QDataStream::readRawData(char *s, int len)
1044 {
1046  return dev->read(s, len);
1047 }
1048 
1049 
1050 /*****************************************************************************
1051  QDataStream write functions
1052  *****************************************************************************/
1053 
1054 
1072 {
1074  if (!dev->putChar(i))
1076  return *this;
1077 }
1078 
1079 
1102 {
1104  if (!noswap) {
1105  i = qbswap(i);
1106  }
1107  if (dev->write((char *)&i, sizeof(qint16)) != sizeof(qint16))
1109  return *this;
1110 }
1111 
1123 {
1125  if (!noswap) {
1126  i = qbswap(i);
1127  }
1128  if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
1130  return *this;
1131 }
1132 
1155 {
1157  if (version() < 6) {
1158  quint32 i1 = i & 0xffffffff;
1159  quint32 i2 = i >> 32;
1160  *this << i2 << i1;
1161  } else {
1162  if (!noswap) {
1163  i = qbswap(i);
1164  }
1165  if (dev->write((char *)&i, sizeof(qint64)) != sizeof(qint64))
1167  }
1168  return *this;
1169 }
1170 
1188 {
1190  if (!dev->putChar(qint8(i)))
1192  return *this;
1193 }
1194 
1208 {
1209  if (version() >= QDataStream::Qt_4_6
1211  *this << double(f);
1212  return *this;
1213  }
1214 
1216  float g = f; // fixes float-on-stack problem
1217  if (!noswap) {
1218  union {
1219  float val1;
1220  quint32 val2;
1221  } x;
1222  x.val1 = g;
1223  x.val2 = qbswap(x.val2);
1224 
1225  if (dev->write((char *)&x.val2, sizeof(float)) != sizeof(float))
1227  return *this;
1228  }
1229 
1230  if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
1232  return *this;
1233 }
1234 
1235 
1249 {
1250  if (version() >= QDataStream::Qt_4_6
1252  *this << float(f);
1253  return *this;
1254  }
1255 
1257 #ifndef Q_DOUBLE_FORMAT
1258  if (noswap) {
1259  if (dev->write((char *)&f, sizeof(double)) != sizeof(double))
1261  } else {
1262  union {
1263  double val1;
1264  quint64 val2;
1265  } x;
1266  x.val1 = f;
1267  x.val2 = qbswap(x.val2);
1268  if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double))
1270  }
1271 #else
1272  union {
1273  double val1;
1274  char val2[8];
1275  } x;
1276  x.val1 = f;
1277  char *p = x.val2;
1278  char b[8];
1279  if (noswap) {
1280  b[Q_DF(0)] = *p++;
1281  b[Q_DF(1)] = *p++;
1282  b[Q_DF(2)] = *p++;
1283  b[Q_DF(3)] = *p++;
1284  b[Q_DF(4)] = *p++;
1285  b[Q_DF(5)] = *p++;
1286  b[Q_DF(6)] = *p++;
1287  b[Q_DF(7)] = *p;
1288  } else {
1289  b[Q_DF(7)] = *p++;
1290  b[Q_DF(6)] = *p++;
1291  b[Q_DF(5)] = *p++;
1292  b[Q_DF(4)] = *p++;
1293  b[Q_DF(3)] = *p++;
1294  b[Q_DF(2)] = *p++;
1295  b[Q_DF(1)] = *p++;
1296  b[Q_DF(0)] = *p;
1297  }
1298  if (dev->write(b, 8) != 8)
1300 #endif
1301  return *this;
1302 }
1303 
1304 
1318 {
1319  if (!s) {
1320  *this << (quint32)0;
1321  return *this;
1322  }
1323  uint len = qstrlen(s) + 1; // also write null terminator
1324  *this << (quint32)len; // write length specifier
1325  writeRawData(s, len);
1326  return *this;
1327 }
1328 
1329 
1341 {
1343  *this << (quint32)len; // write length specifier
1344  if (len)
1345  writeRawData(s, len);
1346  return *this;
1347 }
1348 
1349 
1358 int QDataStream::writeRawData(const char *s, int len)
1359 {
1361  int ret = dev->write(s, len);
1362  if (ret != len)
1364  return ret;
1365 }
1366 
1382 {
1384 
1385  if (dev->isSequential()) {
1386  char buf[4096];
1387  int sumRead = 0;
1388 
1389  while (len > 0) {
1390  int blockSize = qMin(len, (int)sizeof(buf));
1391  int n = dev->read(buf, blockSize);
1392  if (n == -1)
1393  return -1;
1394  if (n == 0)
1395  return sumRead;
1396 
1397  sumRead += n;
1398  len -= blockSize;
1399  }
1400  return sumRead;
1401  } else {
1402  qint64 pos = dev->pos();
1403  qint64 size = dev->size();
1404  if (pos + len > size)
1405  len = size - pos;
1406  if (!dev->seek(pos + len))
1407  return -1;
1408  return len;
1409  }
1410 }
1411 
1412 #ifdef QT3_SUPPORT
1413 
1424 #endif
1425 
1427 
1428 #endif // QT_NO_DATASTREAM
Status status() const
Returns the status of the data stream.
const int blockSize
bool blockSignals(bool b)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition: qobject.cpp:1406
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
Status
This enum describes the current status of the data stream.
Definition: qdatastream.h:101
void qbswap(const T src, uchar *dest)
Definition: qendian.h:74
QDataStream()
Constructs a data stream that has no I/O device.
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
Definition: qbuffer.cpp:315
bool open(OpenMode openMode)
Reimplemented Function
Definition: qbuffer.cpp:338
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...
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
virtual ~QDataStream()
Destroys the data stream.
QIODevice * dev
Definition: qdatastream.h:193
bool getChar(char *c)
Reads one character from the device and stores it in c.
Definition: qiodevice.cpp:1536
bool putChar(char c)
Writes the character c to the device.
Definition: qiodevice.cpp:1486
long ASN1_INTEGER_get ASN1_INTEGER * a
void setStatus(Status status)
Sets the status of the data stream to the status given.
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
FloatingPointPrecision
The precision of floating point numbers used for reading/writing the data.
Definition: qdatastream.h:108
#define CHECK_STREAM_WRITE_PRECOND(retVal)
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i.e.
Definition: qiodevice.cpp:711
QDataStream::FloatingPointPrecision floatingPointPrecision
Definition: qdatastream_p.h:66
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
#define CHECK_STREAM_PRECOND(retVal)
signed char qint8
Definition: qglobal.h:933
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Status q_status
Definition: qdatastream.h:198
int readRawData(char *, int len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
unsigned __int64 quint64
Definition: qglobal.h:943
QDataStream & writeBytes(const char *, uint len)
Writes the length specifier len and the buffer s to the stream and returns a reference to the stream...
short qint16
Definition: qglobal.h:935
unsigned int uint
Definition: qglobal.h:996
void setByteOrder(ByteOrder)
Sets the serialization byte order to bo.
__int64 qint64
Definition: qglobal.h:942
void reset(T *other=0)
Deletes the existing object it is pointing to if any, and sets its pointer to other.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
int version() const
Returns the version number of the data serialization format.
Definition: qdatastream.h:212
uint qstrlen(const char *str)
Definition: qbytearray.h:79
QDataStream & readBytes(char *&, uint &len)
Reads the buffer s from the stream and returns a reference to the stream.
void resetStatus()
Resets the status of the data stream.
unsigned int quint32
Definition: qglobal.h:938
QFactoryLoader * l
FloatingPointPrecision floatingPointPrecision() const
Returns the floating point precision of the data stream.
void unsetDevice()
Unsets the I/O device.
QDataStream & operator>>(qint8 &i)
Reads a signed byte from the stream into i, and returns a reference to the stream.
void setDevice(QIODevice *)
void QDataStream::setDevice(QIODevice *d)
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
ByteOrder byteorder
Definition: qdatastream.h:196
ByteOrder
The byte order used for reading/writing the data.
Definition: qdatastream.h:96
QScopedPointer< QDataStreamPrivate > d
Definition: qdatastream.h:191
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
int skipRawData(int len)
Skips len bytes from the device.
QDataStream & operator<<(qint8 i)
Writes a signed byte, i, to the stream and returns a reference to the stream.
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
void setFloatingPointPrecision(FloatingPointPrecision precision)
Sets the floating point precision of the data stream to precision.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
int writeRawData(const char *, int len)
Writes len bytes from s to the stream.