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