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