/usr/include/QtCore/qdatastream.h
Line | Count | Source (jump to first uncovered line) |
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 | | // Qt-Security score:critical reason:data-parser |
4 | | |
5 | | #ifndef QDATASTREAM_H |
6 | | #define QDATASTREAM_H |
7 | | |
8 | | #include <QtCore/qobjectdefs.h> |
9 | | #include <QtCore/qchar.h> |
10 | | #include <QtCore/qcontainerfwd.h> |
11 | | #include <QtCore/qiodevicebase.h> |
12 | | #include <QtCore/qnamespace.h> |
13 | | #include <QtCore/qscopedpointer.h> |
14 | | #include <QtCore/qttypetraits.h> |
15 | | |
16 | | #include <iterator> // std::distance(), std::next() |
17 | | #include <memory> |
18 | | |
19 | | #ifdef Status |
20 | | #error qdatastream.h must be included before any header file that defines Status |
21 | | #endif |
22 | | |
23 | | QT_BEGIN_NAMESPACE |
24 | | |
25 | | #if QT_CORE_REMOVED_SINCE(6, 3) |
26 | | class qfloat16; |
27 | | #endif |
28 | | class QByteArray; |
29 | | class QDataStream; |
30 | | class QIODevice; |
31 | | class QString; |
32 | | |
33 | | #if !defined(QT_NO_DATASTREAM) |
34 | | namespace QtPrivate { |
35 | | class StreamStateSaver; |
36 | | template <typename Container> |
37 | | QDataStream &readArrayBasedContainer(QDataStream &s, Container &c); |
38 | | template <typename Container> |
39 | | QDataStream &readListBasedContainer(QDataStream &s, Container &c); |
40 | | template <typename Container> |
41 | | QDataStream &readAssociativeContainer(QDataStream &s, Container &c); |
42 | | template <typename Container> |
43 | | QDataStream &writeSequentialContainer(QDataStream &s, const Container &c); |
44 | | template <typename Container> |
45 | | QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c); |
46 | | template <typename Container> |
47 | | QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c); |
48 | | } |
49 | | class Q_CORE_EXPORT QDataStream : public QIODeviceBase |
50 | | { |
51 | | Q_GADGET |
52 | | |
53 | | public: |
54 | | enum Version QT7_ONLY(: quint8) { |
55 | | Qt_1_0 = 1, |
56 | | Qt_2_0 = 2, |
57 | | Qt_2_1 = 3, |
58 | | Qt_3_0 = 4, |
59 | | Qt_3_1 = 5, |
60 | | Qt_3_3 = 6, |
61 | | Qt_4_0 = 7, |
62 | | Qt_4_1 = Qt_4_0, |
63 | | Qt_4_2 = 8, |
64 | | Qt_4_3 = 9, |
65 | | Qt_4_4 = 10, |
66 | | Qt_4_5 = 11, |
67 | | Qt_4_6 = 12, |
68 | | Qt_4_7 = Qt_4_6, |
69 | | Qt_4_8 = Qt_4_7, |
70 | | Qt_4_9 = Qt_4_8, |
71 | | Qt_5_0 = 13, |
72 | | Qt_5_1 = 14, |
73 | | Qt_5_2 = 15, |
74 | | Qt_5_3 = Qt_5_2, |
75 | | Qt_5_4 = 16, |
76 | | Qt_5_5 = Qt_5_4, |
77 | | Qt_5_6 = 17, |
78 | | Qt_5_7 = Qt_5_6, |
79 | | Qt_5_8 = Qt_5_7, |
80 | | Qt_5_9 = Qt_5_8, |
81 | | Qt_5_10 = Qt_5_9, |
82 | | Qt_5_11 = Qt_5_10, |
83 | | Qt_5_12 = 18, |
84 | | Qt_5_13 = 19, |
85 | | Qt_5_14 = Qt_5_13, |
86 | | Qt_5_15 = Qt_5_14, |
87 | | Qt_6_0 = 20, |
88 | | Qt_6_1 = Qt_6_0, |
89 | | Qt_6_2 = Qt_6_0, |
90 | | Qt_6_3 = Qt_6_0, |
91 | | Qt_6_4 = Qt_6_0, |
92 | | Qt_6_5 = Qt_6_0, |
93 | | Qt_6_6 = 21, |
94 | | Qt_6_7 = 22, |
95 | | Qt_6_8 = Qt_6_7, |
96 | | Qt_6_9 = Qt_6_7, |
97 | | Qt_6_10 = 23, |
98 | | Qt_6_11 = 24, |
99 | | Qt_DefaultCompiledVersion = Qt_6_11 |
100 | | #if QT_VERSION >= QT_VERSION_CHECK(6, 12, 0) |
101 | | #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion |
102 | | #endif |
103 | | }; |
104 | | Q_ENUM(Version) |
105 | | |
106 | | enum ByteOrder { |
107 | | BigEndian = QSysInfo::BigEndian, |
108 | | LittleEndian = QSysInfo::LittleEndian |
109 | | }; |
110 | | |
111 | | enum Status QT7_ONLY(: quint8) { |
112 | | Ok, |
113 | | ReadPastEnd, |
114 | | ReadCorruptData, |
115 | | WriteFailed, |
116 | | SizeLimitExceeded, |
117 | | }; |
118 | | |
119 | | enum FloatingPointPrecision QT7_ONLY(: quint8) { |
120 | | SinglePrecision, |
121 | | DoublePrecision |
122 | | }; |
123 | | |
124 | | QDataStream(); |
125 | | explicit QDataStream(QIODevice *); |
126 | | QDataStream(QByteArray *, OpenMode flags); |
127 | | QDataStream(const QByteArray &); |
128 | | ~QDataStream(); |
129 | | |
130 | | QIODevice *device() const; |
131 | | void setDevice(QIODevice *); |
132 | | |
133 | | bool atEnd() const; |
134 | | |
135 | | QT_CORE_INLINE_SINCE(6, 8) |
136 | | Status status() const; |
137 | | void setStatus(Status status); |
138 | | void resetStatus(); |
139 | | |
140 | | QT_CORE_INLINE_SINCE(6, 8) |
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>>(char &i); |
151 | | QDataStream &operator>>(qint8 &i); |
152 | | QDataStream &operator>>(quint8 &i); |
153 | | QDataStream &operator>>(qint16 &i); |
154 | | QDataStream &operator>>(quint16 &i); |
155 | | QDataStream &operator>>(qint32 &i); |
156 | | inline QDataStream &operator>>(quint32 &i); |
157 | | QDataStream &operator>>(qint64 &i); |
158 | | QDataStream &operator>>(quint64 &i); |
159 | 0 | QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; } |
160 | | |
161 | | QDataStream &operator>>(bool &i); |
162 | | #if QT_CORE_REMOVED_SINCE(6, 3) |
163 | | QDataStream &operator>>(qfloat16 &f); |
164 | | #endif |
165 | | QDataStream &operator>>(float &f); |
166 | | QDataStream &operator>>(double &f); |
167 | | QDataStream &operator>>(char *&str); |
168 | | QDataStream &operator>>(char16_t &c); |
169 | | QDataStream &operator>>(char32_t &c); |
170 | | |
171 | | QDataStream &operator<<(char i); |
172 | | QDataStream &operator<<(qint8 i); |
173 | | QDataStream &operator<<(quint8 i); |
174 | | QDataStream &operator<<(qint16 i); |
175 | | QDataStream &operator<<(quint16 i); |
176 | | QDataStream &operator<<(qint32 i); |
177 | | inline QDataStream &operator<<(quint32 i); |
178 | | QDataStream &operator<<(qint64 i); |
179 | | QDataStream &operator<<(quint64 i); |
180 | 0 | QDataStream &operator<<(std::nullptr_t) { return *this; } |
181 | | #if QT_CORE_REMOVED_SINCE(6, 8) || defined(Q_QDOC) |
182 | | QDataStream &operator<<(bool i); |
183 | | #endif |
184 | | #if !defined(Q_QDOC) |
185 | | // Disable implicit conversions to bool (e.g. for pointers) |
186 | | template <typename T, |
187 | | std::enable_if_t<std::is_same_v<T, bool>, bool> = true> |
188 | | QDataStream &operator<<(T i) |
189 | | { |
190 | | return (*this << qint8(i)); |
191 | | } |
192 | | #endif |
193 | | #if QT_CORE_REMOVED_SINCE(6, 3) |
194 | | QDataStream &operator<<(qfloat16 f); |
195 | | #endif |
196 | | QDataStream &operator<<(float f); |
197 | | QDataStream &operator<<(double f); |
198 | | QDataStream &operator<<(const char *str); |
199 | | QDataStream &operator<<(char16_t c); |
200 | | QDataStream &operator<<(char32_t c); |
201 | | |
202 | | explicit operator bool() const noexcept { return status() == Ok; } |
203 | | |
204 | | #if QT_DEPRECATED_SINCE(6, 11) |
205 | | QT_DEPRECATED_VERSION_X_6_11("Use an overload that takes qint64 length.") |
206 | | QDataStream &readBytes(char *&, uint &len); |
207 | | #endif |
208 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
209 | | QDataStream &writeBytes(const char *, uint len); |
210 | | int skipRawData(int len); |
211 | | int readRawData(char *, int len); |
212 | | int writeRawData(const char *, int len); |
213 | | #endif |
214 | | QDataStream &readBytes(char *&, qint64 &len); |
215 | | qint64 readRawData(char *, qint64 len); |
216 | | QDataStream &writeBytes(const char *, qint64 len); |
217 | | qint64 writeRawData(const char *, qint64 len); |
218 | | qint64 skipRawData(qint64 len); |
219 | | |
220 | | void startTransaction(); |
221 | | bool commitTransaction(); |
222 | | void rollbackTransaction(); |
223 | | void abortTransaction(); |
224 | | |
225 | | bool isDeviceTransactionStarted() const; |
226 | | private: |
227 | | Q_DISABLE_COPY(QDataStream) |
228 | | |
229 | | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
230 | | void* const d = nullptr; |
231 | | #endif |
232 | | |
233 | | QIODevice *dev = nullptr; |
234 | | bool owndev = false; |
235 | | bool noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian; |
236 | | quint8 fpPrecision = QDataStream::DoublePrecision; |
237 | | quint8 q_status = Ok; |
238 | | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) |
239 | | ByteOrder byteorder = BigEndian; |
240 | | int ver = Qt_DefaultCompiledVersion; |
241 | | #else |
242 | | Version ver = Qt_DefaultCompiledVersion; |
243 | | #endif |
244 | | quint16 transactionDepth = 0; |
245 | | |
246 | | #if QT_CORE_REMOVED_SINCE(6, 7) |
247 | | int readBlock(char *data, int len); |
248 | | #endif |
249 | | qint64 readBlock(char *data, qint64 len); |
250 | | static inline qint64 readQSizeType(QDataStream &s); |
251 | | static inline bool writeQSizeType(QDataStream &s, qint64 value); |
252 | | static constexpr quint32 NullCode = 0xffffffffu; |
253 | | static constexpr quint32 ExtendedSize = 0xfffffffeu; |
254 | | |
255 | | friend class QtPrivate::StreamStateSaver; |
256 | | Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QString &str); |
257 | | Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QString &str); |
258 | | Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QByteArray &ba); |
259 | | Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QByteArray &ba); |
260 | | template <typename Container> |
261 | | friend QDataStream &QtPrivate::readArrayBasedContainer(QDataStream &s, Container &c); |
262 | | template <typename Container> |
263 | | friend QDataStream &QtPrivate::readListBasedContainer(QDataStream &s, Container &c); |
264 | | template <typename Container> |
265 | | friend QDataStream &QtPrivate::readAssociativeContainer(QDataStream &s, Container &c); |
266 | | template <typename Container> |
267 | | friend QDataStream &QtPrivate::writeSequentialContainer(QDataStream &s, const Container &c); |
268 | | template <typename Container> |
269 | | friend QDataStream &QtPrivate::writeAssociativeContainer(QDataStream &s, const Container &c); |
270 | | template <typename Container> |
271 | | friend QDataStream &QtPrivate::writeAssociativeMultiContainer(QDataStream &s, |
272 | | const Container &c); |
273 | | }; |
274 | | |
275 | | namespace QtPrivate { |
276 | | |
277 | | class StreamStateSaver |
278 | | { |
279 | | Q_DISABLE_COPY_MOVE(StreamStateSaver) |
280 | | public: |
281 | | Q_NODISCARD_CTOR |
282 | | explicit StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status()) |
283 | 0 | { |
284 | 0 | if (!stream->isDeviceTransactionStarted()) |
285 | 0 | stream->resetStatus(); |
286 | 0 | } |
287 | | inline ~StreamStateSaver() |
288 | 0 | { |
289 | 0 | if (oldStatus != QDataStream::Ok) { |
290 | 0 | stream->resetStatus(); |
291 | 0 | stream->setStatus(oldStatus); |
292 | 0 | } |
293 | 0 | } |
294 | | |
295 | | private: |
296 | | QDataStream *stream; |
297 | | QDataStream::Status oldStatus; |
298 | | }; |
299 | | |
300 | | template <typename Container> |
301 | | QDataStream &readArrayBasedContainer(QDataStream &s, Container &c) |
302 | | { |
303 | | StreamStateSaver stateSaver(&s); |
304 | | |
305 | | c.clear(); |
306 | | qint64 size = QDataStream::readQSizeType(s); |
307 | | qsizetype n = size; |
308 | | if (size != n || size < 0) { |
309 | | s.setStatus(QDataStream::SizeLimitExceeded); |
310 | | return s; |
311 | | } |
312 | | c.reserve(n); |
313 | | for (qsizetype i = 0; i < n; ++i) { |
314 | | typename Container::value_type t; |
315 | | if (!(s >> t)) { |
316 | | c.clear(); |
317 | | break; |
318 | | } |
319 | | c.append(t); |
320 | | } |
321 | | |
322 | | return s; |
323 | | } |
324 | | |
325 | | template <typename Container> |
326 | | QDataStream &readListBasedContainer(QDataStream &s, Container &c) |
327 | | { |
328 | | StreamStateSaver stateSaver(&s); |
329 | | |
330 | | c.clear(); |
331 | | qint64 size = QDataStream::readQSizeType(s); |
332 | | qsizetype n = size; |
333 | | if (size != n || size < 0) { |
334 | | s.setStatus(QDataStream::SizeLimitExceeded); |
335 | | return s; |
336 | | } |
337 | | for (qsizetype i = 0; i < n; ++i) { |
338 | | typename Container::value_type t; |
339 | | if (!(s >> t)) { |
340 | | c.clear(); |
341 | | break; |
342 | | } |
343 | | c << t; |
344 | | } |
345 | | |
346 | | return s; |
347 | | } |
348 | | |
349 | | template <typename Container> |
350 | | QDataStream &readAssociativeContainer(QDataStream &s, Container &c) |
351 | | { |
352 | | StreamStateSaver stateSaver(&s); |
353 | | |
354 | | c.clear(); |
355 | | qint64 size = QDataStream::readQSizeType(s); |
356 | | qsizetype n = size; |
357 | | if (size != n || size < 0) { |
358 | | s.setStatus(QDataStream::SizeLimitExceeded); |
359 | | return s; |
360 | | } |
361 | | for (qsizetype i = 0; i < n; ++i) { |
362 | | typename Container::key_type k; |
363 | | typename Container::mapped_type t; |
364 | | if (!(s >> k >> t)) { |
365 | | c.clear(); |
366 | | break; |
367 | | } |
368 | | c.insert(k, t); |
369 | | } |
370 | | |
371 | | return s; |
372 | | } |
373 | | |
374 | | template <typename Container> |
375 | | QDataStream &writeSequentialContainer(QDataStream &s, const Container &c) |
376 | | { |
377 | | if (!QDataStream::writeQSizeType(s, c.size())) |
378 | | return s; |
379 | | for (const typename Container::value_type &t : c) |
380 | | s << t; |
381 | | |
382 | | return s; |
383 | | } |
384 | | |
385 | | template <typename Container> |
386 | | QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) |
387 | | { |
388 | | if (!QDataStream::writeQSizeType(s, c.size())) |
389 | | return s; |
390 | | auto it = c.constBegin(); |
391 | | auto end = c.constEnd(); |
392 | | while (it != end) { |
393 | | s << it.key() << it.value(); |
394 | | ++it; |
395 | | } |
396 | | |
397 | | return s; |
398 | | } |
399 | | |
400 | | template <typename Container> |
401 | | QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c) |
402 | | { |
403 | | if (!QDataStream::writeQSizeType(s, c.size())) |
404 | | return s; |
405 | | auto it = c.constBegin(); |
406 | | auto end = c.constEnd(); |
407 | | while (it != end) { |
408 | | const auto rangeStart = it++; |
409 | | while (it != end && rangeStart.key() == it.key()) |
410 | | ++it; |
411 | | const qint64 last = std::distance(rangeStart, it) - 1; |
412 | | for (qint64 i = last; i >= 0; --i) { |
413 | | auto next = std::next(rangeStart, i); |
414 | | s << next.key() << next.value(); |
415 | | } |
416 | | } |
417 | | |
418 | | return s; |
419 | | } |
420 | | |
421 | | } // QtPrivate namespace |
422 | | |
423 | | template<typename ...T> |
424 | | using QDataStreamIfHasOStreamOperators = |
425 | | std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>; |
426 | | template<typename Container, typename ...T> |
427 | | using QDataStreamIfHasOStreamOperatorsContainer = |
428 | | std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>; |
429 | | |
430 | | template<typename ...T> |
431 | | using QDataStreamIfHasIStreamOperators = |
432 | | std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>; |
433 | | template<typename Container, typename ...T> |
434 | | using QDataStreamIfHasIStreamOperatorsContainer = |
435 | | std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>; |
436 | | |
437 | | /***************************************************************************** |
438 | | QDataStream inline functions |
439 | | *****************************************************************************/ |
440 | | |
441 | | inline QIODevice *QDataStream::device() const |
442 | | { return dev; } |
443 | | |
444 | | #if QT_CORE_INLINE_IMPL_SINCE(6, 8) |
445 | | QDataStream::Status QDataStream::status() const |
446 | | { |
447 | | return Status(q_status); |
448 | | } |
449 | | |
450 | | QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const |
451 | | { |
452 | | return FloatingPointPrecision(fpPrecision); |
453 | | } |
454 | | #endif // INLINE_SINCE 6.8 |
455 | | |
456 | | inline QDataStream::ByteOrder QDataStream::byteOrder() const |
457 | 0 | { |
458 | 0 | if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian) |
459 | 0 | return noswap ? BigEndian : LittleEndian; |
460 | 0 | return noswap ? LittleEndian : BigEndian; |
461 | 0 | } |
462 | | |
463 | | inline int QDataStream::version() const |
464 | | { return ver; } |
465 | | |
466 | | inline void QDataStream::setVersion(int v) |
467 | | { ver = Version(v); } |
468 | | |
469 | | qint64 QDataStream::readQSizeType(QDataStream &s) |
470 | | { |
471 | | quint32 first; |
472 | | s >> first; |
473 | | if (first == NullCode) |
474 | | return -1; |
475 | | if (first < ExtendedSize || s.version() < QDataStream::Qt_6_7) |
476 | | return qint64(first); |
477 | | qint64 extendedLen; |
478 | | s >> extendedLen; |
479 | | return extendedLen; |
480 | | } |
481 | | |
482 | | bool QDataStream::writeQSizeType(QDataStream &s, qint64 value) |
483 | 0 | { |
484 | 0 | if (value < qint64(ExtendedSize)) { |
485 | 0 | s << quint32(value); |
486 | 0 | } else if (s.version() >= QDataStream::Qt_6_7) { |
487 | 0 | s << ExtendedSize << value; |
488 | 0 | } else if (value == qint64(ExtendedSize)) { |
489 | 0 | s << ExtendedSize; |
490 | 0 | } else { |
491 | 0 | s.setStatus(QDataStream::SizeLimitExceeded); // value is too big for old format |
492 | 0 | return false; |
493 | 0 | } |
494 | 0 | return true; |
495 | 0 | } |
496 | | |
497 | | inline QDataStream &QDataStream::operator>>(char &i) |
498 | | { return *this >> reinterpret_cast<qint8&>(i); } |
499 | | |
500 | | inline QDataStream &QDataStream::operator>>(quint8 &i) |
501 | 115M | { return *this >> reinterpret_cast<qint8&>(i); } |
502 | | |
503 | | inline QDataStream &QDataStream::operator>>(quint16 &i) |
504 | 27.3M | { return *this >> reinterpret_cast<qint16&>(i); } |
505 | | |
506 | | inline QDataStream &QDataStream::operator>>(quint32 &i) |
507 | 32.1M | { return *this >> reinterpret_cast<qint32&>(i); } |
508 | | |
509 | | inline QDataStream &QDataStream::operator>>(quint64 &i) |
510 | | { return *this >> reinterpret_cast<qint64&>(i); } |
511 | | |
512 | | inline QDataStream &QDataStream::operator<<(char i) |
513 | 0 | { return *this << qint8(i); } |
514 | | |
515 | | inline QDataStream &QDataStream::operator<<(quint8 i) |
516 | 0 | { return *this << qint8(i); } |
517 | | |
518 | | inline QDataStream &QDataStream::operator<<(quint16 i) |
519 | 0 | { return *this << qint16(i); } |
520 | | |
521 | | inline QDataStream &QDataStream::operator<<(quint32 i) |
522 | 0 | { return *this << qint32(i); } |
523 | | |
524 | | inline QDataStream &QDataStream::operator<<(quint64 i) |
525 | 0 | { return *this << qint64(i); } |
526 | | |
527 | | template <typename Enum> |
528 | | inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e) |
529 | | { return s << e.toInt(); } |
530 | | |
531 | | template <typename Enum> |
532 | | inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e) |
533 | | { |
534 | | typename QFlags<Enum>::Int i; |
535 | | s >> i; |
536 | | e = QFlags<Enum>::fromInt(i); |
537 | | return s; |
538 | | } |
539 | | |
540 | | template <typename T> |
541 | | typename std::enable_if_t<std::is_enum<T>::value, QDataStream &> |
542 | | operator<<(QDataStream &s, const T &t) |
543 | | { |
544 | | // std::underlying_type_t<T> may be long or ulong, for which QDataStream |
545 | | // provides no streaming operators. For those, cast to qint64 or quint64. |
546 | | return s << typename QIntegerForSizeof<T>::Unsigned(t); |
547 | | } |
548 | | |
549 | | template <typename T> |
550 | | typename std::enable_if_t<std::is_enum<T>::value, QDataStream &> |
551 | | operator>>(QDataStream &s, T &t) |
552 | | { |
553 | | typename QIntegerForSizeof<T>::Unsigned i; |
554 | | s >> i; |
555 | | t = T(i); |
556 | | return s; |
557 | | } |
558 | | |
559 | | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, QChar chr); |
560 | | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QChar &chr); |
561 | | |
562 | | #ifndef Q_QDOC |
563 | | |
564 | | template<typename T> |
565 | | inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v) |
566 | | { |
567 | | return QtPrivate::readArrayBasedContainer(s, v); |
568 | | } |
569 | | |
570 | | template<typename T> |
571 | | inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v) |
572 | | { |
573 | | return QtPrivate::writeSequentialContainer(s, v); |
574 | | } |
575 | | |
576 | | template <typename T> |
577 | | inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set) |
578 | | { |
579 | | return QtPrivate::readListBasedContainer(s, set); |
580 | | } |
581 | | |
582 | | template <typename T> |
583 | | inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set) |
584 | | { |
585 | | return QtPrivate::writeSequentialContainer(s, set); |
586 | | } |
587 | | |
588 | | template <class Key, class T> |
589 | | inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash) |
590 | | { |
591 | | return QtPrivate::readAssociativeContainer(s, hash); |
592 | | } |
593 | | |
594 | | template <class Key, class T> |
595 | | |
596 | | inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash) |
597 | | { |
598 | | return QtPrivate::writeAssociativeContainer(s, hash); |
599 | | } |
600 | | |
601 | | template <class Key, class T> |
602 | | inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash) |
603 | | { |
604 | | return QtPrivate::readAssociativeContainer(s, hash); |
605 | | } |
606 | | |
607 | | template <class Key, class T> |
608 | | inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash) |
609 | | { |
610 | | return QtPrivate::writeAssociativeMultiContainer(s, hash); |
611 | | } |
612 | | |
613 | | template <class Key, class T> |
614 | | inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map) |
615 | | { |
616 | | return QtPrivate::readAssociativeContainer(s, map); |
617 | | } |
618 | | |
619 | | template <class Key, class T> |
620 | | inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map) |
621 | | { |
622 | | return QtPrivate::writeAssociativeContainer(s, map); |
623 | | } |
624 | | |
625 | | template <class Key, class T> |
626 | | inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map) |
627 | | { |
628 | | return QtPrivate::readAssociativeContainer(s, map); |
629 | | } |
630 | | |
631 | | template <class Key, class T> |
632 | | inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map) |
633 | | { |
634 | | return QtPrivate::writeAssociativeMultiContainer(s, map); |
635 | | } |
636 | | |
637 | | template <class T1, class T2> |
638 | | inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p) |
639 | | { |
640 | | s >> p.first >> p.second; |
641 | | return s; |
642 | | } |
643 | | |
644 | | template <class T1, class T2> |
645 | | inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p) |
646 | | { |
647 | | s << p.first << p.second; |
648 | | return s; |
649 | | } |
650 | | |
651 | | #else |
652 | | |
653 | | template <class T> |
654 | | QDataStream &operator>>(QDataStream &s, QList<T> &l); |
655 | | |
656 | | template <class T> |
657 | | QDataStream &operator<<(QDataStream &s, const QList<T> &l); |
658 | | |
659 | | template <class T> |
660 | | QDataStream &operator>>(QDataStream &s, QSet<T> &set); |
661 | | |
662 | | template <class T> |
663 | | QDataStream &operator<<(QDataStream &s, const QSet<T> &set); |
664 | | |
665 | | template <class Key, class T> |
666 | | QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash); |
667 | | |
668 | | template <class Key, class T> |
669 | | QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash); |
670 | | |
671 | | template <class Key, class T> |
672 | | QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash); |
673 | | |
674 | | template <class Key, class T> |
675 | | QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash); |
676 | | |
677 | | template <class Key, class T> |
678 | | QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map); |
679 | | |
680 | | template <class Key, class T> |
681 | | QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map); |
682 | | |
683 | | template <class Key, class T> |
684 | | QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map); |
685 | | |
686 | | template <class Key, class T> |
687 | | QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map); |
688 | | |
689 | | template <class T1, class T2> |
690 | | QDataStream &operator>>(QDataStream& s, std::pair<T1, T2> &p); |
691 | | |
692 | | template <class T1, class T2> |
693 | | QDataStream &operator<<(QDataStream& s, const std::pair<T1, T2> &p); |
694 | | |
695 | | #endif // Q_QDOC |
696 | | |
697 | | inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination) |
698 | 0 | { |
699 | 0 | int combined; |
700 | 0 | s >> combined; |
701 | 0 | combination = QKeyCombination::fromCombined(combined); |
702 | 0 | return s; |
703 | 0 | } |
704 | | |
705 | | inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination) |
706 | 0 | { |
707 | 0 | return s << combination.toCombined(); |
708 | 0 | } |
709 | | |
710 | | #endif // QT_NO_DATASTREAM |
711 | | |
712 | | QT_END_NAMESPACE |
713 | | |
714 | | #endif // QDATASTREAM_H |