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