src/qt3support/text/q3textstream.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3textstream.h"
       
    43 #include <qdebug.h>
       
    44 
       
    45 #ifndef QT_NO_TEXTSTREAM
       
    46 #include "qtextcodec.h"
       
    47 #include "qregexp.h"
       
    48 #include "qbuffer.h"
       
    49 #include "qfile.h"
       
    50 #include "q3cstring.h"
       
    51 #include <stdio.h>
       
    52 #include <ctype.h>
       
    53 #include <stdlib.h>
       
    54 #ifndef Q_OS_WINCE
       
    55 #include <locale.h>
       
    56 #endif
       
    57 
       
    58 #if defined(Q_OS_WIN32)
       
    59 #include "qt_windows.h"
       
    60 #endif
       
    61 
       
    62 QT_BEGIN_NAMESPACE
       
    63 
       
    64 #ifndef QT_NO_TEXTCODEC
       
    65 static void resetCodecConverterState(QTextCodec::ConverterState *state) {
       
    66     state->flags = QTextCodec::DefaultConversion;
       
    67     state->remainingChars = state->invalidChars =
       
    68            state->state_data[0] = state->state_data[1] = state->state_data[2] = 0;
       
    69     if (state->d) qFree(state->d);
       
    70     state->d = 0;
       
    71 }
       
    72 #endif
       
    73 
       
    74 /*!
       
    75     \class Q3TextStream
       
    76     \compat
       
    77     \reentrant
       
    78     \brief The Q3TextStream class provides basic functions for reading
       
    79     and writing text using a QIODevice.
       
    80 
       
    81     The text stream class has a functional interface that is very
       
    82     similar to that of the standard C++ iostream class.
       
    83 
       
    84     Qt provides several global functions similar to the ones in iostream:
       
    85     \table
       
    86     \header \i Function \i Meaning
       
    87     \row \i bin \i sets the Q3TextStream to read/write binary numbers
       
    88     \row \i oct \i sets the Q3TextStream to read/write octal numbers
       
    89     \row \i dec \i sets the Q3TextStream to read/write decimal numbers
       
    90     \row \i hex \i sets the Q3TextStream to read/write hexadecimal numbers
       
    91     \row \i endl \i forces a line break
       
    92     \row \i flush \i forces the QIODevice to flush any buffered data
       
    93     \row \i ws \i eats any available whitespace (on input)
       
    94     \row \i reset \i resets the Q3TextStream to its default mode (see reset())
       
    95     \row \i qSetW(int) \i sets the \link width() field width \endlink
       
    96     to the given argument
       
    97     \row \i qSetFill(int) \i sets the \link fill() fill character
       
    98     \endlink to the given argument
       
    99     \row \i qSetPrecision(int) \i sets the \link precision() precision
       
   100     \endlink to the given argument
       
   101     \endtable
       
   102 
       
   103     \warning By default Q3TextStream will automatically detect whether
       
   104     integers in the stream are in decimal, octal, hexadecimal or
       
   105     binary format when reading from the stream. In particular, a
       
   106     leading '0' signifies octal, i.e. the sequence "0100" will be
       
   107     interpreted as 64.
       
   108 
       
   109     The Q3TextStream class reads and writes text; it is not appropriate
       
   110     for dealing with binary data (but QDataStream is).
       
   111 
       
   112     By default, output of Unicode text (i.e. QString) is done using
       
   113     the local 8-bit encoding. This can be changed using the
       
   114     setEncoding() method. For input, the Q3TextStream will auto-detect
       
   115     standard Unicode "byte order marked" text files; otherwise the
       
   116     local 8-bit encoding is used.
       
   117 
       
   118     The QIODevice is set in the constructor, or later using
       
   119     setDevice(). If the end of the input is reached atEnd() returns
       
   120     TRUE. Data can be read into variables of the appropriate type
       
   121     using the operator>>() overloads, or read in its entirety into a
       
   122     single string using read(), or read a line at a time using
       
   123     readLine(). Whitespace can be skipped over using skipWhiteSpace().
       
   124     You can set flags for the stream using flags() or setf(). The
       
   125     stream also supports width(), precision() and fill(); use reset()
       
   126     to reset the defaults.
       
   127 
       
   128     \sa QDataStream
       
   129 */
       
   130 
       
   131 /*!
       
   132     \enum Q3TextStream::Encoding
       
   133 
       
   134     \value Locale
       
   135     \value Latin1
       
   136     \value Unicode
       
   137     \value UnicodeNetworkOrder
       
   138     \value UnicodeReverse
       
   139     \value RawUnicode
       
   140     \value UnicodeUTF8
       
   141 
       
   142     See setEncoding() for an explanation of the encodings.
       
   143 */
       
   144 
       
   145 /*
       
   146   \class QTSManip
       
   147   \internal
       
   148 */
       
   149 
       
   150 #if defined(QT_CHECK_STATE)
       
   151 #undef  CHECK_STREAM_PRECOND
       
   152 #define CHECK_STREAM_PRECOND  if ( !dev ) {				\
       
   153 				qWarning( "Q3TextStream: No device" );	\
       
   154 				return *this; }
       
   155 #else
       
   156 #define CHECK_STREAM_PRECOND
       
   157 #endif
       
   158 
       
   159 
       
   160 #define I_SHORT		0x0010
       
   161 #define I_INT		0x0020
       
   162 #define I_LONG		0x0030
       
   163 #define I_TYPE_MASK	0x00f0
       
   164 
       
   165 #define I_BASE_2	Q3TextStream::bin
       
   166 #define I_BASE_8	Q3TextStream::oct
       
   167 #define I_BASE_10	Q3TextStream::dec
       
   168 #define I_BASE_16	Q3TextStream::hex
       
   169 #define I_BASE_MASK	(Q3TextStream::bin | Q3TextStream::oct | Q3TextStream::dec | Q3TextStream::hex)
       
   170 
       
   171 #define I_SIGNED	0x0100
       
   172 #define I_UNSIGNED	0x0200
       
   173 #define I_SIGN_MASK	0x0f00
       
   174 
       
   175 
       
   176 static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character.
       
   177 static const uint getline_buf_size = 256; // bufsize used by ts_getline()
       
   178 
       
   179 const int Q3TextStream::basefield   = I_BASE_MASK;
       
   180 const int Q3TextStream::adjustfield = ( Q3TextStream::left |
       
   181 				       Q3TextStream::right |
       
   182 				       Q3TextStream::internal );
       
   183 const int Q3TextStream::floatfield  = ( Q3TextStream::scientific |
       
   184 				       Q3TextStream::fixed );
       
   185 
       
   186 
       
   187 class Q3TextStreamPrivate {
       
   188 public:
       
   189 #ifndef QT_NO_TEXTCODEC
       
   190     Q3TextStreamPrivate()
       
   191 	: sourceType( NotSet ) { }
       
   192     ~Q3TextStreamPrivate() {
       
   193     }
       
   194 #else
       
   195     Q3TextStreamPrivate() : sourceType( NotSet ) { }
       
   196     ~Q3TextStreamPrivate() { }
       
   197 #endif
       
   198     QString ungetcBuf;
       
   199 
       
   200     enum SourceType { NotSet, IODevice, String, ByteArray, File };
       
   201     SourceType sourceType;
       
   202 };
       
   203 
       
   204 
       
   205 // skips whitespace and returns the first non-whitespace character
       
   206 QChar Q3TextStream::eat_ws()
       
   207 {
       
   208     QChar c;
       
   209     do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) );
       
   210     return c;
       
   211 }
       
   212 
       
   213 void Q3TextStream::init()
       
   214 {
       
   215     // ### ungetcBuf = QEOF;
       
   216     dev = 0;
       
   217     owndev = FALSE;
       
   218     mapper = 0;
       
   219 #ifndef QT_NO_TEXTCODEC
       
   220     resetCodecConverterState(&mapperReadState);
       
   221     resetCodecConverterState(&mapperWriteState);
       
   222 #endif
       
   223     d = new Q3TextStreamPrivate;
       
   224     doUnicodeHeader = TRUE; // autodetect
       
   225     latin1 = TRUE; // should use locale?
       
   226     internalOrder = QChar::networkOrdered();
       
   227     networkOrder = TRUE;
       
   228 }
       
   229 
       
   230 /*!
       
   231     Constructs a data stream that has no IO device.
       
   232 */
       
   233 
       
   234 Q3TextStream::Q3TextStream()
       
   235 {
       
   236     init();
       
   237     setEncoding( Locale );
       
   238     reset();
       
   239     d->sourceType = Q3TextStreamPrivate::NotSet;
       
   240 }
       
   241 
       
   242 /*!
       
   243     Constructs a text stream that uses the IO device \a iod.
       
   244 */
       
   245 
       
   246 Q3TextStream::Q3TextStream( QIODevice *iod )
       
   247 {
       
   248     init();
       
   249     setEncoding( Locale );
       
   250     dev = iod;
       
   251     reset();
       
   252     d->sourceType = Q3TextStreamPrivate::IODevice;
       
   253 }
       
   254 
       
   255 // TODO: use special-case handling of this case in Q3TextStream, and
       
   256 //	 simplify this class to only deal with QChar or QString data.
       
   257 class QStringBuffer : public QIODevice {
       
   258 public:
       
   259     QStringBuffer( QString* str );
       
   260     ~QStringBuffer();
       
   261     bool  open( OpenMode m );
       
   262     void  close();
       
   263     qint64 size() const;
       
   264 
       
   265 protected:
       
   266     qint64 readData( char *p, qint64 len );
       
   267     qint64 writeData( const char *p, qint64 len );
       
   268 
       
   269     QString* s;
       
   270 
       
   271 private:
       
   272     QStringBuffer( const QStringBuffer & );
       
   273     QStringBuffer &operator=( const QStringBuffer & );
       
   274 };
       
   275 
       
   276 
       
   277 QStringBuffer::QStringBuffer( QString* str )
       
   278 {
       
   279     s = str;
       
   280 }
       
   281 
       
   282 QStringBuffer::~QStringBuffer()
       
   283 {
       
   284 }
       
   285 
       
   286 
       
   287 bool QStringBuffer::open( OpenMode m )
       
   288 {
       
   289     if ( !s ) {
       
   290 #if defined(QT_CHECK_STATE)
       
   291 	qWarning( "QStringBuffer::open: No string" );
       
   292 #endif
       
   293 	return FALSE;
       
   294     }
       
   295     if ( isOpen() ) {
       
   296 #if defined(QT_CHECK_STATE)
       
   297 	qWarning( "QStringBuffer::open: Buffer already open" );
       
   298 #endif
       
   299 	return FALSE;
       
   300     }
       
   301     setOpenMode( m );
       
   302     if ( m & QIODevice::Truncate )
       
   303 	s->truncate( 0 );
       
   304 
       
   305     if ( m & QIODevice::Append ) {
       
   306 	seek(s->length()*sizeof(QChar));
       
   307     } else {
       
   308 	seek(0);
       
   309     }
       
   310     return TRUE;
       
   311 }
       
   312 
       
   313 void QStringBuffer::close()
       
   314 {
       
   315     if ( isOpen() ) {
       
   316 	seek(0);
       
   317         QIODevice::close();
       
   318     }
       
   319 }
       
   320 
       
   321 qint64 QStringBuffer::size() const
       
   322 {
       
   323     return s ? s->length()*sizeof(QChar) : 0;
       
   324 }
       
   325 
       
   326 qint64 QStringBuffer::readData( char *p, qint64 len )
       
   327 {
       
   328 #if defined(QT_CHECK_STATE)
       
   329     Q_CHECK_PTR( p );
       
   330     if ( !isOpen() ) {
       
   331 	qWarning( "QStringBuffer::readBlock: Buffer not open" );
       
   332 	return qint64(-1);
       
   333     }
       
   334     if ( !isReadable() ) {
       
   335 	qWarning( "QStringBuffer::readBlock: Read operation not permitted" );
       
   336 	return qint64(-1);
       
   337     }
       
   338 #endif
       
   339     if ( pos() + len > qint64(s->length()*sizeof(QChar)) ) {
       
   340 	// overflow
       
   341 	if ( pos() >= qint64(s->length()*sizeof(QChar)) ) {
       
   342 	    return -1;
       
   343 	} else {
       
   344 	    len = s->length()*2 - pos();
       
   345 	}
       
   346     }
       
   347     memcpy( p, ((const char*)(s->unicode()))+pos(), len );
       
   348     return len;
       
   349 }
       
   350 
       
   351 qint64 QStringBuffer::writeData( const char *p, qint64 len )
       
   352 {
       
   353 #if defined(QT_CHECK_NULL)
       
   354     if ( p == 0 && len != 0 )
       
   355 	qWarning( "QStringBuffer::writeBlock: Null pointer error" );
       
   356 #endif
       
   357 #if defined(QT_CHECK_STATE)
       
   358     if ( !isOpen() ) {
       
   359 	qWarning( "QStringBuffer::writeBlock: Buffer not open" );
       
   360 	return -1;
       
   361     }
       
   362     if ( !isWritable() ) {
       
   363 	qWarning( "QStringBuffer::writeBlock: Write operation not permitted" );
       
   364 	return -1;
       
   365     }
       
   366     if ( pos()&1 ) {
       
   367 	qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" );
       
   368 	return -1;
       
   369     }
       
   370     if ( len&1 ) {
       
   371 	qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" );
       
   372 	return -1;
       
   373     }
       
   374 #endif
       
   375     s->replace(pos()/2, len/2, (QChar*)p, len/2);
       
   376     return len;
       
   377 }
       
   378 
       
   379 /*!
       
   380     Constructs a text stream that operates on the Unicode QString, \a
       
   381     str, through an internal device. The \a filemode argument is
       
   382     passed to the device's open() function; see \l{QIODevice::mode()}.
       
   383 
       
   384     If you set an encoding or codec with setEncoding() or setCodec(),
       
   385     this setting is ignored for text streams that operate on QString.
       
   386 
       
   387     Example:
       
   388     \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 0
       
   389 
       
   390     Writing data to the text stream will modify the contents of the
       
   391     string. The string will be expanded when data is written beyond
       
   392     the end of the string. Note that the string will not be truncated:
       
   393     \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 1
       
   394 
       
   395     Note that because QString is Unicode, you should not use
       
   396     readRawBytes() or writeRawBytes() on such a stream.
       
   397 */
       
   398 
       
   399 Q3TextStream::Q3TextStream( QString* str, int filemode )
       
   400 {
       
   401     // TODO: optimize for this case as it becomes more common
       
   402     //        (see QStringBuffer above)
       
   403     init();
       
   404     dev = new QStringBuffer( str );
       
   405     ((QStringBuffer *)dev)->open( QIODevice::OpenMode(filemode) );
       
   406     owndev = TRUE;
       
   407     setEncoding(RawUnicode);
       
   408     reset();
       
   409     d->sourceType = Q3TextStreamPrivate::String;
       
   410 }
       
   411 
       
   412 /*! \obsolete
       
   413 
       
   414   This constructor is equivalent to the constructor taking a QString*
       
   415   parameter.
       
   416 */
       
   417 
       
   418 Q3TextStream::Q3TextStream( QString& str, int filemode )
       
   419 {
       
   420     init();
       
   421     dev = new QStringBuffer( &str );
       
   422     ((QStringBuffer *)dev)->open( QIODevice::OpenMode(filemode) );
       
   423     owndev = TRUE;
       
   424     setEncoding(RawUnicode);
       
   425     reset();
       
   426     d->sourceType = Q3TextStreamPrivate::String;
       
   427 }
       
   428 
       
   429 /*!
       
   430     Constructs a text stream that operates on the byte array, \a a,
       
   431     through an internal QBuffer device. The \a mode argument is passed
       
   432     to the device's open() function; see \l{QIODevice::mode()}.
       
   433 
       
   434     Example:
       
   435     \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 2
       
   436 
       
   437     Writing data to the text stream will modify the contents of the
       
   438     array. The array will be expanded when data is written beyond the
       
   439     end of the string.
       
   440 
       
   441     Same example, using a QBuffer:
       
   442     \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 3
       
   443 */
       
   444 
       
   445 Q3TextStream::Q3TextStream( QByteArray &a, int mode )
       
   446 {
       
   447     init();
       
   448     QBuffer *buffer = new QBuffer;
       
   449     buffer->setBuffer( &a );
       
   450     buffer->open( QIODevice::OpenMode(mode) );
       
   451     dev = buffer;
       
   452     owndev = TRUE;
       
   453     setEncoding( Latin1 ); //### Locale???
       
   454     reset();
       
   455     d->sourceType = Q3TextStreamPrivate::ByteArray;
       
   456 }
       
   457 
       
   458 /*!
       
   459     Constructs a text stream that operates on an existing file handle
       
   460     \a fh through an internal QFile device. The \a mode argument is
       
   461     passed to the device's open() function; see \l{QIODevice::mode()}.
       
   462 
       
   463     Note that if you create a Q3TextStream \c cout or another name that
       
   464     is also used for another variable of a different type, some
       
   465     linkers may confuse the two variables, which will often cause
       
   466     crashes.
       
   467 */
       
   468 
       
   469 Q3TextStream::Q3TextStream( FILE *fh, int mode )
       
   470 {
       
   471     init();
       
   472     setEncoding( Locale ); //###
       
   473     dev = new QFile;
       
   474     ((QFile *)dev)->open( QIODevice::OpenMode(mode), fh );
       
   475     owndev = TRUE;
       
   476     reset();
       
   477     d->sourceType = Q3TextStreamPrivate::File;
       
   478 }
       
   479 
       
   480 /*!
       
   481     Destroys the text stream.
       
   482 
       
   483     The destructor does not affect the current IO device.
       
   484 */
       
   485 
       
   486 Q3TextStream::~Q3TextStream()
       
   487 {
       
   488     if ( owndev )
       
   489 	delete dev;
       
   490     delete d;
       
   491 }
       
   492 
       
   493 /*!
       
   494     \since 4.2
       
   495 
       
   496     Positions the read pointer at the first non-whitespace character.
       
   497 */
       
   498 void Q3TextStream::skipWhiteSpace()
       
   499 {
       
   500     ts_ungetc( eat_ws() );
       
   501 }
       
   502 
       
   503 
       
   504 /*!
       
   505     Tries to read \a len characters from the stream and stores them in
       
   506     \a buf. Returns the number of characters really read.
       
   507 
       
   508     \warning There will no QEOF appended if the read reaches the end
       
   509     of the file. EOF is reached when the return value does not equal
       
   510     \a len.
       
   511 */
       
   512 uint Q3TextStream::ts_getbuf( QChar* buf, uint len )
       
   513 {
       
   514     if ( len < 1 )
       
   515 	return 0;
       
   516 
       
   517     uint rnum = 0;   // the number of QChars really read
       
   518 
       
   519     if ( d && d->ungetcBuf.length() ) {
       
   520 	while ( rnum < len && rnum < uint(d->ungetcBuf.length()) ) {
       
   521 	    *buf = d->ungetcBuf.constref( rnum );
       
   522 	    buf++;
       
   523 	    rnum++;
       
   524 	}
       
   525 	d->ungetcBuf = d->ungetcBuf.mid( rnum );
       
   526 	if ( rnum >= len )
       
   527 	    return rnum;
       
   528     }
       
   529 
       
   530     // we use dev->ungetch() for one of the bytes of the unicode
       
   531     // byte-order mark, but a local unget hack for the other byte:
       
   532     int ungetHack = EOF;
       
   533 
       
   534     if ( doUnicodeHeader ) {
       
   535 	doUnicodeHeader = FALSE; // only at the top
       
   536 	int c1 = dev->getch();
       
   537 	if ( c1 == EOF )
       
   538 	    return rnum;
       
   539 	int c2 = dev->getch();
       
   540 	if ( c1 == 0xfe && c2 == 0xff ) {
       
   541 	    mapper = 0;
       
   542 	    latin1 = FALSE;
       
   543 	    internalOrder = QChar::networkOrdered();
       
   544 	    networkOrder = TRUE;
       
   545 	} else if ( c1 == 0xff && c2 == 0xfe ) {
       
   546 	    mapper = 0;
       
   547 	    latin1 = FALSE;
       
   548 	    internalOrder = !QChar::networkOrdered();
       
   549 	    networkOrder = FALSE;
       
   550 	} else {
       
   551 	    if ( c2 != EOF ) {
       
   552 	 	dev->ungetch( c2 );
       
   553 		ungetHack = c1;
       
   554 	    } else {
       
   555 		/*
       
   556 		  A small bug might hide here. If only the first byte
       
   557 		  of a file has made it so far, and that first byte
       
   558 		  is half of the byte-order mark, then the utfness
       
   559 		  will not be detected.
       
   560 		*/
       
   561 	 	dev->ungetch( c1 );
       
   562 	    }
       
   563 	}
       
   564     }
       
   565 
       
   566 #ifndef QT_NO_TEXTCODEC
       
   567     if ( mapper ) {
       
   568 	bool shortRead = FALSE;
       
   569         while( rnum < len ) {
       
   570 	    QString s;
       
   571 	    bool readBlock = !( len == 1+rnum );
       
   572 	    for (;;) {
       
   573 		// for efficiency: normally read a whole block
       
   574 		if ( readBlock ) {
       
   575 		    // guess buffersize; this may be wrong (too small or too
       
   576 		    // big). But we can handle this (either iterate reading
       
   577 		    // or use ungetcBuf).
       
   578 		    // Note that this might cause problems for codecs where
       
   579 		    // one byte can result in >1 Unicode Characters if bytes
       
   580 		    // are written to the stream in the meantime (loss of
       
   581 		    // synchronicity).
       
   582 		    uint rlen = len - rnum;
       
   583 		    char *cbuf = new char[ rlen ];
       
   584 		    if ( ungetHack != EOF ) {
       
   585 			rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
       
   586 			cbuf[0] = (char)ungetHack;
       
   587 			ungetHack = EOF;
       
   588 		    } else {
       
   589 			rlen = dev->readBlock( cbuf, rlen );
       
   590 		    }
       
   591 		    s += mapper->toUnicode( cbuf, rlen, &mapperWriteState );
       
   592 		    delete[] cbuf;
       
   593 		    // use buffered reading only for the first time, because we
       
   594 		    // have to get the stream synchronous again (this is easier
       
   595 		    // with single character reading)
       
   596 		    readBlock = FALSE;
       
   597 		}
       
   598 		// get stream (and codec) in sync
       
   599 		int c;
       
   600 		if ( ungetHack == EOF ) {
       
   601 		    c = dev->getch();
       
   602 		} else {
       
   603 		    c = ungetHack;
       
   604 		    ungetHack = EOF;
       
   605 		}
       
   606 		if ( c == EOF ) {
       
   607 		    shortRead = TRUE;
       
   608 		    break;
       
   609 		}
       
   610 		char b = c;
       
   611 		uint lengthBefore = s.length();
       
   612 		s += mapper->toUnicode( &b, 1, &mapperWriteState );
       
   613 
       
   614 		if ( uint(s.length()) > lengthBefore )
       
   615 		    break; // it seems we are in sync now
       
   616 	    }
       
   617 	    uint i = 0;
       
   618 	    uint end = QMIN( len-rnum, uint(s.length()) );
       
   619 	    while( i < end ) {
       
   620 		*buf = s.constref(i++);
       
   621 		buf++;
       
   622 	    }
       
   623 	    rnum += end;
       
   624 	    if ( uint(s.length()) > i ) {
       
   625 		// could be = but append is clearer
       
   626 		d->ungetcBuf.append( s.mid( i ) );
       
   627 	    }
       
   628 	    if ( shortRead )
       
   629 		return rnum;
       
   630 	}
       
   631     } else
       
   632 #endif
       
   633     if ( latin1 ) {
       
   634 	if ( len == 1+rnum ) {
       
   635 	    // use this method for one character because it is more efficient
       
   636 	    // (arnt doubts whether it makes a difference, but lets it stand)
       
   637 	    int c = (ungetHack == EOF) ? dev->getch() : ungetHack;
       
   638 	    if ( c != EOF ) {
       
   639 		*buf = QLatin1Char((char)c);
       
   640 		buf++;
       
   641 		rnum++;
       
   642 	    }
       
   643 	} else {
       
   644 	    if ( ungetHack != EOF ) {
       
   645 		*buf = QLatin1Char((char)ungetHack);
       
   646 		buf++;
       
   647 		rnum++;
       
   648 		ungetHack = EOF;
       
   649 	    }
       
   650 	    char *cbuf = new char[len - rnum];
       
   651 	    while ( !dev->atEnd() && rnum < len ) {
       
   652 		uint rlen = len - rnum;
       
   653 		rlen = dev->readBlock( cbuf, rlen );
       
   654 		char *it = cbuf;
       
   655 		char *end = cbuf + rlen;
       
   656 		while ( it < end ) {
       
   657 		    *buf = QLatin1Char(*it);
       
   658 		    buf++;
       
   659 		    it++;
       
   660 		}
       
   661 		rnum += rlen;
       
   662 	    }
       
   663 	    delete[] cbuf;
       
   664 	}
       
   665     } else { // UCS-2 or UTF-16
       
   666 	if ( len == 1+rnum ) {
       
   667 	    int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack;
       
   668 
       
   669 
       
   670             if ( c1 == EOF )
       
   671 		return rnum;
       
   672 	    int c2 = dev->getch();
       
   673 
       
   674 
       
   675             if ( c2 == EOF )
       
   676 		return rnum;
       
   677 
       
   678 	    if ( networkOrder ) {
       
   679 		*buf = QChar( c2, c1 );
       
   680 	    } else {
       
   681 		*buf = QChar( c1, c2 );
       
   682 	    }
       
   683 	    buf++;
       
   684 	    rnum++;
       
   685 	} else {
       
   686 	    char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible
       
   687 	    while ( !dev->atEnd() && rnum < len ) {
       
   688 		uint rlen = 2 * ( len-rnum );
       
   689 		if ( ungetHack != EOF ) {
       
   690 		    rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
       
   691 		    cbuf[0] = (char)ungetHack;
       
   692 		    ungetHack = EOF;
       
   693 		} else {
       
   694 		    rlen = dev->readBlock( cbuf, rlen );
       
   695 		}
       
   696 		// We can't use an odd number of bytes, so put it back. But
       
   697 		// do it only if we are capable of reading more -- normally
       
   698 		// there should not be an odd number, but the file might be
       
   699 		// truncated or not in UTF-16...
       
   700 		if ( (rlen & 1) == 1 )
       
   701 		    if ( !dev->atEnd() )
       
   702 			dev->ungetch( cbuf[--rlen] );
       
   703 		uint i = 0;
       
   704 		if ( networkOrder ) {
       
   705 		    while( i < rlen ) {
       
   706 			*buf = QChar( cbuf[i+1], cbuf[i] );
       
   707 			buf++;
       
   708 			i+=2;
       
   709 		    }
       
   710 		} else {
       
   711 		    while( i < rlen ) {
       
   712 			*buf = QChar( cbuf[i], cbuf[i+1] );
       
   713 			buf++;
       
   714 			i+=2;
       
   715 		    }
       
   716 		}
       
   717 		rnum += i/2;
       
   718 	    }
       
   719 	    delete[] cbuf;
       
   720 	}
       
   721     }
       
   722     return rnum;
       
   723 }
       
   724 
       
   725 /*!
       
   726     Tries to read one line, but at most len characters from the stream
       
   727     and stores them in \a buf.
       
   728 
       
   729     Returns the number of characters really read. Newlines are not
       
   730     stripped.
       
   731 
       
   732     There will be a QEOF appended if the read reaches the end of file;
       
   733     this is different to ts_getbuf().
       
   734 
       
   735     This function works only if a newline (as byte) is also a newline
       
   736     (as resulting character) since it uses QIODevice::readLine(). So
       
   737     use it only for such codecs where this is true!
       
   738 
       
   739     This function is (almost) a no-op for UTF 16. Don't use it if
       
   740     doUnicodeHeader is TRUE!
       
   741 */
       
   742 uint Q3TextStream::ts_getline( QChar* buf )
       
   743 {
       
   744     uint rnum=0;   // the number of QChars really read
       
   745     char cbuf[ getline_buf_size+1 ];
       
   746 
       
   747     if ( d && d->ungetcBuf.length() ) {
       
   748 	while( rnum < getline_buf_size && rnum < uint(d->ungetcBuf.length()) ) {
       
   749 	    buf[rnum] = d->ungetcBuf.constref(rnum);
       
   750 	    rnum++;
       
   751 	}
       
   752 	d->ungetcBuf = d->ungetcBuf.mid( rnum );
       
   753 	if ( rnum >= getline_buf_size )
       
   754 	    return rnum;
       
   755     }
       
   756 
       
   757 #ifndef QT_NO_TEXTCODEC
       
   758     if ( mapper ) {
       
   759 	QString s;
       
   760 	bool readBlock = TRUE;
       
   761 	for (;;) {
       
   762 	    // for efficiency: try to read a line
       
   763 	    if ( readBlock ) {
       
   764 		int rlen = getline_buf_size - rnum;
       
   765 		rlen = dev->readLine( cbuf, rlen+1 );
       
   766 		if ( rlen == -1 )
       
   767 		    rlen = 0;
       
   768 		s  += mapper->toUnicode( cbuf, rlen, &mapperWriteState );
       
   769 		readBlock = FALSE;
       
   770 	    }
       
   771 	    if ( dev->atEnd()
       
   772 		    || s.at( s.length()-1 ) == QLatin1Char('\n')
       
   773 		    || s.at( s.length()-1 ) == QLatin1Char('\r')
       
   774 	       ) {
       
   775 		break;
       
   776 	    } else {
       
   777 		// get stream (and codec) in sync
       
   778 		int c;
       
   779 		c = dev->getch();
       
   780 		if ( c == EOF ) {
       
   781 		    break;
       
   782 		}
       
   783 		char b = c;
       
   784 		uint lengthBefore = s.length();
       
   785 		s  += mapper->toUnicode( &b, 1, &mapperWriteState );
       
   786 		if ( uint(s.length()) > lengthBefore )
       
   787 		    break; // it seems we are in sync now
       
   788 	    }
       
   789 	}
       
   790 	uint i = 0;
       
   791 	while( rnum < getline_buf_size && i < uint(s.length()) )
       
   792 	    buf[rnum++] = s.constref(i++);
       
   793 	if ( uint(s.length()) > i )
       
   794 	    // could be = but append is clearer
       
   795 	    d->ungetcBuf.append( s.mid( i ) );
       
   796 	if ( rnum < getline_buf_size && dev->atEnd() )
       
   797 	    buf[rnum++] = QEOF;
       
   798     } else
       
   799 #endif
       
   800     if ( latin1 ) {
       
   801 	int rlen = getline_buf_size - rnum;
       
   802 	rlen = dev->readLine( cbuf, rlen+1 );
       
   803 	if ( rlen == -1 )
       
   804 	    rlen = 0;
       
   805 	char *end = cbuf+rlen;
       
   806 	char *it = cbuf;
       
   807 	buf +=rnum;
       
   808 	while ( it != end ) {
       
   809 	    buf->setCell( *(it++) );
       
   810 	    buf->setRow( 0 );
       
   811 	    buf++;
       
   812 	}
       
   813 	rnum += rlen;
       
   814 	if ( rnum < getline_buf_size && dev->atEnd() )
       
   815 	    buf[1] = QEOF;
       
   816     }
       
   817     return rnum;
       
   818 }
       
   819 
       
   820 
       
   821 /*!
       
   822     Puts one character into the stream.
       
   823 */
       
   824 void Q3TextStream::ts_putc( QChar c )
       
   825 {
       
   826 #ifndef QT_NO_TEXTCODEC
       
   827     if ( mapper ) {
       
   828 	int len = 1;
       
   829 	QString s = c;
       
   830 	Q3CString block = mapper->fromUnicode( s.data(), len );//, &mapperReadState );
       
   831 	dev->writeBlock( block );
       
   832     } else
       
   833 #endif
       
   834     if ( latin1 ) {
       
   835 	if ( c.row() )
       
   836 	    dev->putch( '?' ); // unknown character
       
   837 	else
       
   838 	    dev->putch( c.cell() );
       
   839     } else {
       
   840 	if ( doUnicodeHeader ) {
       
   841 	    doUnicodeHeader = FALSE;
       
   842 	    ts_putc( QChar::ByteOrderMark );
       
   843 	}
       
   844 	if ( internalOrder ) {
       
   845 	    // this case is needed by QStringBuffer
       
   846 	    dev->writeBlock( (char*)&c, sizeof(QChar) );
       
   847 	} else if ( networkOrder ) {
       
   848 	    dev->putch( c.row() );
       
   849 	    dev->putch( c.cell() );
       
   850 	} else {
       
   851 	    dev->putch( c.cell() );
       
   852 	    dev->putch( c.row() );
       
   853 	}
       
   854     }
       
   855 }
       
   856 
       
   857 /*!
       
   858     Puts one character into the stream.
       
   859 */
       
   860 void Q3TextStream::ts_putc( int ch )
       
   861 {
       
   862     ts_putc( QChar((ushort)ch) );
       
   863 }
       
   864 
       
   865 bool Q3TextStream::ts_isdigit( QChar c )
       
   866 {
       
   867     return c.isDigit();
       
   868 }
       
   869 
       
   870 bool Q3TextStream::ts_isspace( QChar c )
       
   871 {
       
   872     return c.isSpace();
       
   873 }
       
   874 
       
   875 void Q3TextStream::ts_ungetc( QChar c )
       
   876 {
       
   877     if ( c.unicode() == 0xffff )
       
   878 	return;
       
   879 
       
   880     d->ungetcBuf.prepend( c );
       
   881 }
       
   882 
       
   883 /*!
       
   884     \since 4.2
       
   885 
       
   886     Reads \a len bytes from the stream into \a s and returns a
       
   887     reference to the stream.
       
   888 
       
   889     The buffer \a s must be preallocated.
       
   890 
       
   891     Note that no encoding is done by this function.
       
   892 
       
   893     \warning The behavior of this function is undefined unless the
       
   894     stream's encoding is set to Unicode or Latin1.
       
   895 
       
   896     \sa QIODevice::readBlock()
       
   897 */
       
   898 
       
   899 Q3TextStream &Q3TextStream::readRawBytes( char *s, uint len )
       
   900 {
       
   901     dev->readBlock( s, len );
       
   902     return *this;
       
   903 }
       
   904 
       
   905 /*!
       
   906     \since 4.2
       
   907 
       
   908     Writes the \a len bytes from \a s to the stream and returns a
       
   909     reference to the stream.
       
   910 
       
   911     Note that no encoding is done by this function.
       
   912 
       
   913     \sa QIODevice::writeBlock()
       
   914 */
       
   915 
       
   916 Q3TextStream &Q3TextStream::writeRawBytes( const char* s, uint len )
       
   917 {
       
   918     dev->writeBlock( s, len );
       
   919     return *this;
       
   920 }
       
   921 
       
   922 
       
   923 Q3TextStream &Q3TextStream::writeBlock( const char* p, uint len )
       
   924 {
       
   925     if ( doUnicodeHeader ) {
       
   926 	doUnicodeHeader = FALSE;
       
   927 	if ( !mapper && !latin1 ) {
       
   928 	    ts_putc( QChar::ByteOrderMark );
       
   929         }
       
   930     }
       
   931     // QCString and const char * are treated as Latin-1
       
   932     if ( !mapper && latin1 ) {
       
   933 	dev->writeBlock( p, len );
       
   934     } else if ( !mapper && internalOrder ) {
       
   935 	QChar *u = new QChar[len];
       
   936 	for ( uint i = 0; i < len; i++ )
       
   937 	    u[i] = QLatin1Char(p[i]);
       
   938 	dev->writeBlock( (char*)u, len * sizeof(QChar) );
       
   939 	delete [] u;
       
   940     }
       
   941 #ifndef QT_NO_TEXTCODEC
       
   942     else if (mapper) {
       
   943         QString s = QString::fromLatin1(p, len);
       
   944         int l = len;
       
   945         Q3CString block = mapper->fromUnicode(s.data(), l );//, &mapperReadState );
       
   946         dev->writeBlock( block );
       
   947     }
       
   948 #endif
       
   949     else {
       
   950 	for ( uint i = 0; i < len; i++ )
       
   951 	    ts_putc( (uchar)p[i] );
       
   952     }
       
   953     return *this;
       
   954 }
       
   955 
       
   956 Q3TextStream &Q3TextStream::writeBlock( const QChar* p, uint len )
       
   957 {
       
   958 #ifndef QT_NO_TEXTCODEC
       
   959     if ( mapper ) {
       
   960 	QConstString s( p, len );
       
   961 	int l = len;
       
   962 	Q3CString block = mapper->fromUnicode( s.string().data(), l );//, &mapperReadState );
       
   963 	dev->writeBlock( block );
       
   964     } else
       
   965 #endif
       
   966     if ( latin1 ) {
       
   967 	dev->write(QString( p, len ).toLatin1());
       
   968     } else if ( internalOrder ) {
       
   969 	if ( doUnicodeHeader ) {
       
   970 	    doUnicodeHeader = FALSE;
       
   971 	    ts_putc( QChar::ByteOrderMark );
       
   972 	}
       
   973 	dev->writeBlock( (char*)p, sizeof(QChar)*len );
       
   974     } else {
       
   975 	for (uint i=0; i<len; i++)
       
   976 	    ts_putc( p[i] );
       
   977     }
       
   978     return *this;
       
   979 }
       
   980 
       
   981 /*!
       
   982     \since 4.2
       
   983 
       
   984     Resets the text stream.
       
   985 
       
   986     \list
       
   987     \i All flags are set to 0.
       
   988     \i The field width is set to 0.
       
   989     \i The fill character is set to ' ' (Space).
       
   990     \i The precision is set to 6.
       
   991     \endlist
       
   992 
       
   993     \sa setf(), width(), fill(), precision()
       
   994 */
       
   995 
       
   996 void Q3TextStream::reset()
       
   997 {
       
   998     fflags = 0;
       
   999     fwidth = 0;
       
  1000     fillchar = ' ';
       
  1001     fprec = 6;
       
  1002 }
       
  1003 
       
  1004 /*!
       
  1005     \fn QIODevice *Q3TextStream::device() const
       
  1006     \since 4.2
       
  1007 
       
  1008     Returns the IO device currently set.
       
  1009 
       
  1010     \sa setDevice(), unsetDevice()
       
  1011 */
       
  1012 
       
  1013 /*!
       
  1014     \since 4.2
       
  1015 
       
  1016     Sets the IO device to \a iod.
       
  1017 
       
  1018     \sa device(), unsetDevice()
       
  1019 */
       
  1020 
       
  1021 void Q3TextStream::setDevice( QIODevice *iod )
       
  1022 {
       
  1023     if ( owndev ) {
       
  1024 	delete dev;
       
  1025 	owndev = FALSE;
       
  1026     }
       
  1027     dev = iod;
       
  1028     d->sourceType = Q3TextStreamPrivate::IODevice;
       
  1029 }
       
  1030 
       
  1031 /*!
       
  1032     \since 4.2
       
  1033 
       
  1034     Unsets the IO device. Equivalent to setDevice( 0 ).
       
  1035 
       
  1036     \sa device(), setDevice()
       
  1037 */
       
  1038 
       
  1039 void Q3TextStream::unsetDevice()
       
  1040 {
       
  1041     setDevice( 0 );
       
  1042     d->sourceType = Q3TextStreamPrivate::NotSet;
       
  1043 }
       
  1044 
       
  1045 /*!
       
  1046     \fn bool Q3TextStream::atEnd() const
       
  1047     \since 4.2
       
  1048 
       
  1049     Returns TRUE if the IO device has reached the end position (end of
       
  1050     the stream or file) or if there is no IO device set; otherwise
       
  1051     returns FALSE.
       
  1052 
       
  1053     \sa QIODevice::atEnd()
       
  1054 */
       
  1055 
       
  1056 /*!\fn bool Q3TextStream::eof() const
       
  1057 
       
  1058   \obsolete
       
  1059 
       
  1060   This function has been renamed to atEnd().
       
  1061 
       
  1062   \sa QIODevice::atEnd()
       
  1063 */
       
  1064 
       
  1065 /*****************************************************************************
       
  1066   Q3TextStream read functions
       
  1067  *****************************************************************************/
       
  1068 
       
  1069 
       
  1070 /*!
       
  1071     \overload
       
  1072 
       
  1073     Reads a char \a c from the stream and returns a reference to the
       
  1074     stream. Note that whitespace is skipped.
       
  1075 */
       
  1076 
       
  1077 Q3TextStream &Q3TextStream::operator>>( char &c )
       
  1078 {
       
  1079     CHECK_STREAM_PRECOND
       
  1080     c = eat_ws().toLatin1();
       
  1081     return *this;
       
  1082 }
       
  1083 
       
  1084 /*!
       
  1085     Reads a char \a c from the stream and returns a reference to the
       
  1086     stream. Note that whitespace is \e not skipped.
       
  1087 */
       
  1088 
       
  1089 Q3TextStream &Q3TextStream::operator>>( QChar &c )
       
  1090 {
       
  1091     CHECK_STREAM_PRECOND
       
  1092     c = ts_getc();
       
  1093     return *this;
       
  1094 }
       
  1095 
       
  1096 
       
  1097 ulong Q3TextStream::input_bin()
       
  1098 {
       
  1099     ulong val = 0;
       
  1100     QChar ch = eat_ws();
       
  1101     int dv = ch.digitValue();
       
  1102     while (  dv == 0 || dv == 1 ) {
       
  1103 	val = ( val << 1 ) + dv;
       
  1104 	ch = ts_getc();
       
  1105 	dv = ch.digitValue();
       
  1106     }
       
  1107     if ( ch != QEOF )
       
  1108 	ts_ungetc( ch );
       
  1109     return val;
       
  1110 }
       
  1111 
       
  1112 ulong Q3TextStream::input_oct()
       
  1113 {
       
  1114     ulong val = 0;
       
  1115     QChar ch = eat_ws();
       
  1116     int dv = ch.digitValue();
       
  1117     while ( dv >= 0 && dv <= 7 ) {
       
  1118 	val = ( val << 3 ) + dv;
       
  1119 	ch = ts_getc();
       
  1120 	dv = ch.digitValue();
       
  1121     }
       
  1122     if ( dv == 8 || dv == 9 ) {
       
  1123 	while ( ts_isdigit(ch) )
       
  1124 	    ch = ts_getc();
       
  1125     }
       
  1126     if ( ch != QEOF )
       
  1127 	ts_ungetc( ch );
       
  1128     return val;
       
  1129 }
       
  1130 
       
  1131 ulong Q3TextStream::input_dec()
       
  1132 {
       
  1133     ulong val = 0;
       
  1134     QChar ch = eat_ws();
       
  1135     int dv = ch.digitValue();
       
  1136     while ( ts_isdigit(ch) ) {
       
  1137 	val = val * 10 + dv;
       
  1138 	ch = ts_getc();
       
  1139 	dv = ch.digitValue();
       
  1140     }
       
  1141     if ( ch != QEOF )
       
  1142 	ts_ungetc( ch );
       
  1143     return val;
       
  1144 }
       
  1145 
       
  1146 ulong Q3TextStream::input_hex()
       
  1147 {
       
  1148     ulong val = 0;
       
  1149     QChar ch = eat_ws();
       
  1150     char c = ch.toLatin1();
       
  1151     while ( isxdigit((uchar) c) ) {
       
  1152 	val <<= 4;
       
  1153 	if ( ts_isdigit(QLatin1Char(c)) )
       
  1154 	    val += c - '0';
       
  1155 	else
       
  1156 	    val += 10 + tolower( (uchar) c ) - 'a';
       
  1157         ch = ts_getc();
       
  1158 	c = ch.toLatin1();
       
  1159     }
       
  1160     if ( ch != QEOF )
       
  1161 	ts_ungetc( ch );
       
  1162     return val;
       
  1163 }
       
  1164 
       
  1165 long Q3TextStream::input_int()
       
  1166 {
       
  1167     long val;
       
  1168     QChar ch;
       
  1169     char c;
       
  1170     switch ( flags() & basefield ) {
       
  1171     case bin:
       
  1172 	val = (long)input_bin();
       
  1173 	break;
       
  1174     case oct:
       
  1175 	val = (long)input_oct();
       
  1176 	break;
       
  1177     case dec:
       
  1178         ch = eat_ws();
       
  1179 	c = ch.toLatin1();
       
  1180 	if ( ch == QEOF ) {
       
  1181 	    val = 0;
       
  1182 	} else {
       
  1183 	    if ( !(c == '-' || c == '+') )
       
  1184 		ts_ungetc( ch );
       
  1185 	    if ( c == '-' ) {
       
  1186 		ulong v = input_dec();
       
  1187 		if ( v ) {		// ensure that LONG_MIN can be read
       
  1188 		    v--;
       
  1189 		    val = -((long)v) - 1;
       
  1190 		} else {
       
  1191 		    val = 0;
       
  1192 		}
       
  1193 	    } else {
       
  1194 		val = (long)input_dec();
       
  1195 	    }
       
  1196 	}
       
  1197 	break;
       
  1198     case hex:
       
  1199 	val = (long)input_hex();
       
  1200 	break;
       
  1201     default:
       
  1202 	val = 0;
       
  1203         ch = eat_ws();
       
  1204 	c = ch.toLatin1();
       
  1205 	if ( c == '0' ) {		// bin, oct or hex
       
  1206             ch = ts_getc();
       
  1207 	    c = ch.toLatin1();
       
  1208 	    if ( tolower((uchar) c) == 'x' )
       
  1209 		val = (long)input_hex();
       
  1210 	    else if ( tolower((uchar) c) == 'b' )
       
  1211 		val = (long)input_bin();
       
  1212 	    else {			// octal
       
  1213 		ts_ungetc( ch );
       
  1214 		if ( c >= '0' && c <= '7' ) {
       
  1215 		    val = (long)input_oct();
       
  1216 		} else {
       
  1217 		    val = 0;
       
  1218 		}
       
  1219 	    }
       
  1220 	} else if ( ts_isdigit(ch) ) {
       
  1221 	    ts_ungetc( ch );
       
  1222 	    val = (long)input_dec();
       
  1223 	} else if ( c == '-' || c == '+' ) {
       
  1224 	    ulong v = input_dec();
       
  1225 	    if ( c == '-' ) {
       
  1226 		if ( v ) {		// ensure that LONG_MIN can be read
       
  1227 		    v--;
       
  1228 		    val = -((long)v) - 1;
       
  1229 		} else {
       
  1230 		    val = 0;
       
  1231 		}
       
  1232 	    } else {
       
  1233 		val = (long)v;
       
  1234 	    }
       
  1235 	}
       
  1236     }
       
  1237     return val;
       
  1238 }
       
  1239 
       
  1240 //
       
  1241 // We use a table-driven FSM to parse floating point numbers
       
  1242 // strtod() cannot be used directly since we're reading from a QIODevice
       
  1243 //
       
  1244 
       
  1245 double Q3TextStream::input_double()
       
  1246 {
       
  1247     const int Init	 = 0;			// states
       
  1248     const int Sign	 = 1;
       
  1249     const int Mantissa	 = 2;
       
  1250     const int Dot	 = 3;
       
  1251     const int Abscissa	 = 4;
       
  1252     const int ExpMark	 = 5;
       
  1253     const int ExpSign	 = 6;
       
  1254     const int Exponent	 = 7;
       
  1255     const int Done	 = 8;
       
  1256 
       
  1257     const int InputSign	 = 1;			// input tokens
       
  1258     const int InputDigit = 2;
       
  1259     const int InputDot	 = 3;
       
  1260     const int InputExp	 = 4;
       
  1261 
       
  1262     static const uchar table[8][5] = {
       
  1263      /* None	 InputSign   InputDigit InputDot InputExp */
       
  1264 	{ 0,	    Sign,     Mantissa,	 Dot,	   0,	   }, // Init
       
  1265 	{ 0,	    0,	      Mantissa,	 Dot,	   0,	   }, // Sign
       
  1266 	{ Done,	    Done,     Mantissa,	 Dot,	   ExpMark,}, // Mantissa
       
  1267 	{ 0,	    0,	      Abscissa,	 0,	   0,	   }, // Dot
       
  1268 	{ Done,	    Done,     Abscissa,	 Done,	   ExpMark,}, // Abscissa
       
  1269 	{ 0,	    ExpSign,  Exponent,	 0,	   0,	   }, // ExpMark
       
  1270 	{ 0,	    0,	      Exponent,	 0,	   0,	   }, // ExpSign
       
  1271 	{ Done,	    Done,     Exponent,	 Done,	   Done	   }  // Exponent
       
  1272     };
       
  1273 
       
  1274     int state = Init;				// parse state
       
  1275     int input;					// input token
       
  1276 
       
  1277     char buf[256];
       
  1278     int i = 0;
       
  1279     QChar c = eat_ws();
       
  1280 
       
  1281     for (;;) {
       
  1282 
       
  1283 	switch ( c.toLatin1() ) {
       
  1284 	    case '+':
       
  1285 	    case '-':
       
  1286 		input = InputSign;
       
  1287 		break;
       
  1288 	    case '0': case '1': case '2': case '3': case '4':
       
  1289 	    case '5': case '6': case '7': case '8': case '9':
       
  1290 		input = InputDigit;
       
  1291 		break;
       
  1292 	    case '.':
       
  1293 		input = InputDot;
       
  1294 		break;
       
  1295 	    case 'e':
       
  1296 	    case 'E':
       
  1297 		input = InputExp;
       
  1298 		break;
       
  1299 	    default:
       
  1300 		input = 0;
       
  1301 		break;
       
  1302 	}
       
  1303 
       
  1304 	state = table[state][input];
       
  1305 
       
  1306 	if  ( state == 0 || state == Done || i > 250 ) {
       
  1307 	    if ( i > 250 ) {			// ignore rest of digits
       
  1308 		do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) );
       
  1309 	    }
       
  1310 	    if ( c != QEOF )
       
  1311 		ts_ungetc( c );
       
  1312 	    buf[i] = '\0';
       
  1313 	    char *end;
       
  1314 	    return strtod( buf, &end );
       
  1315 	}
       
  1316 
       
  1317 	buf[i++] = c.toLatin1();
       
  1318 	c = ts_getc();
       
  1319     }
       
  1320 
       
  1321 #if !defined(Q_CC_EDG)
       
  1322     return 0.0;
       
  1323 #endif
       
  1324 }
       
  1325 
       
  1326 
       
  1327 /*!
       
  1328     \overload
       
  1329 
       
  1330     Reads a signed \c short integer \a i from the stream and returns a
       
  1331     reference to the stream. See flags() for an explanation of the
       
  1332     expected input format.
       
  1333 */
       
  1334 
       
  1335 Q3TextStream &Q3TextStream::operator>>( signed short &i )
       
  1336 {
       
  1337     CHECK_STREAM_PRECOND
       
  1338     i = (signed short)input_int();
       
  1339     return *this;
       
  1340 }
       
  1341 
       
  1342 
       
  1343 /*!
       
  1344     \overload
       
  1345 
       
  1346     Reads an unsigned \c short integer \a i from the stream and
       
  1347     returns a reference to the stream. See flags() for an explanation
       
  1348     of the expected input format.
       
  1349 */
       
  1350 
       
  1351 Q3TextStream &Q3TextStream::operator>>( unsigned short &i )
       
  1352 {
       
  1353     CHECK_STREAM_PRECOND
       
  1354     i = (unsigned short)input_int();
       
  1355     return *this;
       
  1356 }
       
  1357 
       
  1358 
       
  1359 /*!
       
  1360     \overload
       
  1361 
       
  1362     Reads a signed \c int \a i from the stream and returns a reference
       
  1363     to the stream. See flags() for an explanation of the expected
       
  1364     input format.
       
  1365 */
       
  1366 
       
  1367 Q3TextStream &Q3TextStream::operator>>( signed int &i )
       
  1368 {
       
  1369     CHECK_STREAM_PRECOND
       
  1370     i = (signed int)input_int();
       
  1371     return *this;
       
  1372 }
       
  1373 
       
  1374 
       
  1375 /*!
       
  1376     \overload
       
  1377 
       
  1378     Reads an unsigned \c int \a i from the stream and returns a
       
  1379     reference to the stream. See flags() for an explanation of the
       
  1380     expected input format.
       
  1381 */
       
  1382 
       
  1383 Q3TextStream &Q3TextStream::operator>>( unsigned int &i )
       
  1384 {
       
  1385     CHECK_STREAM_PRECOND
       
  1386     i = (unsigned int)input_int();
       
  1387     return *this;
       
  1388 }
       
  1389 
       
  1390 
       
  1391 /*!
       
  1392     \overload
       
  1393 
       
  1394     Reads a signed \c long int \a i from the stream and returns a
       
  1395     reference to the stream. See flags() for an explanation of the
       
  1396     expected input format.
       
  1397 */
       
  1398 
       
  1399 Q3TextStream &Q3TextStream::operator>>( signed long &i )
       
  1400 {
       
  1401     CHECK_STREAM_PRECOND
       
  1402     i = (signed long)input_int();
       
  1403     return *this;
       
  1404 }
       
  1405 
       
  1406 
       
  1407 /*!
       
  1408     \overload
       
  1409 
       
  1410     Reads an unsigned \c long int \a i from the stream and returns a
       
  1411     reference to the stream. See flags() for an explanation of the
       
  1412     expected input format.
       
  1413 */
       
  1414 
       
  1415 Q3TextStream &Q3TextStream::operator>>( unsigned long &i )
       
  1416 {
       
  1417     CHECK_STREAM_PRECOND
       
  1418     i = (unsigned long)input_int();
       
  1419     return *this;
       
  1420 }
       
  1421 
       
  1422 
       
  1423 /*!
       
  1424     \overload
       
  1425 
       
  1426     Reads a \c float \a f from the stream and returns a reference to
       
  1427     the stream. See flags() for an explanation of the expected input
       
  1428     format.
       
  1429 */
       
  1430 
       
  1431 Q3TextStream &Q3TextStream::operator>>( float &f )
       
  1432 {
       
  1433     CHECK_STREAM_PRECOND
       
  1434     f = (float)input_double();
       
  1435     return *this;
       
  1436 }
       
  1437 
       
  1438 
       
  1439 /*!
       
  1440     \overload
       
  1441 
       
  1442     Reads a \c double \a f from the stream and returns a reference to
       
  1443     the stream. See flags() for an explanation of the expected input
       
  1444     format.
       
  1445 */
       
  1446 
       
  1447 Q3TextStream &Q3TextStream::operator>>( double &f )
       
  1448 {
       
  1449     CHECK_STREAM_PRECOND
       
  1450     f = input_double();
       
  1451     return *this;
       
  1452 }
       
  1453 
       
  1454 
       
  1455 /*!
       
  1456     \overload
       
  1457 
       
  1458     Reads a "word" from the stream into \a s and returns a reference
       
  1459     to the stream.
       
  1460 
       
  1461     A word consists of characters for which isspace() returns FALSE.
       
  1462 */
       
  1463 
       
  1464 Q3TextStream &Q3TextStream::operator>>( char *s )
       
  1465 {
       
  1466     CHECK_STREAM_PRECOND
       
  1467     int maxlen = width( 0 );
       
  1468     QChar c = eat_ws();
       
  1469     if ( !maxlen )
       
  1470 	maxlen = -1;
       
  1471     while ( c != QEOF ) {
       
  1472 	if ( ts_isspace(c) || maxlen-- == 0 ) {
       
  1473 	    ts_ungetc( c );
       
  1474 	    break;
       
  1475 	}
       
  1476 	*s++ = c.toLatin1();
       
  1477 	c = ts_getc();
       
  1478     }
       
  1479 
       
  1480     *s = '\0';
       
  1481     return *this;
       
  1482 }
       
  1483 
       
  1484 /*!
       
  1485     \overload
       
  1486 
       
  1487     Reads a "word" from the stream into \a str and returns a reference
       
  1488     to the stream.
       
  1489 
       
  1490     A word consists of characters for which isspace() returns FALSE.
       
  1491 */
       
  1492 
       
  1493 Q3TextStream &Q3TextStream::operator>>( QString &str )
       
  1494 {
       
  1495     CHECK_STREAM_PRECOND
       
  1496     str=QString::fromLatin1("");
       
  1497     QChar	c = eat_ws();
       
  1498 
       
  1499     while ( c != QEOF ) {
       
  1500 	if ( ts_isspace(c) ) {
       
  1501 	    ts_ungetc( c );
       
  1502 	    break;
       
  1503 	}
       
  1504 
       
  1505 	str += c;
       
  1506 	c = ts_getc();
       
  1507     }
       
  1508 
       
  1509     return *this;
       
  1510 }
       
  1511 
       
  1512 /*!
       
  1513     \overload
       
  1514 
       
  1515     Reads a "word" from the stream into \a str and returns a reference
       
  1516     to the stream.
       
  1517 
       
  1518     A word consists of characters for which isspace() returns FALSE.
       
  1519 */
       
  1520 
       
  1521 Q3TextStream &Q3TextStream::operator>>( Q3CString &str )
       
  1522 {
       
  1523     CHECK_STREAM_PRECOND
       
  1524     Q3CString  *dynbuf = 0;
       
  1525     const int buflen = 256;
       
  1526     char      buffer[buflen];
       
  1527     char     *s = buffer;
       
  1528     int	      i = 0;
       
  1529     QChar	      c = eat_ws();
       
  1530 
       
  1531     while ( c != QEOF ) {
       
  1532 	if ( ts_isspace(c) ) {
       
  1533 	    ts_ungetc( c );
       
  1534 	    break;
       
  1535 	}
       
  1536 	if ( i >= buflen-1 ) {
       
  1537 	    if ( !dynbuf )  {			// create dynamic buffer
       
  1538 		dynbuf = new Q3CString(buflen*2);
       
  1539 		memcpy( dynbuf->data(), s, i );	// copy old data
       
  1540 	    } else if ( i >= (int)dynbuf->size()-1 ) {
       
  1541 		dynbuf->resize( dynbuf->size()*2 );
       
  1542 	    }
       
  1543 	    s = dynbuf->data();
       
  1544 	}
       
  1545 	s[i++] = c.toLatin1();
       
  1546 	c = ts_getc();
       
  1547     }
       
  1548     str.resize( i );
       
  1549     memcpy( str.data(), s, i );
       
  1550 
       
  1551     delete dynbuf;
       
  1552     return *this;
       
  1553 }
       
  1554 
       
  1555 
       
  1556 /*!
       
  1557     \since 4.2
       
  1558 
       
  1559     Reads a line from the stream and returns a string containing the
       
  1560     text.
       
  1561 
       
  1562     The returned string does not contain any trailing newline or
       
  1563     carriage return. Note that this is different from
       
  1564     QIODevice::readLine(), which does not strip the newline at the end
       
  1565     of the line.
       
  1566 
       
  1567     On EOF you will get a QString that is null. On reading an empty
       
  1568     line the returned QString is empty but not null.
       
  1569 
       
  1570     \sa QIODevice::readLine()
       
  1571 */
       
  1572 
       
  1573 QString Q3TextStream::readLine()
       
  1574 {
       
  1575 #if defined(QT_CHECK_STATE)
       
  1576     if ( !dev ) {
       
  1577 	qWarning( "Q3TextStream::readLine: No device" );
       
  1578 	return QString::null;
       
  1579     }
       
  1580 #endif
       
  1581     bool readCharByChar = TRUE;
       
  1582     QString result;
       
  1583 #if 0
       
  1584     if ( !doUnicodeHeader && (
       
  1585 	    (latin1) ||
       
  1586 	    (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8
       
  1587        ) ) {
       
  1588 	readCharByChar = FALSE;
       
  1589 	// use optimized read line
       
  1590 	QChar c[getline_buf_size];
       
  1591 	int pos = 0;
       
  1592 	bool eof = FALSE;
       
  1593 
       
  1594 	for (;;) {
       
  1595 	    pos = ts_getline( c );
       
  1596 	    if ( pos == 0 ) {
       
  1597 		// something went wrong; try fallback
       
  1598 		readCharByChar = TRUE;
       
  1599 		//dev->resetStatus();
       
  1600 		break;
       
  1601 	    }
       
  1602 	    if ( c[pos-1] == QEOF || c[pos-1] == '\n' ) {
       
  1603 		if ( pos>2 && c[pos-1]==QEOF && c[pos-2]=='\n' ) {
       
  1604 		    result += QString( c, pos-2 );
       
  1605 		} else if ( pos > 1 ) {
       
  1606 		    result += QString( c, pos-1 );
       
  1607 		}
       
  1608 		if ( pos == 1 && c[pos-1] == QEOF )
       
  1609 		    eof = TRUE;
       
  1610 		break;
       
  1611 	    } else {
       
  1612 		result += QString( c, pos );
       
  1613 	    }
       
  1614 	}
       
  1615 	if ( eof && result.isEmpty() )
       
  1616 	    return QString::null;
       
  1617     }
       
  1618 #endif
       
  1619     if ( readCharByChar ) {
       
  1620 	const int buf_size = 256;
       
  1621 	QChar c[buf_size];
       
  1622 	int pos = 0;
       
  1623 
       
  1624 	c[pos] = ts_getc();
       
  1625 	if ( c[pos] == QEOF )
       
  1626 	    return QString::null;
       
  1627 
       
  1628 	while ( c[pos] != QEOF && c[pos] != QLatin1Char('\n') ) {
       
  1629 	    if ( c[pos] == QLatin1Char('\r') ) { // ( handle mac and dos )
       
  1630 		QChar nextc = ts_getc();
       
  1631 		if ( nextc != QLatin1Char('\n') )
       
  1632 		    ts_ungetc( nextc );
       
  1633 		break;
       
  1634 	    }
       
  1635 	    pos++;
       
  1636 	    if ( pos >= buf_size ) {
       
  1637 		result += QString( c, pos );
       
  1638 		pos = 0;
       
  1639 	    }
       
  1640 	    c[pos] = ts_getc();
       
  1641 	}
       
  1642 	result += QString( c, pos );
       
  1643     }
       
  1644 
       
  1645     return result;
       
  1646 }
       
  1647 
       
  1648 
       
  1649 /*!
       
  1650     \since 4.2
       
  1651 
       
  1652     Reads the entire stream from the current position, and returns a string
       
  1653     containing the text.
       
  1654 
       
  1655     \sa readLine()
       
  1656 */
       
  1657 
       
  1658 QString Q3TextStream::read()
       
  1659 {
       
  1660 #if defined(QT_CHECK_STATE)
       
  1661     if ( !dev ) {
       
  1662 	qWarning( "Q3TextStream::read: No device" );
       
  1663 	return QString::null;
       
  1664     }
       
  1665 #endif
       
  1666     QString    result;
       
  1667     const uint bufsize = 512;
       
  1668     QChar      buf[bufsize];
       
  1669     uint       i, num, start;
       
  1670     bool       skipped_cr = FALSE;
       
  1671 
       
  1672     for (;;) {
       
  1673 	num = ts_getbuf(buf,bufsize);
       
  1674 	// convert dos (\r\n) and mac (\r) style eol to unix style (\n)
       
  1675 	start = 0;
       
  1676 	for ( i=0; i<num; i++ ) {
       
  1677 	    if ( buf[i] == QLatin1Char('\r') ) {
       
  1678 		// Only skip single cr's preceding lf's
       
  1679 		if ( skipped_cr ) {
       
  1680 		    result += buf[i];
       
  1681 		    start++;
       
  1682 		} else {
       
  1683 		    result += QString( &buf[start], i-start );
       
  1684 		    start = i+1;
       
  1685 		    skipped_cr = TRUE;
       
  1686 		}
       
  1687 	    } else {
       
  1688 		if ( skipped_cr ) {
       
  1689 		    if ( buf[i] != QLatin1Char('\n') ) {
       
  1690 			// Should not have skipped it
       
  1691 			result += QLatin1Char('\n');
       
  1692 		    }
       
  1693 		    skipped_cr = FALSE;
       
  1694 		}
       
  1695 	    }
       
  1696 	}
       
  1697 	if ( start < num )
       
  1698 	    result += QString( &buf[start], i-start );
       
  1699 	if ( num != bufsize ) // if ( EOF )
       
  1700 	    break;
       
  1701     }
       
  1702     return result;
       
  1703 }
       
  1704 
       
  1705 
       
  1706 
       
  1707 /*****************************************************************************
       
  1708   Q3TextStream write functions
       
  1709  *****************************************************************************/
       
  1710 
       
  1711 /*!
       
  1712     \since 4.2
       
  1713 
       
  1714     Writes character \c char to the stream and returns a reference to
       
  1715     the stream.
       
  1716 
       
  1717     The character \a c is assumed to be Latin1 encoded independent of
       
  1718     the Encoding set for the Q3TextStream.
       
  1719 */
       
  1720 Q3TextStream &Q3TextStream::operator<<( QChar c )
       
  1721 {
       
  1722     CHECK_STREAM_PRECOND
       
  1723     ts_putc( c );
       
  1724     return *this;
       
  1725 }
       
  1726 
       
  1727 /*!
       
  1728     \overload
       
  1729     \since 4.2
       
  1730 
       
  1731     Writes character \a c to the stream and returns a reference to the
       
  1732     stream.
       
  1733 */
       
  1734 Q3TextStream &Q3TextStream::operator<<( char c )
       
  1735 {
       
  1736     CHECK_STREAM_PRECOND
       
  1737     unsigned char uc = (unsigned char) c;
       
  1738     ts_putc( uc );
       
  1739     return *this;
       
  1740 }
       
  1741 
       
  1742 Q3TextStream &Q3TextStream::output_int( int format, ulong n, bool neg )
       
  1743 {
       
  1744     static const char hexdigits_lower[] = "0123456789abcdef";
       
  1745     static const char hexdigits_upper[] = "0123456789ABCDEF";
       
  1746     CHECK_STREAM_PRECOND
       
  1747     char buf[76];
       
  1748     register char *p;
       
  1749     int	  len;
       
  1750     const char *hexdigits;
       
  1751 
       
  1752     switch ( flags() & I_BASE_MASK ) {
       
  1753 
       
  1754 	case I_BASE_2:				// output binary number
       
  1755 	    switch ( format & I_TYPE_MASK ) {
       
  1756 		case I_SHORT: len=16; break;
       
  1757 		case I_INT:   len=sizeof(int)*8; break;
       
  1758 		case I_LONG:  len=32; break;
       
  1759 		default:      len = 0;
       
  1760 	    }
       
  1761 	    p = &buf[74];			// go reverse order
       
  1762 	    *p = '\0';
       
  1763 	    while ( len-- ) {
       
  1764 		*--p = (char)(n&1) + '0';
       
  1765 		n >>= 1;
       
  1766 		if ( !n )
       
  1767 		    break;
       
  1768 	    }
       
  1769 	    if ( flags() & showbase ) {		// show base
       
  1770 		*--p = (flags() & uppercase) ? 'B' : 'b';
       
  1771 		*--p = '0';
       
  1772 	    }
       
  1773 	    break;
       
  1774 
       
  1775 	case I_BASE_8:				// output octal number
       
  1776 	    p = &buf[74];
       
  1777 	    *p = '\0';
       
  1778 	    do {
       
  1779 		*--p = (char)(n&7) + '0';
       
  1780 		n >>= 3;
       
  1781 	    } while ( n );
       
  1782 	    if ( flags() & showbase )
       
  1783 		*--p = '0';
       
  1784 	    break;
       
  1785 
       
  1786 	case I_BASE_16:				// output hexadecimal number
       
  1787 	    p = &buf[74];
       
  1788 	    *p = '\0';
       
  1789 	    hexdigits = (flags() & uppercase) ?
       
  1790 		hexdigits_upper : hexdigits_lower;
       
  1791 	    do {
       
  1792 		*--p = hexdigits[(int)n&0xf];
       
  1793 		n >>= 4;
       
  1794 	    } while ( n );
       
  1795 	    if ( flags() & showbase ) {
       
  1796 		*--p = (flags() & uppercase) ? 'X' : 'x';
       
  1797 		*--p = '0';
       
  1798 	    }
       
  1799 	    break;
       
  1800 
       
  1801 	default:				// decimal base is default
       
  1802 	    p = &buf[74];
       
  1803 	    *p = '\0';
       
  1804 	    if ( neg )
       
  1805 		n = (ulong)(-(long)n);
       
  1806 	    do {
       
  1807 		*--p = ((int)(n%10)) + '0';
       
  1808 		n /= 10;
       
  1809 	    } while ( n );
       
  1810 	    if ( neg )
       
  1811 		*--p = '-';
       
  1812 	    else if ( flags() & showpos )
       
  1813 		*--p = '+';
       
  1814 	    if ( (flags() & internal) && fwidth && !ts_isdigit(QLatin1Char(*p)) ) {
       
  1815 		ts_putc( *p );			// special case for internal
       
  1816 		++p;				//   padding
       
  1817 		fwidth--;
       
  1818 		return *this << (const char*)p;
       
  1819 	    }
       
  1820     }
       
  1821     if ( fwidth ) {				// adjustment required
       
  1822 	if ( !(flags() & left) ) {		// but NOT left adjustment
       
  1823 	    len = qstrlen(p);
       
  1824 	    int padlen = fwidth - len;
       
  1825 	    if ( padlen <= 0 ) {		// no padding required
       
  1826 		writeBlock( p, len );
       
  1827 	    } else if ( padlen < (int)(p-buf) ) { // speeds up padding
       
  1828 		memset( p-padlen, (char)fillchar, padlen );
       
  1829 		writeBlock( p-padlen, padlen+len );
       
  1830 	    }
       
  1831 	    else				// standard padding
       
  1832 		*this << (const char*)p;
       
  1833 	}
       
  1834 	else
       
  1835 	    *this << (const char*)p;
       
  1836 	fwidth = 0;				// reset field width
       
  1837     }
       
  1838     else {
       
  1839 	writeBlock( p, qstrlen(p) );
       
  1840     }
       
  1841     return *this;
       
  1842 }
       
  1843 
       
  1844 
       
  1845 /*!
       
  1846     \overload
       
  1847     \since 4.2
       
  1848 
       
  1849     Writes a \c short integer \a i to the stream and returns a
       
  1850     reference to the stream.
       
  1851 */
       
  1852 
       
  1853 Q3TextStream &Q3TextStream::operator<<( signed short i )
       
  1854 {
       
  1855     return output_int( I_SHORT | I_SIGNED, i, i < 0 );
       
  1856 }
       
  1857 
       
  1858 
       
  1859 /*!
       
  1860     \overload
       
  1861     \since 4.2
       
  1862 
       
  1863     Writes an \c unsigned \c short integer \a i to the stream and
       
  1864     returns a reference to the stream.
       
  1865 */
       
  1866 
       
  1867 Q3TextStream &Q3TextStream::operator<<( unsigned short i )
       
  1868 {
       
  1869     return output_int( I_SHORT | I_UNSIGNED, i, FALSE );
       
  1870 }
       
  1871 
       
  1872 
       
  1873 /*!
       
  1874     \overload
       
  1875     \since 4.2
       
  1876 
       
  1877     Writes an \c int \a i to the stream and returns a reference to the
       
  1878     stream.
       
  1879 */
       
  1880 
       
  1881 Q3TextStream &Q3TextStream::operator<<( signed int i )
       
  1882 {
       
  1883     return output_int( I_INT | I_SIGNED, i, i < 0 );
       
  1884 }
       
  1885 
       
  1886 
       
  1887 /*!
       
  1888     \overload
       
  1889     \since 4.2
       
  1890 
       
  1891     Writes an \c unsigned \c int \a i to the stream and returns a
       
  1892     reference to the stream.
       
  1893 */
       
  1894 
       
  1895 Q3TextStream &Q3TextStream::operator<<( unsigned int i )
       
  1896 {
       
  1897     return output_int( I_INT | I_UNSIGNED, i, FALSE );
       
  1898 }
       
  1899 
       
  1900 
       
  1901 /*!
       
  1902     \overload
       
  1903     \since 4.2
       
  1904 
       
  1905     Writes a \c long \c int \a i to the stream and returns a reference
       
  1906     to the stream.
       
  1907 */
       
  1908 
       
  1909 Q3TextStream &Q3TextStream::operator<<( signed long i )
       
  1910 {
       
  1911     return output_int( I_LONG | I_SIGNED, i, i < 0 );
       
  1912 }
       
  1913 
       
  1914 
       
  1915 /*!
       
  1916     \overload
       
  1917     \since 4.2
       
  1918 
       
  1919     Writes an \c unsigned \c long \c int \a i to the stream and
       
  1920     returns a reference to the stream.
       
  1921 */
       
  1922 
       
  1923 Q3TextStream &Q3TextStream::operator<<( unsigned long i )
       
  1924 {
       
  1925     return output_int( I_LONG | I_UNSIGNED, i, FALSE );
       
  1926 }
       
  1927 
       
  1928 
       
  1929 /*!
       
  1930     \overload
       
  1931     \since 4.2
       
  1932 
       
  1933     Writes a \c float \a f to the stream and returns a reference to
       
  1934     the stream.
       
  1935 */
       
  1936 
       
  1937 Q3TextStream &Q3TextStream::operator<<( float f )
       
  1938 {
       
  1939     return *this << (double)f;
       
  1940 }
       
  1941 
       
  1942 /*!
       
  1943     \overload
       
  1944     \since 4.2
       
  1945 
       
  1946     Writes a \c double \a f to the stream and returns a reference to
       
  1947     the stream.
       
  1948 */
       
  1949 
       
  1950 Q3TextStream &Q3TextStream::operator<<( double f )
       
  1951 {
       
  1952     CHECK_STREAM_PRECOND
       
  1953     char f_char;
       
  1954     char format[16];
       
  1955     if ( (flags()&floatfield) == fixed )
       
  1956 	f_char = 'f';
       
  1957     else if ( (flags()&floatfield) == scientific )
       
  1958 	f_char = (flags() & uppercase) ? 'E' : 'e';
       
  1959     else
       
  1960 	f_char = (flags() & uppercase) ? 'G' : 'g';
       
  1961     register char *fs = format;			// generate format string
       
  1962     *fs++ = '%';				//   "%.<prec>l<f_char>"
       
  1963     *fs++ = '.';
       
  1964     int prec = precision();
       
  1965     if ( prec > 99 )
       
  1966 	prec = 99;
       
  1967     if ( prec >= 10 ) {
       
  1968 	*fs++ = prec / 10 + '0';
       
  1969 	*fs++ = prec % 10 + '0';
       
  1970     } else {
       
  1971 	*fs++ = prec + '0';
       
  1972     }
       
  1973     *fs++ = 'l';
       
  1974     *fs++ = f_char;
       
  1975     *fs = '\0';
       
  1976     QString num;
       
  1977     num.sprintf(format, f);			// convert to text
       
  1978     if ( fwidth )				// padding
       
  1979 	*this << num.latin1();
       
  1980     else					// just write it
       
  1981 	writeBlock(num.latin1(), num.length());
       
  1982     return *this;
       
  1983 }
       
  1984 
       
  1985 
       
  1986 /*!
       
  1987     \overload
       
  1988     \since 4.2
       
  1989 
       
  1990     Writes a string to the stream and returns a reference to the
       
  1991     stream.
       
  1992 
       
  1993     The string \a s is assumed to be Latin1 encoded independent of the
       
  1994     Encoding set for the Q3TextStream.
       
  1995 */
       
  1996 
       
  1997 Q3TextStream &Q3TextStream::operator<<( const char* s )
       
  1998 {
       
  1999     CHECK_STREAM_PRECOND
       
  2000     char padbuf[48];
       
  2001     uint len = qstrlen( s );			// don't write null terminator
       
  2002     if ( fwidth ) {				// field width set
       
  2003 	int padlen = fwidth - len;
       
  2004 	fwidth = 0;				// reset width
       
  2005 	if ( padlen > 0 ) {
       
  2006 	    char *ppad;
       
  2007 	    if ( padlen > 46 ) {		// create extra big fill buffer
       
  2008 		ppad = new char[padlen];
       
  2009 		Q_CHECK_PTR( ppad );
       
  2010 	    } else {
       
  2011 		ppad = padbuf;
       
  2012 	    }
       
  2013 	    memset( ppad, (char)fillchar, padlen );	// fill with fillchar
       
  2014 	    if ( !(flags() & left) ) {
       
  2015 		writeBlock( ppad, padlen );
       
  2016 		padlen = 0;
       
  2017 	    }
       
  2018 	    writeBlock( s, len );
       
  2019 	    if ( padlen )
       
  2020 		writeBlock( ppad, padlen );
       
  2021 	    if ( ppad != padbuf )		// delete extra big fill buf
       
  2022 		delete[] ppad;
       
  2023 	    return *this;
       
  2024 	}
       
  2025     }
       
  2026     writeBlock( s, len );
       
  2027     return *this;
       
  2028 }
       
  2029 
       
  2030 /*!
       
  2031     \overload
       
  2032     \since 4.2
       
  2033 
       
  2034     Writes \a s to the stream and returns a reference to the stream.
       
  2035 
       
  2036     The string \a s is assumed to be Latin1 encoded independent of the
       
  2037     Encoding set for the Q3TextStream.
       
  2038 */
       
  2039 
       
  2040 Q3TextStream &Q3TextStream::operator<<( const Q3CString & s )
       
  2041 {
       
  2042     return operator<<(s.data());
       
  2043 }
       
  2044 
       
  2045 /*!
       
  2046     \overload
       
  2047     \since 4.2
       
  2048 
       
  2049     Writes \a s to the stream and returns a reference to the stream.
       
  2050 */
       
  2051 
       
  2052 Q3TextStream &Q3TextStream::operator<<( const QString& s )
       
  2053 {
       
  2054     if ( !mapper && latin1 )
       
  2055 	return operator<<(s.latin1());
       
  2056     CHECK_STREAM_PRECOND
       
  2057     QString s1 = s;
       
  2058     if ( fwidth ) {				// field width set
       
  2059 	if ( !(flags() & left) ) {
       
  2060 	    s1 = s.rightJustify(fwidth, QLatin1Char((char)fillchar));
       
  2061 	} else {
       
  2062 	    s1 = s.leftJustify(fwidth, QLatin1Char((char)fillchar));
       
  2063 	}
       
  2064 	fwidth = 0;				// reset width
       
  2065     }
       
  2066     writeBlock( s1.unicode(), s1.length() );
       
  2067     return *this;
       
  2068 }
       
  2069 
       
  2070 
       
  2071 /*!
       
  2072     \overload
       
  2073     \since 4.2
       
  2074 
       
  2075     Writes a pointer to the stream and returns a reference to the
       
  2076     stream.
       
  2077 
       
  2078     The \a ptr is output as an unsigned long hexadecimal integer.
       
  2079 */
       
  2080 
       
  2081 Q3TextStream &Q3TextStream::operator<<( void *ptr )
       
  2082 {
       
  2083     int f = flags();
       
  2084     setf( hex, basefield );
       
  2085     setf( showbase );
       
  2086     unsetf( uppercase );
       
  2087     output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE );
       
  2088     flags( f );
       
  2089     return *this;
       
  2090 }
       
  2091 
       
  2092 
       
  2093 /*!
       
  2094     \fn int Q3TextStream::flags() const
       
  2095     \since 4.2
       
  2096 
       
  2097     Returns the current stream flags. The default value is 0.
       
  2098 
       
  2099     \table
       
  2100     \header \i Flag \i Meaning
       
  2101     \row \i \c skipws \i Not currently used; whitespace always skipped
       
  2102     \row \i \c left \i Numeric fields are left-aligned
       
  2103     \row \i \c right
       
  2104 	 \i Not currently used (by default, numerics are right-aligned)
       
  2105     \row \i \c internal \i Puts any padding spaces between +/- and value
       
  2106     \row \i \c bin \i Output \e and input only in binary
       
  2107     \row \i \c oct \i Output \e and input only in octal
       
  2108     \row \i \c dec \i Output \e and input only in decimal
       
  2109     \row \i \c hex \i Output \e and input only in hexadecimal
       
  2110     \row \i \c showbase
       
  2111 	 \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin,
       
  2112 	 \c oct, or \c hex format
       
  2113     \row \i \c showpoint \i Not currently used
       
  2114     \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x
       
  2115     \row \i \c showpos \i Shows + for positive numeric values
       
  2116     \row \i \c scientific \i Uses scientific notation for floating point values
       
  2117     \row \i \c fixed \i Uses fixed-point notation for floating point values
       
  2118     \endtable
       
  2119 
       
  2120     Note that unless \c bin, \c oct, \c dec, or \c hex is set, the
       
  2121     input base is octal if the value starts with 0, hexadecimal if it
       
  2122     starts with 0x, binary if it starts with 0b, and decimal
       
  2123     otherwise.
       
  2124 
       
  2125     \sa setf(), unsetf()
       
  2126 */
       
  2127 
       
  2128 /*!
       
  2129     \fn int Q3TextStream::flags( int f )
       
  2130 
       
  2131     \overload
       
  2132 
       
  2133     Sets the stream flags to \a f. Returns the previous stream flags.
       
  2134 
       
  2135     \sa setf(), unsetf(), flags()
       
  2136 */
       
  2137 
       
  2138 /*!
       
  2139     \fn int Q3TextStream::setf( int bits )
       
  2140     \since 4.2
       
  2141 
       
  2142     Sets the stream flag bits \a bits. Returns the previous stream
       
  2143     flags.
       
  2144 
       
  2145     Equivalent to \c{flags( flags() | bits )}.
       
  2146 
       
  2147     \sa unsetf()
       
  2148 */
       
  2149 
       
  2150 /*!
       
  2151     \fn int Q3TextStream::setf( int bits, int mask )
       
  2152 
       
  2153     \overload
       
  2154 
       
  2155     Sets the stream flag bits \a bits with a bit mask \a mask. Returns
       
  2156     the previous stream flags.
       
  2157 
       
  2158     Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}.
       
  2159 
       
  2160     \sa setf(), unsetf()
       
  2161 */
       
  2162 
       
  2163 /*!
       
  2164     \fn int Q3TextStream::unsetf( int bits )
       
  2165     \since 4.2
       
  2166 
       
  2167     Clears the stream flag bits \a bits. Returns the previous stream
       
  2168     flags.
       
  2169 
       
  2170     Equivalent to \c{flags( flags() & ~mask )}.
       
  2171 
       
  2172     \sa setf()
       
  2173 */
       
  2174 
       
  2175 /*!
       
  2176     \fn int Q3TextStream::width() const
       
  2177     \since 4.2
       
  2178 
       
  2179     Returns the field width. The default value is 0.
       
  2180 */
       
  2181 
       
  2182 /*!
       
  2183     \fn int Q3TextStream::width( int w )
       
  2184 
       
  2185     \overload
       
  2186 
       
  2187     Sets the field width to \a w. Returns the previous field width.
       
  2188 */
       
  2189 
       
  2190 /*!
       
  2191     \fn int Q3TextStream::fill() const
       
  2192     \since 4.2
       
  2193 
       
  2194     Returns the fill character. The default value is ' ' (space).
       
  2195 */
       
  2196 
       
  2197 /*!
       
  2198     \fn int Q3TextStream::fill( int f )
       
  2199     \overload
       
  2200 
       
  2201     Sets the fill character to \a f. Returns the previous fill character.
       
  2202 */
       
  2203 
       
  2204 /*!
       
  2205     \fn int Q3TextStream::precision() const
       
  2206     \since 4.2
       
  2207 
       
  2208     Returns the precision. The default value is 6.
       
  2209 */
       
  2210 
       
  2211 /*!
       
  2212     \fn int Q3TextStream::precision( int p )
       
  2213 
       
  2214     \overload
       
  2215 
       
  2216     Sets the precision to \a p. Returns the previous precision setting.
       
  2217 */
       
  2218 
       
  2219 
       
  2220 Q3TextStream &bin( Q3TextStream &s )
       
  2221 {
       
  2222     s.setf(Q3TextStream::bin,Q3TextStream::basefield);
       
  2223     return s;
       
  2224 }
       
  2225 
       
  2226 Q3TextStream &oct( Q3TextStream &s )
       
  2227 {
       
  2228     s.setf(Q3TextStream::oct,Q3TextStream::basefield);
       
  2229     return s;
       
  2230 }
       
  2231 
       
  2232 Q3TextStream &dec( Q3TextStream &s )
       
  2233 {
       
  2234     s.setf(Q3TextStream::dec,Q3TextStream::basefield);
       
  2235     return s;
       
  2236 }
       
  2237 
       
  2238 Q3TextStream &hex( Q3TextStream &s )
       
  2239 {
       
  2240     s.setf(Q3TextStream::hex,Q3TextStream::basefield);
       
  2241     return s;
       
  2242 }
       
  2243 
       
  2244 Q3TextStream &endl( Q3TextStream &s )
       
  2245 {
       
  2246     return s << '\n';
       
  2247 }
       
  2248 
       
  2249 Q3TextStream &flush( Q3TextStream &s )
       
  2250 {
       
  2251     return s;
       
  2252 }
       
  2253 
       
  2254 Q3TextStream &ws( Q3TextStream &s )
       
  2255 {
       
  2256     s.skipWhiteSpace();
       
  2257     return s;
       
  2258 }
       
  2259 
       
  2260 Q3TextStream &reset( Q3TextStream &s )
       
  2261 {
       
  2262     s.reset();
       
  2263     return s;
       
  2264 }
       
  2265 
       
  2266 /*!
       
  2267   \since 4.2
       
  2268 
       
  2269   Sets the encoding of this stream to \a e, where \a e is one of the
       
  2270   following values:
       
  2271   \table
       
  2272   \header \i Encoding \i Meaning
       
  2273   \row \i Locale
       
  2274        \i Uses local file format (Latin1 if locale is not set), but
       
  2275        autodetecting Unicode(utf16) on input.
       
  2276   \row \i Unicode
       
  2277        \i Uses Unicode(utf16) for input and output. Output will be
       
  2278        written in the order most efficient for the current platform
       
  2279        (i.e. the order used internally in QString).
       
  2280   \row \i UnicodeUTF8
       
  2281        \i Using Unicode(utf8) for input and output. If you use it for
       
  2282        input it will autodetect utf16 and use it instead of utf8.
       
  2283   \row \i Latin1
       
  2284        \i ISO-8859-1. Will not autodetect utf16.
       
  2285   \row \i UnicodeNetworkOrder
       
  2286        \i Uses network order Unicode(utf16) for input and output.
       
  2287        Useful when reading Unicode data that does not start with the
       
  2288        byte order marker.
       
  2289   \row \i UnicodeReverse
       
  2290        \i Uses reverse network order Unicode(utf16) for input and
       
  2291        output. Useful when reading Unicode data that does not start
       
  2292        with the byte order marker or when writing data that should be
       
  2293        read by buggy Windows applications.
       
  2294   \row \i RawUnicode
       
  2295        \i Like Unicode, but does not write the byte order marker nor
       
  2296        does it auto-detect the byte order. Useful only when writing to
       
  2297        non-persistent storage used by a single process.
       
  2298   \endtable
       
  2299 
       
  2300   \c Locale and all Unicode encodings, except \c RawUnicode, will look
       
  2301   at the first two bytes in an input stream to determine the byte
       
  2302   order. The initial byte order marker will be stripped off before
       
  2303   data is read.
       
  2304 
       
  2305   Note that this function should be called before any data is read to
       
  2306   or written from the stream.
       
  2307 
       
  2308   \sa setCodec()
       
  2309 */
       
  2310 
       
  2311 void Q3TextStream::setEncoding( Encoding e )
       
  2312 {
       
  2313     resetCodecConverterState(&mapperReadState);
       
  2314     resetCodecConverterState(&mapperWriteState);
       
  2315 
       
  2316     if ( d->sourceType == Q3TextStreamPrivate::String )
       
  2317 	return;
       
  2318 
       
  2319     switch ( e ) {
       
  2320     case Unicode:
       
  2321 	mapper = 0;
       
  2322 	latin1 = FALSE;
       
  2323 	doUnicodeHeader = TRUE;
       
  2324 	internalOrder = TRUE;
       
  2325 	networkOrder = QChar::networkOrdered();
       
  2326 	break;
       
  2327     case UnicodeUTF8:
       
  2328 #ifndef QT_NO_TEXTCODEC
       
  2329 	mapper = QTextCodec::codecForMib( 106 );
       
  2330         mapperWriteState.flags |= QTextCodec::IgnoreHeader;
       
  2331 	latin1 = FALSE;
       
  2332 	doUnicodeHeader = TRUE;
       
  2333 	internalOrder = TRUE;
       
  2334 	networkOrder = QChar::networkOrdered();
       
  2335 #else
       
  2336 	mapper = 0;
       
  2337 	latin1 = TRUE;
       
  2338 	doUnicodeHeader = TRUE;
       
  2339 #endif
       
  2340 	break;
       
  2341     case UnicodeNetworkOrder:
       
  2342 	mapper = 0;
       
  2343 	latin1 = FALSE;
       
  2344 	doUnicodeHeader = TRUE;
       
  2345 	internalOrder = QChar::networkOrdered();
       
  2346 	networkOrder = TRUE;
       
  2347 	break;
       
  2348     case UnicodeReverse:
       
  2349 	mapper = 0;
       
  2350 	latin1 = FALSE;
       
  2351 	doUnicodeHeader = TRUE;
       
  2352 	internalOrder = !QChar::networkOrdered();
       
  2353 	networkOrder = FALSE;
       
  2354 	break;
       
  2355     case RawUnicode:
       
  2356 	mapper = 0;
       
  2357 	latin1 = FALSE;
       
  2358 	doUnicodeHeader = FALSE;
       
  2359 	internalOrder = TRUE;
       
  2360 	networkOrder = QChar::networkOrdered();
       
  2361 	break;
       
  2362     case Locale:
       
  2363 	latin1 = TRUE; // fallback to Latin-1
       
  2364 #ifndef QT_NO_TEXTCODEC
       
  2365 	mapper = QTextCodec::codecForLocale();
       
  2366         mapperReadState.flags |= QTextCodec::IgnoreHeader;
       
  2367         mapperWriteState.flags |= QTextCodec::IgnoreHeader;
       
  2368 	// optimized Latin-1 processing
       
  2369 #if defined(Q_OS_WIN32)
       
  2370 	if ( GetACP() == 1252 )
       
  2371 	    mapper = 0;
       
  2372 #endif
       
  2373 	if ( mapper && mapper->mibEnum() == 4 )
       
  2374 #endif
       
  2375 	    mapper = 0;
       
  2376 
       
  2377 	doUnicodeHeader = TRUE; // If it reads as Unicode, accept it
       
  2378 	break;
       
  2379     case Latin1:
       
  2380 	mapper = 0;
       
  2381 	doUnicodeHeader = FALSE;
       
  2382 	latin1 = TRUE;
       
  2383 	break;
       
  2384     }
       
  2385 }
       
  2386 
       
  2387 
       
  2388 #ifndef QT_NO_TEXTCODEC
       
  2389 /*!
       
  2390     \since 4.2
       
  2391 
       
  2392     Sets the codec for this stream to \a codec. Will not try to
       
  2393     autodetect Unicode.
       
  2394 
       
  2395     Note that this function should be called before any data is read
       
  2396     to/written from the stream.
       
  2397 
       
  2398     \sa setEncoding(), codec()
       
  2399 */
       
  2400 
       
  2401 void Q3TextStream::setCodec( QTextCodec *codec )
       
  2402 {
       
  2403     if ( d->sourceType == Q3TextStreamPrivate::String )
       
  2404 	return; // QString does not need any codec
       
  2405     mapper = codec;
       
  2406     latin1 = ( codec->mibEnum() == 4 );
       
  2407     if ( latin1 )
       
  2408 	mapper = 0;
       
  2409     doUnicodeHeader = FALSE;
       
  2410 }
       
  2411 
       
  2412 /*!
       
  2413   Returns the codec actually used for this stream.
       
  2414   \since 4.2
       
  2415 
       
  2416   If Unicode is automatically detected in input, a codec with \link
       
  2417   QTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned.
       
  2418 
       
  2419   \sa setCodec()
       
  2420 */
       
  2421 
       
  2422 QTextCodec *Q3TextStream::codec()
       
  2423 {
       
  2424     if ( mapper ) {
       
  2425 	return mapper;
       
  2426     } else {
       
  2427 	// 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2"
       
  2428 	return QTextCodec::codecForMib( latin1 ? 4 : 1000 );
       
  2429     }
       
  2430 }
       
  2431 
       
  2432 #endif
       
  2433 
       
  2434 QT_END_NAMESPACE
       
  2435 
       
  2436 #endif // QT_NO_TEXTSTREAM