Coverage Report

Created: 2025-07-16 07:53

/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