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