|
1 /**************************************************************************** |
|
2 ** |
|
3 ** |
|
4 ** Implementation of QDataStream class |
|
5 ** |
|
6 ** Created : 930831 |
|
7 ** |
|
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. |
|
9 ** |
|
10 ** This file is part of the tools module of the Qt GUI Toolkit. |
|
11 ** |
|
12 ** This file may be distributed under the terms of the Q Public License |
|
13 ** as defined by Trolltech AS of Norway and appearing in the file |
|
14 ** LICENSE.QPL included in the packaging of this file. |
|
15 ** |
|
16 ** This file may be distributed and/or modified under the terms of the |
|
17 ** GNU General Public License version 2 as published by the Free Software |
|
18 ** Foundation and appearing in the file LICENSE.GPL included in the |
|
19 ** packaging of this file. |
|
20 ** |
|
21 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition |
|
22 ** licenses may use this file in accordance with the Qt Commercial License |
|
23 ** Agreement provided with the Software. |
|
24 ** |
|
25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
|
26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
27 ** |
|
28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for |
|
29 ** information about Qt Commercial License Agreements. |
|
30 ** See http://www.trolltech.com/qpl/ for QPL licensing information. |
|
31 ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
|
32 ** |
|
33 ** Contact info@trolltech.com if any conditions of this licensing are |
|
34 ** not clear to you. |
|
35 ** |
|
36 **********************************************************************/ |
|
37 |
|
38 #include "qdatastream.h" |
|
39 |
|
40 #ifndef QT_NO_DATASTREAM |
|
41 #include "qbuffer.h" |
|
42 #include <stdio.h> |
|
43 #include <ctype.h> |
|
44 #include <stdlib.h> |
|
45 |
|
46 // REVISED: warwick |
|
47 /*! |
|
48 \class QDataStream qdatastream.h |
|
49 |
|
50 \brief The QDataStream class provides serialization of |
|
51 binary data to a QIODevice. |
|
52 |
|
53 \ingroup io |
|
54 |
|
55 A data stream is a binary stream of encoded information which is 100% |
|
56 independent of the host computer operation system, CPU or byte order. A |
|
57 stream that is written by a PC under DOS/Windows can be read by a |
|
58 Sun SPARC running Solaris. |
|
59 |
|
60 The QDataStream class implements serialization of primitive types, like |
|
61 \c char, \c short, \c int, \c char* etc. Serialization of more complex |
|
62 data is accomplished by breaking up the data into primitive units. |
|
63 |
|
64 The programmer can select which byte order to use when serializing data. |
|
65 The default setting is big endian (MSB first). Changing it to little |
|
66 endian breaks the portability (unless the reader also changes to little |
|
67 endian). We recommend keeping this setting unless you have |
|
68 special requirements. |
|
69 |
|
70 A data stream cooperates closely with a QIODevice. A QIODevice |
|
71 represents an input/output medium one can read data from and write data |
|
72 to. The QFile class is an example of an IO device. |
|
73 |
|
74 Example (write data to a stream): |
|
75 \code |
|
76 QFile f( "file.dta" ); |
|
77 f.open( IO_WriteOnly ); // open file for writing |
|
78 QDataStream s( &f ); // serialize using f |
|
79 s << "the answer is"; // serialize string |
|
80 s << (Q_INT32)42; // serialize integer |
|
81 \endcode |
|
82 |
|
83 Example (read data from a stream): |
|
84 \code |
|
85 QFile f( "file.dta" ); |
|
86 f.open( IO_ReadOnly ); // open file for reading |
|
87 QDataStream s( &f ); // serialize using f |
|
88 char *str; |
|
89 Q_INT32 a; |
|
90 s >> str >> a; // "the answer is" and 42 |
|
91 delete str; // delete string |
|
92 \endcode |
|
93 |
|
94 In the last example, if you read into a QString instead of a \c char* |
|
95 you do not have to delete it. |
|
96 |
|
97 Normally, each item written to the stream is written in a fixed binary |
|
98 format. |
|
99 For example, a \c char* is written as a 32-bit integer equal to the |
|
100 length of the string including the NUL byte, followed by all the |
|
101 characters of the string including the NUL byte. Similarly when |
|
102 reading a string, 4 bytes are read to create the 32-bit length value, |
|
103 then that many characters for the string including the NUL. For a complete |
|
104 description of all Qt types supporting data streaming see \link |
|
105 datastreamformat.html Format of the QDataStream operators \endlink . |
|
106 |
|
107 If you want a "parsing" input stream, see QTextStream. If you just want the |
|
108 data to be human-readable to aid in debugging, you can set the data |
|
109 stream into printable data mode with setPrintableData(). The data is |
|
110 then written slower, in a human readable bloated form that is sufficient |
|
111 for debugging. |
|
112 |
|
113 If you are producing a new binary data format, such as a file format |
|
114 for documents created by your application, you could use a QDataStream |
|
115 to write the data in a portable format. Typically, you would write |
|
116 a brief header containing a magic string and a version number to give |
|
117 yourself room for future expansion. For example: |
|
118 |
|
119 \code |
|
120 // Open the file. |
|
121 QFile f( "file.xxx" ); |
|
122 f.open( IO_WriteOnly ); |
|
123 QDataStream s( &f ); |
|
124 |
|
125 // Write a header with a "magic number" and a version |
|
126 s << 0xa0b0c0d0; |
|
127 s << 123; |
|
128 |
|
129 // Write the data |
|
130 s << [lots of interesting data] |
|
131 \endcode |
|
132 |
|
133 Then read it in with: |
|
134 |
|
135 \code |
|
136 // Open the file. |
|
137 QFile f( "file.xxx" ); |
|
138 f.open( IO_ReadOnly ); |
|
139 QDataStream s( &f ); |
|
140 |
|
141 // Read and check the header |
|
142 Q_UINT32 magic; |
|
143 s >> magic; |
|
144 if ( magic != 0xa0b0c0d0 ) |
|
145 return XXX_BAD_FILE_FORMAT; |
|
146 |
|
147 // Read the version |
|
148 Q_INT32 version; |
|
149 s >> version; |
|
150 if ( version < 100 ) |
|
151 return XXX_BAD_FILE_TOO_OLD; |
|
152 if ( version > 123 ) |
|
153 return XXX_BAD_FILE_TOO_NEW; |
|
154 if ( version <= 110 ) |
|
155 s.setVersion(1); |
|
156 |
|
157 // Read the data |
|
158 s >> [lots of interesting data]; |
|
159 if ( version > 120 ) |
|
160 s >> [data new in XXX version 1.2]; |
|
161 s >> [other interesting data]; |
|
162 \endcode |
|
163 |
|
164 \sa QTextStream QVariant |
|
165 */ |
|
166 |
|
167 |
|
168 /***************************************************************************** |
|
169 QDataStream member functions |
|
170 *****************************************************************************/ |
|
171 |
|
172 #if defined(CHECK_STATE) |
|
173 #undef CHECK_STREAM_PRECOND |
|
174 #define CHECK_STREAM_PRECOND if ( !dev ) { \ |
|
175 qWarning( "QDataStream: No device" ); \ |
|
176 return *this; } |
|
177 #else |
|
178 #define CHECK_STREAM_PRECOND |
|
179 #endif |
|
180 |
|
181 static int systemWordSize = 0; |
|
182 static bool systemBigEndian; |
|
183 |
|
184 static const int DefaultStreamVersion = 3; |
|
185 // 3 is default in Qt 2.1 |
|
186 // 2 is the Qt 2.0.x format |
|
187 // 1 is the Qt 1.x format |
|
188 |
|
189 /*! |
|
190 Constructs a data stream that has no IO device. |
|
191 |
|
192 \sa setDevice() |
|
193 */ |
|
194 |
|
195 QDataStream::QDataStream() |
|
196 { |
|
197 if ( systemWordSize == 0 ) // get system features |
|
198 qSysInfo( &systemWordSize, &systemBigEndian ); |
|
199 dev = 0; // no device set |
|
200 owndev = FALSE; |
|
201 byteorder = BigEndian; // default byte order |
|
202 printable = FALSE; |
|
203 ver = DefaultStreamVersion; |
|
204 noswap = systemBigEndian; |
|
205 } |
|
206 |
|
207 /*! |
|
208 Constructs a data stream that uses the IO device \a d. |
|
209 |
|
210 \sa setDevice(), device() |
|
211 */ |
|
212 |
|
213 QDataStream::QDataStream( QIODevice *d ) |
|
214 { |
|
215 if ( systemWordSize == 0 ) // get system features |
|
216 qSysInfo( &systemWordSize, &systemBigEndian ); |
|
217 dev = d; // set device |
|
218 owndev = FALSE; |
|
219 byteorder = BigEndian; // default byte order |
|
220 printable = FALSE; |
|
221 ver = DefaultStreamVersion; |
|
222 noswap = systemBigEndian; |
|
223 } |
|
224 |
|
225 /*! |
|
226 Constructs a data stream that operates on a byte array through an |
|
227 internal QBuffer device. |
|
228 |
|
229 Example: |
|
230 \code |
|
231 static char bindata[] = { 231, 1, 44, ... }; |
|
232 QByteArray a; |
|
233 a.setRawData( bindata, sizeof(bindata) ); // a points to bindata |
|
234 QDataStream s( a, IO_ReadOnly ); // open on a's data |
|
235 s >> [something]; // read raw bindata |
|
236 a.resetRawData( bindata, sizeof(bindata) ); // finished |
|
237 \endcode |
|
238 |
|
239 The QArray::setRawData() function is not for the inexperienced. |
|
240 */ |
|
241 |
|
242 QDataStream::QDataStream( QByteArray a, int mode ) |
|
243 { |
|
244 if ( systemWordSize == 0 ) // get system features |
|
245 qSysInfo( &systemWordSize, &systemBigEndian ); |
|
246 dev = new QBuffer( a ); // create device |
|
247 ((QBuffer *)dev)->open( mode ); // open device |
|
248 owndev = TRUE; |
|
249 byteorder = BigEndian; // default byte order |
|
250 printable = FALSE; |
|
251 ver = DefaultStreamVersion; |
|
252 noswap = systemBigEndian; |
|
253 } |
|
254 |
|
255 /*! |
|
256 Destructs the data stream. |
|
257 |
|
258 The destructor will not affect the current IO device, unless it |
|
259 is an internal IO device processing a QByteArray passed in the constructor. |
|
260 */ |
|
261 |
|
262 QDataStream::~QDataStream() |
|
263 { |
|
264 if ( owndev ) |
|
265 delete dev; |
|
266 } |
|
267 |
|
268 |
|
269 /*! |
|
270 \fn QIODevice *QDataStream::device() const |
|
271 Returns the IO device currently set. |
|
272 \sa setDevice(), unsetDevice() |
|
273 */ |
|
274 |
|
275 /*! |
|
276 void QDataStream::setDevice(QIODevice *d ) |
|
277 Sets the IO device to \a d. |
|
278 \sa device(), unsetDevice() |
|
279 */ |
|
280 |
|
281 void QDataStream::setDevice(QIODevice *d ) |
|
282 { |
|
283 if ( owndev ) { |
|
284 delete dev; |
|
285 owndev = FALSE; |
|
286 } |
|
287 dev = d; |
|
288 } |
|
289 |
|
290 /*! |
|
291 Unsets the IO device. This is the same as calling setDevice( 0 ). |
|
292 \sa device(), setDevice() |
|
293 */ |
|
294 |
|
295 void QDataStream::unsetDevice() |
|
296 { |
|
297 setDevice( 0 ); |
|
298 } |
|
299 |
|
300 |
|
301 /*! |
|
302 \fn bool QDataStream::atEnd() const |
|
303 Returns TRUE if the IO device has reached the end position (end of |
|
304 stream or file) or if there is no IO device set. |
|
305 |
|
306 Returns FALSE if the current position of the read/write head of the IO |
|
307 device is somewhere before the end position. |
|
308 |
|
309 \sa QIODevice::atEnd() |
|
310 */ |
|
311 |
|
312 /*!\fn bool QDataStream::eof() const |
|
313 |
|
314 \obsolete |
|
315 |
|
316 Returns TRUE if the IO device has reached the end position (end of |
|
317 stream or file) or if there is no IO device set. |
|
318 |
|
319 Returns FALSE if the current position of the read/write head of the IO |
|
320 device is somewhere before the end position. |
|
321 |
|
322 \sa QIODevice::atEnd() |
|
323 */ |
|
324 |
|
325 /*! |
|
326 \fn int QDataStream::byteOrder() const |
|
327 Returns the current byte order setting - either \c BigEndian or |
|
328 \c LittleEndian. |
|
329 |
|
330 \sa setByteOrder() |
|
331 */ |
|
332 |
|
333 /*! |
|
334 Sets the serialization byte order to \a bo. |
|
335 |
|
336 The \a bo parameter can be \c QDataStream::BigEndian or |
|
337 \c QDataStream::LittleEndian. |
|
338 |
|
339 The default setting is big endian. We recommend leaving this setting unless |
|
340 you have special requirements. |
|
341 |
|
342 \sa byteOrder() |
|
343 */ |
|
344 |
|
345 void QDataStream::setByteOrder( int bo ) |
|
346 { |
|
347 byteorder = bo; |
|
348 if ( systemBigEndian ) |
|
349 noswap = byteorder == BigEndian; |
|
350 else |
|
351 noswap = byteorder == LittleEndian; |
|
352 } |
|
353 |
|
354 |
|
355 /*! |
|
356 \fn bool QDataStream::isPrintableData() const |
|
357 Returns TRUE if the printable data flag has been set. |
|
358 \sa setPrintableData() |
|
359 */ |
|
360 |
|
361 /*! |
|
362 \fn void QDataStream::setPrintableData( bool enable ) |
|
363 Sets or clears the printable data flag. |
|
364 |
|
365 If this flag is set, the write functions will generate output that |
|
366 consists of printable characters (7 bit ASCII). |
|
367 |
|
368 We recommend enabling printable data only for debugging purposes |
|
369 (it is slower and creates larger output). |
|
370 */ |
|
371 |
|
372 |
|
373 /*! |
|
374 \fn int QDataStream::version() const |
|
375 Returns the version number of the data serialization format. |
|
376 In Qt 2.1, this number is by default 3. |
|
377 \sa setVersion() |
|
378 */ |
|
379 |
|
380 /*! |
|
381 \fn void QDataStream::setVersion( int v ) |
|
382 Sets the version number of the data serialization format. |
|
383 |
|
384 In order to accomodate for new functionality, the datastream |
|
385 serialization format of some Qt classes has changed in some versions of |
|
386 Qt. If you want to read data that was created by an earlier version of |
|
387 Qt, or write data that can be read by a program that was compiled with |
|
388 an earlier version of Qt, use this function to modify the serialization |
|
389 format of QDataStream. |
|
390 |
|
391 For Qt 1.x compatibility, use \a v == 1. |
|
392 |
|
393 For Qt 2.0.x compatibility, use \a v == 2 (Not required for reading in |
|
394 Qt 2.1). |
|
395 |
|
396 \sa version() |
|
397 */ |
|
398 |
|
399 /***************************************************************************** |
|
400 QDataStream read functions |
|
401 *****************************************************************************/ |
|
402 |
|
403 |
|
404 static Q_INT32 read_int_ascii( QDataStream *s ) |
|
405 { |
|
406 register int n = 0; |
|
407 char buf[40]; |
|
408 while ( TRUE ) { |
|
409 buf[n] = s->device()->getch(); |
|
410 if ( buf[n] == '\n' || n > 38 ) // $-terminator |
|
411 break; |
|
412 n++; |
|
413 } |
|
414 buf[n] = '\0'; |
|
415 return atol( buf ); |
|
416 } |
|
417 |
|
418 |
|
419 /*! |
|
420 \fn QDataStream &QDataStream::operator>>( Q_UINT8 &i ) |
|
421 Reads an unsigned byte from the stream and returns a reference to |
|
422 the stream. |
|
423 */ |
|
424 |
|
425 /*! |
|
426 Reads a signed byte from the stream. |
|
427 */ |
|
428 |
|
429 QDataStream &QDataStream::operator>>( Q_INT8 &i ) |
|
430 { |
|
431 CHECK_STREAM_PRECOND |
|
432 if ( printable ) { // printable data |
|
433 i = (Q_INT8)dev->getch(); |
|
434 if ( i == '\\' ) { // read octal code |
|
435 char buf[4]; |
|
436 dev->readBlock( buf, 3 ); |
|
437 i = (buf[2] & 0x07)+((buf[1] & 0x07) << 3)+((buf[0] & 0x07) << 6); |
|
438 } |
|
439 } else { // data or text |
|
440 i = (Q_INT8)dev->getch(); |
|
441 } |
|
442 return *this; |
|
443 } |
|
444 |
|
445 |
|
446 /*! |
|
447 \fn QDataStream &QDataStream::operator>>( Q_UINT16 &i ) |
|
448 Reads an unsigned 16-bit integer from the stream and returns a reference to |
|
449 the stream. |
|
450 */ |
|
451 |
|
452 /*! |
|
453 Reads a signed 16-bit integer from the stream and returns a reference to |
|
454 the stream. |
|
455 */ |
|
456 |
|
457 QDataStream &QDataStream::operator>>( Q_INT16 &i ) |
|
458 { |
|
459 CHECK_STREAM_PRECOND |
|
460 if ( printable ) { // printable data |
|
461 i = (Q_INT16)read_int_ascii( this ); |
|
462 } else if ( noswap ) { // no conversion needed |
|
463 dev->readBlock( (char *)&i, sizeof(Q_INT16) ); |
|
464 } else { // swap bytes |
|
465 register uchar *p = (uchar *)(&i); |
|
466 char b[2]; |
|
467 dev->readBlock( b, 2 ); |
|
468 *p++ = b[1]; |
|
469 *p = b[0]; |
|
470 } |
|
471 return *this; |
|
472 } |
|
473 |
|
474 |
|
475 /*! |
|
476 \fn QDataStream &QDataStream::operator>>( Q_UINT32 &i ) |
|
477 Reads an unsigned 32-bit integer from the stream and returns a reference to |
|
478 the stream. |
|
479 */ |
|
480 |
|
481 /*! |
|
482 Reads a signed 32-bit integer from the stream and returns a reference to |
|
483 the stream. |
|
484 */ |
|
485 |
|
486 QDataStream &QDataStream::operator>>( Q_INT32 &i ) |
|
487 { |
|
488 CHECK_STREAM_PRECOND |
|
489 if ( printable ) { // printable data |
|
490 i = read_int_ascii( this ); |
|
491 } else if ( noswap ) { // no conversion needed |
|
492 dev->readBlock( (char *)&i, sizeof(Q_INT32) ); |
|
493 } else { // swap bytes |
|
494 register uchar *p = (uchar *)(&i); |
|
495 char b[4]; |
|
496 dev->readBlock( b, 4 ); |
|
497 *p++ = b[3]; |
|
498 *p++ = b[2]; |
|
499 *p++ = b[1]; |
|
500 *p = b[0]; |
|
501 } |
|
502 return *this; |
|
503 } |
|
504 |
|
505 /*! |
|
506 \fn QDataStream &QDataStream::operator>>( Q_UINT64 &i ) |
|
507 Reads an unsigned 64-bit integer from the stream and returns a reference to |
|
508 the stream, or uses the Q_UINT32 operator if 64 bit is not available. |
|
509 */ |
|
510 |
|
511 /*! |
|
512 Reads a signed 64-bit integer from the stream and returns a reference to |
|
513 the stream, or uses the Q_UINT32 operator if 64 bit is not available. |
|
514 */ |
|
515 |
|
516 QDataStream &QDataStream::operator>>( Q_INT64 &i ) |
|
517 { |
|
518 CHECK_STREAM_PRECOND |
|
519 if ( printable ) { // printable data |
|
520 i = read_int_ascii( this ); |
|
521 } else if ( noswap ) { // no conversion needed |
|
522 dev->readBlock( (char *)&i, sizeof(Q_INT64) ); |
|
523 } else { // swap bytes |
|
524 register uchar *p = (uchar *)(&i); |
|
525 char b[sizeof(Q_INT64)]; |
|
526 dev->readBlock( b, sizeof(Q_INT64) ); |
|
527 if ( sizeof(Q_INT64) == 8 ) { |
|
528 *p++ = b[7]; |
|
529 *p++ = b[6]; |
|
530 *p++ = b[5]; |
|
531 *p++ = b[4]; |
|
532 } |
|
533 *p++ = b[3]; |
|
534 *p++ = b[2]; |
|
535 *p++ = b[1]; |
|
536 *p = b[0]; |
|
537 } |
|
538 return *this; |
|
539 } |
|
540 |
|
541 static double read_double_ascii( QDataStream *s ) |
|
542 { |
|
543 register int n = 0; |
|
544 char buf[80]; |
|
545 while ( TRUE ) { |
|
546 buf[n] = s->device()->getch(); |
|
547 if ( buf[n] == '\n' || n > 78 ) // $-terminator |
|
548 break; |
|
549 n++; |
|
550 } |
|
551 buf[n] = '\0'; |
|
552 return atof( buf ); |
|
553 } |
|
554 |
|
555 |
|
556 /*! |
|
557 Reads a 32-bit floating point number from the stream using the standard |
|
558 IEEE754 format. Returns a reference to the stream. |
|
559 */ |
|
560 |
|
561 QDataStream &QDataStream::operator>>( float &f ) |
|
562 { |
|
563 CHECK_STREAM_PRECOND |
|
564 if ( printable ) { // printable data |
|
565 f = (float)read_double_ascii( this ); |
|
566 } else if ( noswap ) { // no conversion needed |
|
567 dev->readBlock( (char *)&f, sizeof(float) ); |
|
568 } else { // swap bytes |
|
569 register uchar *p = (uchar *)(&f); |
|
570 char b[4]; |
|
571 dev->readBlock( b, 4 ); |
|
572 *p++ = b[3]; |
|
573 *p++ = b[2]; |
|
574 *p++ = b[1]; |
|
575 *p = b[0]; |
|
576 } |
|
577 return *this; |
|
578 } |
|
579 |
|
580 |
|
581 /*! |
|
582 Reads a 64-bit floating point number from the stream using the standard |
|
583 IEEE754 format. Returns a reference to the stream. |
|
584 */ |
|
585 |
|
586 QDataStream &QDataStream::operator>>( double &f ) |
|
587 { |
|
588 CHECK_STREAM_PRECOND |
|
589 if ( printable ) { // printable data |
|
590 f = read_double_ascii( this ); |
|
591 } else if ( noswap ) { // no conversion needed |
|
592 dev->readBlock( (char *)&f, sizeof(double) ); |
|
593 } else { // swap bytes |
|
594 register uchar *p = (uchar *)(&f); |
|
595 char b[8]; |
|
596 dev->readBlock( b, 8 ); |
|
597 *p++ = b[7]; |
|
598 *p++ = b[6]; |
|
599 *p++ = b[5]; |
|
600 *p++ = b[4]; |
|
601 *p++ = b[3]; |
|
602 *p++ = b[2]; |
|
603 *p++ = b[1]; |
|
604 *p = b[0]; |
|
605 } |
|
606 return *this; |
|
607 } |
|
608 |
|
609 |
|
610 /*! |
|
611 Reads the '\0'-terminated string \a s from the stream and returns |
|
612 a reference to the stream. |
|
613 |
|
614 Space for the string is allocated using \c new - the caller must |
|
615 eventually call delete[] on the value. |
|
616 */ |
|
617 |
|
618 QDataStream &QDataStream::operator>>( char *&s ) |
|
619 { |
|
620 uint len = 0; |
|
621 return readBytes( s, len ); |
|
622 } |
|
623 |
|
624 |
|
625 /*! |
|
626 Reads the buffer \a s from the stream and returns a reference to the |
|
627 stream. |
|
628 |
|
629 The buffer \a s is allocated using \c new. Destroy it with the \c delete[] |
|
630 operator. If the length is zero or \a s cannot be allocated, \a s is |
|
631 set to 0. |
|
632 |
|
633 The \a l parameter will be set to the length of the buffer. |
|
634 |
|
635 The serialization format is an Q_UINT32 length specifier first, then the |
|
636 data (\a l bytes). |
|
637 |
|
638 \sa readRawBytes(), writeBytes() |
|
639 */ |
|
640 |
|
641 QDataStream &QDataStream::readBytes( char *&s, uint &l ) |
|
642 { |
|
643 CHECK_STREAM_PRECOND |
|
644 Q_UINT32 len; |
|
645 *this >> len; // first read length spec |
|
646 l = (uint)len; |
|
647 if ( len == 0 || eof() ) { |
|
648 s = 0; |
|
649 return *this; |
|
650 } else { |
|
651 s = new char[len]; // create char array |
|
652 CHECK_PTR( s ); |
|
653 if ( !s ) // no memory |
|
654 return *this; |
|
655 return readRawBytes( s, (uint)len ); |
|
656 } |
|
657 } |
|
658 |
|
659 |
|
660 /*! |
|
661 Reads \a len bytes from the stream into \a s and returns a reference to |
|
662 the stream. |
|
663 |
|
664 The buffer \a s must be preallocated. |
|
665 |
|
666 \sa readBytes(), QIODevice::readBlock(), writeRawBytes() |
|
667 */ |
|
668 |
|
669 QDataStream &QDataStream::readRawBytes( char *s, uint len ) |
|
670 { |
|
671 CHECK_STREAM_PRECOND |
|
672 if ( printable ) { // printable data |
|
673 register Q_INT8 *p = (Q_INT8*)s; |
|
674 while ( len-- ) |
|
675 *this >> *p++; |
|
676 } else { // read data char array |
|
677 dev->readBlock( s, len ); |
|
678 } |
|
679 return *this; |
|
680 } |
|
681 |
|
682 |
|
683 /***************************************************************************** |
|
684 QDataStream write functions |
|
685 *****************************************************************************/ |
|
686 |
|
687 |
|
688 /*! |
|
689 \fn QDataStream &QDataStream::operator<<( Q_UINT8 i ) |
|
690 Writes an unsigned byte to the stream and returns a reference to |
|
691 the stream. |
|
692 */ |
|
693 |
|
694 /*! |
|
695 Writes a signed byte to the stream. |
|
696 */ |
|
697 |
|
698 QDataStream &QDataStream::operator<<( Q_INT8 i ) |
|
699 { |
|
700 CHECK_STREAM_PRECOND |
|
701 if ( printable && (i == '\\' || !isprint(i)) ) { |
|
702 char buf[6]; // write octal code |
|
703 buf[0] = '\\'; |
|
704 buf[1] = '0' + ((i >> 6) & 0x07); |
|
705 buf[2] = '0' + ((i >> 3) & 0x07); |
|
706 buf[3] = '0' + (i & 0x07); |
|
707 buf[4] = '\0'; |
|
708 dev->writeBlock( buf, 4 ); |
|
709 } else { |
|
710 dev->putch( i ); |
|
711 } |
|
712 return *this; |
|
713 } |
|
714 |
|
715 |
|
716 /*! |
|
717 \fn QDataStream &QDataStream::operator<<( Q_UINT16 i ) |
|
718 Writes an unsigned 16-bit integer to the stream and returns a reference |
|
719 to the stream. |
|
720 */ |
|
721 |
|
722 /*! |
|
723 Writes a signed 16-bit integer to the stream and returns a reference to |
|
724 the stream. |
|
725 */ |
|
726 |
|
727 QDataStream &QDataStream::operator<<( Q_INT16 i ) |
|
728 { |
|
729 CHECK_STREAM_PRECOND |
|
730 if ( printable ) { // printable data |
|
731 char buf[16]; |
|
732 sprintf( buf, "%d\n", i ); |
|
733 dev->writeBlock( buf, strlen(buf) ); |
|
734 } else if ( noswap ) { // no conversion needed |
|
735 dev->writeBlock( (char *)&i, sizeof(Q_INT16) ); |
|
736 } else { // swap bytes |
|
737 register uchar *p = (uchar *)(&i); |
|
738 char b[2]; |
|
739 b[1] = *p++; |
|
740 b[0] = *p; |
|
741 dev->writeBlock( b, 2 ); |
|
742 } |
|
743 return *this; |
|
744 } |
|
745 |
|
746 |
|
747 /*! |
|
748 \fn QDataStream &QDataStream::operator<<( Q_UINT32 i ) |
|
749 Writes an unsigned 32-bit integer to the stream and returns a reference to |
|
750 the stream. |
|
751 */ |
|
752 |
|
753 /*! |
|
754 Writes a signed 32-bit integer to the stream and returns a reference to |
|
755 the stream. |
|
756 */ |
|
757 |
|
758 QDataStream &QDataStream::operator<<( Q_INT32 i ) |
|
759 { |
|
760 CHECK_STREAM_PRECOND |
|
761 if ( printable ) { // printable data |
|
762 char buf[16]; |
|
763 sprintf( buf, "%d\n", i ); |
|
764 dev->writeBlock( buf, strlen(buf) ); |
|
765 } else if ( noswap ) { // no conversion needed |
|
766 dev->writeBlock( (char *)&i, sizeof(Q_INT32) ); |
|
767 } else { // swap bytes |
|
768 register uchar *p = (uchar *)(&i); |
|
769 char b[4]; |
|
770 b[3] = *p++; |
|
771 b[2] = *p++; |
|
772 b[1] = *p++; |
|
773 b[0] = *p; |
|
774 dev->writeBlock( b, 4 ); |
|
775 } |
|
776 return *this; |
|
777 } |
|
778 |
|
779 /*! |
|
780 \fn QDataStream &QDataStream::operator<<( Q_UINT64 i ) |
|
781 Writes an unsigned 64-bit integer to the stream and returns a reference to |
|
782 the stream, or uses the Q_UINT32-operator if 64 bit is not available. |
|
783 */ |
|
784 |
|
785 /*! |
|
786 Writes a signed 64-bit integer to the stream and returns a reference to |
|
787 the stream, or calls the Q_INT32-operator if 64 bit is not available. |
|
788 */ |
|
789 |
|
790 QDataStream &QDataStream::operator<<( Q_INT64 i ) |
|
791 { |
|
792 CHECK_STREAM_PRECOND |
|
793 if ( printable ) { // printable data |
|
794 char buf[20]; |
|
795 sprintf( buf, "%ld\n", i ); |
|
796 dev->writeBlock( buf, strlen(buf) ); |
|
797 } else if ( noswap ) { // no conversion needed |
|
798 dev->writeBlock( (char *)&i, sizeof(Q_INT64) ); |
|
799 } else { // swap bytes |
|
800 register uchar *p = (uchar *)(&i); |
|
801 char b[sizeof(Q_INT64)]; |
|
802 if ( sizeof(Q_INT64) == 8 ) { |
|
803 b[7] = *p++; |
|
804 b[6] = *p++; |
|
805 b[5] = *p++; |
|
806 b[4] = *p++; |
|
807 } |
|
808 b[3] = *p++; |
|
809 b[2] = *p++; |
|
810 b[1] = *p++; |
|
811 b[0] = *p; |
|
812 dev->writeBlock( b, sizeof(Q_INT64) ); |
|
813 } |
|
814 return *this; |
|
815 } |
|
816 |
|
817 /*! |
|
818 \fn QDataStream &QDataStream::operator<<( uint i ) |
|
819 Writes an unsigned integer to the stream as a 32-bit unsigned integer |
|
820 (Q_UINT32). |
|
821 Returns a reference to the stream. |
|
822 */ |
|
823 |
|
824 /*! |
|
825 \fn QDataStream &QDataStream::operator<<( int i ) |
|
826 Writes a signed integer to the stream as a 32-bit signed integer (Q_INT32). |
|
827 Returns a reference to the stream. |
|
828 */ |
|
829 |
|
830 |
|
831 /*! |
|
832 Writes a 32-bit floating point number to the stream using the standard |
|
833 IEEE754 format. Returns a reference to the stream. |
|
834 */ |
|
835 |
|
836 QDataStream &QDataStream::operator<<( float f ) |
|
837 { |
|
838 CHECK_STREAM_PRECOND |
|
839 if ( printable ) { // printable data |
|
840 char buf[32]; |
|
841 sprintf( buf, "%g\n", (double)f ); |
|
842 dev->writeBlock( buf, strlen(buf) ); |
|
843 } else { |
|
844 float g = f; // fixes float-on-stack problem |
|
845 if ( noswap ) { // no conversion needed |
|
846 dev->writeBlock( (char *)&g, sizeof(float) ); |
|
847 } else { // swap bytes |
|
848 register uchar *p = (uchar *)(&g); |
|
849 char b[4]; |
|
850 b[3] = *p++; |
|
851 b[2] = *p++; |
|
852 b[1] = *p++; |
|
853 b[0] = *p; |
|
854 dev->writeBlock( b, 4 ); |
|
855 } |
|
856 } |
|
857 return *this; |
|
858 } |
|
859 |
|
860 |
|
861 /*! |
|
862 Writes a 64-bit floating point number to the stream using the standard |
|
863 IEEE754 format. Returns a reference to the stream. |
|
864 */ |
|
865 |
|
866 QDataStream &QDataStream::operator<<( double f ) |
|
867 { |
|
868 CHECK_STREAM_PRECOND |
|
869 if ( printable ) { // printable data |
|
870 char buf[32]; |
|
871 sprintf( buf, "%g\n", f ); |
|
872 dev->writeBlock( buf, strlen(buf) ); |
|
873 } else if ( noswap ) { // no conversion needed |
|
874 dev->writeBlock( (char *)&f, sizeof(double) ); |
|
875 } else { // swap bytes |
|
876 register uchar *p = (uchar *)(&f); |
|
877 char b[8]; |
|
878 b[7] = *p++; |
|
879 b[6] = *p++; |
|
880 b[5] = *p++; |
|
881 b[4] = *p++; |
|
882 b[3] = *p++; |
|
883 b[2] = *p++; |
|
884 b[1] = *p++; |
|
885 b[0] = *p; |
|
886 dev->writeBlock( b, 8 ); |
|
887 } |
|
888 return *this; |
|
889 } |
|
890 |
|
891 |
|
892 /*! |
|
893 Writes the '\0'-terminated string \a s to the stream and returns |
|
894 a reference to the stream. |
|
895 |
|
896 The string is serialized using writeBytes(). |
|
897 */ |
|
898 |
|
899 QDataStream &QDataStream::operator<<( const char *s ) |
|
900 { |
|
901 if ( !s ) { |
|
902 *this << (Q_UINT32)0; |
|
903 return *this; |
|
904 } |
|
905 uint len = qstrlen( s ) + 1; // also write null terminator |
|
906 *this << (Q_UINT32)len; // write length specifier |
|
907 return writeRawBytes( s, len ); |
|
908 } |
|
909 |
|
910 |
|
911 /*! |
|
912 Writes the length specifier \a len and the buffer \a s to the stream and |
|
913 returns a reference to the stream. |
|
914 |
|
915 The \a len is serialized as an Q_UINT32, followed by \a len bytes from |
|
916 \a s. |
|
917 |
|
918 \sa writeRawBytes(), readBytes() |
|
919 */ |
|
920 |
|
921 QDataStream &QDataStream::writeBytes(const char *s, uint len) |
|
922 { |
|
923 CHECK_STREAM_PRECOND |
|
924 *this << (Q_UINT32)len; // write length specifier |
|
925 if ( len ) |
|
926 writeRawBytes( s, len ); |
|
927 return *this; |
|
928 } |
|
929 |
|
930 |
|
931 /*! |
|
932 Writes \a len bytes from \a s to the stream and returns a reference to the |
|
933 stream. |
|
934 |
|
935 \sa writeBytes(), QIODevice::writeBlock(), readRawBytes() |
|
936 */ |
|
937 |
|
938 QDataStream &QDataStream::writeRawBytes( const char *s, uint len ) |
|
939 { |
|
940 CHECK_STREAM_PRECOND |
|
941 if ( printable ) { // write printable |
|
942 register char *p = (char *)s; |
|
943 while ( len-- ) |
|
944 *this << *p++; |
|
945 } else { // write data char array |
|
946 dev->writeBlock( s, len ); |
|
947 } |
|
948 return *this; |
|
949 } |
|
950 |
|
951 #endif // QT_NO_DATASTREAM |