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/qiodevicebase.h>
45#include <QtCore/qcontainerfwd.h>
46#include <QtCore/qnamespace.h>
47
48#ifdef Status
49#error qdatastream.h must be included before any header file that defines Status
50#endif
51
52QT_BEGIN_NAMESPACE
53
54class qfloat16;
55class QByteArray;
56class QIODevice;
57
58#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
59class QDataStreamPrivate;
60namespace QtPrivate {
61class StreamStateSaver;
62}
63class Q_CORE_EXPORT QDataStream : public QIODeviceBase
64{
65public:
66 enum Version {
67 Qt_1_0 = 1,
68 Qt_2_0 = 2,
69 Qt_2_1 = 3,
70 Qt_3_0 = 4,
71 Qt_3_1 = 5,
72 Qt_3_3 = 6,
73 Qt_4_0 = 7,
74 Qt_4_1 = Qt_4_0,
75 Qt_4_2 = 8,
76 Qt_4_3 = 9,
77 Qt_4_4 = 10,
78 Qt_4_5 = 11,
79 Qt_4_6 = 12,
80 Qt_4_7 = Qt_4_6,
81 Qt_4_8 = Qt_4_7,
82 Qt_4_9 = Qt_4_8,
83 Qt_5_0 = 13,
84 Qt_5_1 = 14,
85 Qt_5_2 = 15,
86 Qt_5_3 = Qt_5_2,
87 Qt_5_4 = 16,
88 Qt_5_5 = Qt_5_4,
89 Qt_5_6 = 17,
90 Qt_5_7 = Qt_5_6,
91 Qt_5_8 = Qt_5_7,
92 Qt_5_9 = Qt_5_8,
93 Qt_5_10 = Qt_5_9,
94 Qt_5_11 = Qt_5_10,
95 Qt_5_12 = 18,
96 Qt_5_13 = 19,
97 Qt_5_14 = Qt_5_13,
98 Qt_5_15 = Qt_5_14,
99 Qt_6_0 = 20,
100 Qt_DefaultCompiledVersion = Qt_6_0
101#if QT_VERSION >= 0x060100
102#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
103#endif
104 };
105
106 enum ByteOrder {
107 BigEndian = QSysInfo::BigEndian,
108 LittleEndian = QSysInfo::LittleEndian
109 };
110
111 enum Status {
112 Ok,
113 ReadPastEnd,
114 ReadCorruptData,
115 WriteFailed
116 };
117
118 enum FloatingPointPrecision {
119 SinglePrecision,
120 DoublePrecision
121 };
122
123 QDataStream();
124 explicit QDataStream(QIODevice *);
125 QDataStream(QByteArray *, OpenMode flags);
126 QDataStream(const QByteArray &);
127 ~QDataStream();
128
129 QIODevice *device() const;
130 void setDevice(QIODevice *);
131
132 bool atEnd() const;
133
134 Status status() const;
135 void setStatus(Status status);
136 void resetStatus();
137
138 FloatingPointPrecision floatingPointPrecision() const;
139 void setFloatingPointPrecision(FloatingPointPrecision precision);
140
141 ByteOrder byteOrder() const;
142 void setByteOrder(ByteOrder);
143
144 int version() const;
145 void setVersion(int);
146
147 QDataStream &operator>>(char &i);
148 QDataStream &operator>>(qint8 &i);
149 QDataStream &operator>>(quint8 &i);
150 QDataStream &operator>>(qint16 &i);
151 QDataStream &operator>>(quint16 &i);
152 QDataStream &operator>>(qint32 &i);
153 inline QDataStream &operator>>(quint32 &i);
154 QDataStream &operator>>(qint64 &i);
155 QDataStream &operator>>(quint64 &i);
156 QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; }
157
158 QDataStream &operator>>(bool &i);
159 QDataStream &operator>>(qfloat16 &f);
160 QDataStream &operator>>(float &f);
161 QDataStream &operator>>(double &f);
162 QDataStream &operator>>(char *&str);
163 QDataStream &operator>>(char16_t &c);
164 QDataStream &operator>>(char32_t &c);
165
166 QDataStream &operator<<(char i);
167 QDataStream &operator<<(qint8 i);
168 QDataStream &operator<<(quint8 i);
169 QDataStream &operator<<(qint16 i);
170 QDataStream &operator<<(quint16 i);
171 QDataStream &operator<<(qint32 i);
172 inline QDataStream &operator<<(quint32 i);
173 QDataStream &operator<<(qint64 i);
174 QDataStream &operator<<(quint64 i);
175 QDataStream &operator<<(std::nullptr_t) { return *this; }
176 QDataStream &operator<<(bool i);
177 QDataStream &operator<<(qfloat16 f);
178 QDataStream &operator<<(float f);
179 QDataStream &operator<<(double f);
180 QDataStream &operator<<(const char *str);
181 QDataStream &operator<<(char16_t c);
182 QDataStream &operator<<(char32_t c);
183
184
185 QDataStream &readBytes(char *&, uint &len);
186 int readRawData(char *, int len);
187
188 QDataStream &writeBytes(const char *, uint len);
189 int writeRawData(const char *, int len);
190
191 int skipRawData(int len);
192
193 void startTransaction();
194 bool commitTransaction();
195 void rollbackTransaction();
196 void abortTransaction();
197
198 bool isDeviceTransactionStarted() const;
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->isDeviceTransactionStarted())
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.insert(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 auto it = c.constBegin();
318 auto end = c.constEnd();
319 while (it != end) {
320 s << it.key() << it.value();
321 ++it;
322 }
323
324 return s;
325}
326
327template <typename Container>
328QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
329{
330 s << quint32(c.size());
331 auto it = c.constBegin();
332 auto end = c.constEnd();
333 while (it != end) {
334 const auto rangeStart = it++;
335 while (it != end && rangeStart.key() == it.key())
336 ++it;
337 const qint64 last = std::distance(rangeStart, it) - 1;
338 for (qint64 i = last; i >= 0; --i) {
339 auto next = std::next(rangeStart, i);
340 s << next.key() << next.value();
341 }
342 }
343
344 return s;
345}
346
347} // QtPrivate namespace
348
349template<typename ...T>
350using QDataStreamIfHasOStreamOperators =
351 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
352template<typename ...T>
353using QDataStreamIfHasIStreamOperators =
354 std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
355
356/*****************************************************************************
357 QDataStream inline functions
358 *****************************************************************************/
359
360inline QIODevice *QDataStream::device() const
361{ return dev; }
362
363inline QDataStream::ByteOrder QDataStream::byteOrder() const
364{ return byteorder; }
365
366inline int QDataStream::version() const
367{ return ver; }
368
369inline void QDataStream::setVersion(int v)
370{ ver = v; }
371
372inline QDataStream &QDataStream::operator>>(char &i)
373{ return *this >> reinterpret_cast<qint8&>(i); }
374
375inline QDataStream &QDataStream::operator>>(quint8 &i)
376{ return *this >> reinterpret_cast<qint8&>(i); }
377
378inline QDataStream &QDataStream::operator>>(quint16 &i)
379{ return *this >> reinterpret_cast<qint16&>(i); }
380
381inline QDataStream &QDataStream::operator>>(quint32 &i)
382{ return *this >> reinterpret_cast<qint32&>(i); }
383
384inline QDataStream &QDataStream::operator>>(quint64 &i)
385{ return *this >> reinterpret_cast<qint64&>(i); }
386
387inline QDataStream &QDataStream::operator<<(char i)
388{ return *this << qint8(i); }
389
390inline QDataStream &QDataStream::operator<<(quint8 i)
391{ return *this << qint8(i); }
392
393inline QDataStream &QDataStream::operator<<(quint16 i)
394{ return *this << qint16(i); }
395
396inline QDataStream &QDataStream::operator<<(quint32 i)
397{ return *this << qint32(i); }
398
399inline QDataStream &QDataStream::operator<<(quint64 i)
400{ return *this << qint64(i); }
401
402template <typename Enum>
403inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
404{ return s << typename QFlags<Enum>::Int(e); }
405
406template <typename Enum>
407inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
408{
409 typename QFlags<Enum>::Int i;
410 s >> i;
411 e = QFlag(i);
412 return s;
413}
414
415template <typename T>
416typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
417operator<<(QDataStream &s, const T &t)
418{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
419
420template <typename T>
421typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
422operator>>(QDataStream &s, T &t)
423{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
424
425template<typename T>
426inline QDataStreamIfHasIStreamOperators<T> operator>>(QDataStream &s, QList<T> &v)
427{
428 return QtPrivate::readArrayBasedContainer(s, v);
429}
430
431template<typename T>
432inline QDataStreamIfHasOStreamOperators<T> operator<<(QDataStream &s, const QList<T> &v)
433{
434 return QtPrivate::writeSequentialContainer(s, v);
435}
436
437template <typename T>
438inline QDataStreamIfHasIStreamOperators<T> operator>>(QDataStream &s, QSet<T> &set)
439{
440 return QtPrivate::readListBasedContainer(s, set);
441}
442
443template <typename T>
444inline QDataStreamIfHasOStreamOperators<T> operator<<(QDataStream &s, const QSet<T> &set)
445{
446 return QtPrivate::writeSequentialContainer(s, set);
447}
448
449template <class Key, class T>
450inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
451{
452 return QtPrivate::readAssociativeContainer(s, hash);
453}
454
455template <class Key, class T>
456
457inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
458{
459 return QtPrivate::writeAssociativeContainer(s, hash);
460}
461
462template <class Key, class T>
463inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
464{
465 return QtPrivate::readAssociativeContainer(s, hash);
466}
467
468template <class Key, class T>
469inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
470{
471 return QtPrivate::writeAssociativeMultiContainer(s, hash);
472}
473
474template <class Key, class T>
475inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
476{
477 return QtPrivate::readAssociativeContainer(s, map);
478}
479
480template <class Key, class T>
481inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
482{
483 return QtPrivate::writeAssociativeContainer(s, map);
484}
485
486template <class Key, class T>
487inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
488{
489 return QtPrivate::readAssociativeContainer(s, map);
490}
491
492template <class Key, class T>
493inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
494{
495 return QtPrivate::writeAssociativeMultiContainer(s, map);
496}
497
498#ifndef QT_NO_DATASTREAM
499template <class T1, class T2>
500inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p)
501{
502 s >> p.first >> p.second;
503 return s;
504}
505
506template <class T1, class T2>
507inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p)
508{
509 s << p.first << p.second;
510 return s;
511}
512#endif
513
514inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination)
515{
516 int combined;
517 s >> combined;
518 combination = QKeyCombination::fromCombined(combined);
519 return s;
520}
521
522inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination)
523{
524 return s << combination.toCombined();
525}
526
527#endif // QT_NO_DATASTREAM
528
529QT_END_NAMESPACE
530
531#endif // QDATASTREAM_H
532