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_6_1 = Qt_6_0,
101 Qt_6_2 = Qt_6_0,
102 Qt_DefaultCompiledVersion = Qt_6_2
103#if QT_VERSION >= 0x060300
104#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
105#endif
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 *, OpenMode flags);
128 QDataStream(const QByteArray &);
129 ~QDataStream();
130
131 QIODevice *device() const;
132 void setDevice(QIODevice *);
133
134 bool atEnd() const;
135
136 Status status() const;
137 void setStatus(Status status);
138 void resetStatus();
139
140 FloatingPointPrecision floatingPointPrecision() const;
141 void setFloatingPointPrecision(FloatingPointPrecision precision);
142
143 ByteOrder byteOrder() const;
144 void setByteOrder(ByteOrder);
145
146 int version() const;
147 void setVersion(int);
148
149 QDataStream &operator>>(char &i);
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 inline 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 QDataStream &operator>>(char16_t &c);
166 QDataStream &operator>>(char32_t &c);
167
168 QDataStream &operator<<(char i);
169 QDataStream &operator<<(qint8 i);
170 QDataStream &operator<<(quint8 i);
171 QDataStream &operator<<(qint16 i);
172 QDataStream &operator<<(quint16 i);
173 QDataStream &operator<<(qint32 i);
174 inline QDataStream &operator<<(quint32 i);
175 QDataStream &operator<<(qint64 i);
176 QDataStream &operator<<(quint64 i);
177 QDataStream &operator<<(std::nullptr_t) { return *this; }
178 QDataStream &operator<<(bool i);
179 QDataStream &operator<<(qfloat16 f);
180 QDataStream &operator<<(float f);
181 QDataStream &operator<<(double f);
182 QDataStream &operator<<(const char *str);
183 QDataStream &operator<<(char16_t c);
184 QDataStream &operator<<(char32_t c);
185
186
187 QDataStream &readBytes(char *&, uint &len);
188 int readRawData(char *, int len);
189
190 QDataStream &writeBytes(const char *, uint len);
191 int writeRawData(const char *, int len);
192
193 int skipRawData(int len);
194
195 void startTransaction();
196 bool commitTransaction();
197 void rollbackTransaction();
198 void abortTransaction();
199
200 bool isDeviceTransactionStarted() const;
201private:
202 Q_DISABLE_COPY(QDataStream)
203
204 QScopedPointer<QDataStreamPrivate> d;
205
206 QIODevice *dev;
207 bool owndev;
208 bool noswap;
209 ByteOrder byteorder;
210 int ver;
211 Status q_status;
212
213 int readBlock(char *data, int len);
214 friend class QtPrivate::StreamStateSaver;
215};
216
217namespace QtPrivate {
218
219class StreamStateSaver
220{
221public:
222 inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
223 {
224 if (!stream->isDeviceTransactionStarted())
225 stream->resetStatus();
226 }
227 inline ~StreamStateSaver()
228 {
229 if (oldStatus != QDataStream::Ok) {
230 stream->resetStatus();
231 stream->setStatus(oldStatus);
232 }
233 }
234
235private:
236 QDataStream *stream;
237 QDataStream::Status oldStatus;
238};
239
240template <typename Container>
241QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
242{
243 StreamStateSaver stateSaver(&s);
244
245 c.clear();
246 quint32 n;
247 s >> n;
248 c.reserve(n);
249 for (quint32 i = 0; i < n; ++i) {
250 typename Container::value_type t;
251 s >> t;
252 if (s.status() != QDataStream::Ok) {
253 c.clear();
254 break;
255 }
256 c.append(t);
257 }
258
259 return s;
260}
261
262template <typename Container>
263QDataStream &readListBasedContainer(QDataStream &s, Container &c)
264{
265 StreamStateSaver stateSaver(&s);
266
267 c.clear();
268 quint32 n;
269 s >> n;
270 for (quint32 i = 0; i < n; ++i) {
271 typename Container::value_type t;
272 s >> t;
273 if (s.status() != QDataStream::Ok) {
274 c.clear();
275 break;
276 }
277 c << t;
278 }
279
280 return s;
281}
282
283template <typename Container>
284QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
285{
286 StreamStateSaver stateSaver(&s);
287
288 c.clear();
289 quint32 n;
290 s >> n;
291 for (quint32 i = 0; i < n; ++i) {
292 typename Container::key_type k;
293 typename Container::mapped_type t;
294 s >> k >> t;
295 if (s.status() != QDataStream::Ok) {
296 c.clear();
297 break;
298 }
299 c.insert(k, t);
300 }
301
302 return s;
303}
304
305template <typename Container>
306QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
307{
308 s << quint32(c.size());
309 for (const typename Container::value_type &t : c)
310 s << t;
311
312 return s;
313}
314
315template <typename Container>
316QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
317{
318 s << quint32(c.size());
319 auto it = c.constBegin();
320 auto end = c.constEnd();
321 while (it != end) {
322 s << it.key() << it.value();
323 ++it;
324 }
325
326 return s;
327}
328
329template <typename Container>
330QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
331{
332 s << quint32(c.size());
333 auto it = c.constBegin();
334 auto end = c.constEnd();
335 while (it != end) {
336 const auto rangeStart = it++;
337 while (it != end && rangeStart.key() == it.key())
338 ++it;
339 const qint64 last = std::distance(rangeStart, it) - 1;
340 for (qint64 i = last; i >= 0; --i) {
341 auto next = std::next(rangeStart, i);
342 s << next.key() << next.value();
343 }
344 }
345
346 return s;
347}
348
349} // QtPrivate namespace
350
351template<typename ...T>
352using QDataStreamIfHasOStreamOperators =
353 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
354template<typename Container, typename ...T>
355using QDataStreamIfHasOStreamOperatorsContainer =
356 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
357
358template<typename ...T>
359using QDataStreamIfHasIStreamOperators =
360 std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
361template<typename Container, typename ...T>
362using QDataStreamIfHasIStreamOperatorsContainer =
363 std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
364
365/*****************************************************************************
366 QDataStream inline functions
367 *****************************************************************************/
368
369inline QIODevice *QDataStream::device() const
370{ return dev; }
371
372inline QDataStream::ByteOrder QDataStream::byteOrder() const
373{ return byteorder; }
374
375inline int QDataStream::version() const
376{ return ver; }
377
378inline void QDataStream::setVersion(int v)
379{ ver = v; }
380
381inline QDataStream &QDataStream::operator>>(char &i)
382{ return *this >> reinterpret_cast<qint8&>(i); }
383
384inline QDataStream &QDataStream::operator>>(quint8 &i)
385{ return *this >> reinterpret_cast<qint8&>(i); }
386
387inline QDataStream &QDataStream::operator>>(quint16 &i)
388{ return *this >> reinterpret_cast<qint16&>(i); }
389
390inline QDataStream &QDataStream::operator>>(quint32 &i)
391{ return *this >> reinterpret_cast<qint32&>(i); }
392
393inline QDataStream &QDataStream::operator>>(quint64 &i)
394{ return *this >> reinterpret_cast<qint64&>(i); }
395
396inline QDataStream &QDataStream::operator<<(char i)
397{ return *this << qint8(i); }
398
399inline QDataStream &QDataStream::operator<<(quint8 i)
400{ return *this << qint8(i); }
401
402inline QDataStream &QDataStream::operator<<(quint16 i)
403{ return *this << qint16(i); }
404
405inline QDataStream &QDataStream::operator<<(quint32 i)
406{ return *this << qint32(i); }
407
408inline QDataStream &QDataStream::operator<<(quint64 i)
409{ return *this << qint64(i); }
410
411template <typename Enum>
412inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
413{ return s << typename QFlags<Enum>::Int(e); }
414
415template <typename Enum>
416inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
417{
418 typename QFlags<Enum>::Int i;
419 s >> i;
420 e = QFlag(i);
421 return s;
422}
423
424template <typename T>
425typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
426operator<<(QDataStream &s, const T &t)
427{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
428
429template <typename T>
430typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
431operator>>(QDataStream &s, T &t)
432{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
433
434template<typename T>
435inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v)
436{
437 return QtPrivate::readArrayBasedContainer(s, v);
438}
439
440template<typename T>
441inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v)
442{
443 return QtPrivate::writeSequentialContainer(s, v);
444}
445
446template <typename T>
447inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set)
448{
449 return QtPrivate::readListBasedContainer(s, set);
450}
451
452template <typename T>
453inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set)
454{
455 return QtPrivate::writeSequentialContainer(s, set);
456}
457
458template <class Key, class T>
459inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
460{
461 return QtPrivate::readAssociativeContainer(s, hash);
462}
463
464template <class Key, class T>
465
466inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
467{
468 return QtPrivate::writeAssociativeContainer(s, hash);
469}
470
471template <class Key, class T>
472inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
473{
474 return QtPrivate::readAssociativeContainer(s, hash);
475}
476
477template <class Key, class T>
478inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
479{
480 return QtPrivate::writeAssociativeMultiContainer(s, hash);
481}
482
483template <class Key, class T>
484inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
485{
486 return QtPrivate::readAssociativeContainer(s, map);
487}
488
489template <class Key, class T>
490inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
491{
492 return QtPrivate::writeAssociativeContainer(s, map);
493}
494
495template <class Key, class T>
496inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
497{
498 return QtPrivate::readAssociativeContainer(s, map);
499}
500
501template <class Key, class T>
502inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
503{
504 return QtPrivate::writeAssociativeMultiContainer(s, map);
505}
506
507#ifndef QT_NO_DATASTREAM
508template <class T1, class T2>
509inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p)
510{
511 s >> p.first >> p.second;
512 return s;
513}
514
515template <class T1, class T2>
516inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p)
517{
518 s << p.first << p.second;
519 return s;
520}
521#endif
522
523inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination)
524{
525 int combined;
526 s >> combined;
527 combination = QKeyCombination::fromCombined(combined);
528 return s;
529}
530
531inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination)
532{
533 return s << combination.toCombined();
534}
535
536#endif // QT_NO_DATASTREAM
537
538QT_END_NAMESPACE
539
540#endif // QDATASTREAM_H
541

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