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