1 | // Copyright (C) 2016 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 | #include "qdatastream.h" |
5 | #include "qdatastream_p.h" |
6 | |
7 | #if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED) |
8 | #include "qbuffer.h" |
9 | #include "qfloat16.h" |
10 | #include "qstring.h" |
11 | #include <stdio.h> |
12 | #include <ctype.h> |
13 | #include <stdlib.h> |
14 | #include "qendian.h" |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | constexpr quint32 QDataStream::NullCode; |
19 | constexpr quint32 QDataStream::ExtendedSize; |
20 | |
21 | /*! |
22 | \class QDataStream |
23 | \inmodule QtCore |
24 | \ingroup qtserialization |
25 | \reentrant |
26 | \brief The QDataStream class provides serialization of binary data |
27 | to a QIODevice. |
28 | |
29 | \ingroup io |
30 | |
31 | |
32 | A data stream is a binary stream of encoded information which is |
33 | 100% independent of the host computer's operating system, CPU or |
34 | byte order. For example, a data stream that is written by a PC |
35 | under Windows can be read by a Sun SPARC running Solaris. |
36 | |
37 | You can also use a data stream to read/write \l{raw}{raw |
38 | unencoded binary data}. If you want a "parsing" input stream, see |
39 | QTextStream. |
40 | |
41 | The QDataStream class implements the serialization of C++'s basic |
42 | data types, like \c char, \c short, \c int, \c{char *}, etc. |
43 | Serialization of more complex data is accomplished by breaking up |
44 | the data into primitive units. |
45 | |
46 | A data stream cooperates closely with a QIODevice. A QIODevice |
47 | represents an input/output medium one can read data from and write |
48 | data to. The QFile class is an example of an I/O device. |
49 | |
50 | Example (write binary data to a stream): |
51 | |
52 | \snippet code/src_corelib_io_qdatastream.cpp 0 |
53 | |
54 | Example (read binary data from a stream): |
55 | |
56 | \snippet code/src_corelib_io_qdatastream.cpp 1 |
57 | |
58 | Each item written to the stream is written in a predefined binary |
59 | format that varies depending on the item's type. Supported Qt |
60 | types include QBrush, QColor, QDateTime, QFont, QPixmap, QString, |
61 | QVariant and many others. For the complete list of all Qt types |
62 | supporting data streaming see \l{Serializing Qt Data Types}. |
63 | |
64 | For integers it is best to always cast to a Qt integer type for |
65 | writing, and to read back into the same Qt integer type. This |
66 | ensures that you get integers of the size you want and insulates |
67 | you from compiler and platform differences. |
68 | |
69 | Enumerations can be serialized through QDataStream without the |
70 | need of manually defining streaming operators. Enum classes are |
71 | serialized using the declared size. |
72 | |
73 | The initial I/O device is usually set in the constructor, but can be |
74 | changed with setDevice(). If you've reached the end of the data |
75 | (or if there is no I/O device set) atEnd() will return true. |
76 | |
77 | \section1 Serializing containers and strings |
78 | |
79 | The serialization format is a length specifier first, then \a l bytes of data. |
80 | The length specifier is one quint32 if the version is less than 6.7 or if the |
81 | number of elements is less than 0xfffffffe (2^32 -2). Otherwise there is |
82 | an extend value 0xfffffffe followed by one quint64 with the actual value. |
83 | In addition for containers that support isNull(), it is encoded as a single |
84 | quint32 with all bits set and no data. |
85 | |
86 | To take one example, if the string size fits into 32 bits, a \c{char *} string |
87 | is written as a 32-bit integer equal to the length of the string, including |
88 | the '\\0' byte, followed by all the characters of the string, including the |
89 | '\\0' byte. If the string size is greater, the value 0xffffffffe is written |
90 | as a marker of an extended size, followed by 64 bits of the actual size. |
91 | When reading a \c {char *} string, 4 bytes are read first. If the value is |
92 | not equal to 0xffffffffe (the marker of extended size), then these 4 bytes |
93 | are treated as the 32 bit size of the string. Otherwise, the next 8 bytes are |
94 | read and treated as a 64 bit size of the string. Then, all the characters for |
95 | the \c {char *} string, including the '\\0' terminator, are read. |
96 | |
97 | \section1 Versioning |
98 | |
99 | QDataStream's binary format has evolved since Qt 1.0, and is |
100 | likely to continue evolving to reflect changes done in Qt. When |
101 | inputting or outputting complex types, it's very important to |
102 | make sure that the same version of the stream (version()) is used |
103 | for reading and writing. If you need both forward and backward |
104 | compatibility, you can hardcode the version number in the |
105 | application: |
106 | |
107 | \snippet code/src_corelib_io_qdatastream.cpp 2 |
108 | |
109 | If you are producing a new binary data format, such as a file |
110 | format for documents created by your application, you could use a |
111 | QDataStream to write the data in a portable format. Typically, you |
112 | would write a brief header containing a magic string and a version |
113 | number to give yourself room for future expansion. For example: |
114 | |
115 | \snippet code/src_corelib_io_qdatastream.cpp 3 |
116 | |
117 | Then read it in with: |
118 | |
119 | \snippet code/src_corelib_io_qdatastream.cpp 4 |
120 | |
121 | You can select which byte order to use when serializing data. The |
122 | default setting is big-endian (MSB first). Changing it to little-endian |
123 | breaks the portability (unless the reader also changes to |
124 | little-endian). We recommend keeping this setting unless you have |
125 | special requirements. |
126 | |
127 | \target raw |
128 | \section1 Reading and Writing Raw Binary Data |
129 | |
130 | You may wish to read/write your own raw binary data to/from the |
131 | data stream directly. Data may be read from the stream into a |
132 | preallocated \c{char *} using readRawData(). Similarly data can be |
133 | written to the stream using writeRawData(). Note that any |
134 | encoding/decoding of the data must be done by you. |
135 | |
136 | A similar pair of functions is readBytes() and writeBytes(). These |
137 | differ from their \e raw counterparts as follows: readBytes() |
138 | reads a quint32 which is taken to be the length of the data to be |
139 | read, then that number of bytes is read into the preallocated |
140 | \c{char *}; writeBytes() writes a quint32 containing the length of the |
141 | data, followed by the data. Note that any encoding/decoding of |
142 | the data (apart from the length quint32) must be done by you. |
143 | |
144 | \section1 Reading and Writing Qt Collection Classes |
145 | |
146 | The Qt container classes can also be serialized to a QDataStream. |
147 | These include QList, QSet, QHash, and QMap. |
148 | The stream operators are declared as non-members of the classes. |
149 | |
150 | \target Serializing Qt Classes |
151 | \section1 Reading and Writing Other Qt Classes |
152 | |
153 | In addition to the overloaded stream operators documented here, |
154 | any Qt classes that you might want to serialize to a QDataStream |
155 | will have appropriate stream operators declared as non-member of |
156 | the class: |
157 | |
158 | \snippet code/src_corelib_serialization_qdatastream.cpp 0 |
159 | |
160 | For example, here are the stream operators declared as non-members |
161 | of the QImage class: |
162 | |
163 | \snippet code/src_corelib_serialization_qdatastream.cpp 1 |
164 | |
165 | To see if your favorite Qt class has similar stream operators |
166 | defined, check the \b {Related Non-Members} section of the |
167 | class's documentation page. |
168 | |
169 | \section1 Using Read Transactions |
170 | |
171 | When a data stream operates on an asynchronous device, the chunks of data |
172 | can arrive at arbitrary points in time. The QDataStream class implements |
173 | a transaction mechanism that provides the ability to read the data |
174 | atomically with a series of stream operators. As an example, you can |
175 | handle incomplete reads from a socket by using a transaction in a slot |
176 | connected to the readyRead() signal: |
177 | |
178 | \snippet code/src_corelib_io_qdatastream.cpp 6 |
179 | |
180 | If no full packet is received, this code restores the stream to the |
181 | initial position, after which you need to wait for more data to arrive. |
182 | |
183 | \section1 Corruption and Security |
184 | |
185 | QDataStream is not resilient against corrupted data inputs and should |
186 | therefore not be used for security-sensitive situations, even when using |
187 | transactions. Transactions will help determine if a valid input can |
188 | currently be decoded with the data currently available on an asynchronous |
189 | device, but will assume that the data that is available is correctly |
190 | formed. |
191 | |
192 | Additionally, many QDataStream demarshalling operators will allocate memory |
193 | based on information found in the stream. Those operators perform no |
194 | verification on whether the requested amount of memory is reasonable or if |
195 | it is compatible with the amount of data available in the stream (example: |
196 | demarshalling a QByteArray or QString may see the request for allocation of |
197 | several gigabytes of data). |
198 | |
199 | QDataStream should not be used on content whose provenance cannot be |
200 | trusted. Applications should be designed to attempt to decode only streams |
201 | whose provenance is at least as trustworthy as that of the application |
202 | itself or its plugins. |
203 | |
204 | \sa QTextStream, QVariant |
205 | */ |
206 | |
207 | /*! |
208 | \enum QDataStream::ByteOrder |
209 | |
210 | The byte order used for reading/writing the data. |
211 | |
212 | \value BigEndian Most significant byte first (the default) |
213 | \value LittleEndian Least significant byte first |
214 | */ |
215 | |
216 | /*! |
217 | \enum QDataStream::FloatingPointPrecision |
218 | |
219 | The precision of floating point numbers used for reading/writing the data. This will only have |
220 | an effect if the version of the data stream is Qt_4_6 or higher. |
221 | |
222 | \warning The floating point precision must be set to the same value on the object that writes |
223 | and the object that reads the data stream. |
224 | |
225 | \value SinglePrecision All floating point numbers in the data stream have 32-bit precision. |
226 | \value DoublePrecision All floating point numbers in the data stream have 64-bit precision. |
227 | |
228 | \sa setFloatingPointPrecision(), floatingPointPrecision() |
229 | */ |
230 | |
231 | /*! |
232 | \enum QDataStream::Status |
233 | |
234 | This enum describes the current status of the data stream. |
235 | |
236 | \value Ok The data stream is operating normally. |
237 | \value ReadPastEnd The data stream has read past the end of the |
238 | data in the underlying device. |
239 | \value ReadCorruptData The data stream has read corrupt data. |
240 | \value WriteFailed The data stream cannot write to the underlying device. |
241 | \value [since 6.7] SizeLimitExceeded The data stream cannot read or write |
242 | the data because its size is larger than supported |
243 | by the current platform. This can happen, for |
244 | example, when trying to read more that 2 GiB of |
245 | data on a 32-bit platform. |
246 | */ |
247 | |
248 | /***************************************************************************** |
249 | QDataStream member functions |
250 | *****************************************************************************/ |
251 | |
252 | #define Q_VOID |
253 | |
254 | #undef CHECK_STREAM_PRECOND |
255 | #ifndef QT_NO_DEBUG |
256 | #define CHECK_STREAM_PRECOND(retVal) \ |
257 | if (!dev) { \ |
258 | qWarning("QDataStream: No device"); \ |
259 | return retVal; \ |
260 | } |
261 | #else |
262 | #define CHECK_STREAM_PRECOND(retVal) \ |
263 | if (!dev) { \ |
264 | return retVal; \ |
265 | } |
266 | #endif |
267 | |
268 | #define CHECK_STREAM_WRITE_PRECOND(retVal) \ |
269 | CHECK_STREAM_PRECOND(retVal) \ |
270 | if (q_status != Ok) \ |
271 | return retVal; |
272 | |
273 | #define CHECK_STREAM_TRANSACTION_PRECOND(retVal) \ |
274 | if (transactionDepth == 0) { \ |
275 | qWarning("QDataStream: No transaction in progress"); \ |
276 | return retVal; \ |
277 | } |
278 | |
279 | /*! |
280 | Constructs a data stream that has no I/O device. |
281 | |
282 | \sa setDevice() |
283 | */ |
284 | |
285 | QDataStream::QDataStream() |
286 | { |
287 | } |
288 | |
289 | /*! |
290 | Constructs a data stream that uses the I/O device \a d. |
291 | |
292 | \sa setDevice(), device() |
293 | */ |
294 | |
295 | QDataStream::QDataStream(QIODevice *d) |
296 | { |
297 | dev = d; // set device |
298 | } |
299 | |
300 | /*! |
301 | \fn QDataStream::QDataStream(QByteArray *a, OpenMode mode) |
302 | |
303 | Constructs a data stream that operates on a byte array, \a a. The |
304 | \a mode describes how the device is to be used. |
305 | |
306 | Alternatively, you can use QDataStream(const QByteArray &) if you |
307 | just want to read from a byte array. |
308 | |
309 | Since QByteArray is not a QIODevice subclass, internally a QBuffer |
310 | is created to wrap the byte array. |
311 | */ |
312 | |
313 | QDataStream::QDataStream(QByteArray *a, OpenMode flags) |
314 | { |
315 | QBuffer *buf = new QBuffer(a); |
316 | #ifndef QT_NO_QOBJECT |
317 | buf->blockSignals(b: true); |
318 | #endif |
319 | buf->open(openMode: flags); |
320 | dev = buf; |
321 | owndev = true; |
322 | } |
323 | |
324 | /*! |
325 | Constructs a read-only data stream that operates on byte array \a a. |
326 | Use QDataStream(QByteArray*, int) if you want to write to a byte |
327 | array. |
328 | |
329 | Since QByteArray is not a QIODevice subclass, internally a QBuffer |
330 | is created to wrap the byte array. |
331 | */ |
332 | QDataStream::QDataStream(const QByteArray &a) |
333 | { |
334 | QBuffer *buf = new QBuffer; |
335 | #ifndef QT_NO_QOBJECT |
336 | buf->blockSignals(b: true); |
337 | #endif |
338 | buf->setData(a); |
339 | buf->open(openMode: QIODevice::ReadOnly); |
340 | dev = buf; |
341 | owndev = true; |
342 | } |
343 | |
344 | /*! |
345 | Destroys the data stream. |
346 | |
347 | The destructor will not affect the current I/O device, unless it is |
348 | an internal I/O device (e.g. a QBuffer) processing a QByteArray |
349 | passed in the \e constructor, in which case the internal I/O device |
350 | is destroyed. |
351 | */ |
352 | |
353 | QDataStream::~QDataStream() |
354 | { |
355 | if (owndev) |
356 | delete dev; |
357 | } |
358 | |
359 | |
360 | /*! |
361 | \fn QIODevice *QDataStream::device() const |
362 | |
363 | Returns the I/O device currently set, or \nullptr if no |
364 | device is currently set. |
365 | |
366 | \sa setDevice() |
367 | */ |
368 | |
369 | /*! |
370 | void QDataStream::setDevice(QIODevice *d) |
371 | |
372 | Sets the I/O device to \a d, which can be \nullptr |
373 | to unset to current I/O device. |
374 | |
375 | \sa device() |
376 | */ |
377 | |
378 | void QDataStream::setDevice(QIODevice *d) |
379 | { |
380 | if (owndev) { |
381 | delete dev; |
382 | owndev = false; |
383 | } |
384 | dev = d; |
385 | } |
386 | |
387 | /*! |
388 | \fn bool QDataStream::atEnd() const |
389 | |
390 | Returns \c true if the I/O device has reached the end position (end of |
391 | the stream or file) or if there is no I/O device set; otherwise |
392 | returns \c false. |
393 | |
394 | \sa QIODevice::atEnd() |
395 | */ |
396 | |
397 | bool QDataStream::atEnd() const |
398 | { |
399 | return dev ? dev->atEnd() : true; |
400 | } |
401 | |
402 | /*! |
403 | \fn QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const |
404 | |
405 | Returns the floating point precision of the data stream. |
406 | |
407 | \since 4.6 |
408 | |
409 | \sa FloatingPointPrecision, setFloatingPointPrecision() |
410 | */ |
411 | |
412 | /*! |
413 | Sets the floating point precision of the data stream to \a precision. If the floating point precision is |
414 | DoublePrecision and the version of the data stream is Qt_4_6 or higher, all floating point |
415 | numbers will be written and read with 64-bit precision. If the floating point precision is |
416 | SinglePrecision and the version is Qt_4_6 or higher, all floating point numbers will be written |
417 | and read with 32-bit precision. |
418 | |
419 | For versions prior to Qt_4_6, the precision of floating point numbers in the data stream depends |
420 | on the stream operator called. |
421 | |
422 | The default is DoublePrecision. |
423 | |
424 | Note that this property does not affect the serialization or deserialization of \c qfloat16 |
425 | instances. |
426 | |
427 | \warning This property must be set to the same value on the object that writes and the object |
428 | that reads the data stream. |
429 | |
430 | \since 4.6 |
431 | */ |
432 | void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision) |
433 | { |
434 | fpPrecision = precision; |
435 | } |
436 | |
437 | /*! |
438 | \fn QDataStream::status() const |
439 | |
440 | Returns the status of the data stream. |
441 | |
442 | \sa Status, setStatus(), resetStatus() |
443 | */ |
444 | |
445 | /*! |
446 | Resets the status of the data stream. |
447 | |
448 | \sa Status, status(), setStatus() |
449 | */ |
450 | void QDataStream::resetStatus() |
451 | { |
452 | q_status = Ok; |
453 | } |
454 | |
455 | /*! |
456 | Sets the status of the data stream to the \a status given. |
457 | |
458 | Subsequent calls to setStatus() are ignored until resetStatus() |
459 | is called. |
460 | |
461 | \sa Status, status(), resetStatus() |
462 | */ |
463 | void QDataStream::setStatus(Status status) |
464 | { |
465 | if (q_status == Ok) |
466 | q_status = status; |
467 | } |
468 | |
469 | /*! |
470 | \fn int QDataStream::byteOrder() const |
471 | |
472 | Returns the current byte order setting -- either BigEndian or |
473 | LittleEndian. |
474 | |
475 | \sa setByteOrder() |
476 | */ |
477 | |
478 | /*! |
479 | Sets the serialization byte order to \a bo. |
480 | |
481 | The \a bo parameter can be QDataStream::BigEndian or |
482 | QDataStream::LittleEndian. |
483 | |
484 | The default setting is big-endian. We recommend leaving this |
485 | setting unless you have special requirements. |
486 | |
487 | \sa byteOrder() |
488 | */ |
489 | |
490 | void QDataStream::setByteOrder(ByteOrder bo) |
491 | { |
492 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) |
493 | // accessed by inline byteOrder() prior to Qt 6.8 |
494 | byteorder = bo; |
495 | #endif |
496 | if (QSysInfo::ByteOrder == QSysInfo::BigEndian) |
497 | noswap = (bo == BigEndian); |
498 | else |
499 | noswap = (bo == LittleEndian); |
500 | } |
501 | |
502 | |
503 | /*! |
504 | \enum QDataStream::Version |
505 | |
506 | This enum provides symbolic synonyms for the data serialization |
507 | format version numbers. |
508 | |
509 | \value Qt_1_0 Version 1 (Qt 1.x) |
510 | \value Qt_2_0 Version 2 (Qt 2.0) |
511 | \value Qt_2_1 Version 3 (Qt 2.1, 2.2, 2.3) |
512 | \value Qt_3_0 Version 4 (Qt 3.0) |
513 | \value Qt_3_1 Version 5 (Qt 3.1, 3.2) |
514 | \value Qt_3_3 Version 6 (Qt 3.3) |
515 | \value Qt_4_0 Version 7 (Qt 4.0, Qt 4.1) |
516 | \value Qt_4_1 Version 7 (Qt 4.0, Qt 4.1) |
517 | \value Qt_4_2 Version 8 (Qt 4.2) |
518 | \value Qt_4_3 Version 9 (Qt 4.3) |
519 | \value Qt_4_4 Version 10 (Qt 4.4) |
520 | \value Qt_4_5 Version 11 (Qt 4.5) |
521 | \value Qt_4_6 Version 12 (Qt 4.6, Qt 4.7, Qt 4.8) |
522 | \value Qt_4_7 Same as Qt_4_6. |
523 | \value Qt_4_8 Same as Qt_4_6. |
524 | \value Qt_4_9 Same as Qt_4_6. |
525 | \value Qt_5_0 Version 13 (Qt 5.0) |
526 | \value Qt_5_1 Version 14 (Qt 5.1) |
527 | \value Qt_5_2 Version 15 (Qt 5.2) |
528 | \value Qt_5_3 Same as Qt_5_2 |
529 | \value Qt_5_4 Version 16 (Qt 5.4) |
530 | \value Qt_5_5 Same as Qt_5_4 |
531 | \value Qt_5_6 Version 17 (Qt 5.6) |
532 | \value Qt_5_7 Same as Qt_5_6 |
533 | \value Qt_5_8 Same as Qt_5_6 |
534 | \value Qt_5_9 Same as Qt_5_6 |
535 | \value Qt_5_10 Same as Qt_5_6 |
536 | \value Qt_5_11 Same as Qt_5_6 |
537 | \value Qt_5_12 Version 18 (Qt 5.12) |
538 | \value Qt_5_13 Version 19 (Qt 5.13) |
539 | \value Qt_5_14 Same as Qt_5_13 |
540 | \value Qt_5_15 Same as Qt_5_13 |
541 | \value Qt_6_0 Version 20 (Qt 6.0) |
542 | \value Qt_6_1 Same as Qt_6_0 |
543 | \value Qt_6_2 Same as Qt_6_0 |
544 | \value Qt_6_3 Same as Qt_6_0 |
545 | \value Qt_6_4 Same as Qt_6_0 |
546 | \value Qt_6_5 Same as Qt_6_0 |
547 | \value Qt_6_6 Version 21 (Qt 6.6) |
548 | \value Qt_6_7 Version 22 (Qt 6.7) |
549 | \value Qt_6_8 Same as Qt_6_7 |
550 | \omitvalue Qt_DefaultCompiledVersion |
551 | |
552 | \sa setVersion(), version() |
553 | */ |
554 | |
555 | /*! |
556 | \fn int QDataStream::version() const |
557 | |
558 | Returns the version number of the data serialization format. |
559 | |
560 | \sa setVersion(), Version |
561 | */ |
562 | |
563 | /*! |
564 | \fn void QDataStream::setVersion(int v) |
565 | |
566 | Sets the version number of the data serialization format to \a v, |
567 | a value of the \l Version enum. |
568 | |
569 | You don't \e have to set a version if you are using the current |
570 | version of Qt, but for your own custom binary formats we |
571 | recommend that you do; see \l{Versioning} in the Detailed |
572 | Description. |
573 | |
574 | To accommodate new functionality, the datastream serialization |
575 | format of some Qt classes has changed in some versions of Qt. If |
576 | you want to read data that was created by an earlier version of |
577 | Qt, or write data that can be read by a program that was compiled |
578 | with an earlier version of Qt, use this function to modify the |
579 | serialization format used by QDataStream. |
580 | |
581 | The \l Version enum provides symbolic constants for the different |
582 | versions of Qt. For example: |
583 | |
584 | \snippet code/src_corelib_io_qdatastream.cpp 5 |
585 | |
586 | \sa version(), Version |
587 | */ |
588 | |
589 | /*! |
590 | \since 5.7 |
591 | |
592 | Starts a new read transaction on the stream. |
593 | |
594 | Defines a restorable point within the sequence of read operations. For |
595 | sequential devices, read data will be duplicated internally to allow |
596 | recovery in case of incomplete reads. For random-access devices, |
597 | this function saves the current position of the stream. Call |
598 | commitTransaction(), rollbackTransaction(), or abortTransaction() to |
599 | finish the current transaction. |
600 | |
601 | Once a transaction is started, subsequent calls to this function will make |
602 | the transaction recursive. Inner transactions act as agents of the |
603 | outermost transaction (i.e., report the status of read operations to the |
604 | outermost transaction, which can restore the position of the stream). |
605 | |
606 | \note Restoring to the point of the nested startTransaction() call is not |
607 | supported. |
608 | |
609 | When an error occurs during a transaction (including an inner transaction |
610 | failing), reading from the data stream is suspended (all subsequent read |
611 | operations return empty/zero values) and subsequent inner transactions are |
612 | forced to fail. Starting a new outermost transaction recovers from this |
613 | state. This behavior makes it unnecessary to error-check every read |
614 | operation separately. |
615 | |
616 | \sa commitTransaction(), rollbackTransaction(), abortTransaction() |
617 | */ |
618 | |
619 | void QDataStream::startTransaction() |
620 | { |
621 | CHECK_STREAM_PRECOND(Q_VOID) |
622 | |
623 | if (++transactionDepth == 1) { |
624 | dev->startTransaction(); |
625 | resetStatus(); |
626 | } |
627 | } |
628 | |
629 | /*! |
630 | \since 5.7 |
631 | |
632 | Completes a read transaction. Returns \c true if no read errors have |
633 | occurred during the transaction; otherwise returns \c false. |
634 | |
635 | If called on an inner transaction, committing will be postponed until |
636 | the outermost commitTransaction(), rollbackTransaction(), or |
637 | abortTransaction() call occurs. |
638 | |
639 | Otherwise, if the stream status indicates reading past the end of the |
640 | data, this function restores the stream data to the point of the |
641 | startTransaction() call. When this situation occurs, you need to wait for |
642 | more data to arrive, after which you start a new transaction. If the data |
643 | stream has read corrupt data or any of the inner transactions was aborted, |
644 | this function aborts the transaction. |
645 | |
646 | \sa startTransaction(), rollbackTransaction(), abortTransaction() |
647 | */ |
648 | |
649 | bool QDataStream::commitTransaction() |
650 | { |
651 | CHECK_STREAM_TRANSACTION_PRECOND(false) |
652 | if (--transactionDepth == 0) { |
653 | CHECK_STREAM_PRECOND(false) |
654 | |
655 | if (q_status == ReadPastEnd) { |
656 | dev->rollbackTransaction(); |
657 | return false; |
658 | } |
659 | dev->commitTransaction(); |
660 | } |
661 | return q_status == Ok; |
662 | } |
663 | |
664 | /*! |
665 | \since 5.7 |
666 | |
667 | Reverts a read transaction. |
668 | |
669 | This function is commonly used to rollback the transaction when an |
670 | incomplete read was detected prior to committing the transaction. |
671 | |
672 | If called on an inner transaction, reverting is delegated to the outermost |
673 | transaction, and subsequently started inner transactions are forced to |
674 | fail. |
675 | |
676 | For the outermost transaction, restores the stream data to the point of |
677 | the startTransaction() call. If the data stream has read corrupt data or |
678 | any of the inner transactions was aborted, this function aborts the |
679 | transaction. |
680 | |
681 | If the preceding stream operations were successful, sets the status of the |
682 | data stream to \value ReadPastEnd. |
683 | |
684 | \sa startTransaction(), commitTransaction(), abortTransaction() |
685 | */ |
686 | |
687 | void QDataStream::rollbackTransaction() |
688 | { |
689 | setStatus(ReadPastEnd); |
690 | |
691 | CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID) |
692 | if (--transactionDepth != 0) |
693 | return; |
694 | |
695 | CHECK_STREAM_PRECOND(Q_VOID) |
696 | if (q_status == ReadPastEnd) |
697 | dev->rollbackTransaction(); |
698 | else |
699 | dev->commitTransaction(); |
700 | } |
701 | |
702 | /*! |
703 | \since 5.7 |
704 | |
705 | Aborts a read transaction. |
706 | |
707 | This function is commonly used to discard the transaction after |
708 | higher-level protocol errors or loss of stream synchronization. |
709 | |
710 | If called on an inner transaction, aborting is delegated to the outermost |
711 | transaction, and subsequently started inner transactions are forced to |
712 | fail. |
713 | |
714 | For the outermost transaction, discards the restoration point and any |
715 | internally duplicated data of the stream. Will not affect the current |
716 | read position of the stream. |
717 | |
718 | Sets the status of the data stream to \value ReadCorruptData. |
719 | |
720 | \sa startTransaction(), commitTransaction(), rollbackTransaction() |
721 | */ |
722 | |
723 | void QDataStream::abortTransaction() |
724 | { |
725 | q_status = ReadCorruptData; |
726 | |
727 | CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID) |
728 | if (--transactionDepth != 0) |
729 | return; |
730 | |
731 | CHECK_STREAM_PRECOND(Q_VOID) |
732 | dev->commitTransaction(); |
733 | } |
734 | |
735 | /*! |
736 | \internal |
737 | */ |
738 | bool QDataStream::isDeviceTransactionStarted() const |
739 | { |
740 | return dev && dev->isTransactionStarted(); |
741 | } |
742 | |
743 | /***************************************************************************** |
744 | QDataStream read functions |
745 | *****************************************************************************/ |
746 | |
747 | /*! |
748 | \internal |
749 | */ |
750 | |
751 | qint64 QDataStream::readBlock(char *data, qint64 len) |
752 | { |
753 | // Disable reads on failure in transacted stream |
754 | if (q_status != Ok && dev->isTransactionStarted()) |
755 | return -1; |
756 | |
757 | const qint64 readResult = dev->read(data, maxlen: len); |
758 | if (readResult != len) |
759 | setStatus(ReadPastEnd); |
760 | return readResult; |
761 | } |
762 | |
763 | /*! |
764 | \fn QDataStream &QDataStream::operator>>(std::nullptr_t &ptr) |
765 | \since 5.9 |
766 | \overload |
767 | |
768 | Simulates reading a \c{std::nullptr_t} from the stream into \a ptr and |
769 | returns a reference to the stream. This function does not actually read |
770 | anything from the stream, as \c{std::nullptr_t} values are stored as 0 |
771 | bytes. |
772 | */ |
773 | |
774 | /*! |
775 | \fn QDataStream &QDataStream::operator>>(quint8 &i) |
776 | \overload |
777 | |
778 | Reads an unsigned byte from the stream into \a i, and returns a |
779 | reference to the stream. |
780 | */ |
781 | |
782 | /*! |
783 | Reads a signed byte from the stream into \a i, and returns a |
784 | reference to the stream. |
785 | */ |
786 | |
787 | QDataStream &QDataStream::operator>>(qint8 &i) |
788 | { |
789 | i = 0; |
790 | CHECK_STREAM_PRECOND(*this) |
791 | char c; |
792 | if (readBlock(data: &c, len: 1) == 1) |
793 | i = qint8(c); |
794 | return *this; |
795 | } |
796 | |
797 | |
798 | /*! |
799 | \fn QDataStream &QDataStream::operator>>(quint16 &i) |
800 | \overload |
801 | |
802 | Reads an unsigned 16-bit integer from the stream into \a i, and |
803 | returns a reference to the stream. |
804 | */ |
805 | |
806 | /*! |
807 | \overload |
808 | |
809 | Reads a signed 16-bit integer from the stream into \a i, and |
810 | returns a reference to the stream. |
811 | */ |
812 | |
813 | QDataStream &QDataStream::operator>>(qint16 &i) |
814 | { |
815 | i = 0; |
816 | CHECK_STREAM_PRECOND(*this) |
817 | if (readBlock(data: reinterpret_cast<char *>(&i), len: 2) != 2) { |
818 | i = 0; |
819 | } else { |
820 | if (!noswap) { |
821 | i = qbswap(source: i); |
822 | } |
823 | } |
824 | return *this; |
825 | } |
826 | |
827 | |
828 | /*! |
829 | \fn QDataStream &QDataStream::operator>>(quint32 &i) |
830 | \overload |
831 | |
832 | Reads an unsigned 32-bit integer from the stream into \a i, and |
833 | returns a reference to the stream. |
834 | */ |
835 | |
836 | /*! |
837 | \overload |
838 | |
839 | Reads a signed 32-bit integer from the stream into \a i, and |
840 | returns a reference to the stream. |
841 | */ |
842 | |
843 | QDataStream &QDataStream::operator>>(qint32 &i) |
844 | { |
845 | i = 0; |
846 | CHECK_STREAM_PRECOND(*this) |
847 | if (readBlock(data: reinterpret_cast<char *>(&i), len: 4) != 4) { |
848 | i = 0; |
849 | } else { |
850 | if (!noswap) { |
851 | i = qbswap(source: i); |
852 | } |
853 | } |
854 | return *this; |
855 | } |
856 | |
857 | /*! |
858 | \fn QDataStream &QDataStream::operator>>(quint64 &i) |
859 | \overload |
860 | |
861 | Reads an unsigned 64-bit integer from the stream, into \a i, and |
862 | returns a reference to the stream. |
863 | */ |
864 | |
865 | /*! |
866 | \overload |
867 | |
868 | Reads a signed 64-bit integer from the stream into \a i, and |
869 | returns a reference to the stream. |
870 | */ |
871 | |
872 | QDataStream &QDataStream::operator>>(qint64 &i) |
873 | { |
874 | i = qint64(0); |
875 | CHECK_STREAM_PRECOND(*this) |
876 | if (version() < 6) { |
877 | quint32 i1, i2; |
878 | *this >> i2 >> i1; |
879 | i = ((quint64)i1 << 32) + i2; |
880 | } else { |
881 | if (readBlock(data: reinterpret_cast<char *>(&i), len: 8) != 8) { |
882 | i = qint64(0); |
883 | } else { |
884 | if (!noswap) { |
885 | i = qbswap(source: i); |
886 | } |
887 | } |
888 | } |
889 | return *this; |
890 | } |
891 | |
892 | /*! |
893 | Reads a boolean value from the stream into \a i. Returns a |
894 | reference to the stream. |
895 | */ |
896 | QDataStream &QDataStream::operator>>(bool &i) |
897 | { |
898 | qint8 v; |
899 | *this >> v; |
900 | i = !!v; |
901 | return *this; |
902 | } |
903 | |
904 | /*! |
905 | \overload |
906 | |
907 | Reads a floating point number from the stream into \a f, |
908 | using the standard IEEE 754 format. Returns a reference to the |
909 | stream. |
910 | |
911 | \sa setFloatingPointPrecision() |
912 | */ |
913 | |
914 | QDataStream &QDataStream::operator>>(float &f) |
915 | { |
916 | if (version() >= QDataStream::Qt_4_6 |
917 | && floatingPointPrecision() == QDataStream::DoublePrecision) { |
918 | double d; |
919 | *this >> d; |
920 | f = d; |
921 | return *this; |
922 | } |
923 | |
924 | f = 0.0f; |
925 | CHECK_STREAM_PRECOND(*this) |
926 | if (readBlock(data: reinterpret_cast<char *>(&f), len: 4) != 4) { |
927 | f = 0.0f; |
928 | } else { |
929 | if (!noswap) { |
930 | union { |
931 | float val1; |
932 | quint32 val2; |
933 | } x; |
934 | x.val2 = qbswap(source: *reinterpret_cast<quint32 *>(&f)); |
935 | f = x.val1; |
936 | } |
937 | } |
938 | return *this; |
939 | } |
940 | |
941 | /*! |
942 | \overload |
943 | |
944 | Reads a floating point number from the stream into \a f, |
945 | using the standard IEEE 754 format. Returns a reference to the |
946 | stream. |
947 | |
948 | \sa setFloatingPointPrecision() |
949 | */ |
950 | |
951 | QDataStream &QDataStream::operator>>(double &f) |
952 | { |
953 | if (version() >= QDataStream::Qt_4_6 |
954 | && floatingPointPrecision() == QDataStream::SinglePrecision) { |
955 | float d; |
956 | *this >> d; |
957 | f = d; |
958 | return *this; |
959 | } |
960 | |
961 | f = 0.0; |
962 | CHECK_STREAM_PRECOND(*this) |
963 | if (readBlock(data: reinterpret_cast<char *>(&f), len: 8) != 8) { |
964 | f = 0.0; |
965 | } else { |
966 | if (!noswap) { |
967 | union { |
968 | double val1; |
969 | quint64 val2; |
970 | } x; |
971 | x.val2 = qbswap(source: *reinterpret_cast<quint64 *>(&f)); |
972 | f = x.val1; |
973 | } |
974 | } |
975 | return *this; |
976 | } |
977 | |
978 | |
979 | /*! |
980 | \overload |
981 | |
982 | Reads string \a s from the stream and returns a reference to the stream. |
983 | |
984 | The string is deserialized using \c{readBytes()} where the serialization |
985 | format is a \c quint32 length specifier first, followed by that many bytes |
986 | of data. The resulting string is always '\\0'-terminated. |
987 | |
988 | Space for the string is allocated using \c{new []} -- the caller must |
989 | destroy it with \c{delete []}. |
990 | |
991 | \sa readBytes(), readRawData() |
992 | */ |
993 | |
994 | QDataStream &QDataStream::operator>>(char *&s) |
995 | { |
996 | qint64 len = 0; |
997 | return readBytes(s, len); |
998 | } |
999 | |
1000 | /*! |
1001 | \overload |
1002 | \since 6.0 |
1003 | |
1004 | Reads a 16bit wide char from the stream into \a c and |
1005 | returns a reference to the stream. |
1006 | */ |
1007 | QDataStream &QDataStream::operator>>(char16_t &c) |
1008 | { |
1009 | quint16 u; |
1010 | *this >> u; |
1011 | c = char16_t(u); |
1012 | return *this; |
1013 | } |
1014 | |
1015 | /*! |
1016 | \overload |
1017 | \since 6.0 |
1018 | |
1019 | Reads a 32bit wide character from the stream into \a c and |
1020 | returns a reference to the stream. |
1021 | */ |
1022 | QDataStream &QDataStream::operator>>(char32_t &c) |
1023 | { |
1024 | quint32 u; |
1025 | *this >> u; |
1026 | c = char32_t(u); |
1027 | return *this; |
1028 | } |
1029 | |
1030 | #if QT_DEPRECATED_SINCE(6, 11) |
1031 | |
1032 | /*! |
1033 | \deprecated [6.11] Use an overload that takes qint64 length instead. |
1034 | */ |
1035 | QDataStream &QDataStream::readBytes(char *&s, uint &l) |
1036 | { |
1037 | qint64 length = 0; |
1038 | (void)readBytes(s, len&: length); |
1039 | if (length != qint64(uint(length))) { |
1040 | setStatus(SizeLimitExceeded); // Cannot store length in l |
1041 | delete[] s; |
1042 | l = 0; |
1043 | return *this; |
1044 | } |
1045 | l = uint(length); |
1046 | return *this; |
1047 | } |
1048 | |
1049 | #endif // QT_DEPRECATED_SINCE(6, 11) |
1050 | |
1051 | /*! |
1052 | \since 6.7 |
1053 | Reads the buffer \a s from the stream and returns a reference to |
1054 | the stream. |
1055 | |
1056 | The buffer \a s is allocated using \c{new []}. Destroy it with the |
1057 | \c{delete []} operator. |
1058 | |
1059 | The \a l parameter is set to the length of the buffer. If the |
1060 | string read is empty, \a l is set to 0 and \a s is set to \nullptr. |
1061 | |
1062 | The serialization format is a length specifier first, then \a l |
1063 | bytes of data. The length specifier is one quint32 if the version |
1064 | is less than 6.7 or if the number of elements is less than 0xfffffffe |
1065 | (2^32 -2), otherwise there is an extend value 0xfffffffe followed by |
1066 | one quint64 with the actual value. In addition for containers that |
1067 | support isNull(), it is encoded as a single quint32 with all bits |
1068 | set and no data. |
1069 | |
1070 | \sa readRawData(), writeBytes() |
1071 | */ |
1072 | |
1073 | QDataStream &QDataStream::readBytes(char *&s, qint64 &l) |
1074 | { |
1075 | s = nullptr; |
1076 | l = 0; |
1077 | CHECK_STREAM_PRECOND(*this) |
1078 | |
1079 | qint64 length = readQSizeType(s&: *this); |
1080 | if (length == 0) |
1081 | return *this; |
1082 | |
1083 | qsizetype len = qsizetype(length); |
1084 | if (length != len || length < 0) { |
1085 | setStatus(SizeLimitExceeded); // Cannot store len |
1086 | return *this; |
1087 | } |
1088 | |
1089 | qsizetype step = (dev->bytesAvailable() >= len) ? len : 1024 * 1024; |
1090 | qsizetype allocated = 0; |
1091 | std::unique_ptr<char[]> curBuf = nullptr; |
1092 | |
1093 | constexpr qsizetype StepIncreaseThreshold = std::numeric_limits<qsizetype>::max() / 2; |
1094 | do { |
1095 | qsizetype blockSize = qMin(a: step, b: len - allocated); |
1096 | const qsizetype n = allocated + blockSize + 1; |
1097 | if (const auto prevBuf = std::exchange(obj&: curBuf, new_val: std::make_unique<char[]>(num: n))) |
1098 | memcpy(dest: curBuf.get(), src: prevBuf.get(), n: allocated); |
1099 | if (readBlock(data: curBuf.get() + allocated, len: blockSize) != blockSize) |
1100 | return *this; |
1101 | allocated += blockSize; |
1102 | if (step <= StepIncreaseThreshold) |
1103 | step *= 2; |
1104 | } while (allocated < len); |
1105 | |
1106 | s = curBuf.release(); |
1107 | s[len] = '\0'; |
1108 | l = len; |
1109 | return *this; |
1110 | } |
1111 | |
1112 | /*! |
1113 | Reads at most \a len bytes from the stream into \a s and returns the number of |
1114 | bytes read. If an error occurs, this function returns -1. |
1115 | |
1116 | The buffer \a s must be preallocated. The data is \e not decoded. |
1117 | |
1118 | \sa readBytes(), QIODevice::read(), writeRawData() |
1119 | */ |
1120 | |
1121 | qint64 QDataStream::readRawData(char *s, qint64 len) |
1122 | { |
1123 | CHECK_STREAM_PRECOND(-1) |
1124 | return readBlock(data: s, len); |
1125 | } |
1126 | |
1127 | /*! \fn template <class T1, class T2> QDataStream &operator>>(QDataStream &in, std::pair<T1, T2> &pair) |
1128 | \since 6.0 |
1129 | \relates QDataStream |
1130 | |
1131 | Reads a pair from stream \a in into \a pair. |
1132 | |
1133 | This function requires the T1 and T2 types to implement \c operator>>(). |
1134 | |
1135 | \sa {Serializing Qt Data Types} |
1136 | */ |
1137 | |
1138 | /***************************************************************************** |
1139 | QDataStream write functions |
1140 | *****************************************************************************/ |
1141 | |
1142 | /*! |
1143 | \fn QDataStream &QDataStream::operator<<(std::nullptr_t ptr) |
1144 | \since 5.9 |
1145 | \overload |
1146 | |
1147 | Simulates writing a \c{std::nullptr_t}, \a ptr, to the stream and returns a |
1148 | reference to the stream. This function does not actually write anything to |
1149 | the stream, as \c{std::nullptr_t} values are stored as 0 bytes. |
1150 | */ |
1151 | |
1152 | /*! |
1153 | \fn QDataStream &QDataStream::operator<<(quint8 i) |
1154 | \overload |
1155 | |
1156 | Writes an unsigned byte, \a i, to the stream and returns a |
1157 | reference to the stream. |
1158 | */ |
1159 | |
1160 | /*! |
1161 | Writes a signed byte, \a i, to the stream and returns a reference |
1162 | to the stream. |
1163 | */ |
1164 | |
1165 | QDataStream &QDataStream::operator<<(qint8 i) |
1166 | { |
1167 | CHECK_STREAM_WRITE_PRECOND(*this) |
1168 | if (!dev->putChar(c: i)) |
1169 | q_status = WriteFailed; |
1170 | return *this; |
1171 | } |
1172 | |
1173 | |
1174 | /*! |
1175 | \fn QDataStream &QDataStream::operator<<(quint16 i) |
1176 | \overload |
1177 | |
1178 | Writes an unsigned 16-bit integer, \a i, to the stream and returns |
1179 | a reference to the stream. |
1180 | */ |
1181 | |
1182 | /*! |
1183 | \overload |
1184 | |
1185 | Writes a signed 16-bit integer, \a i, to the stream and returns a |
1186 | reference to the stream. |
1187 | */ |
1188 | |
1189 | QDataStream &QDataStream::operator<<(qint16 i) |
1190 | { |
1191 | CHECK_STREAM_WRITE_PRECOND(*this) |
1192 | if (!noswap) { |
1193 | i = qbswap(source: i); |
1194 | } |
1195 | if (dev->write(data: (char *)&i, len: sizeof(qint16)) != sizeof(qint16)) |
1196 | q_status = WriteFailed; |
1197 | return *this; |
1198 | } |
1199 | |
1200 | /*! |
1201 | \overload |
1202 | |
1203 | Writes a signed 32-bit integer, \a i, to the stream and returns a |
1204 | reference to the stream. |
1205 | */ |
1206 | |
1207 | QDataStream &QDataStream::operator<<(qint32 i) |
1208 | { |
1209 | CHECK_STREAM_WRITE_PRECOND(*this) |
1210 | if (!noswap) { |
1211 | i = qbswap(source: i); |
1212 | } |
1213 | if (dev->write(data: (char *)&i, len: sizeof(qint32)) != sizeof(qint32)) |
1214 | q_status = WriteFailed; |
1215 | return *this; |
1216 | } |
1217 | |
1218 | /*! |
1219 | \fn QDataStream &QDataStream::operator<<(quint64 i) |
1220 | \overload |
1221 | |
1222 | Writes an unsigned 64-bit integer, \a i, to the stream and returns a |
1223 | reference to the stream. |
1224 | */ |
1225 | |
1226 | /*! |
1227 | \overload |
1228 | |
1229 | Writes a signed 64-bit integer, \a i, to the stream and returns a |
1230 | reference to the stream. |
1231 | */ |
1232 | |
1233 | QDataStream &QDataStream::operator<<(qint64 i) |
1234 | { |
1235 | CHECK_STREAM_WRITE_PRECOND(*this) |
1236 | if (version() < 6) { |
1237 | quint32 i1 = i & 0xffffffff; |
1238 | quint32 i2 = i >> 32; |
1239 | *this << i2 << i1; |
1240 | } else { |
1241 | if (!noswap) { |
1242 | i = qbswap(source: i); |
1243 | } |
1244 | if (dev->write(data: (char *)&i, len: sizeof(qint64)) != sizeof(qint64)) |
1245 | q_status = WriteFailed; |
1246 | } |
1247 | return *this; |
1248 | } |
1249 | |
1250 | /*! |
1251 | \fn QDataStream &QDataStream::operator<<(quint32 i) |
1252 | \overload |
1253 | |
1254 | Writes an unsigned integer, \a i, to the stream as a 32-bit |
1255 | unsigned integer (quint32). Returns a reference to the stream. |
1256 | */ |
1257 | |
1258 | /*! |
1259 | \fn QDataStream &QDataStream::operator<<(bool i) |
1260 | \overload |
1261 | |
1262 | Writes a boolean value, \a i, to the stream. Returns a reference |
1263 | to the stream. |
1264 | */ |
1265 | |
1266 | /*! |
1267 | \overload |
1268 | |
1269 | Writes a floating point number, \a f, to the stream using |
1270 | the standard IEEE 754 format. Returns a reference to the stream. |
1271 | |
1272 | \sa setFloatingPointPrecision() |
1273 | */ |
1274 | |
1275 | QDataStream &QDataStream::operator<<(float f) |
1276 | { |
1277 | if (version() >= QDataStream::Qt_4_6 |
1278 | && floatingPointPrecision() == QDataStream::DoublePrecision) { |
1279 | *this << double(f); |
1280 | return *this; |
1281 | } |
1282 | |
1283 | CHECK_STREAM_WRITE_PRECOND(*this) |
1284 | float g = f; // fixes float-on-stack problem |
1285 | if (!noswap) { |
1286 | union { |
1287 | float val1; |
1288 | quint32 val2; |
1289 | } x; |
1290 | x.val1 = g; |
1291 | x.val2 = qbswap(source: x.val2); |
1292 | |
1293 | if (dev->write(data: (char *)&x.val2, len: sizeof(float)) != sizeof(float)) |
1294 | q_status = WriteFailed; |
1295 | return *this; |
1296 | } |
1297 | |
1298 | if (dev->write(data: (char *)&g, len: sizeof(float)) != sizeof(float)) |
1299 | q_status = WriteFailed; |
1300 | return *this; |
1301 | } |
1302 | |
1303 | |
1304 | /*! |
1305 | \overload |
1306 | |
1307 | Writes a floating point number, \a f, to the stream using |
1308 | the standard IEEE 754 format. Returns a reference to the stream. |
1309 | |
1310 | \sa setFloatingPointPrecision() |
1311 | */ |
1312 | |
1313 | QDataStream &QDataStream::operator<<(double f) |
1314 | { |
1315 | if (version() >= QDataStream::Qt_4_6 |
1316 | && floatingPointPrecision() == QDataStream::SinglePrecision) { |
1317 | *this << float(f); |
1318 | return *this; |
1319 | } |
1320 | |
1321 | CHECK_STREAM_WRITE_PRECOND(*this) |
1322 | if (noswap) { |
1323 | if (dev->write(data: (char *)&f, len: sizeof(double)) != sizeof(double)) |
1324 | q_status = WriteFailed; |
1325 | } else { |
1326 | union { |
1327 | double val1; |
1328 | quint64 val2; |
1329 | } x; |
1330 | x.val1 = f; |
1331 | x.val2 = qbswap(source: x.val2); |
1332 | if (dev->write(data: (char *)&x.val2, len: sizeof(double)) != sizeof(double)) |
1333 | q_status = WriteFailed; |
1334 | } |
1335 | return *this; |
1336 | } |
1337 | |
1338 | |
1339 | /*! |
1340 | \overload |
1341 | |
1342 | Writes the '\\0'-terminated string \a s to the stream and returns a |
1343 | reference to the stream. |
1344 | |
1345 | The string is serialized using \c{writeBytes()}. |
1346 | |
1347 | \sa writeBytes(), writeRawData() |
1348 | */ |
1349 | |
1350 | QDataStream &QDataStream::operator<<(const char *s) |
1351 | { |
1352 | // Include null terminator, unless s itself is null |
1353 | const qint64 len = s ? qint64(qstrlen(str: s)) + 1 : 0; |
1354 | writeBytes(s, len); |
1355 | return *this; |
1356 | } |
1357 | |
1358 | /*! |
1359 | \overload |
1360 | \since 6.0 |
1361 | |
1362 | Writes a character, \a c, to the stream. Returns a reference to |
1363 | the stream |
1364 | */ |
1365 | QDataStream &QDataStream::operator<<(char16_t c) |
1366 | { |
1367 | return *this << qint16(c); |
1368 | } |
1369 | |
1370 | /*! |
1371 | \overload |
1372 | \since 6.0 |
1373 | |
1374 | Writes a character, \a c, to the stream. Returns a reference to |
1375 | the stream |
1376 | */ |
1377 | QDataStream &QDataStream::operator<<(char32_t c) |
1378 | { |
1379 | return *this << qint32(c); |
1380 | } |
1381 | |
1382 | /*! |
1383 | Writes the length specifier \a len and the buffer \a s to the |
1384 | stream and returns a reference to the stream. |
1385 | |
1386 | The \a len is serialized as a quint32 and an optional quint64, |
1387 | followed by \a len bytes from \a s. Note that the data is |
1388 | \e not encoded. |
1389 | |
1390 | \sa writeRawData(), readBytes() |
1391 | */ |
1392 | |
1393 | QDataStream &QDataStream::writeBytes(const char *s, qint64 len) |
1394 | { |
1395 | if (len < 0) { |
1396 | q_status = WriteFailed; |
1397 | return *this; |
1398 | } |
1399 | CHECK_STREAM_WRITE_PRECOND(*this) |
1400 | // Write length then, if any, content |
1401 | if (writeQSizeType(s&: *this, value: len) && len > 0) |
1402 | writeRawData(s, len); |
1403 | return *this; |
1404 | } |
1405 | |
1406 | /*! |
1407 | Writes \a len bytes from \a s to the stream. Returns the |
1408 | number of bytes actually written, or -1 on error. |
1409 | The data is \e not encoded. |
1410 | |
1411 | \sa writeBytes(), QIODevice::write(), readRawData() |
1412 | */ |
1413 | |
1414 | qint64 QDataStream::writeRawData(const char *s, qint64 len) |
1415 | { |
1416 | CHECK_STREAM_WRITE_PRECOND(-1) |
1417 | qint64 ret = dev->write(data: s, len); |
1418 | if (ret != len) |
1419 | q_status = WriteFailed; |
1420 | return ret; |
1421 | } |
1422 | |
1423 | /*! |
1424 | \since 4.1 |
1425 | |
1426 | Skips \a len bytes from the device. Returns the number of bytes |
1427 | actually skipped, or -1 on error. |
1428 | |
1429 | This is equivalent to calling readRawData() on a buffer of length |
1430 | \a len and ignoring the buffer. |
1431 | |
1432 | \sa QIODevice::seek() |
1433 | */ |
1434 | qint64 QDataStream::skipRawData(qint64 len) |
1435 | { |
1436 | CHECK_STREAM_PRECOND(-1) |
1437 | if (q_status != Ok && dev->isTransactionStarted()) |
1438 | return -1; |
1439 | |
1440 | const qint64 skipResult = dev->skip(maxSize: len); |
1441 | if (skipResult != len) |
1442 | setStatus(ReadPastEnd); |
1443 | return skipResult; |
1444 | } |
1445 | |
1446 | /*! |
1447 | \fn template <class T1, class T2> QDataStream &operator<<(QDataStream &out, const std::pair<T1, T2> &pair) |
1448 | \since 6.0 |
1449 | \relates QDataStream |
1450 | |
1451 | Writes the pair \a pair to stream \a out. |
1452 | |
1453 | This function requires the T1 and T2 types to implement \c operator<<(). |
1454 | |
1455 | \sa {Serializing Qt Data Types} |
1456 | */ |
1457 | |
1458 | QT_END_NAMESPACE |
1459 | |
1460 | #endif // QT_NO_DATASTREAM |
1461 |
Definitions
- QDataStream
- QDataStream
- QDataStream
- QDataStream
- ~QDataStream
- setDevice
- atEnd
- setFloatingPointPrecision
- resetStatus
- setStatus
- setByteOrder
- startTransaction
- commitTransaction
- rollbackTransaction
- abortTransaction
- isDeviceTransactionStarted
- readBlock
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- operator>>
- readBytes
- readBytes
- readRawData
- operator<<
- operator<<
- operator<<
- operator<<
- operator<<
- operator<<
- operator<<
- operator<<
- operator<<
- writeBytes
- writeRawData
Learn Advanced QML with KDAB
Find out more