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