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