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