1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QDATASTREAM_H
5#define QDATASTREAM_H
6
7#include <QtCore/qscopedpointer.h>
8#include <QtCore/qiodevicebase.h>
9#include <QtCore/qcontainerfwd.h>
10#include <QtCore/qnamespace.h>
11
12#ifdef Status
13#error qdatastream.h must be included before any header file that defines Status
14#endif
15
16QT_BEGIN_NAMESPACE
17
18#if QT_CORE_REMOVED_SINCE(6, 3)
19class qfloat16;
20#endif
21class QByteArray;
22class QIODevice;
23
24#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
25class QDataStreamPrivate;
26namespace QtPrivate {
27class StreamStateSaver;
28}
29class Q_CORE_EXPORT QDataStream : public QIODeviceBase
30{
31public:
32 enum Version {
33 Qt_1_0 = 1,
34 Qt_2_0 = 2,
35 Qt_2_1 = 3,
36 Qt_3_0 = 4,
37 Qt_3_1 = 5,
38 Qt_3_3 = 6,
39 Qt_4_0 = 7,
40 Qt_4_1 = Qt_4_0,
41 Qt_4_2 = 8,
42 Qt_4_3 = 9,
43 Qt_4_4 = 10,
44 Qt_4_5 = 11,
45 Qt_4_6 = 12,
46 Qt_4_7 = Qt_4_6,
47 Qt_4_8 = Qt_4_7,
48 Qt_4_9 = Qt_4_8,
49 Qt_5_0 = 13,
50 Qt_5_1 = 14,
51 Qt_5_2 = 15,
52 Qt_5_3 = Qt_5_2,
53 Qt_5_4 = 16,
54 Qt_5_5 = Qt_5_4,
55 Qt_5_6 = 17,
56 Qt_5_7 = Qt_5_6,
57 Qt_5_8 = Qt_5_7,
58 Qt_5_9 = Qt_5_8,
59 Qt_5_10 = Qt_5_9,
60 Qt_5_11 = Qt_5_10,
61 Qt_5_12 = 18,
62 Qt_5_13 = 19,
63 Qt_5_14 = Qt_5_13,
64 Qt_5_15 = Qt_5_14,
65 Qt_6_0 = 20,
66 Qt_6_1 = Qt_6_0,
67 Qt_6_2 = Qt_6_0,
68 Qt_6_3 = Qt_6_0,
69 Qt_6_4 = Qt_6_0,
70 Qt_6_5 = Qt_6_0,
71 Qt_6_6 = 21,
72 Qt_DefaultCompiledVersion = Qt_6_6
73#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
74#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
75#endif
76 };
77
78 enum ByteOrder {
79 BigEndian = QSysInfo::BigEndian,
80 LittleEndian = QSysInfo::LittleEndian
81 };
82
83 enum Status {
84 Ok,
85 ReadPastEnd,
86 ReadCorruptData,
87 WriteFailed
88 };
89
90 enum FloatingPointPrecision {
91 SinglePrecision,
92 DoublePrecision
93 };
94
95 QDataStream();
96 explicit QDataStream(QIODevice *);
97 QDataStream(QByteArray *, OpenMode flags);
98 QDataStream(const QByteArray &);
99 ~QDataStream();
100
101 QIODevice *device() const;
102 void setDevice(QIODevice *);
103
104 bool atEnd() const;
105
106 Status status() const;
107 void setStatus(Status status);
108 void resetStatus();
109
110 FloatingPointPrecision floatingPointPrecision() const;
111 void setFloatingPointPrecision(FloatingPointPrecision precision);
112
113 ByteOrder byteOrder() const;
114 void setByteOrder(ByteOrder);
115
116 int version() const;
117 void setVersion(int);
118
119 QDataStream &operator>>(char &i);
120 QDataStream &operator>>(qint8 &i);
121 QDataStream &operator>>(quint8 &i);
122 QDataStream &operator>>(qint16 &i);
123 QDataStream &operator>>(quint16 &i);
124 QDataStream &operator>>(qint32 &i);
125 inline QDataStream &operator>>(quint32 &i);
126 QDataStream &operator>>(qint64 &i);
127 QDataStream &operator>>(quint64 &i);
128 QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; }
129
130 QDataStream &operator>>(bool &i);
131#if QT_CORE_REMOVED_SINCE(6, 3)
132 QDataStream &operator>>(qfloat16 &f);
133#endif
134 QDataStream &operator>>(float &f);
135 QDataStream &operator>>(double &f);
136 QDataStream &operator>>(char *&str);
137 QDataStream &operator>>(char16_t &c);
138 QDataStream &operator>>(char32_t &c);
139
140 QDataStream &operator<<(char i);
141 QDataStream &operator<<(qint8 i);
142 QDataStream &operator<<(quint8 i);
143 QDataStream &operator<<(qint16 i);
144 QDataStream &operator<<(quint16 i);
145 QDataStream &operator<<(qint32 i);
146 inline QDataStream &operator<<(quint32 i);
147 QDataStream &operator<<(qint64 i);
148 QDataStream &operator<<(quint64 i);
149 QDataStream &operator<<(std::nullptr_t) { return *this; }
150 QDataStream &operator<<(bool i);
151#if QT_CORE_REMOVED_SINCE(6, 3)
152 QDataStream &operator<<(qfloat16 f);
153#endif
154 QDataStream &operator<<(float f);
155 QDataStream &operator<<(double f);
156 QDataStream &operator<<(const char *str);
157 QDataStream &operator<<(char16_t c);
158 QDataStream &operator<<(char32_t c);
159
160
161 QDataStream &readBytes(char *&, uint &len);
162 int readRawData(char *, int len);
163
164 QDataStream &writeBytes(const char *, uint len);
165 int writeRawData(const char *, int len);
166
167 int skipRawData(int len);
168
169 void startTransaction();
170 bool commitTransaction();
171 void rollbackTransaction();
172 void abortTransaction();
173
174 bool isDeviceTransactionStarted() const;
175private:
176 Q_DISABLE_COPY(QDataStream)
177
178 QScopedPointer<QDataStreamPrivate> d;
179
180 QIODevice *dev;
181 bool owndev;
182 bool noswap;
183 ByteOrder byteorder;
184 int ver;
185 Status q_status;
186
187 int readBlock(char *data, int len);
188 friend class QtPrivate::StreamStateSaver;
189};
190
191namespace QtPrivate {
192
193class StreamStateSaver
194{
195public:
196 inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
197 {
198 if (!stream->isDeviceTransactionStarted())
199 stream->resetStatus();
200 }
201 inline ~StreamStateSaver()
202 {
203 if (oldStatus != QDataStream::Ok) {
204 stream->resetStatus();
205 stream->setStatus(oldStatus);
206 }
207 }
208
209private:
210 QDataStream *stream;
211 QDataStream::Status oldStatus;
212};
213
214template <typename Container>
215QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
216{
217 StreamStateSaver stateSaver(&s);
218
219 c.clear();
220 quint32 n;
221 s >> n;
222 c.reserve(n);
223 for (quint32 i = 0; i < n; ++i) {
224 typename Container::value_type t;
225 s >> t;
226 if (s.status() != QDataStream::Ok) {
227 c.clear();
228 break;
229 }
230 c.append(t);
231 }
232
233 return s;
234}
235
236template <typename Container>
237QDataStream &readListBasedContainer(QDataStream &s, Container &c)
238{
239 StreamStateSaver stateSaver(&s);
240
241 c.clear();
242 quint32 n;
243 s >> n;
244 for (quint32 i = 0; i < n; ++i) {
245 typename Container::value_type t;
246 s >> t;
247 if (s.status() != QDataStream::Ok) {
248 c.clear();
249 break;
250 }
251 c << t;
252 }
253
254 return s;
255}
256
257template <typename Container>
258QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
259{
260 StreamStateSaver stateSaver(&s);
261
262 c.clear();
263 quint32 n;
264 s >> n;
265 for (quint32 i = 0; i < n; ++i) {
266 typename Container::key_type k;
267 typename Container::mapped_type t;
268 s >> k >> t;
269 if (s.status() != QDataStream::Ok) {
270 c.clear();
271 break;
272 }
273 c.insert(k, t);
274 }
275
276 return s;
277}
278
279template <typename Container>
280QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
281{
282 s << quint32(c.size());
283 for (const typename Container::value_type &t : c)
284 s << t;
285
286 return s;
287}
288
289template <typename Container>
290QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
291{
292 s << quint32(c.size());
293 auto it = c.constBegin();
294 auto end = c.constEnd();
295 while (it != end) {
296 s << it.key() << it.value();
297 ++it;
298 }
299
300 return s;
301}
302
303template <typename Container>
304QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
305{
306 s << quint32(c.size());
307 auto it = c.constBegin();
308 auto end = c.constEnd();
309 while (it != end) {
310 const auto rangeStart = it++;
311 while (it != end && rangeStart.key() == it.key())
312 ++it;
313 const qint64 last = std::distance(rangeStart, it) - 1;
314 for (qint64 i = last; i >= 0; --i) {
315 auto next = std::next(rangeStart, i);
316 s << next.key() << next.value();
317 }
318 }
319
320 return s;
321}
322
323} // QtPrivate namespace
324
325template<typename ...T>
326using QDataStreamIfHasOStreamOperators =
327 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
328template<typename Container, typename ...T>
329using QDataStreamIfHasOStreamOperatorsContainer =
330 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
331
332template<typename ...T>
333using QDataStreamIfHasIStreamOperators =
334 std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
335template<typename Container, typename ...T>
336using QDataStreamIfHasIStreamOperatorsContainer =
337 std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
338
339/*****************************************************************************
340 QDataStream inline functions
341 *****************************************************************************/
342
343inline QIODevice *QDataStream::device() const
344{ return dev; }
345
346inline QDataStream::ByteOrder QDataStream::byteOrder() const
347{ return byteorder; }
348
349inline int QDataStream::version() const
350{ return ver; }
351
352inline void QDataStream::setVersion(int v)
353{ ver = v; }
354
355inline QDataStream &QDataStream::operator>>(char &i)
356{ return *this >> reinterpret_cast<qint8&>(i); }
357
358inline QDataStream &QDataStream::operator>>(quint8 &i)
359{ return *this >> reinterpret_cast<qint8&>(i); }
360
361inline QDataStream &QDataStream::operator>>(quint16 &i)
362{ return *this >> reinterpret_cast<qint16&>(i); }
363
364inline QDataStream &QDataStream::operator>>(quint32 &i)
365{ return *this >> reinterpret_cast<qint32&>(i); }
366
367inline QDataStream &QDataStream::operator>>(quint64 &i)
368{ return *this >> reinterpret_cast<qint64&>(i); }
369
370inline QDataStream &QDataStream::operator<<(char i)
371{ return *this << qint8(i); }
372
373inline QDataStream &QDataStream::operator<<(quint8 i)
374{ return *this << qint8(i); }
375
376inline QDataStream &QDataStream::operator<<(quint16 i)
377{ return *this << qint16(i); }
378
379inline QDataStream &QDataStream::operator<<(quint32 i)
380{ return *this << qint32(i); }
381
382inline QDataStream &QDataStream::operator<<(quint64 i)
383{ return *this << qint64(i); }
384
385template <typename Enum>
386inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
387{ return s << typename QFlags<Enum>::Int(e); }
388
389template <typename Enum>
390inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
391{
392 typename QFlags<Enum>::Int i;
393 s >> i;
394 e = QFlag(i);
395 return s;
396}
397
398template <typename T>
399typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
400operator<<(QDataStream &s, const T &t)
401{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
402
403template <typename T>
404typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
405operator>>(QDataStream &s, T &t)
406{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
407
408#ifndef Q_QDOC
409
410template<typename T>
411inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v)
412{
413 return QtPrivate::readArrayBasedContainer(s, v);
414}
415
416template<typename T>
417inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v)
418{
419 return QtPrivate::writeSequentialContainer(s, v);
420}
421
422template <typename T>
423inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set)
424{
425 return QtPrivate::readListBasedContainer(s, set);
426}
427
428template <typename T>
429inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set)
430{
431 return QtPrivate::writeSequentialContainer(s, set);
432}
433
434template <class Key, class T>
435inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
436{
437 return QtPrivate::readAssociativeContainer(s, hash);
438}
439
440template <class Key, class T>
441
442inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
443{
444 return QtPrivate::writeAssociativeContainer(s, hash);
445}
446
447template <class Key, class T>
448inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
449{
450 return QtPrivate::readAssociativeContainer(s, hash);
451}
452
453template <class Key, class T>
454inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
455{
456 return QtPrivate::writeAssociativeMultiContainer(s, hash);
457}
458
459template <class Key, class T>
460inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
461{
462 return QtPrivate::readAssociativeContainer(s, map);
463}
464
465template <class Key, class T>
466inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
467{
468 return QtPrivate::writeAssociativeContainer(s, map);
469}
470
471template <class Key, class T>
472inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
473{
474 return QtPrivate::readAssociativeContainer(s, map);
475}
476
477template <class Key, class T>
478inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
479{
480 return QtPrivate::writeAssociativeMultiContainer(s, map);
481}
482
483template <class T1, class T2>
484inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p)
485{
486 s >> p.first >> p.second;
487 return s;
488}
489
490template <class T1, class T2>
491inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p)
492{
493 s << p.first << p.second;
494 return s;
495}
496
497#else
498
499template <class T>
500QDataStream &operator>>(QDataStream &s, QList<T> &l);
501
502template <class T>
503QDataStream &operator<<(QDataStream &s, const QList<T> &l);
504
505template <class T>
506QDataStream &operator>>(QDataStream &s, QSet<T> &set);
507
508template <class T>
509QDataStream &operator<<(QDataStream &s, const QSet<T> &set);
510
511template <class Key, class T>
512QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash);
513
514template <class Key, class T>
515QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash);
516
517template <class Key, class T>
518QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash);
519
520template <class Key, class T>
521QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash);
522
523template <class Key, class T>
524QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map);
525
526template <class Key, class T>
527QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map);
528
529template <class Key, class T>
530QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map);
531
532template <class Key, class T>
533QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map);
534
535template <class T1, class T2>
536QDataStream &operator>>(QDataStream& s, std::pair<T1, T2> &p);
537
538template <class T1, class T2>
539QDataStream &operator<<(QDataStream& s, const std::pair<T1, T2> &p);
540
541#endif // Q_QDOC
542
543inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination)
544{
545 int combined;
546 s >> combined;
547 combination = QKeyCombination::fromCombined(combined);
548 return s;
549}
550
551inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination)
552{
553 return s << combination.toCombined();
554}
555
556#endif // QT_NO_DATASTREAM
557
558QT_END_NAMESPACE
559
560#endif // QDATASTREAM_H
561

source code of qtbase/src/corelib/serialization/qdatastream.h