70bcab1044480d0112635f5633e4946f3d697440
[platform/upstream/doxygen.git] / qtools / qdatastream.cpp
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 accommodate 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 (Q_INT32)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