1 /****************************************************************************
4 ** Implementation of QDataStream class
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
10 ** This file is part of the tools module of the Qt GUI Toolkit.
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.
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.
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.
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.
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.
33 ** Contact info@trolltech.com if any conditions of this licensing are
36 **********************************************************************/
38 #include "qdatastream.h"
40 #ifndef QT_NO_DATASTREAM
48 \class QDataStream qdatastream.h
50 \brief The QDataStream class provides serialization of
51 binary data to a QIODevice.
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.
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.
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
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.
74 Example (write data to a stream):
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
83 Example (read data from a stream):
85 QFile f( "file.dta" );
86 f.open( IO_ReadOnly ); // open file for reading
87 QDataStream s( &f ); // serialize using f
90 s >> str >> a; // "the answer is" and 42
91 delete str; // delete string
94 In the last example, if you read into a QString instead of a \c char*
95 you do not have to delete it.
97 Normally, each item written to the stream is written in a fixed binary
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 .
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
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:
121 QFile f( "file.xxx" );
122 f.open( IO_WriteOnly );
125 // Write a header with a "magic number" and a version
130 s << [lots of interesting data]
133 Then read it in with:
137 QFile f( "file.xxx" );
138 f.open( IO_ReadOnly );
141 // Read and check the header
144 if ( magic != 0xa0b0c0d0 )
145 return XXX_BAD_FILE_FORMAT;
151 return XXX_BAD_FILE_TOO_OLD;
153 return XXX_BAD_FILE_TOO_NEW;
154 if ( version <= 110 )
158 s >> [lots of interesting data];
160 s >> [data new in XXX version 1.2];
161 s >> [other interesting data];
164 \sa QTextStream QVariant
168 /*****************************************************************************
169 QDataStream member functions
170 *****************************************************************************/
172 #if defined(CHECK_STATE)
173 #undef CHECK_STREAM_PRECOND
174 #define CHECK_STREAM_PRECOND if ( !dev ) { \
175 qWarning( "QDataStream: No device" ); \
178 #define CHECK_STREAM_PRECOND
181 static int systemWordSize = 0;
182 static bool systemBigEndian;
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
190 Constructs a data stream that has no IO device.
195 QDataStream::QDataStream()
197 if ( systemWordSize == 0 ) // get system features
198 qSysInfo( &systemWordSize, &systemBigEndian );
199 dev = 0; // no device set
201 byteorder = BigEndian; // default byte order
203 ver = DefaultStreamVersion;
204 noswap = systemBigEndian;
208 Constructs a data stream that uses the IO device \a d.
210 \sa setDevice(), device()
213 QDataStream::QDataStream( QIODevice *d )
215 if ( systemWordSize == 0 ) // get system features
216 qSysInfo( &systemWordSize, &systemBigEndian );
217 dev = d; // set device
219 byteorder = BigEndian; // default byte order
221 ver = DefaultStreamVersion;
222 noswap = systemBigEndian;
226 Constructs a data stream that operates on a byte array through an
227 internal QBuffer device.
231 static char bindata[] = { 231, 1, 44, ... };
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
239 The QArray::setRawData() function is not for the inexperienced.
242 QDataStream::QDataStream( QByteArray a, int mode )
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
249 byteorder = BigEndian; // default byte order
251 ver = DefaultStreamVersion;
252 noswap = systemBigEndian;
256 Destructs the data stream.
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.
262 QDataStream::~QDataStream()
270 \fn QIODevice *QDataStream::device() const
271 Returns the IO device currently set.
272 \sa setDevice(), unsetDevice()
276 void QDataStream::setDevice(QIODevice *d )
277 Sets the IO device to \a d.
278 \sa device(), unsetDevice()
281 void QDataStream::setDevice(QIODevice *d )
291 Unsets the IO device. This is the same as calling setDevice( 0 ).
292 \sa device(), setDevice()
295 void QDataStream::unsetDevice()
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.
306 Returns FALSE if the current position of the read/write head of the IO
307 device is somewhere before the end position.
309 \sa QIODevice::atEnd()
312 /*!\fn bool QDataStream::eof() const
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.
319 Returns FALSE if the current position of the read/write head of the IO
320 device is somewhere before the end position.
322 \sa QIODevice::atEnd()
326 \fn int QDataStream::byteOrder() const
327 Returns the current byte order setting - either \c BigEndian or
334 Sets the serialization byte order to \a bo.
336 The \a bo parameter can be \c QDataStream::BigEndian or
337 \c QDataStream::LittleEndian.
339 The default setting is big endian. We recommend leaving this setting unless
340 you have special requirements.
345 void QDataStream::setByteOrder( int bo )
348 if ( systemBigEndian )
349 noswap = byteorder == BigEndian;
351 noswap = byteorder == LittleEndian;
356 \fn bool QDataStream::isPrintableData() const
357 Returns TRUE if the printable data flag has been set.
358 \sa setPrintableData()
362 \fn void QDataStream::setPrintableData( bool enable )
363 Sets or clears the printable data flag.
365 If this flag is set, the write functions will generate output that
366 consists of printable characters (7 bit ASCII).
368 We recommend enabling printable data only for debugging purposes
369 (it is slower and creates larger output).
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.
381 \fn void QDataStream::setVersion( int v )
382 Sets the version number of the data serialization format.
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.
391 For Qt 1.x compatibility, use \a v == 1.
393 For Qt 2.0.x compatibility, use \a v == 2 (Not required for reading in
399 /*****************************************************************************
400 QDataStream read functions
401 *****************************************************************************/
404 static Q_INT32 read_int_ascii( QDataStream *s )
409 buf[n] = s->device()->getch();
410 if ( buf[n] == '\n' || n > 38 ) // $-terminator
415 return (Q_INT32)atol( buf );
420 \fn QDataStream &QDataStream::operator>>( Q_UINT8 &i )
421 Reads an unsigned byte from the stream and returns a reference to
426 Reads a signed byte from the stream.
429 QDataStream &QDataStream::operator>>( Q_INT8 &i )
432 if ( printable ) { // printable data
433 i = (Q_INT8)dev->getch();
434 if ( i == '\\' ) { // read octal code
436 dev->readBlock( buf, 3 );
437 i = (buf[2] & 0x07)+((buf[1] & 0x07) << 3)+((buf[0] & 0x07) << 6);
439 } else { // data or text
440 i = (Q_INT8)dev->getch();
447 \fn QDataStream &QDataStream::operator>>( Q_UINT16 &i )
448 Reads an unsigned 16-bit integer from the stream and returns a reference to
453 Reads a signed 16-bit integer from the stream and returns a reference to
457 QDataStream &QDataStream::operator>>( Q_INT16 &i )
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);
467 dev->readBlock( b, 2 );
476 \fn QDataStream &QDataStream::operator>>( Q_UINT32 &i )
477 Reads an unsigned 32-bit integer from the stream and returns a reference to
482 Reads a signed 32-bit integer from the stream and returns a reference to
486 QDataStream &QDataStream::operator>>( Q_INT32 &i )
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);
496 dev->readBlock( b, 4 );
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.
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.
516 QDataStream &QDataStream::operator>>( Q_INT64 &i )
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 ) {
541 static double read_double_ascii( QDataStream *s )
546 buf[n] = s->device()->getch();
547 if ( buf[n] == '\n' || n > 78 ) // $-terminator
557 Reads a 32-bit floating point number from the stream using the standard
558 IEEE754 format. Returns a reference to the stream.
561 QDataStream &QDataStream::operator>>( float &f )
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);
571 dev->readBlock( b, 4 );
582 Reads a 64-bit floating point number from the stream using the standard
583 IEEE754 format. Returns a reference to the stream.
586 QDataStream &QDataStream::operator>>( double &f )
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);
596 dev->readBlock( b, 8 );
611 Reads the '\0'-terminated string \a s from the stream and returns
612 a reference to the stream.
614 Space for the string is allocated using \c new - the caller must
615 eventually call delete[] on the value.
618 QDataStream &QDataStream::operator>>( char *&s )
621 return readBytes( s, len );
626 Reads the buffer \a s from the stream and returns a reference to the
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
633 The \a l parameter will be set to the length of the buffer.
635 The serialization format is an Q_UINT32 length specifier first, then the
638 \sa readRawBytes(), writeBytes()
641 QDataStream &QDataStream::readBytes( char *&s, uint &l )
645 *this >> len; // first read length spec
647 if ( len == 0 || eof() ) {
651 s = new char[len]; // create char array
653 if ( !s ) // no memory
655 return readRawBytes( s, (uint)len );
661 Reads \a len bytes from the stream into \a s and returns a reference to
664 The buffer \a s must be preallocated.
666 \sa readBytes(), QIODevice::readBlock(), writeRawBytes()
669 QDataStream &QDataStream::readRawBytes( char *s, uint len )
672 if ( printable ) { // printable data
673 register Q_INT8 *p = (Q_INT8*)s;
676 } else { // read data char array
677 dev->readBlock( s, len );
683 /*****************************************************************************
684 QDataStream write functions
685 *****************************************************************************/
689 \fn QDataStream &QDataStream::operator<<( Q_UINT8 i )
690 Writes an unsigned byte to the stream and returns a reference to
695 Writes a signed byte to the stream.
698 QDataStream &QDataStream::operator<<( Q_INT8 i )
701 if ( printable && (i == '\\' || !isprint(i)) ) {
702 char buf[6]; // write octal code
704 buf[1] = '0' + ((i >> 6) & 0x07);
705 buf[2] = '0' + ((i >> 3) & 0x07);
706 buf[3] = '0' + (i & 0x07);
708 dev->writeBlock( buf, 4 );
717 \fn QDataStream &QDataStream::operator<<( Q_UINT16 i )
718 Writes an unsigned 16-bit integer to the stream and returns a reference
723 Writes a signed 16-bit integer to the stream and returns a reference to
727 QDataStream &QDataStream::operator<<( Q_INT16 i )
730 if ( printable ) { // printable data
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);
741 dev->writeBlock( b, 2 );
748 \fn QDataStream &QDataStream::operator<<( Q_UINT32 i )
749 Writes an unsigned 32-bit integer to the stream and returns a reference to
754 Writes a signed 32-bit integer to the stream and returns a reference to
758 QDataStream &QDataStream::operator<<( Q_INT32 i )
761 if ( printable ) { // printable data
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);
774 dev->writeBlock( b, 4 );
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.
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.
790 QDataStream &QDataStream::operator<<( Q_INT64 i )
793 if ( printable ) { // printable data
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 ) {
812 dev->writeBlock( b, sizeof(Q_INT64) );
818 \fn QDataStream &QDataStream::operator<<( uint i )
819 Writes an unsigned integer to the stream as a 32-bit unsigned integer
821 Returns a reference to the stream.
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.
832 Writes a 32-bit floating point number to the stream using the standard
833 IEEE754 format. Returns a reference to the stream.
836 QDataStream &QDataStream::operator<<( float f )
839 if ( printable ) { // printable data
841 sprintf( buf, "%g\n", (double)f );
842 dev->writeBlock( buf, strlen(buf) );
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);
854 dev->writeBlock( b, 4 );
862 Writes a 64-bit floating point number to the stream using the standard
863 IEEE754 format. Returns a reference to the stream.
866 QDataStream &QDataStream::operator<<( double f )
869 if ( printable ) { // printable data
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);
886 dev->writeBlock( b, 8 );
893 Writes the '\0'-terminated string \a s to the stream and returns
894 a reference to the stream.
896 The string is serialized using writeBytes().
899 QDataStream &QDataStream::operator<<( const char *s )
902 *this << (Q_UINT32)0;
905 uint len = qstrlen( s ) + 1; // also write null terminator
906 *this << (Q_UINT32)len; // write length specifier
907 return writeRawBytes( s, len );
912 Writes the length specifier \a len and the buffer \a s to the stream and
913 returns a reference to the stream.
915 The \a len is serialized as an Q_UINT32, followed by \a len bytes from
918 \sa writeRawBytes(), readBytes()
921 QDataStream &QDataStream::writeBytes(const char *s, uint len)
924 *this << (Q_UINT32)len; // write length specifier
926 writeRawBytes( s, len );
932 Writes \a len bytes from \a s to the stream and returns a reference to the
935 \sa writeBytes(), QIODevice::writeBlock(), readRawBytes()
938 QDataStream &QDataStream::writeRawBytes( const char *s, uint len )
941 if ( printable ) { // write printable
942 register char *p = (char *)s;
945 } else { // write data char array
946 dev->writeBlock( s, len );
951 #endif // QT_NO_DATASTREAM