Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
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␊ |
952 |