Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qtextstream.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qtextstream.cpp,v 1.2 2003/07/10 02:40:12 llornkcor Exp $
00003 **
00004 ** Implementation of QTextStream class
00005 **
00006 ** Created : 940922
00007 **
00008 ** Copyright (C) 1992-2002 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the tools module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
00035 **
00036 **********************************************************************/
00037 
00038 #include "qtextstream.h"
00039 
00040 #ifndef QT_NO_TEXTSTREAM
00041 #include "qtextcodec.h"
00042 #include "qregexp.h"
00043 #include "qbuffer.h"
00044 #include "qfile.h"
00045 #include <stdio.h>
00046 #include <ctype.h>
00047 #include <stdlib.h>
00048 
00049 #if defined(Q_OS_WIN32)
00050 #include <windows.h>
00051 #endif
00052 
00127 /*
00128   \class QTSManip
00129 
00130   \brief The QTSManip class is an internal helper class for the
00131   QTextStream.
00132 
00133   It is generally a very bad idea to use this class directly in
00134   application programs.
00135 
00136   \internal
00137 
00138   This class makes it possible to give the QTextStream function objects
00139   with arguments, like this:
00140   \code
00141     QTextStream cout( stdout, IO_WriteOnly );
00142     cout << setprecision( 8 );          // QTSManip used here!
00143     cout << 3.14159265358979323846;
00144   \endcode
00145 
00146   The setprecision() function returns a QTSManip object.
00147   The QTSManip object contains a pointer to a member function in
00148   QTextStream and an integer argument.
00149   When serializing a QTSManip into a QTextStream, the function
00150   is executed with the argument.
00151 */
00152 
00175 /*****************************************************************************
00176   QTextStream member functions
00177  *****************************************************************************/
00178 
00179 #if defined(QT_CHECK_STATE)
00180 #undef  CHECK_STREAM_PRECOND
00181 #define CHECK_STREAM_PRECOND  if ( !dev ) {                             \
00182                                 qWarning( "QTextStream: No device" );   \
00183                                 return *this; }
00184 #else
00185 #define CHECK_STREAM_PRECOND
00186 #endif
00187 
00188 
00189 #define I_SHORT         0x0010
00190 #define I_INT           0x0020
00191 #define I_LONG          0x0030
00192 #define I_TYPE_MASK     0x00f0
00193 
00194 #define I_BASE_2        QTS::bin
00195 #define I_BASE_8        QTS::oct
00196 #define I_BASE_10       QTS::dec
00197 #define I_BASE_16       QTS::hex
00198 #define I_BASE_MASK     (QTS::bin | QTS::oct | QTS::dec | QTS::hex)
00199 
00200 #define I_SIGNED        0x0100
00201 #define I_UNSIGNED      0x0200
00202 #define I_SIGN_MASK     0x0f00
00203 
00204 
00205 static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character.
00206 static const uint getline_buf_size = 256; // bufsize used by ts_getline()
00207 
00208 const int QTextStream::basefield   = I_BASE_MASK;
00209 const int QTextStream::adjustfield = ( QTextStream::left |
00210                                        QTextStream::right |
00211                                        QTextStream::internal );
00212 const int QTextStream::floatfield  = ( QTextStream::scientific |
00213                                        QTextStream::fixed );
00214 
00215 
00216 class QTextStreamPrivate {
00217 public:
00218 #ifndef QT_NO_TEXTCODEC
00219     QTextStreamPrivate()
00220         : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { }
00221     ~QTextStreamPrivate() {
00222         delete decoder;
00223         delete encoder;
00224     }
00225     QTextDecoder *decoder;
00226     QTextEncoder *encoder;
00227 #else
00228     QTextStreamPrivate() : sourceType( NotSet ) { }
00229     ~QTextStreamPrivate() { }
00230 #endif
00231     QString ungetcBuf;
00232 
00233     enum SourceType { NotSet, IODevice, String, ByteArray, File };
00234     SourceType sourceType;
00235 };
00236 
00237 
00238 // skips whitespace and returns the first non-whitespace character
00239 QChar QTextStream::eat_ws()
00240 {
00241     QChar c;
00242     do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) );
00243     return c;
00244 }
00245 
00246 void QTextStream::init()
00247 {
00248     // ### ungetcBuf = QEOF;
00249     dev = 0;
00250     owndev = FALSE;
00251     mapper = 0;
00252     d = new QTextStreamPrivate;
00253     doUnicodeHeader = TRUE; // autodetect
00254     latin1 = TRUE; // should use locale?
00255     internalOrder = QChar::networkOrdered();
00256     networkOrder = TRUE;
00257 }
00258 
00263 QTextStream::QTextStream()
00264 {
00265     init();
00266     setEncoding( Locale ); //###
00267     reset();
00268     d->sourceType = QTextStreamPrivate::NotSet;
00269 }
00270 
00275 QTextStream::QTextStream( QIODevice *iod )
00276 {
00277     init();
00278     setEncoding( Locale ); //###
00279     dev = iod;
00280     reset();
00281     d->sourceType = QTextStreamPrivate::IODevice;
00282 }
00283 
00284 // TODO: use special-case handling of this case in QTextStream, and
00285 //       simplify this class to only deal with QChar or QString data.
00286 class QStringBuffer : public QIODevice {
00287 public:
00288     QStringBuffer( QString* str );
00289     ~QStringBuffer();
00290     bool  open( int m );
00291     void  close();
00292     void  flush();
00293     Offset  size() const;
00294     Offset  at()   const;
00295     bool  at( Offset pos );
00296     Q_LONG readBlock( char *p, Q_ULONG len );
00297     Q_LONG writeBlock( const char *p, Q_ULONG len );
00298     int   getch();
00299     int   putch( int ch );
00300     int   ungetch( int ch );
00301 protected:
00302     QString* s;
00303 
00304 private:        // Disabled copy constructor and operator=
00305     QStringBuffer( const QStringBuffer & );
00306     QStringBuffer &operator=( const QStringBuffer & );
00307 };
00308 
00309 
00310 QStringBuffer::QStringBuffer( QString* str )
00311 {
00312     s = str;
00313 }
00314 
00315 QStringBuffer::~QStringBuffer()
00316 {
00317 }
00318 
00319 
00320 bool QStringBuffer::open( int m )
00321 {
00322     if ( !s ) {
00323 #if defined(QT_CHECK_STATE)
00324         qWarning( "QStringBuffer::open: No string" );
00325 #endif
00326         return FALSE;
00327     }
00328     if ( isOpen() ) {                           // buffer already open
00329 #if defined(QT_CHECK_STATE)
00330         qWarning( "QStringBuffer::open: Buffer already open" );
00331 #endif
00332         return FALSE;
00333     }
00334     setMode( m );
00335     if ( m & IO_Truncate ) {                    // truncate buffer
00336         s->truncate( 0 );
00337     }
00338     if ( m & IO_Append ) {                      // append to end of buffer
00339         ioIndex = s->length()*sizeof(QChar);
00340     } else {
00341         ioIndex = 0;
00342     }
00343     setState( IO_Open );
00344     setStatus( 0 );
00345     return TRUE;
00346 }
00347 
00348 void QStringBuffer::close()
00349 {
00350     if ( isOpen() ) {
00351         setFlags( IO_Direct );
00352         ioIndex = 0;
00353     }
00354 }
00355 
00356 void QStringBuffer::flush()
00357 {
00358 }
00359 
00360 QIODevice::Offset QStringBuffer::size() const
00361 {
00362     return s ? s->length()*sizeof(QChar) : 0;
00363 }
00364 
00365 QIODevice::Offset  QStringBuffer::at()   const
00366 {
00367     return ioIndex;
00368 }
00369 
00370 bool QStringBuffer::at( Offset pos )
00371 {
00372 #if defined(QT_CHECK_STATE)
00373     if ( !isOpen() ) {
00374         qWarning( "QStringBuffer::at: Buffer is not open" );
00375         return FALSE;
00376     }
00377 #endif
00378     if ( pos >= s->length()*2 ) {
00379 #if defined(QT_CHECK_RANGE)
00380 #if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET)
00381         qWarning( "QStringBuffer::at: Index %llu out of range", pos );
00382 #else
00383         qWarning( "QStringBuffer::at: Index %lu out of range", pos );
00384 #endif
00385 #endif
00386         return FALSE;
00387     }
00388     ioIndex = pos;
00389     return TRUE;
00390 }
00391 
00392 
00393 Q_LONG QStringBuffer::readBlock( char *p, Q_ULONG len )
00394 {
00395 #if defined(QT_CHECK_STATE)
00396     Q_CHECK_PTR( p );
00397     if ( !isOpen() ) {                          // buffer not open
00398         qWarning( "QStringBuffer::readBlock: Buffer not open" );
00399         return -1;
00400     }
00401     if ( !isReadable() ) {                      // reading not permitted
00402         qWarning( "QStringBuffer::readBlock: Read operation not permitted" );
00403         return -1;
00404     }
00405 #endif
00406     if ( ioIndex + len > s->length()*sizeof(QChar) ) {
00407         // overflow
00408         if ( (uint)ioIndex >= s->length()*sizeof(QChar) ) {
00409             setStatus( IO_ReadError );
00410             return -1;
00411         } else {
00412             len = s->length()*2 - (uint)ioIndex;
00413         }
00414     }
00415     memcpy( p, ((const char*)(s->unicode()))+ioIndex, len );
00416     ioIndex += len;
00417     return len;
00418 }
00419 
00420 Q_LONG QStringBuffer::writeBlock( const char *p, Q_ULONG len )
00421 {
00422 #if defined(QT_CHECK_NULL)
00423     if ( p == 0 && len != 0 )
00424         qWarning( "QStringBuffer::writeBlock: Null pointer error" );
00425 #endif
00426 #if defined(QT_CHECK_STATE)
00427     if ( !isOpen() ) {                          // buffer not open
00428         qWarning( "QStringBuffer::writeBlock: Buffer not open" );
00429         return -1;
00430     }
00431     if ( !isWritable() ) {                      // writing not permitted
00432         qWarning( "QStringBuffer::writeBlock: Write operation not permitted" );
00433         return -1;
00434     }
00435     if ( ioIndex&1 ) {
00436         qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" );
00437         return -1;
00438     }
00439     if ( len&1 ) {
00440         qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" );
00441         return -1;
00442     }
00443 #endif
00444     s->replace(ioIndex/2, len/2, (QChar*)p, len/2);
00445     ioIndex += len;
00446     return len;
00447 }
00448 
00449 int QStringBuffer::getch()
00450 {
00451 #if defined(QT_CHECK_STATE)
00452     if ( !isOpen() ) {                          // buffer not open
00453         qWarning( "QStringBuffer::getch: Buffer not open" );
00454         return -1;
00455     }
00456     if ( !isReadable() ) {                      // reading not permitted
00457         qWarning( "QStringBuffer::getch: Read operation not permitted" );
00458         return -1;
00459     }
00460 #endif
00461     if ( (uint)ioIndex >= s->length()*2 ) {           // overflow
00462         setStatus( IO_ReadError );
00463         return -1;
00464     }
00465     return (int) *( (const char *) s->unicode() + ioIndex++ );
00466 }
00467 
00468 int QStringBuffer::putch( int ch )
00469 {
00470     char c = ch;
00471     if ( writeBlock(&c,1) < 0 )
00472         return -1;
00473     else
00474         return ch;
00475 }
00476 
00477 int QStringBuffer::ungetch( int ch )
00478 {
00479 #if defined(QT_CHECK_STATE)
00480     if ( !isOpen() ) {                          // buffer not open
00481         qWarning( "QStringBuffer::ungetch: Buffer not open" );
00482         return -1;
00483     }
00484     if ( !isReadable() ) {                      // reading not permitted
00485         qWarning( "QStringBuffer::ungetch: Read operation not permitted" );
00486         return -1;
00487     }
00488 #endif
00489     if ( ch != -1 ) { // something to do with eof
00490         if ( ioIndex )
00491             ioIndex--;
00492         else
00493             ch = -1;
00494     }
00495     return ch;
00496 }
00497 
00498 
00527 QTextStream::QTextStream( QString* str, int filemode )
00528 {
00529     // TODO: optimize for this case as it becomes more common
00530     //        (see QStringBuffer above)
00531     init();
00532     dev = new QStringBuffer( str );
00533     ((QStringBuffer *)dev)->open( filemode );
00534     owndev = TRUE;
00535     setEncoding(RawUnicode);
00536     reset();
00537     d->sourceType = QTextStreamPrivate::String;
00538 }
00539 
00546 QTextStream::QTextStream( QString& str, int filemode )
00547 {
00548     init();
00549     dev = new QStringBuffer( &str );
00550     ((QStringBuffer *)dev)->open( filemode );
00551     owndev = TRUE;
00552     setEncoding(RawUnicode);
00553     reset();
00554     d->sourceType = QTextStreamPrivate::String;
00555 }
00556 
00584 QTextStream::QTextStream( QByteArray a, int mode )
00585 {
00586     init();
00587     dev = new QBuffer( a );
00588     ((QBuffer *)dev)->open( mode );
00589     owndev = TRUE;
00590     setEncoding( Latin1 ); //### Locale???
00591     reset();
00592     d->sourceType = QTextStreamPrivate::ByteArray;
00593 }
00594 
00606 QTextStream::QTextStream( FILE *fh, int mode )
00607 {
00608     init();
00609     setEncoding( Locale ); //###
00610     dev = new QFile;
00611     ((QFile *)dev)->open( mode, fh );
00612     owndev = TRUE;
00613     reset();
00614     d->sourceType = QTextStreamPrivate::File;
00615 }
00616 
00623 QTextStream::~QTextStream()
00624 {
00625     if ( owndev )
00626         delete dev;
00627     delete d;
00628 }
00629 
00633 void QTextStream::skipWhiteSpace()
00634 {
00635     ts_ungetc( eat_ws() );
00636 }
00637 
00638 
00647 uint QTextStream::ts_getbuf( QChar* buf, uint len )
00648 {
00649     if( len < 1 )
00650         return 0;
00651 
00652     uint rnum=0;   // the number of QChars really read
00653 
00654     if ( d && d->ungetcBuf.length() ) {
00655         while( rnum < len && rnum < d->ungetcBuf.length() ) {
00656             *buf = d->ungetcBuf.constref( rnum );
00657             buf++;
00658             rnum++;
00659         }
00660         d->ungetcBuf = d->ungetcBuf.mid( rnum );
00661         if ( rnum >= len )
00662             return rnum;
00663     }
00664 
00665     // we use dev->ungetch() for one of the bytes of the unicode
00666     // byte-order mark, but a local unget hack for the other byte:
00667     int ungetHack = EOF;
00668 
00669     if ( doUnicodeHeader ) {
00670         doUnicodeHeader = FALSE; // only at the top
00671         int c1 = dev->getch();
00672         if ( c1 == EOF )
00673             return rnum;
00674         int c2 = dev->getch();
00675         if ( c1 == 0xfe && c2 == 0xff ) {
00676             mapper = 0;
00677             latin1 = FALSE;
00678             internalOrder = QChar::networkOrdered();
00679             networkOrder = TRUE;
00680         } else if ( c1 == 0xff && c2 == 0xfe ) {
00681             mapper = 0;
00682             latin1 = FALSE;
00683             internalOrder = !QChar::networkOrdered();
00684             networkOrder = FALSE;
00685         } else {
00686             if ( c2 != EOF ) {
00687                 dev->ungetch( c2 );
00688                 ungetHack = c1;
00689             } else {
00690                 /*
00691                   A small bug might hide here. If only the first byte
00692                   of a file has made it so far, and that first byte
00693                   is half of the byte-order mark, then the utfness
00694                   will not be detected.
00695                 */
00696                 dev->ungetch( c1 );
00697             }
00698         }
00699     }
00700 
00701 #ifndef QT_NO_TEXTCODEC
00702     if ( mapper ) {
00703         bool shortRead = FALSE;
00704         if ( !d->decoder )
00705             d->decoder = mapper->makeDecoder();
00706         while( rnum < len ) {
00707             QString s;
00708             bool readBlock = !( len == 1+rnum );
00709             for (;;) {
00710                 // for efficiency: normally read a whole block
00711                 if ( readBlock ) {
00712                     // guess buffersize; this may be wrong (too small or too
00713                     // big). But we can handle this (either iterate reading
00714                     // or use ungetcBuf).
00715                     // Note that this might cause problems for codecs where
00716                     // one byte can result in >1 Unicode Characters if bytes
00717                     // are written to the stream in the meantime (loss of
00718                     // synchronicity).
00719                     uint rlen = len - rnum;
00720                     char *cbuf = new char[ rlen ];
00721                     if ( ungetHack != EOF ) {
00722                         rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
00723                         cbuf[0] = (char)ungetHack;
00724                         ungetHack = EOF;
00725                     } else {
00726                         rlen = dev->readBlock( cbuf, rlen );
00727                     }
00728                     s  += d->decoder->toUnicode( cbuf, rlen );
00729                     delete[] cbuf;
00730                     // use buffered reading only for the first time, because we
00731                     // have to get the stream synchronous again (this is easier
00732                     // with single character reading)
00733                     readBlock = FALSE;
00734                 }
00735                 // get stream (and codec) in sync
00736                 int c;
00737                 if ( ungetHack == EOF ) {
00738                     c = dev->getch();
00739                 } else {
00740                     c = ungetHack;
00741                     ungetHack = EOF;
00742                 }
00743                 if ( c == EOF ) {
00744                     shortRead = TRUE;
00745                     break;
00746                 }
00747                 char b = c;
00748                 uint lengthBefore = s.length();
00749                 s  += d->decoder->toUnicode( &b, 1 );
00750                 if ( s.length() > lengthBefore )
00751                     break; // it seems we are in sync now
00752             }
00753             uint i = 0;
00754             uint end = QMIN( len-rnum, s.length() );
00755             while( i < end ) {
00756                 *buf = s.constref(i++);
00757                 buf++;
00758             }
00759             rnum += end;
00760             if ( s.length() > i )
00761                 // could be = but append is clearer
00762                 d->ungetcBuf.append( s.mid( i ) );
00763             if ( shortRead )
00764                 return rnum;
00765         }
00766     } else
00767 #endif
00768     if ( latin1 ) {
00769         if ( len == 1+rnum ) {
00770             // use this method for one character because it is more efficient
00771             // (arnt doubts whether it makes a difference, but lets it stand)
00772             int c = (ungetHack == EOF) ? dev->getch() : ungetHack;
00773             if ( c != EOF ) {
00774                 *buf = (char)c;
00775                 buf++;
00776                 rnum++;
00777             }
00778         } else {
00779             if ( ungetHack != EOF ) {
00780                 *buf = (char)ungetHack;
00781                 buf++;
00782                 rnum++;
00783                 ungetHack = EOF;
00784             }
00785             char *cbuf = new char[len - rnum];
00786             while ( !dev->atEnd() && rnum < len ) {
00787                 uint rlen = len - rnum;
00788                 rlen = dev->readBlock( cbuf, rlen );
00789                 char *it = cbuf;
00790                 char *end = cbuf + rlen;
00791                 while ( it < end ) {
00792                     *buf = *it;
00793                     buf++;
00794                     it++;
00795                 }
00796                 rnum += rlen;
00797             }
00798             delete[] cbuf;
00799         }
00800     } else { // UCS-2 or UTF-16
00801         if ( len == 1+rnum ) {
00802             int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack;
00803             if ( c1 == EOF )
00804                 return rnum;
00805             int c2 = dev->getch();
00806             if ( c2 == EOF )
00807                 return rnum;
00808 
00809             if ( networkOrder ) {
00810                 *buf = QChar( c2, c1 );
00811             } else {
00812                 *buf = QChar( c1, c2 );
00813             }
00814             buf++;
00815             rnum++;
00816         } else {
00817             char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible
00818             while ( !dev->atEnd() && rnum < len ) {
00819                 uint rlen = 2 * ( len-rnum );
00820                 if ( ungetHack != EOF ) {
00821                     rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
00822                     cbuf[0] = (char)ungetHack;
00823                     ungetHack = EOF;
00824                 } else {
00825                     rlen = dev->readBlock( cbuf, rlen );
00826                 }
00827                 // We can't use an odd number of bytes, so put it back. But
00828                 // do it only if we are capable of reading more -- normally
00829                 // there should not be an odd number, but the file might be
00830                 // truncated or not in UTF-16...
00831                 if ( (rlen & 1) == 1 )
00832                     if ( !dev->atEnd() )
00833                         dev->ungetch( cbuf[--rlen] );
00834                 uint i = 0;
00835                 if ( networkOrder ) {
00836                     while( i < rlen ) {
00837                         *buf = QChar( cbuf[i+1], cbuf[i] );
00838                         buf++;
00839                         i+=2;
00840                     }
00841                 } else {
00842                     while( i < rlen ) {
00843                         *buf = QChar( cbuf[i], cbuf[i+1] );
00844                         buf++;
00845                         i+=2;
00846                     }
00847                 }
00848                 rnum += i/2;
00849             }
00850             delete[] cbuf;
00851         }
00852     }
00853     return rnum;
00854 }
00855 
00873 uint QTextStream::ts_getline( QChar* buf )
00874 {
00875     uint rnum=0;   // the number of QChars really read
00876     char cbuf[ getline_buf_size+1 ];
00877 
00878     if ( d && d->ungetcBuf.length() ) {
00879         while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) {
00880             buf[rnum] = d->ungetcBuf.constref(rnum);
00881             rnum++;
00882         }
00883         d->ungetcBuf = d->ungetcBuf.mid( rnum );
00884         if ( rnum >= getline_buf_size )
00885             return rnum;
00886     }
00887 
00888 #ifndef QT_NO_TEXTCODEC
00889     if ( mapper ) {
00890         if ( !d->decoder )
00891             d->decoder = mapper->makeDecoder();
00892         QString s;
00893         bool readBlock = TRUE;
00894         for (;;) {
00895             // for efficiency: try to read a line
00896             if ( readBlock ) {
00897                 int rlen = getline_buf_size - rnum;
00898                 rlen = dev->readLine( cbuf, rlen+1 );
00899                 if ( rlen == -1 )
00900                     rlen = 0;
00901                 s  += d->decoder->toUnicode( cbuf, rlen );
00902                 readBlock = FALSE;
00903             }
00904             if ( dev->atEnd()
00905                     || s.at( s.length()-1 ) == '\n'
00906                     || s.at( s.length()-1 ) == '\r'
00907                ) {
00908                 break;
00909             } else {
00910                 // get stream (and codec) in sync
00911                 int c;
00912                 c = dev->getch();
00913                 if ( c == EOF ) {
00914                     break;
00915                 }
00916                 char b = c;
00917                 uint lengthBefore = s.length();
00918                 s  += d->decoder->toUnicode( &b, 1 );
00919                 if ( s.length() > lengthBefore )
00920                     break; // it seems we are in sync now
00921             }
00922         }
00923         uint i = 0;
00924         while( rnum < getline_buf_size && i < s.length() )
00925             buf[rnum++] = s.constref(i++);
00926         if ( s.length() > i )
00927             // could be = but append is clearer
00928             d->ungetcBuf.append( s.mid( i ) );
00929         if ( rnum < getline_buf_size && dev->atEnd() )
00930             buf[rnum++] = QEOF;
00931     } else
00932 #endif
00933     if ( latin1 ) {
00934         int rlen = getline_buf_size - rnum;
00935         rlen = dev->readLine( cbuf, rlen+1 );
00936         if ( rlen == -1 )
00937             rlen = 0;
00938         char *end = cbuf+rlen;
00939         char *it = cbuf;
00940         buf +=rnum;
00941         while ( it != end ) {
00942             buf->setCell( *(it++) );
00943             buf->setRow( 0 );
00944             buf++;
00945         }
00946         rnum += rlen;
00947         if ( rnum < getline_buf_size && dev->atEnd() )
00948             buf[1] = QEOF;
00949     }
00950     return rnum;
00951 }
00952 
00953 
00957 void QTextStream::ts_putc( QChar c )
00958 {
00959 #ifndef QT_NO_TEXTCODEC
00960     if ( mapper ) {
00961         if ( !d->encoder )
00962             d->encoder = mapper->makeEncoder();
00963         int len = 1;
00964         QString s = c;
00965         QCString block = d->encoder->fromUnicode( s, len );
00966         dev->writeBlock( block, len );
00967     } else
00968 #endif
00969     if ( latin1 ) {
00970         if ( c.row() )
00971             dev->putch( '?' ); // unknown character
00972         else
00973             dev->putch( c.cell() );
00974     } else {
00975         if ( doUnicodeHeader ) {
00976             doUnicodeHeader = FALSE;
00977             ts_putc( QChar::byteOrderMark );
00978         }
00979         if ( internalOrder ) {
00980             // this case is needed by QStringBuffer
00981             dev->writeBlock( (char*)&c, sizeof(QChar) );
00982         } else if ( networkOrder ) {
00983             dev->putch( c.row() );
00984             dev->putch( c.cell() );
00985         } else {
00986             dev->putch( c.cell() );
00987             dev->putch( c.row() );
00988         }
00989     }
00990 }
00991 
00995 void QTextStream::ts_putc( int ch )
00996 {
00997     ts_putc( QChar((ushort)ch) );
00998 }
00999 
01000 bool QTextStream::ts_isdigit( QChar c )
01001 {
01002     return c.isDigit();
01003 }
01004 
01005 bool QTextStream::ts_isspace( QChar c )
01006 {
01007     return c.isSpace();
01008 }
01009 
01010 void QTextStream::ts_ungetc( QChar c )
01011 {
01012     if ( c.unicode() == 0xffff )
01013         return;
01014 
01015     d->ungetcBuf.prepend( c );
01016 }
01017 
01018 
01019 
01034 QTextStream &QTextStream::readRawBytes( char *s, uint len )
01035 {
01036     dev->readBlock( s, len );
01037     return *this;
01038 }
01039 
01049 QTextStream &QTextStream::writeRawBytes( const char* s, uint len )
01050 {
01051     dev->writeBlock( s, len );
01052     return *this;
01053 }
01054 
01055 
01056 QTextStream &QTextStream::writeBlock( const char* p, uint len )
01057 {
01058     if ( doUnicodeHeader ) {
01059         doUnicodeHeader = FALSE;
01060         if ( !mapper && !latin1 )
01061             ts_putc( QChar::byteOrderMark );
01062     }
01063     // QCString and const char * are treated as Latin-1
01064     if ( !mapper && latin1 ) {
01065         dev->writeBlock( p, len );
01066     } else if ( !mapper && internalOrder ) {
01067         QChar *u = new QChar[len];
01068         for ( uint i = 0; i < len; i++ )
01069             u[i] = p[i];
01070         dev->writeBlock( (char*)u, len * sizeof(QChar) );
01071         delete [] u;
01072     } else {
01073         for ( uint i = 0; i < len; i++ )
01074             ts_putc( (uchar)p[i] );
01075     }
01076     return *this;
01077 }
01078 
01079 QTextStream &QTextStream::writeBlock( const QChar* p, uint len )
01080 {
01081 #ifndef QT_NO_TEXTCODEC
01082     if ( mapper ) {
01083         if ( !d->encoder )
01084             d->encoder = mapper->makeEncoder();
01085         QConstString s( p, len );
01086         int l = len;
01087         QCString block = d->encoder->fromUnicode( s.string(), l );
01088         dev->writeBlock( block, l );
01089     } else
01090 #endif
01091     if ( latin1 ) {
01092         char *str = QString::unicodeToLatin1( p, len );
01093         dev->writeBlock( str, len );
01094         delete [] str;
01095     } else if ( internalOrder ) {
01096         if ( doUnicodeHeader ) {
01097             doUnicodeHeader = FALSE;
01098             ts_putc( QChar::byteOrderMark );
01099         }
01100         dev->writeBlock( (char*)p, sizeof(QChar)*len );
01101     } else {
01102         for (uint i=0; i<len; i++)
01103             ts_putc( p[i] );
01104     }
01105     return *this;
01106 }
01107 
01121 void QTextStream::reset()
01122 {
01123     fflags = 0;
01124     fwidth = 0;
01125     fillchar = ' ';
01126     fprec = 6;
01127 }
01128 
01143 void QTextStream::setDevice( QIODevice *iod )
01144 {
01145     if ( owndev ) {
01146         delete dev;
01147         owndev = FALSE;
01148     }
01149     dev = iod;
01150     d->sourceType = QTextStreamPrivate::IODevice;
01151 }
01152 
01159 void QTextStream::unsetDevice()
01160 {
01161     setDevice( 0 );
01162     d->sourceType = QTextStreamPrivate::NotSet;
01163 }
01164 
01184 /*****************************************************************************
01185   QTextStream read functions
01186  *****************************************************************************/
01187 
01188 
01196 QTextStream &QTextStream::operator>>( char &c )
01197 {
01198     CHECK_STREAM_PRECOND
01199     c = eat_ws();
01200     return *this;
01201 }
01202 
01208 QTextStream &QTextStream::operator>>( QChar &c )
01209 {
01210     CHECK_STREAM_PRECOND
01211     c = ts_getc();
01212     return *this;
01213 }
01214 
01215 
01216 ulong QTextStream::input_bin()
01217 {
01218     ulong val = 0;
01219     QChar ch = eat_ws();
01220     int dv = ch.digitValue();
01221     while (  dv == 0 || dv == 1 ) {
01222         val = ( val << 1 ) + dv;
01223         ch = ts_getc();
01224         dv = ch.digitValue();
01225     }
01226     if ( ch != QEOF )
01227         ts_ungetc( ch );
01228     return val;
01229 }
01230 
01231 ulong QTextStream::input_oct()
01232 {
01233     ulong val = 0;
01234     QChar ch = eat_ws();
01235     int dv = ch.digitValue();
01236     while ( dv >= 0 && dv <= 7 ) {
01237         val = ( val << 3 ) + dv;
01238         ch = ts_getc();
01239         dv = ch.digitValue();
01240     }
01241     if ( dv == 8 || dv == 9 ) {
01242         while ( ts_isdigit(ch) )
01243             ch = ts_getc();
01244     }
01245     if ( ch != QEOF )
01246         ts_ungetc( ch );
01247     return val;
01248 }
01249 
01250 ulong QTextStream::input_dec()
01251 {
01252     ulong val = 0;
01253     QChar ch = eat_ws();
01254     int dv = ch.digitValue();
01255     while ( ts_isdigit(ch) ) {
01256         val = val * 10 + dv;
01257         ch = ts_getc();
01258         dv = ch.digitValue();
01259     }
01260     if ( ch != QEOF )
01261         ts_ungetc( ch );
01262     return val;
01263 }
01264 
01265 ulong QTextStream::input_hex()
01266 {
01267     ulong val = 0;
01268     QChar ch = eat_ws();
01269     char c = ch;
01270     while ( isxdigit((uchar) c) ) {
01271         val <<= 4;
01272         if ( ts_isdigit(c) )
01273             val += c - '0';
01274         else
01275             val += 10 + tolower( (uchar) c ) - 'a';
01276         c = ch = ts_getc();
01277     }
01278     if ( ch != QEOF )
01279         ts_ungetc( ch );
01280     return val;
01281 }
01282 
01283 long QTextStream::input_int()
01284 {
01285     long val;
01286     QChar ch;
01287     char c;
01288     switch ( flags() & basefield ) {
01289     case bin:
01290         val = (long)input_bin();
01291         break;
01292     case oct:
01293         val = (long)input_oct();
01294         break;
01295     case dec:
01296         c = ch = eat_ws();
01297         if ( ch == QEOF ) {
01298             val = 0;
01299         } else {
01300             if ( !(c == '-' || c == '+') )
01301                 ts_ungetc( ch );
01302             if ( c == '-' ) {
01303                 ulong v = input_dec();
01304                 if ( v ) {              // ensure that LONG_MIN can be read
01305                     v--;
01306                     val = -((long)v) - 1;
01307                 } else {
01308                     val = 0;
01309                 }
01310             } else {
01311                 val = (long)input_dec();
01312             }
01313         }
01314         break;
01315     case hex:
01316         val = (long)input_hex();
01317         break;
01318     default:
01319         val = 0;
01320         c = ch = eat_ws();
01321         if ( c == '0' ) {               // bin, oct or hex
01322             c = ch = ts_getc();
01323             if ( tolower((uchar) c) == 'x' )
01324                 val = (long)input_hex();
01325             else if ( tolower((uchar) c) == 'b' )
01326                 val = (long)input_bin();
01327             else {                      // octal
01328                 ts_ungetc( ch );
01329                 if ( c >= '0' && c <= '7' ) {
01330                     val = (long)input_oct();
01331                 } else {
01332                     val = 0;
01333                 }
01334             }
01335         } else if ( ts_isdigit(ch) ) {
01336             ts_ungetc( ch );
01337             val = (long)input_dec();
01338         } else if ( c == '-' || c == '+' ) {
01339             ulong v = input_dec();
01340             if ( c == '-' ) {
01341                 if ( v ) {              // ensure that LONG_MIN can be read
01342                     v--;
01343                     val = -((long)v) - 1;
01344                 } else {
01345                     val = 0;
01346                 }
01347             } else {
01348                 val = (long)v;
01349             }
01350         }
01351     }
01352     return val;
01353 }
01354 
01355 //
01356 // We use a table-driven FSM to parse floating point numbers
01357 // strtod() cannot be used directly since we're reading from a QIODevice
01358 //
01359 
01360 double QTextStream::input_double()
01361 {
01362     const int Init       = 0;                   // states
01363     const int Sign       = 1;
01364     const int Mantissa   = 2;
01365     const int Dot        = 3;
01366     const int Abscissa   = 4;
01367     const int ExpMark    = 5;
01368     const int ExpSign    = 6;
01369     const int Exponent   = 7;
01370     const int Done       = 8;
01371 
01372     const int InputSign  = 1;                   // input tokens
01373     const int InputDigit = 2;
01374     const int InputDot   = 3;
01375     const int InputExp   = 4;
01376 
01377     static const uchar table[8][5] = {
01378      /* None     InputSign   InputDigit InputDot InputExp */
01379         { 0,        Sign,     Mantissa,  Dot,      0,      }, // Init
01380         { 0,        0,        Mantissa,  Dot,      0,      }, // Sign
01381         { Done,     Done,     Mantissa,  Dot,      ExpMark,}, // Mantissa
01382         { 0,        0,        Abscissa,  0,        0,      }, // Dot
01383         { Done,     Done,     Abscissa,  Done,     ExpMark,}, // Abscissa
01384         { 0,        ExpSign,  Exponent,  0,        0,      }, // ExpMark
01385         { 0,        0,        Exponent,  0,        0,      }, // ExpSign
01386         { Done,     Done,     Exponent,  Done,     Done    }  // Exponent
01387     };
01388 
01389     int state = Init;                           // parse state
01390     int input;                                  // input token
01391 
01392     char buf[256];
01393     int i = 0;
01394     QChar c = eat_ws();
01395 
01396     for (;;) {
01397 
01398         switch ( c ) {
01399             case '+':
01400             case '-':
01401                 input = InputSign;
01402                 break;
01403             case '0': case '1': case '2': case '3': case '4':
01404             case '5': case '6': case '7': case '8': case '9':
01405                 input = InputDigit;
01406                 break;
01407             case '.':
01408                 input = InputDot;
01409                 break;
01410             case 'e':
01411             case 'E':
01412                 input = InputExp;
01413                 break;
01414             default:
01415                 input = 0;
01416                 break;
01417         }
01418 
01419         state = table[state][input];
01420 
01421         if  ( state == 0 || state == Done || i > 250 ) {
01422             if ( i > 250 ) {                    // ignore rest of digits
01423                 do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) );
01424             }
01425             if ( c != QEOF )
01426                 ts_ungetc( c );
01427             buf[i] = '\0';
01428             char *end;
01429             return strtod( buf, &end );
01430         }
01431 
01432         buf[i++] = c;
01433         c = ts_getc();
01434     }
01435 
01436 #if !defined(Q_CC_EDG)
01437     return 0.0;
01438 #endif
01439 }
01440 
01441 
01450 QTextStream &QTextStream::operator>>( signed short &i )
01451 {
01452     CHECK_STREAM_PRECOND
01453     i = (signed short)input_int();
01454     return *this;
01455 }
01456 
01457 
01466 QTextStream &QTextStream::operator>>( unsigned short &i )
01467 {
01468     CHECK_STREAM_PRECOND
01469     i = (unsigned short)input_int();
01470     return *this;
01471 }
01472 
01473 
01482 QTextStream &QTextStream::operator>>( signed int &i )
01483 {
01484     CHECK_STREAM_PRECOND
01485     i = (signed int)input_int();
01486     return *this;
01487 }
01488 
01489 
01498 QTextStream &QTextStream::operator>>( unsigned int &i )
01499 {
01500     CHECK_STREAM_PRECOND
01501     i = (unsigned int)input_int();
01502     return *this;
01503 }
01504 
01505 
01514 QTextStream &QTextStream::operator>>( signed long &i )
01515 {
01516     CHECK_STREAM_PRECOND
01517     i = (signed long)input_int();
01518     return *this;
01519 }
01520 
01521 
01530 QTextStream &QTextStream::operator>>( unsigned long &i )
01531 {
01532     CHECK_STREAM_PRECOND
01533     i = (unsigned long)input_int();
01534     return *this;
01535 }
01536 
01537 
01546 QTextStream &QTextStream::operator>>( float &f )
01547 {
01548     CHECK_STREAM_PRECOND
01549     f = (float)input_double();
01550     return *this;
01551 }
01552 
01553 
01562 QTextStream &QTextStream::operator>>( double &f )
01563 {
01564     CHECK_STREAM_PRECOND
01565     f = input_double();
01566     return *this;
01567 }
01568 
01569 
01579 QTextStream &QTextStream::operator>>( char *s )
01580 {
01581     CHECK_STREAM_PRECOND
01582     int maxlen = width( 0 );
01583     QChar c = eat_ws();
01584     if ( !maxlen )
01585         maxlen = -1;
01586     while ( c != QEOF ) {
01587         if ( ts_isspace(c) || maxlen-- == 0 ) {
01588             ts_ungetc( c );
01589             break;
01590         }
01591         *s++ = c;
01592         c = ts_getc();
01593     }
01594 
01595     *s = '\0';
01596     return *this;
01597 }
01598 
01608 QTextStream &QTextStream::operator>>( QString &str )
01609 {
01610     CHECK_STREAM_PRECOND
01611     str=QString::fromLatin1("");
01612     QChar       c = eat_ws();
01613 
01614     while ( c != QEOF ) {
01615         if ( ts_isspace(c) ) {
01616             ts_ungetc( c );
01617             break;
01618         }
01619         str += c;
01620         c = ts_getc();
01621     }
01622     return *this;
01623 }
01624 
01634 QTextStream &QTextStream::operator>>( QCString &str )
01635 {
01636     CHECK_STREAM_PRECOND
01637     QCString  *dynbuf = 0;
01638     const int buflen = 256;
01639     char      buffer[buflen];
01640     char     *s = buffer;
01641     int       i = 0;
01642     QChar             c = eat_ws();
01643 
01644     while ( c != QEOF ) {
01645         if ( ts_isspace(c) ) {
01646             ts_ungetc( c );
01647             break;
01648         }
01649         if ( i >= buflen-1 ) {
01650             if ( !dynbuf )  {                   // create dynamic buffer
01651                 dynbuf = new QCString(buflen*2);
01652                 memcpy( dynbuf->data(), s, i ); // copy old data
01653             } else if ( i >= (int)dynbuf->size()-1 ) {
01654                 dynbuf->resize( dynbuf->size()*2 );
01655             }
01656             s = dynbuf->data();
01657         }
01658         s[i++] = c;
01659         c = ts_getc();
01660     }
01661     str.resize( i+1 );
01662     memcpy( str.data(), s, i );
01663     delete dynbuf;
01664     return *this;
01665 }
01666 
01667 
01683 QString QTextStream::readLine()
01684 {
01685 #if defined(QT_CHECK_STATE)
01686     if ( !dev ) {
01687         qWarning( "QTextStream::readLine: No device" );
01688         return QString::null;
01689     }
01690 #endif
01691     bool readCharByChar = TRUE;
01692     QString result;
01693 #if 0
01694     if ( !doUnicodeHeader && (
01695             (latin1) ||
01696             (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8
01697        ) ) {
01698         readCharByChar = FALSE;
01699         // use optimized read line
01700         QChar c[getline_buf_size];
01701         int pos = 0;
01702         bool eof = FALSE;
01703 
01704         for (;;) {
01705             pos = ts_getline( c );
01706             if ( pos == 0 ) {
01707                 // something went wrong; try fallback
01708                 readCharByChar = TRUE;
01709                 //dev->resetStatus();
01710                 break;
01711             }
01712             if ( c[pos-1] == QEOF || c[pos-1] == '\n' ) {
01713                 if ( pos>2 && c[pos-1]==QEOF && c[pos-2]=='\n' ) {
01714                     result += QString( c, pos-2 );
01715                 } else if ( pos > 1 ) {
01716                     result += QString( c, pos-1 );
01717                 }
01718                 if ( pos == 1 && c[pos-1] == QEOF )
01719                     eof = TRUE;
01720                 break;
01721             } else {
01722                 result += QString( c, pos );
01723             }
01724         }
01725         if ( eof && result.isEmpty() )
01726             return QString::null;
01727     }
01728 #endif
01729     if ( readCharByChar ) {
01730         // read character by character
01731         const int buf_size = 256;
01732         QChar c[buf_size];
01733         int pos = 0;
01734 
01735         c[pos] = ts_getc();
01736         if ( c[pos] == QEOF ) {
01737             return QString::null;
01738         }
01739 
01740         while ( c[pos] != QEOF && c[pos] != '\n' ) {
01741             if ( c[pos] == '\r' ) { // ( handle mac and dos )
01742                 QChar nextc =  ts_getc();
01743                 if ( nextc != '\n' )
01744                     ts_ungetc( nextc );
01745                 break;
01746             }
01747             pos++;
01748             if ( pos >= buf_size ) {
01749                 result += QString( c, pos );
01750                 pos = 0;
01751             }
01752             c[pos] = ts_getc();
01753         }
01754         result += QString( c, pos );
01755     }
01756 
01757     return result;
01758 }
01759 
01760 
01767 QString QTextStream::read()
01768 {
01769 #if defined(QT_CHECK_STATE)
01770     if ( !dev ) {
01771         qWarning( "QTextStream::read: No device" );
01772         return QString::null;
01773     }
01774 #endif
01775     QString    result;
01776     const uint bufsize = 512;
01777     QChar      buf[bufsize];
01778     uint       i, num, start;
01779     bool       skipped_cr = FALSE;
01780 
01781     for (;;) {
01782         num = ts_getbuf(buf,bufsize);
01783         // convert dos (\r\n) and mac (\r) style eol to unix style (\n)
01784         start = 0;
01785         for ( i=0; i<num; i++ ) {
01786             if ( buf[i] == '\r' ) {
01787                 // Only skip single cr's preceding lf's
01788                 if ( skipped_cr ) {
01789                     result += buf[i];
01790                     start++;
01791                 } else {
01792                     result += QString( &buf[start], i-start );
01793                     start = i+1;
01794                     skipped_cr = TRUE;
01795                 }
01796             } else {
01797                 if ( skipped_cr ) {
01798                     if ( buf[i] != '\n' ) {
01799                         // Should not have skipped it
01800                         result += '\n';
01801                     }
01802                     skipped_cr = FALSE;
01803                 }
01804             }
01805         }
01806         if ( start < num )
01807             result += QString( &buf[start], i-start );
01808         if ( num != bufsize ) // if ( EOF )
01809             break;
01810     }
01811     return result;
01812 }
01813 
01814 
01815 
01816 /*****************************************************************************
01817   QTextStream write functions
01818  *****************************************************************************/
01819 
01827 QTextStream &QTextStream::operator<<( QChar c )
01828 {
01829     CHECK_STREAM_PRECOND
01830     ts_putc( c );
01831     return *this;
01832 }
01833 
01840 QTextStream &QTextStream::operator<<( char c )
01841 {
01842     CHECK_STREAM_PRECOND
01843     unsigned char uc = (unsigned char) c;
01844     ts_putc( uc );
01845     return *this;
01846 }
01847 
01848 QTextStream &QTextStream::output_int( int format, ulong n, bool neg )
01849 {
01850     static const char hexdigits_lower[] = "0123456789abcdef";
01851     static const char hexdigits_upper[] = "0123456789ABCDEF";
01852     CHECK_STREAM_PRECOND
01853     char buf[76];
01854     register char *p;
01855     int   len;
01856     const char *hexdigits;
01857 
01858     switch ( flags() & I_BASE_MASK ) {
01859 
01860         case I_BASE_2:                          // output binary number
01861             switch ( format & I_TYPE_MASK ) {
01862                 case I_SHORT: len=16; break;
01863                 case I_INT:   len=sizeof(int)*8; break;
01864                 case I_LONG:  len=32; break;
01865                 default:      len = 0;
01866             }
01867             p = &buf[74];                       // go reverse order
01868             *p = '\0';
01869             while ( len-- ) {
01870                 *--p = (char)(n&1) + '0';
01871                 n >>= 1;
01872                 if ( !n )
01873                     break;
01874             }
01875             if ( flags() & showbase ) {         // show base
01876                 *--p = (flags() & uppercase) ? 'B' : 'b';
01877                 *--p = '0';
01878             }
01879             break;
01880 
01881         case I_BASE_8:                          // output octal number
01882             p = &buf[74];
01883             *p = '\0';
01884             do {
01885                 *--p = (char)(n&7) + '0';
01886                 n >>= 3;
01887             } while ( n );
01888             if ( flags() & showbase )
01889                 *--p = '0';
01890             break;
01891 
01892         case I_BASE_16:                         // output hexadecimal number
01893             p = &buf[74];
01894             *p = '\0';
01895             hexdigits = (flags() & uppercase) ?
01896                 hexdigits_upper : hexdigits_lower;
01897             do {
01898                 *--p = hexdigits[(int)n&0xf];
01899                 n >>= 4;
01900             } while ( n );
01901             if ( flags() & showbase ) {
01902                 *--p = (flags() & uppercase) ? 'X' : 'x';
01903                 *--p = '0';
01904             }
01905             break;
01906 
01907         default:                                // decimal base is default
01908             p = &buf[74];
01909             *p = '\0';
01910             if ( neg )
01911                 n = (ulong)(-(long)n);
01912             do {
01913                 *--p = ((int)(n%10)) + '0';
01914                 n /= 10;
01915             } while ( n );
01916             if ( neg )
01917                 *--p = '-';
01918             else if ( flags() & showpos )
01919                 *--p = '+';
01920             if ( (flags() & internal) && fwidth && !ts_isdigit(*p) ) {
01921                 ts_putc( *p );                  // special case for internal
01922                 ++p;                            //   padding
01923                 fwidth--;
01924                 return *this << (const char*)p;
01925             }
01926     }
01927     if ( fwidth ) {                             // adjustment required
01928         if ( !(flags() & left) ) {              // but NOT left adjustment
01929             len = qstrlen(p);
01930             int padlen = fwidth - len;
01931             if ( padlen <= 0 ) {                // no padding required
01932                 writeBlock( p, len );
01933             } else if ( padlen < (int)(p-buf) ) { // speeds up padding
01934                 memset( p-padlen, (char)fillchar, padlen );
01935                 writeBlock( p-padlen, padlen+len );
01936             }
01937             else                                // standard padding
01938                 *this << (const char*)p;
01939         }
01940         else
01941             *this << (const char*)p;
01942         fwidth = 0;                             // reset field width
01943     }
01944     else
01945         writeBlock( p, qstrlen(p) );
01946     return *this;
01947 }
01948 
01949 
01957 QTextStream &QTextStream::operator<<( signed short i )
01958 {
01959     return output_int( I_SHORT | I_SIGNED, i, i < 0 );
01960 }
01961 
01962 
01970 QTextStream &QTextStream::operator<<( unsigned short i )
01971 {
01972     return output_int( I_SHORT | I_UNSIGNED, i, FALSE );
01973 }
01974 
01975 
01983 QTextStream &QTextStream::operator<<( signed int i )
01984 {
01985     return output_int( I_INT | I_SIGNED, i, i < 0 );
01986 }
01987 
01988 
01996 QTextStream &QTextStream::operator<<( unsigned int i )
01997 {
01998     return output_int( I_INT | I_UNSIGNED, i, FALSE );
01999 }
02000 
02001 
02009 QTextStream &QTextStream::operator<<( signed long i )
02010 {
02011     return output_int( I_LONG | I_SIGNED, i, i < 0 );
02012 }
02013 
02014 
02022 QTextStream &QTextStream::operator<<( unsigned long i )
02023 {
02024     return output_int( I_LONG | I_UNSIGNED, i, FALSE );
02025 }
02026 
02027 
02035 QTextStream &QTextStream::operator<<( float f )
02036 {
02037     return *this << (double)f;
02038 }
02039 
02040 
02048 QTextStream &QTextStream::operator<<( double f )
02049 {
02050     CHECK_STREAM_PRECOND
02051     char buf[64];
02052     char f_char;
02053     char format[16];
02054     if ( (flags()&floatfield) == fixed )
02055         f_char = 'f';
02056     else if ( (flags()&floatfield) == scientific )
02057         f_char = (flags() & uppercase) ? 'E' : 'e';
02058     else
02059         f_char = (flags() & uppercase) ? 'G' : 'g';
02060     register char *fs = format;                 // generate format string
02061     *fs++ = '%';                                //   "%.<prec>l<f_char>"
02062     *fs++ = '.';
02063     int prec = precision();
02064     if ( prec > 99 )
02065         prec = 99;
02066     if ( prec >= 10 ) {
02067         *fs++ = prec / 10 + '0';
02068         *fs++ = prec % 10 + '0';
02069     } else {
02070         *fs++ = prec + '0';
02071     }
02072     *fs++ = 'l';
02073     *fs++ = f_char;
02074     *fs = '\0';
02075     sprintf( buf, format, f );                  // convert to text
02076     if ( fwidth )                               // padding
02077         *this << (const char*)buf;
02078     else                                        // just write it
02079         writeBlock( buf, qstrlen(buf) );
02080     return *this;
02081 }
02082 
02083 
02094 QTextStream &QTextStream::operator<<( const char* s )
02095 {
02096     CHECK_STREAM_PRECOND
02097     char padbuf[48];
02098     uint len = qstrlen( s );                    // don't write null terminator
02099     if ( fwidth ) {                             // field width set
02100         int padlen = fwidth - len;
02101         fwidth = 0;                             // reset width
02102         if ( padlen > 0 ) {
02103             char *ppad;
02104             if ( padlen > 46 ) {                // create extra big fill buffer
02105                 ppad = new char[padlen];
02106                 Q_CHECK_PTR( ppad );
02107             } else {
02108                 ppad = padbuf;
02109             }
02110             memset( ppad, (char)fillchar, padlen );     // fill with fillchar
02111             if ( !(flags() & left) ) {
02112                 writeBlock( ppad, padlen );
02113                 padlen = 0;
02114             }
02115             writeBlock( s, len );
02116             if ( padlen )
02117                 writeBlock( ppad, padlen );
02118             if ( ppad != padbuf )               // delete extra big fill buf
02119                 delete[] ppad;
02120             return *this;
02121         }
02122     }
02123     writeBlock( s, len );
02124     return *this;
02125 }
02126 
02136 QTextStream &QTextStream::operator<<( const QCString & s )
02137 {
02138     return operator<<(s.data());
02139 }
02140 
02147 QTextStream &QTextStream::operator<<( const QString& s )
02148 {
02149     if ( !mapper && latin1 )
02150         return operator<<(s.latin1());
02151     CHECK_STREAM_PRECOND
02152     QString s1 = s;
02153     if ( fwidth ) {                             // field width set
02154         if ( !(flags() & left) ) {
02155             s1 = s.rightJustify(fwidth, (char)fillchar);
02156         } else {
02157             s1 = s.leftJustify(fwidth, (char)fillchar);
02158         }
02159         fwidth = 0;                             // reset width
02160     }
02161     writeBlock( s1.unicode(), s1.length() );
02162     return *this;
02163 }
02164 
02165 
02175 QTextStream &QTextStream::operator<<( void *ptr )
02176 {
02177     int f = flags();
02178     setf( hex, basefield );
02179     setf( showbase );
02180     unsetf( uppercase );
02181     output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE );
02182     flags( f );
02183     return *this;
02184 }
02185 
02186 
02307  /*****************************************************************************
02308   QTextStream manipulators
02309  *****************************************************************************/
02310 
02311 QTextStream &bin( QTextStream &s )
02312 {
02313     s.setf(QTS::bin,QTS::basefield);
02314     return s;
02315 }
02316 
02317 QTextStream &oct( QTextStream &s )
02318 {
02319     s.setf(QTS::oct,QTS::basefield);
02320     return s;
02321 }
02322 
02323 QTextStream &dec( QTextStream &s )
02324 {
02325     s.setf(QTS::dec,QTS::basefield);
02326     return s;
02327 }
02328 
02329 QTextStream &hex( QTextStream &s )
02330 {
02331     s.setf(QTS::hex,QTS::basefield);
02332     return s;
02333 }
02334 
02335 QTextStream &endl( QTextStream &s )
02336 {
02337     return s << '\n';
02338 }
02339 
02340 QTextStream &flush( QTextStream &s )
02341 {
02342     if ( s.device() )
02343         s.device()->flush();
02344     return s;
02345 }
02346 
02347 QTextStream &ws( QTextStream &s )
02348 {
02349     s.skipWhiteSpace();
02350     return s;
02351 }
02352 
02353 QTextStream &reset( QTextStream &s )
02354 {
02355     s.reset();
02356     return s;
02357 }
02358 
02359 
02479 void QTextStream::setEncoding( Encoding e )
02480 {
02481     if ( d->sourceType == QTextStreamPrivate::String )
02482         return;
02483 
02484     switch ( e ) {
02485     case Unicode:
02486         mapper = 0;
02487         latin1 = FALSE;
02488         doUnicodeHeader = TRUE;
02489         internalOrder = TRUE;
02490         networkOrder = QChar::networkOrdered();
02491         break;
02492     case UnicodeUTF8:
02493 #ifndef QT_NO_TEXTCODEC
02494         mapper = QTextCodec::codecForMib( 106 );
02495         latin1 = FALSE;
02496         doUnicodeHeader = TRUE;
02497         internalOrder = TRUE;
02498         networkOrder = QChar::networkOrdered();
02499 #else
02500         mapper = 0;
02501         latin1 = TRUE;
02502         doUnicodeHeader = TRUE;
02503 #endif
02504         break;
02505     case UnicodeNetworkOrder:
02506         mapper = 0;
02507         latin1 = FALSE;
02508         doUnicodeHeader = TRUE;
02509         internalOrder = QChar::networkOrdered();
02510         networkOrder = TRUE;
02511         break;
02512     case UnicodeReverse:
02513         mapper = 0;
02514         latin1 = FALSE;
02515         doUnicodeHeader = TRUE;
02516         internalOrder = !QChar::networkOrdered();
02517         networkOrder = FALSE;
02518         break;
02519     case RawUnicode:
02520         mapper = 0;
02521         latin1 = FALSE;
02522         doUnicodeHeader = FALSE;
02523         internalOrder = TRUE;
02524         networkOrder = QChar::networkOrdered();
02525         break;
02526     case Locale:
02527         latin1 = TRUE; // fallback to Latin-1
02528 #ifndef QT_NO_TEXTCODEC
02529         mapper = QTextCodec::codecForLocale();
02530         // optimized Latin-1 processing
02531 #if defined(Q_OS_WIN32)
02532         if ( GetACP() == 1252 )
02533             mapper = 0;
02534 #endif
02535         if ( mapper && mapper->mibEnum() == 4 )
02536 #endif
02537             mapper = 0;
02538 
02539         doUnicodeHeader = TRUE; // If it reads as Unicode, accept it
02540         break;
02541     case Latin1:
02542         mapper = 0;
02543         doUnicodeHeader = FALSE;
02544         latin1 = TRUE;
02545         break;
02546     }
02547 }
02548 
02549 
02550 #ifndef QT_NO_TEXTCODEC
02551 
02561 void QTextStream::setCodec( QTextCodec *codec )
02562 {
02563     if ( d->sourceType == QTextStreamPrivate::String )
02564         return; // QString does not need any codec
02565     mapper = codec;
02566     latin1 = ( codec->mibEnum() == 4 );
02567     if ( latin1 )
02568         mapper = 0;
02569     doUnicodeHeader = FALSE;
02570 }
02571 
02581 QTextCodec *QTextStream::codec()
02582 {
02583     if ( mapper ) {
02584         return mapper;
02585     } else {
02586         // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2"
02587         return QTextCodec::codecForMib( latin1 ? 4 : 1000 );
02588     }
02589 }
02590 
02591 #endif
02592 
02593 #endif // QT_NO_TEXTSTREAM

Generated on Sat Nov 5 16:18:34 2005 for OPIE by  doxygen 1.4.2