summaryrefslogtreecommitdiffstats
path: root/src/tools/qdatastream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/qdatastream.cpp')
-rw-r--r--src/tools/qdatastream.cpp1170
1 files changed, 1170 insertions, 0 deletions
diff --git a/src/tools/qdatastream.cpp b/src/tools/qdatastream.cpp
new file mode 100644
index 000000000..0c59fdaf8
--- /dev/null
+++ b/src/tools/qdatastream.cpp
@@ -0,0 +1,1170 @@
+/****************************************************************************
+**
+** Implementation of TQDataStream class
+**
+** Created : 930831
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the tools module of the TQt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free TQt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing retquirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qdatastream.h"
+
+#ifndef QT_NO_DATASTREAM
+#include "qbuffer.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifndef Q_OS_TEMP
+#include <locale.h>
+#else
+#include "qt_windows.h"
+#endif
+
+/*!
+ \class TQDataStream qdatastream.h
+ \reentrant
+ \brief The TQDataStream class provides serialization of binary data
+ to a TQIODevice.
+
+ \ingroup io
+
+ A data stream is a binary stream of encoded information which is
+ 100% independent of the host computer's operating system, CPU or
+ byte order. For example, a data stream that is written by a PC
+ under Windows can be read by a Sun SPARC running Solaris.
+
+ You can also use a data stream to read/write \link #raw raw
+ unencoded binary data\endlink. If you want a "parsing" input
+ stream, see TQTextStream.
+
+ The TQDataStream class implements the serialization of C++'s basic
+ data types, like \c char, \c short, \c int, \c char*, etc.
+ Serialization of more complex data is accomplished by breaking up
+ the data into primitive units.
+
+ A data stream cooperates closely with a TQIODevice. A TQIODevice
+ represents an input/output medium one can read data from and write
+ data to. The TQFile class is an example of an IO device.
+
+ Example (write binary data to a stream):
+ \code
+ TQFile file( "file.dat" );
+ file.open( IO_WriteOnly );
+ TQDataStream stream( &file ); // we will serialize the data into the file
+ stream << "the answer is"; // serialize a string
+ stream << (Q_INT32)42; // serialize an integer
+ \endcode
+
+ Example (read binary data from a stream):
+ \code
+ TQFile file( "file.dat" );
+ file.open( IO_ReadOnly );
+ TQDataStream stream( &file ); // read the data serialized from the file
+ TQString str;
+ Q_INT32 a;
+ stream >> str >> a; // extract "the answer is" and 42
+ \endcode
+
+ Each item written to the stream is written in a predefined binary
+ format that varies depending on the item's type. Supported TQt
+ types include TQBrush, TQColor, TQDateTime, TQFont, TQPixmap, TQString,
+ TQVariant and many others. For the complete list of all TQt types
+ supporting data streaming see the \link datastreamformat.html
+ Format of the TQDataStream operators \endlink.
+
+ For integers it is best to always cast to a TQt integer type for
+ writing, and to read back into the same TQt integer type. This
+ ensures that you get integers of the size you want and insulates
+ you from compiler and platform differences.
+
+ To take one example, a \c char* string is written as a 32-bit
+ integer equal to the length of the string including the NUL byte
+ ('\0'), followed by all the characters of the string including the
+ NUL byte. When reading a \c char* string, 4 bytes are read to
+ create the 32-bit length value, then that many characters for the
+ \c char* string including the NUL are read.
+
+ The initial IODevice is usually set in the constructor, but can be
+ changed with setDevice(). If you've reached the end of the data
+ (or if there is no IODevice set) atEnd() will return TRUE.
+
+ If you want the data to be compatible with an earlier version of
+ TQt use setVersion().
+
+ If you want the data to be human-readable, e.g. for debugging, you
+ can set the data stream into printable data mode with
+ setPrintableData(). The data is then written slower, in a bloated
+ but human readable format.
+
+ If you are producing a new binary data format, such as a file
+ format for documents created by your application, you could use a
+ TQDataStream to write the data in a portable format. Typically, you
+ would write a brief header containing a magic string and a version
+ number to give yourself room for future expansion. For example:
+
+ \code
+ TQFile file( "file.xxx" );
+ file.open( IO_WriteOnly );
+ TQDataStream stream( &file );
+
+ // Write a header with a "magic number" and a version
+ stream << (Q_UINT32)0xA0B0C0D0;
+ stream << (Q_INT32)123;
+
+ // Write the data
+ stream << [lots of interesting data]
+ \endcode
+
+ Then read it in with:
+
+ \code
+ TQFile file( "file.xxx" );
+ file.open( IO_ReadOnly );
+ TQDataStream stream( &file );
+
+ // Read and check the header
+ Q_UINT32 magic;
+ stream >> magic;
+ if ( magic != 0xA0B0C0D0 )
+ return XXX_BAD_FILE_FORMAT;
+
+ // Read the version
+ Q_INT32 version;
+ stream >> version;
+ if ( version < 100 )
+ return XXX_BAD_FILE_TOO_OLD;
+ if ( version > 123 )
+ return XXX_BAD_FILE_TOO_NEW;
+ if ( version <= 110 )
+ stream.setVersion(1);
+
+ // Read the data
+ stream >> [lots of interesting data];
+ if ( version > 120 )
+ stream >> [data new in XXX version 1.2];
+ stream >> [other interesting data];
+ \endcode
+
+ You can select which byte order to use when serializing data. The
+ default setting is big endian (MSB first). Changing it to little
+ endian breaks the portability (unless the reader also changes to
+ little endian). We recommend keeping this setting unless you have
+ special retquirements.
+
+ \target raw
+ \section1 Reading and writing raw binary data
+
+ You may wish to read/write your own raw binary data to/from the
+ data stream directly. Data may be read from the stream into a
+ preallocated char* using readRawBytes(). Similarly data can be
+ written to the stream using writeRawBytes(). Notice that any
+ encoding/decoding of the data must be done by you.
+
+ A similar pair of functions is readBytes() and writeBytes(). These
+ differ from their \e raw counterparts as follows: readBytes()
+ reads a Q_UINT32 which is taken to be the length of the data to be
+ read, then that number of bytes is read into the preallocated
+ char*; writeBytes() writes a Q_UINT32 containing the length of the
+ data, followed by the data. Notice that any encoding/decoding of
+ the data (apart from the length Q_UINT32) must be done by you.
+
+ \sa TQTextStream TQVariant
+*/
+
+/*!
+ \enum TQDataStream::ByteOrder
+
+ The byte order used for reading/writing the data.
+
+ \value BigEndian the default
+ \value LittleEndian
+*/
+
+
+/*****************************************************************************
+ TQDataStream member functions
+ *****************************************************************************/
+
+#if defined(QT_CHECK_STATE)
+#undef CHECK_STREAM_PRECOND
+#define CHECK_STREAM_PRECOND if ( !dev ) { \
+ qWarning( "TQDataStream: No device" ); \
+ return *this; }
+#else
+#define CHECK_STREAM_PRECOND
+#endif
+
+static int systemWordSize = 0;
+static bool systemBigEndian;
+
+static const int DefaultStreamVersion = 6;
+// ### On next version bump, TQPen::width() should not be restricted to 8-bit values.
+// ### On next version bump, when streaming invalid TQVariants, just the type should
+// be written, no "data" after it
+// 6 is default in TQt 3.3
+// 5 is default in TQt 3.1
+// 4 is default in TQt 3.0
+// 3 is default in TQt 2.1
+// 2 is the TQt 2.0.x format
+// 1 is the TQt 1.x format
+
+/*!
+ Constructs a data stream that has no IO device.
+
+ \sa setDevice()
+*/
+
+TQDataStream::TQDataStream()
+{
+ if ( systemWordSize == 0 ) // get system features
+ qSysInfo( &systemWordSize, &systemBigEndian );
+ dev = 0; // no device set
+ owndev = FALSE;
+ byteorder = BigEndian; // default byte order
+ printable = FALSE;
+ ver = DefaultStreamVersion;
+ noswap = systemBigEndian;
+}
+
+/*!
+ Constructs a data stream that uses the IO device \a d.
+
+ \warning If you use TQSocket or TQSocketDevice as the IO device \a d
+ for reading data, you must make sure that enough data is available
+ on the socket for the operation to successfully proceed;
+ TQDataStream does not have any means to handle or recover from
+ short-reads.
+
+ \sa setDevice(), device()
+*/
+
+TQDataStream::TQDataStream( TQIODevice *d )
+{
+ if ( systemWordSize == 0 ) // get system features
+ qSysInfo( &systemWordSize, &systemBigEndian );
+ dev = d; // set device
+ owndev = FALSE;
+ byteorder = BigEndian; // default byte order
+ printable = FALSE;
+ ver = DefaultStreamVersion;
+ noswap = systemBigEndian;
+}
+
+/*!
+ Constructs a data stream that operates on a byte array, \a a,
+ through an internal TQBuffer device. The \a mode is a
+ TQIODevice::mode(), usually either \c IO_ReadOnly or \c
+ IO_WriteOnly.
+
+ Example:
+ \code
+ static char bindata[] = { 231, 1, 44, ... };
+ TQByteArray a;
+ a.setRawData( bindata, sizeof(bindata) ); // a points to bindata
+ TQDataStream stream( a, IO_ReadOnly ); // open on a's data
+ stream >> [something]; // read raw bindata
+ a.resetRawData( bindata, sizeof(bindata) ); // finished
+ \endcode
+
+ The TQByteArray::setRawData() function is not for the inexperienced.
+*/
+
+TQDataStream::TQDataStream( TQByteArray a, int mode )
+{
+ if ( systemWordSize == 0 ) // get system features
+ qSysInfo( &systemWordSize, &systemBigEndian );
+ dev = new TQBuffer( a ); // create device
+ ((TQBuffer *)dev)->open( mode ); // open device
+ owndev = TRUE;
+ byteorder = BigEndian; // default byte order
+ printable = FALSE;
+ ver = DefaultStreamVersion;
+ noswap = systemBigEndian;
+}
+
+/*!
+ Destroys the data stream.
+
+ The destructor will not affect the current IO device, unless it is
+ an internal IO device processing a TQByteArray passed in the \e
+ constructor, in which case the internal IO device is destroyed.
+*/
+
+TQDataStream::~TQDataStream()
+{
+ if ( owndev )
+ delete dev;
+}
+
+
+/*!
+ \fn TQIODevice *TQDataStream::device() const
+
+ Returns the IO device currently set.
+
+ \sa setDevice(), unsetDevice()
+*/
+
+/*!
+ void TQDataStream::setDevice(TQIODevice *d )
+
+ Sets the IO device to \a d.
+
+ \sa device(), unsetDevice()
+*/
+
+void TQDataStream::setDevice(TQIODevice *d )
+{
+ if ( owndev ) {
+ delete dev;
+ owndev = FALSE;
+ }
+ dev = d;
+}
+
+/*!
+ Unsets the IO device. This is the same as calling setDevice( 0 ).
+
+ \sa device(), setDevice()
+*/
+
+void TQDataStream::unsetDevice()
+{
+ setDevice( 0 );
+}
+
+
+/*!
+ \fn bool TQDataStream::atEnd() const
+
+ Returns TRUE if the IO device has reached the end position (end of
+ the stream or file) or if there is no IO device set; otherwise
+ returns FALSE, i.e. if the current position of the IO device is
+ before the end position.
+
+ \sa TQIODevice::atEnd()
+*/
+
+/*!\fn bool TQDataStream::eof() const
+
+ \obsolete
+
+ Returns TRUE if the IO device has reached the end position (end of
+ stream or file) or if there is no IO device set.
+
+ Returns FALSE if the current position of the read/write head of the IO
+ device is somewhere before the end position.
+
+ \sa TQIODevice::atEnd()
+*/
+
+/*!
+ \fn int TQDataStream::byteOrder() const
+
+ Returns the current byte order setting -- either \c BigEndian or
+ \c LittleEndian.
+
+ \sa setByteOrder()
+*/
+
+/*!
+ Sets the serialization byte order to \a bo.
+
+ The \a bo parameter can be \c TQDataStream::BigEndian or \c
+ TQDataStream::LittleEndian.
+
+ The default setting is big endian. We recommend leaving this
+ setting unless you have special retquirements.
+
+ \sa byteOrder()
+*/
+
+void TQDataStream::setByteOrder( int bo )
+{
+ byteorder = bo;
+ if ( systemBigEndian )
+ noswap = byteorder == BigEndian;
+ else
+ noswap = byteorder == LittleEndian;
+}
+
+
+/*!
+ \fn bool TQDataStream::isPrintableData() const
+
+ Returns TRUE if the printable data flag has been set; otherwise
+ returns FALSE.
+
+ \sa setPrintableData()
+*/
+
+/*!
+ \fn void TQDataStream::setPrintableData( bool enable )
+
+ If \a enable is TRUE, data will be output in a human readable
+ format. If \a enable is FALSE, data will be output in a binary
+ format.
+
+ If \a enable is TRUE, the write functions will generate output
+ that consists of printable characters (7 bit ASCII). This output
+ will typically be a lot larger than the default binary output, and
+ consequently slower to write.
+
+ We recommend only enabling printable data for debugging purposes.
+*/
+
+
+/*!
+ \fn int TQDataStream::version() const
+
+ Returns the version number of the data serialization format. In TQt
+ 3.1, this number is 5.
+
+ \sa setVersion()
+*/
+
+/*!
+ \fn void TQDataStream::setVersion( int v )
+
+ Sets the version number of the data serialization format to \a v.
+
+ You don't need to set a version if you are using the current
+ version of TQt.
+
+ In order to accommodate new functionality, the datastream
+ serialization format of some TQt classes has changed in some
+ versions of TQt. If you want to read data that was created by an
+ earlier version of TQt, or write data that can be read by a program
+ that was compiled with an earlier version of TQt, use this function
+ to modify the serialization format of TQDataStream.
+
+ \table
+ \header \i TQt Version \i TQDataStream Version
+ \row \i TQt 3.3 \i11 6
+ \row \i TQt 3.2 \i11 5
+ \row \i TQt 3.1 \i11 5
+ \row \i TQt 3.0 \i11 4
+ \row \i TQt 2.1.x and TQt 2.2.x \i11 3
+ \row \i TQt 2.0.x \i11 2
+ \row \i TQt 1.x \i11 1
+ \endtable
+
+ \sa version()
+*/
+
+/*****************************************************************************
+ TQDataStream read functions
+ *****************************************************************************/
+
+#if defined(Q_OS_HPUX) && !defined(__LP64__)
+extern "C" long long __strtoll( const char *, char**, int );
+#endif
+
+static Q_INT64 read_int_ascii( TQDataStream *s )
+{
+ register int n = 0;
+ char buf[40];
+ for ( ;; ) {
+ buf[n] = s->device()->getch();
+ if ( buf[n] == '\n' || n > 38 ) // $-terminator
+ break;
+ n++;
+ }
+ buf[n] = '\0';
+
+#if defined(__LP64__) || defined(Q_OS_OSF)
+ // sizeof(long) == 8
+ return strtol(buf, (char **)0, 10);
+#else
+# if defined(Q_OS_TEMP)
+ return strtol( buf, (char**)0, 10 );
+# elif defined(Q_OS_WIN)
+ return _atoi64( buf );
+# elif defined(Q_OS_HPUX)
+ return __strtoll( buf, (char**)0, 10 );
+# elif defined(Q_OS_MACX) && defined(QT_MACOSX_VERSION) && QT_MACOSX_VERSION < 0x1020
+ return strtoq( buf, (char**)0, 10 );
+# else
+ return strtoll( buf, (char**)0, 10 ); // C99 function
+# endif
+#endif
+}
+
+/*!
+ \overload TQDataStream &TQDataStream::operator>>( Q_UINT8 &i )
+
+ Reads an unsigned byte from the stream into \a i, and returns a
+ reference to the stream.
+*/
+
+/*!
+ Reads a signed byte from the stream into \a i, and returns a
+ reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( Q_INT8 &i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ i = (Q_INT8)dev->getch();
+ if ( i == '\\' ) { // read octal code
+ char buf[4];
+ dev->readBlock( buf, 3 );
+ i = (buf[2] & 0x07)+((buf[1] & 0x07) << 3)+((buf[0] & 0x07) << 6);
+ }
+ } else { // data or text
+ i = (Q_INT8)dev->getch();
+ }
+ return *this;
+}
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator>>( Q_UINT16 &i )
+
+ Reads an unsigned 16-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 16-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( Q_INT16 &i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ i = (Q_INT16)read_int_ascii( this );
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&i, sizeof(Q_INT16) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[2];
+ dev->readBlock( b, 2 );
+ *p++ = b[1];
+ *p = b[0];
+ }
+ return *this;
+}
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator>>( Q_UINT32 &i )
+
+ Reads an unsigned 32-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 32-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( Q_INT32 &i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ i = (Q_INT32)read_int_ascii( this );
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&i, sizeof(Q_INT32) );
+ } else { // swap bytes
+ uchar *p = (uchar *)(&i);
+ char b[4];
+ dev->readBlock( b, 4 );
+ *p++ = b[3];
+ *p++ = b[2];
+ *p++ = b[1];
+ *p = b[0];
+ }
+ return *this;
+}
+
+/*!
+ \overload TQDataStream &TQDataStream::operator>>( Q_UINT64 &i )
+
+ Reads an unsigned 64-bit integer from the stream, into \a i, and
+ returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Reads a signed 64-bit integer from the stream into \a i, and
+ returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( Q_INT64 &i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ i = read_int_ascii( this );
+ } else if ( version() < 6 ) {
+ Q_UINT32 i1, i2;
+ *this >> i2 >> i1;
+ i = ((Q_UINT64)i1 << 32) + i2;
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&i, sizeof(Q_INT64) );
+ } else { // swap bytes
+ uchar *p = (uchar *)(&i);
+ char b[8];
+ dev->readBlock( b, 8 );
+ *p++ = b[7];
+ *p++ = b[6];
+ *p++ = b[5];
+ *p++ = b[4];
+ *p++ = b[3];
+ *p++ = b[2];
+ *p++ = b[1];
+ *p = b[0];
+ }
+ return *this;
+}
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator>>( Q_ULONG &i )
+
+ Reads an unsigned integer of the system's word length from the
+ stream, into \a i, and returns a reference to the stream.
+*/
+
+#if !defined(Q_OS_WIN64)
+/*!
+ \overload
+
+ Reads a signed integer of the system's word length from the stream
+ into \a i, and returns a reference to the stream.
+
+*/
+
+TQDataStream &TQDataStream::operator>>( Q_LONG &i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ i = (Q_LONG)read_int_ascii( this );
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&i, sizeof(Q_LONG) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[sizeof(Q_LONG)];
+ dev->readBlock( b, sizeof(Q_LONG) );
+ for ( int j = sizeof(Q_LONG); j; )
+ *p++ = b[--j];
+ }
+ return *this;
+}
+#endif
+
+static double read_double_ascii( TQDataStream *s )
+{
+ register int n = 0;
+ char buf[80];
+ for ( ;; ) {
+ buf[n] = s->device()->getch();
+ if ( buf[n] == '\n' || n > 78 ) // $-terminator
+ break;
+ n++;
+ }
+ buf[n] = '\0';
+ return atof( buf );
+}
+
+
+/*!
+ \overload
+
+ Reads a 32-bit floating point number from the stream into \a f,
+ using the standard IEEE754 format. Returns a reference to the
+ stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( float &f )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ f = (float)read_double_ascii( this );
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&f, sizeof(float) );
+ } else { // swap bytes
+ uchar *p = (uchar *)(&f);
+ char b[4];
+ dev->readBlock( b, 4 );
+ *p++ = b[3];
+ *p++ = b[2];
+ *p++ = b[1];
+ *p = b[0];
+ }
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Reads a 64-bit floating point number from the stream into \a f,
+ using the standard IEEE754 format. Returns a reference to the
+ stream.
+*/
+
+TQDataStream &TQDataStream::operator>>( double &f )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ f = read_double_ascii( this );
+ } else if ( noswap ) { // no conversion needed
+ dev->readBlock( (char *)&f, sizeof(double) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&f);
+ char b[8];
+ dev->readBlock( b, 8 );
+ *p++ = b[7];
+ *p++ = b[6];
+ *p++ = b[5];
+ *p++ = b[4];
+ *p++ = b[3];
+ *p++ = b[2];
+ *p++ = b[1];
+ *p = b[0];
+ }
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Reads the '\0'-terminated string \a s from the stream and returns
+ a reference to the stream.
+
+ Space for the string is allocated using \c new -- the caller must
+ destroy it with delete[].
+*/
+
+TQDataStream &TQDataStream::operator>>( char *&s )
+{
+ uint len = 0;
+ return readBytes( s, len );
+}
+
+
+/*!
+ Reads the buffer \a s from the stream and returns a reference to
+ the stream.
+
+ The buffer \a s is allocated using \c new. Destroy it with the \c
+ delete[] operator. If the length is zero or \a s cannot be
+ allocated, \a s is set to 0.
+
+ The \a l parameter will be set to the length of the buffer.
+
+ The serialization format is a Q_UINT32 length specifier first,
+ then \a l bytes of data. Note that the data is \e not encoded.
+
+ \sa readRawBytes(), writeBytes()
+*/
+
+TQDataStream &TQDataStream::readBytes( char *&s, uint &l )
+{
+ CHECK_STREAM_PRECOND
+ Q_UINT32 len;
+ *this >> len; // first read length spec
+ l = (uint)len;
+ if ( len == 0 || eof() ) {
+ s = 0;
+ return *this;
+ } else {
+ s = new char[len]; // create char array
+ Q_CHECK_PTR( s );
+ if ( !s ) // no memory
+ return *this;
+ return readRawBytes( s, (uint)len );
+ }
+}
+
+
+/*!
+ Reads \a len bytes from the stream into \a s and returns a
+ reference to the stream.
+
+ The buffer \a s must be preallocated. The data is \e not encoded.
+
+ \sa readBytes(), TQIODevice::readBlock(), writeRawBytes()
+*/
+
+TQDataStream &TQDataStream::readRawBytes( char *s, uint len )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ register Q_INT8 *p = (Q_INT8*)s;
+ if ( version() < 4 ) {
+ while ( len-- ) {
+ Q_INT32 tmp;
+ *this >> tmp;
+ *p++ = tmp;
+ }
+ } else {
+ while ( len-- )
+ *this >> *p++;
+ }
+ } else { // read data char array
+ dev->readBlock( s, len );
+ }
+ return *this;
+}
+
+
+/*****************************************************************************
+ TQDataStream write functions
+ *****************************************************************************/
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator<<( Q_UINT8 i )
+
+ Writes an unsigned byte, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ Writes a signed byte, \a i, to the stream and returns a reference
+ to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( Q_INT8 i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable && (i == '\\' || !isprint((uchar) i)) ) {
+ char buf[6]; // write octal code
+ buf[0] = '\\';
+ buf[1] = '0' + ((i >> 6) & 0x07);
+ buf[2] = '0' + ((i >> 3) & 0x07);
+ buf[3] = '0' + (i & 0x07);
+ buf[4] = '\0';
+ dev->writeBlock( buf, 4 );
+ } else {
+ dev->putch( i );
+ }
+ return *this;
+}
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator<<( Q_UINT16 i )
+
+ Writes an unsigned 16-bit integer, \a i, to the stream and returns
+ a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Writes a signed 16-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( Q_INT16 i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ char buf[16];
+ sprintf( buf, "%d\n", i );
+ dev->writeBlock( buf, strlen(buf) );
+ } else if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&i, sizeof(Q_INT16) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[2];
+ b[1] = *p++;
+ b[0] = *p;
+ dev->writeBlock( b, 2 );
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes a signed 32-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( Q_INT32 i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ char buf[16];
+ sprintf( buf, "%d\n", i );
+ dev->writeBlock( buf, strlen(buf) );
+ } else if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&i, sizeof(Q_INT32) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[4];
+ b[3] = *p++;
+ b[2] = *p++;
+ b[1] = *p++;
+ b[0] = *p;
+ dev->writeBlock( b, 4 );
+ }
+ return *this;
+}
+
+/*!
+ \overload TQDataStream &TQDataStream::operator<<( Q_UINT64 i )
+
+ Writes an unsigned 64-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Writes a signed 64-bit integer, \a i, to the stream and returns a
+ reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( Q_INT64 i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ char buf[16];
+#ifdef Q_OS_WIN
+ sprintf( buf, "%I64d\n", i );
+#else
+ sprintf( buf, "%lld\n", i );
+#endif
+ dev->writeBlock( buf, strlen(buf) );
+ } else if ( version() < 6 ) {
+ Q_UINT32 i1 = i & 0xffffffff;
+ Q_UINT32 i2 = i >> 32;
+ *this << i2 << i1;
+ } else if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&i, sizeof(Q_INT64) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[8];
+ b[7] = *p++;
+ b[6] = *p++;
+ b[5] = *p++;
+ b[4] = *p++;
+ b[3] = *p++;
+ b[2] = *p++;
+ b[1] = *p++;
+ b[0] = *p;
+ dev->writeBlock( b, 8 );
+ }
+ return *this;
+}
+
+/*!
+ \overload TQDataStream &TQDataStream::operator<<( Q_ULONG i )
+
+ Writes an unsigned integer \a i, of the system's word length, to
+ the stream and returns a reference to the stream.
+*/
+
+#if !defined(Q_OS_WIN64)
+/*!
+ \overload
+
+ Writes a signed integer \a i, of the system's word length, to the
+ stream and returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( Q_LONG i )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ char buf[20];
+ sprintf( buf, "%ld\n", i );
+ dev->writeBlock( buf, strlen(buf) );
+ } else if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&i, sizeof(Q_LONG) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&i);
+ char b[sizeof(Q_LONG)];
+ for ( int j = sizeof(Q_LONG); j; )
+ b[--j] = *p++;
+ dev->writeBlock( b, sizeof(Q_LONG) );
+ }
+ return *this;
+}
+#endif
+
+
+/*!
+ \overload TQDataStream &TQDataStream::operator<<( Q_UINT32 i )
+
+ Writes an unsigned integer, \a i, to the stream as a 32-bit
+ unsigned integer (Q_UINT32). Returns a reference to the stream.
+*/
+
+/*!
+ \overload
+
+ Writes a 32-bit floating point number, \a f, to the stream using
+ the standard IEEE754 format. Returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( float f )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ TQString num = TQString::number((double)f);
+ dev->writeBlock(num.latin1(), num.length());
+ dev->putch('\n');
+ } else {
+ float g = f; // fixes float-on-stack problem
+ if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&g, sizeof(float) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&g);
+ char b[4];
+ b[3] = *p++;
+ b[2] = *p++;
+ b[1] = *p++;
+ b[0] = *p;
+ dev->writeBlock( b, 4 );
+ }
+ }
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Writes a 64-bit floating point number, \a f, to the stream using
+ the standard IEEE754 format. Returns a reference to the stream.
+*/
+
+TQDataStream &TQDataStream::operator<<( double f )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // printable data
+ TQString num = TQString::number((double)f);
+ dev->writeBlock(num.latin1(), num.length());
+ dev->putch('\n');
+ } else if ( noswap ) { // no conversion needed
+ dev->writeBlock( (char *)&f, sizeof(double) );
+ } else { // swap bytes
+ register uchar *p = (uchar *)(&f);
+ char b[8];
+ b[7] = *p++;
+ b[6] = *p++;
+ b[5] = *p++;
+ b[4] = *p++;
+ b[3] = *p++;
+ b[2] = *p++;
+ b[1] = *p++;
+ b[0] = *p;
+ dev->writeBlock( b, 8 );
+ }
+ return *this;
+}
+
+
+/*!
+ \overload
+
+ Writes the '\0'-terminated string \a s to the stream and returns a
+ reference to the stream.
+
+ The string is serialized using writeBytes().
+*/
+
+TQDataStream &TQDataStream::operator<<( const char *s )
+{
+ if ( !s ) {
+ *this << (Q_UINT32)0;
+ return *this;
+ }
+ uint len = qstrlen( s ) + 1; // also write null terminator
+ *this << (Q_UINT32)len; // write length specifier
+ return writeRawBytes( s, len );
+}
+
+
+/*!
+ Writes the length specifier \a len and the buffer \a s to the
+ stream and returns a reference to the stream.
+
+ The \a len is serialized as a Q_UINT32, followed by \a len bytes
+ from \a s. Note that the data is \e not encoded.
+
+ \sa writeRawBytes(), readBytes()
+*/
+
+TQDataStream &TQDataStream::writeBytes(const char *s, uint len)
+{
+ CHECK_STREAM_PRECOND
+ *this << (Q_UINT32)len; // write length specifier
+ if ( len )
+ writeRawBytes( s, len );
+ return *this;
+}
+
+
+/*!
+ Writes \a len bytes from \a s to the stream and returns a
+ reference to the stream. The data is \e not encoded.
+
+ \sa writeBytes(), TQIODevice::writeBlock(), readRawBytes()
+*/
+
+TQDataStream &TQDataStream::writeRawBytes( const char *s, uint len )
+{
+ CHECK_STREAM_PRECOND
+ if ( printable ) { // write printable
+ if ( version() < 4 ) {
+ register char *p = (char *)s;
+ while ( len-- )
+ *this << *p++;
+ } else {
+ register Q_INT8 *p = (Q_INT8*)s;
+ while ( len-- )
+ *this << *p++;
+ }
+ } else { // write data char array
+ dev->writeBlock( s, len );
+ }
+ return *this;
+}
+
+#endif // QT_NO_DATASTREAM