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#ifndef QDATASTREAM_H
41#define QDATASTREAM_H
42
43#include <QtCore/qscopedpointer.h>
44#include <QtCore/qiodevice.h>
45#include <QtCore/qpair.h>
46
47#ifdef Status
48#error qdatastream.h must be included before any header file that defines Status
49#endif
50
51QT_BEGIN_NAMESPACE
52
53class qfloat16;
54class QByteArray;
55class QIODevice;
56
57template <typename T> class QList;
58template <typename T> class QLinkedList;
59template <typename T> class QVector;
60template <typename T> class QSet;
61template <class Key, class T> class QHash;
62template <class Key, class T> class QMap;
63
64#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
65class QDataStreamPrivate;
66namespace QtPrivate {
67class StreamStateSaver;
68}
69class Q_CORE_EXPORT QDataStream
70{
71public:
72 enum Version {
73 Qt_1_0 = 1,
74 Qt_2_0 = 2,
75 Qt_2_1 = 3,
76 Qt_3_0 = 4,
77 Qt_3_1 = 5,
78 Qt_3_3 = 6,
79 Qt_4_0 = 7,
80 Qt_4_1 = Qt_4_0,
81 Qt_4_2 = 8,
82 Qt_4_3 = 9,
83 Qt_4_4 = 10,
84 Qt_4_5 = 11,
85 Qt_4_6 = 12,
86 Qt_4_7 = Qt_4_6,
87 Qt_4_8 = Qt_4_7,
88 Qt_4_9 = Qt_4_8,
89 Qt_5_0 = 13,
90 Qt_5_1 = 14,
91 Qt_5_2 = 15,
92 Qt_5_3 = Qt_5_2,
93 Qt_5_4 = 16,
94 Qt_5_5 = Qt_5_4,
95 Qt_5_6 = 17,
96 Qt_5_7 = Qt_5_6,
97 Qt_5_8 = Qt_5_7,
98 Qt_5_9 = Qt_5_8,
99 Qt_5_10 = Qt_5_9,
100 Qt_5_11 = Qt_5_10,
101 Qt_5_12 = 18,
102 Qt_5_13 = 19,
103 Qt_5_14 = Qt_5_13,
104#if QT_VERSION >= 0x050f00
105#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
106#endif
107 Qt_DefaultCompiledVersion = Qt_5_14
108 };
109
110 enum ByteOrder {
111 BigEndian = QSysInfo::BigEndian,
112 LittleEndian = QSysInfo::LittleEndian
113 };
114
115 enum Status {
116 Ok,
117 ReadPastEnd,
118 ReadCorruptData,
119 WriteFailed
120 };
121
122 enum FloatingPointPrecision {
123 SinglePrecision,
124 DoublePrecision
125 };
126
127 QDataStream();
128 explicit QDataStream(QIODevice *);
129 QDataStream(QByteArray *, QIODevice::OpenMode flags);
130 QDataStream(const QByteArray &);
131 ~QDataStream();
132
133 QIODevice *device() const;
134 void setDevice(QIODevice *);
135#if QT_DEPRECATED_SINCE(5, 13)
136 QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
137 void unsetDevice();
138#endif
139
140 bool atEnd() const;
141
142 Status status() const;
143 void setStatus(Status status);
144 void resetStatus();
145
146 FloatingPointPrecision floatingPointPrecision() const;
147 void setFloatingPointPrecision(FloatingPointPrecision precision);
148
149 ByteOrder byteOrder() const;
150 void setByteOrder(ByteOrder);
151
152 int version() const;
153 void setVersion(int);
154
155 QDataStream &operator>>(qint8 &i);
156 QDataStream &operator>>(quint8 &i);
157 QDataStream &operator>>(qint16 &i);
158 QDataStream &operator>>(quint16 &i);
159 QDataStream &operator>>(qint32 &i);
160 inline QDataStream &operator>>(quint32 &i);
161 QDataStream &operator>>(qint64 &i);
162 QDataStream &operator>>(quint64 &i);
163 QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; }
164
165 QDataStream &operator>>(bool &i);
166 QDataStream &operator>>(qfloat16 &f);
167 QDataStream &operator>>(float &f);
168 QDataStream &operator>>(double &f);
169 QDataStream &operator>>(char *&str);
170
171 QDataStream &operator<<(qint8 i);
172 QDataStream &operator<<(quint8 i);
173 QDataStream &operator<<(qint16 i);
174 QDataStream &operator<<(quint16 i);
175 QDataStream &operator<<(qint32 i);
176 inline QDataStream &operator<<(quint32 i);
177 QDataStream &operator<<(qint64 i);
178 QDataStream &operator<<(quint64 i);
179 QDataStream &operator<<(std::nullptr_t) { return *this; }
180 QDataStream &operator<<(bool i);
181 QDataStream &operator<<(qfloat16 f);
182 QDataStream &operator<<(float f);
183 QDataStream &operator<<(double f);
184 QDataStream &operator<<(const char *str);
185
186 QDataStream &readBytes(char *&, uint &len);
187 int readRawData(char *, int len);
188
189 QDataStream &writeBytes(const char *, uint len);
190 int writeRawData(const char *, int len);
191
192 int skipRawData(int len);
193
194 void startTransaction();
195 bool commitTransaction();
196 void rollbackTransaction();
197 void abortTransaction();
198
199private:
200 Q_DISABLE_COPY(QDataStream)
201
202 QScopedPointer<QDataStreamPrivate> d;
203
204 QIODevice *dev;
205 bool owndev;
206 bool noswap;
207 ByteOrder byteorder;
208 int ver;
209 Status q_status;
210
211 int readBlock(char *data, int len);
212 friend class QtPrivate::StreamStateSaver;
213};
214
215namespace QtPrivate {
216
217class StreamStateSaver
218{
219public:
220 inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
221 {
222 if (!stream->dev || !stream->dev->isTransactionStarted())
223 stream->resetStatus();
224 }
225 inline ~StreamStateSaver()
226 {
227 if (oldStatus != QDataStream::Ok) {
228 stream->resetStatus();
229 stream->setStatus(oldStatus);
230 }
231 }
232
233private:
234 QDataStream *stream;
235 QDataStream::Status oldStatus;
236};
237
238template <typename Container>
239QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
240{
241 StreamStateSaver stateSaver(&s);
242
243 c.clear();
244 quint32 n;
245 s >> n;
246 c.reserve(n);
247 for (quint32 i = 0; i < n; ++i) {
248 typename Container::value_type t;
249 s >> t;
250 if (s.status() != QDataStream::Ok) {
251 c.clear();
252 break;
253 }
254 c.append(t);
255 }
256
257 return s;
258}
259
260template <typename Container>
261QDataStream &readListBasedContainer(QDataStream &s, Container &c)
262{
263 StreamStateSaver stateSaver(&s);
264
265 c.clear();
266 quint32 n;
267 s >> n;
268 for (quint32 i = 0; i < n; ++i) {
269 typename Container::value_type t;
270 s >> t;
271 if (s.status() != QDataStream::Ok) {
272 c.clear();
273 break;
274 }
275 c << t;
276 }
277
278 return s;
279}
280
281template <typename Container>
282QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
283{
284 StreamStateSaver stateSaver(&s);
285
286 c.clear();
287 quint32 n;
288 s >> n;
289 for (quint32 i = 0; i < n; ++i) {
290 typename Container::key_type k;
291 typename Container::mapped_type t;
292 s >> k >> t;
293 if (s.status() != QDataStream::Ok) {
294 c.clear();
295 break;
296 }
297 c.insertMulti(k, t);
298 }
299
300 return s;
301}
302
303template <typename Container>
304QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
305{
306 s << quint32(c.size());
307 for (const typename Container::value_type &t : c)
308 s << t;
309
310 return s;
311}
312
313template <typename Container>
314QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
315{
316 s << quint32(c.size());
317 // Deserialization should occur in the reverse order.
318 // Otherwise, value() will return the least recently inserted
319 // value instead of the most recently inserted one.
320 auto it = c.constEnd();
321 auto begin = c.constBegin();
322 while (it != begin) {
323 --it;
324 s << it.key() << it.value();
325 }
326
327 return s;
328}
329
330} // QtPrivate namespace
331
332/*****************************************************************************
333 QDataStream inline functions
334 *****************************************************************************/
335
336inline QIODevice *QDataStream::device() const
337{ return dev; }
338
339inline QDataStream::ByteOrder QDataStream::byteOrder() const
340{ return byteorder; }
341
342inline int QDataStream::version() const
343{ return ver; }
344
345inline void QDataStream::setVersion(int v)
346{ ver = v; }
347
348inline QDataStream &QDataStream::operator>>(quint8 &i)
349{ return *this >> reinterpret_cast<qint8&>(i); }
350
351inline QDataStream &QDataStream::operator>>(quint16 &i)
352{ return *this >> reinterpret_cast<qint16&>(i); }
353
354inline QDataStream &QDataStream::operator>>(quint32 &i)
355{ return *this >> reinterpret_cast<qint32&>(i); }
356
357inline QDataStream &QDataStream::operator>>(quint64 &i)
358{ return *this >> reinterpret_cast<qint64&>(i); }
359
360inline QDataStream &QDataStream::operator<<(quint8 i)
361{ return *this << qint8(i); }
362
363inline QDataStream &QDataStream::operator<<(quint16 i)
364{ return *this << qint16(i); }
365
366inline QDataStream &QDataStream::operator<<(quint32 i)
367{ return *this << qint32(i); }
368
369inline QDataStream &QDataStream::operator<<(quint64 i)
370{ return *this << qint64(i); }
371
372template <typename Enum>
373inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
374{ return s << e.i; }
375
376template <typename Enum>
377inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
378{ return s >> e.i; }
379
380template <typename T>
381inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
382{
383 return QtPrivate::readArrayBasedContainer(s, l);
384}
385
386template <typename T>
387inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
388{
389 return QtPrivate::writeSequentialContainer(s, l);
390}
391
392template <typename T>
393inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
394{
395 return QtPrivate::readListBasedContainer(s, l);
396}
397
398template <typename T>
399inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
400{
401 return QtPrivate::writeSequentialContainer(s, l);
402}
403
404template<typename T>
405inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
406{
407 return QtPrivate::readArrayBasedContainer(s, v);
408}
409
410template<typename T>
411inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v)
412{
413 return QtPrivate::writeSequentialContainer(s, v);
414}
415
416template <typename T>
417inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
418{
419 return QtPrivate::readListBasedContainer(s, set);
420}
421
422template <typename T>
423inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
424{
425 return QtPrivate::writeSequentialContainer(s, set);
426}
427
428template <class Key, class T>
429inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
430{
431 return QtPrivate::readAssociativeContainer(s, hash);
432}
433
434template <class Key, class T>
435inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
436{
437 return QtPrivate::writeAssociativeContainer(s, hash);
438}
439
440template <class Key, class T>
441inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
442{
443 return QtPrivate::readAssociativeContainer(s, map);
444}
445
446template <class Key, class T>
447inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
448{
449 return QtPrivate::writeAssociativeContainer(s, map);
450}
451
452#ifndef QT_NO_DATASTREAM
453template <class T1, class T2>
454inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p)
455{
456 s >> p.first >> p.second;
457 return s;
458}
459
460template <class T1, class T2>
461inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p)
462{
463 s << p.first << p.second;
464 return s;
465}
466#endif
467
468#endif // QT_NO_DATASTREAM
469
470QT_END_NAMESPACE
471
472#endif // QDATASTREAM_H
473