📄 qtextstream.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qtextstream.h"#ifndef QT_NO_TEXTSTREAM#ifndef QT_NO_TEXTCODEC#include "qtextcodec.h"#endif#include "qregexp.h"#include "qbuffer.h"#include "qfile.h"#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <locale.h>#if defined(Q_OS_WIN32)#include <windows.h>#endif/*! \class QTextStream qtextstream.h \reentrant \brief The QTextStream class provides basic functions for reading and writing text using a QIODevice. \ingroup io \ingroup text \mainclass The text stream class has a functional interface that is very similar to that of the standard C++ iostream class. Qt provides several global functions similar to the ones in iostream: \table \header \i Function \i Meaning \row \i bin \i sets the QTextStream to read/write binary numbers \row \i oct \i sets the QTextStream to read/write octal numbers \row \i dec \i sets the QTextStream to read/write decimal numbers \row \i hex \i sets the QTextStream to read/write hexadecimal numbers \row \i endl \i forces a line break \row \i flush \i forces the QIODevice to flush any buffered data \row \i ws \i eats any available whitespace (on input) \row \i reset \i resets the QTextStream to its default mode (see reset()) \row \i qSetW(int) \i sets the \link width() field width \endlink to the given argument \row \i qSetFill(int) \i sets the \link fill() fill character \endlink to the given argument \row \i qSetPrecision(int) \i sets the \link precision() precision \endlink to the given argument \endtable \warning By default QTextStream will automatically detect whether integers in the stream are in decimal, octal, hexadecimal or binary format when reading from the stream. In particular, a leading '0' signifies octal, i.e. the sequence "0100" will be interpreted as 64. The QTextStream class reads and writes text; it is not appropriate for dealing with binary data (but QDataStream is). By default, output of Unicode text (i.e. QString) is done using the local 8-bit encoding. This can be changed using the setEncoding() method. For input, the QTextStream will auto-detect standard Unicode "byte order marked" text files; otherwise the local 8-bit encoding is used. The QIODevice is set in the constructor, or later using setDevice(). If the end of the input is reached atEnd() returns TRUE. Data can be read into variables of the appropriate type using the operator>>() overloads, or read in its entirety into a single string using read(), or read a line at a time using readLine(). Whitespace can be skipped over using skipWhiteSpace(). You can set flags for the stream using flags() or setf(). The stream also supports width(), precision() and fill(); use reset() to reset the defaults. \sa QDataStream*//*! \enum QTextStream::Encoding \value Locale \value Latin1 \value Unicode \value UnicodeNetworkOrder \value UnicodeReverse \value RawUnicode \value UnicodeUTF8 See setEncoding() for an explanation of the encodings.*//* \class QTSManip \brief The QTSManip class is an internal helper class for the QTextStream. It is generally a very bad idea to use this class directly in application programs. \internal This class makes it possible to give the QTextStream function objects with arguments, like this: \code QTextStream cout( stdout, IO_WriteOnly ); cout << setprecision( 8 ); // QTSManip used here! cout << 3.14159265358979323846; \endcode The setprecision() function returns a QTSManip object. The QTSManip object contains a pointer to a member function in QTextStream and an integer argument. When serializing a QTSManip into a QTextStream, the function is executed with the argument.*//*! \fn QTSManip::QTSManip( QTSMFI m, int a ) Constructs a QTSManip object which will call \a m (a member function in QTextStream which accepts a single int) with argument \a a when QTSManip::exec() is called. Used internally in e.g. endl: \code s << "some text" << endl << "more text"; \endcode*//*! \fn void QTSManip::exec( QTextStream& s ) Calls the member function specified in the constructor, for object \a s. Used internally in e.g. endl: \code s << "some text" << endl << "more text"; \endcode*//***************************************************************************** QTextStream member functions *****************************************************************************/#if defined(QT_CHECK_STATE)#undef CHECK_STREAM_PRECOND#define CHECK_STREAM_PRECOND if ( !dev ) { \ qWarning( "QTextStream: No device" ); \ return *this; }#else#define CHECK_STREAM_PRECOND#endif#define I_SHORT 0x0010#define I_INT 0x0020#define I_LONG 0x0030#define I_TYPE_MASK 0x00f0#define I_BASE_2 QTS::bin#define I_BASE_8 QTS::oct#define I_BASE_10 QTS::dec#define I_BASE_16 QTS::hex#define I_BASE_MASK (QTS::bin | QTS::oct | QTS::dec | QTS::hex)#define I_SIGNED 0x0100#define I_UNSIGNED 0x0200#define I_SIGN_MASK 0x0f00static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character.static const uint getline_buf_size = 256; // bufsize used by ts_getline()const int QTextStream::basefield = I_BASE_MASK;const int QTextStream::adjustfield = ( QTextStream::left | QTextStream::right | QTextStream::internal );const int QTextStream::floatfield = ( QTextStream::scientific | QTextStream::fixed );class QTextStreamPrivate {public:#ifndef QT_NO_TEXTCODEC QTextStreamPrivate() : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { } ~QTextStreamPrivate() { delete decoder; delete encoder; } QTextDecoder *decoder; QTextEncoder *encoder;#else QTextStreamPrivate() : sourceType( NotSet ) { } ~QTextStreamPrivate() { }#endif QString ungetcBuf; enum SourceType { NotSet, IODevice, String, ByteArray, File }; SourceType sourceType;};// skips whitespace and returns the first non-whitespace characterQChar QTextStream::eat_ws(){ QChar c; do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) ); return c;}void QTextStream::init(){ // ### ungetcBuf = QEOF; dev = 0; owndev = FALSE; mapper = 0; d = new QTextStreamPrivate; doUnicodeHeader = TRUE; // autodetect latin1 = TRUE; // should use locale? internalOrder = QChar::networkOrdered(); networkOrder = TRUE;}/*! Constructs a data stream that has no IO device.*/QTextStream::QTextStream(){ init(); setEncoding( Locale ); reset(); d->sourceType = QTextStreamPrivate::NotSet;}/*! Constructs a text stream that uses the IO device \a iod.*/QTextStream::QTextStream( QIODevice *iod ){ init(); setEncoding( Locale ); dev = iod; reset(); d->sourceType = QTextStreamPrivate::IODevice;}// TODO: use special-case handling of this case in QTextStream, and// simplify this class to only deal with QChar or QString data.class QStringBuffer : public QIODevice {public: QStringBuffer( QString* str ); ~QStringBuffer(); bool open( int m ); void close(); void flush(); Offset size() const; Offset at() const; bool at( Offset pos ); Q_LONG readBlock( char *p, Q_ULONG len ); Q_LONG writeBlock( const char *p, Q_ULONG len ); int getch(); int putch( int ch ); int ungetch( int ch );protected: QString* s;private: QStringBuffer( const QStringBuffer & ); QStringBuffer &operator=( const QStringBuffer & );};QStringBuffer::QStringBuffer( QString* str ){ s = str;}QStringBuffer::~QStringBuffer(){}bool QStringBuffer::open( int m ){ if ( !s ) {#if defined(QT_CHECK_STATE) qWarning( "QStringBuffer::open: No string" );#endif return FALSE; } if ( isOpen() ) {#if defined(QT_CHECK_STATE) qWarning( "QStringBuffer::open: Buffer already open" );#endif return FALSE; } setMode( m ); if ( m & IO_Truncate ) s->truncate( 0 ); if ( m & IO_Append ) { ioIndex = s->length()*sizeof(QChar); } else { ioIndex = 0; } setState( IO_Open ); resetStatus(); return TRUE;}void QStringBuffer::close(){ if ( isOpen() ) { setFlags( IO_Direct ); ioIndex = 0; }}void QStringBuffer::flush(){}QIODevice::Offset QStringBuffer::size() const{ return s ? s->length()*sizeof(QChar) : 0;}QIODevice::Offset QStringBuffer::at() const{ return ioIndex;}bool QStringBuffer::at( Offset pos ){#if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QStringBuffer::at: Buffer is not open" ); return FALSE; }#endif if ( pos >= s->length()*2 ) {#if defined(QT_CHECK_RANGE)#if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) qWarning( "QStringBuffer::at: Index %llu out of range", pos );#else qWarning( "QStringBuffer::at: Index %lu out of range", pos );#endif#endif return FALSE; } ioIndex = pos; return TRUE;}Q_LONG QStringBuffer::readBlock( char *p, Q_ULONG len ){#if defined(QT_CHECK_STATE) Q_CHECK_PTR( p ); if ( !isOpen() ) { qWarning( "QStringBuffer::readBlock: Buffer not open" ); return -1; } if ( !isReadable() ) { qWarning( "QStringBuffer::readBlock: Read operation not permitted" ); return -1; }#endif if ( ioIndex + len > s->length()*sizeof(QChar) ) { // overflow if ( (uint)ioIndex >= s->length()*sizeof(QChar) ) { setStatus( IO_ReadError ); return -1; } else { len = s->length()*2 - (uint)ioIndex; } } memcpy( p, ((const char*)(s->unicode()))+ioIndex, len ); ioIndex += len; return len;}Q_LONG QStringBuffer::writeBlock( const char *p, Q_ULONG len ){#if defined(QT_CHECK_NULL) if ( p == 0 && len != 0 ) qWarning( "QStringBuffer::writeBlock: Null pointer error" );#endif#if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QStringBuffer::writeBlock: Buffer not open" ); return -1; } if ( !isWritable() ) { qWarning( "QStringBuffer::writeBlock: Write operation not permitted" ); return -1; } if ( ioIndex&1 ) { qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" ); return -1; } if ( len&1 ) { qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" ); return -1; }#endif s->replace(ioIndex/2, len/2, (QChar*)p, len/2); ioIndex += len; return len;}int QStringBuffer::getch(){#if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QStringBuffer::getch: Buffer not open" ); return -1; } if ( !isReadable() ) { qWarning( "QStringBuffer::getch: Read operation not permitted" ); return -1; }#endif if ( (uint)ioIndex >= s->length()*2 ) { // overflow setStatus( IO_ReadError ); return -1; } return (int)((const uchar *)s->unicode())[ioIndex++];}int QStringBuffer::putch( int ch ){ char c = ch; if ( writeBlock(&c,1) < 0 ) return -1; else return ch;}int QStringBuffer::ungetch( int ch ){#if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QStringBuffer::ungetch: Buffer not open" ); return -1; } if ( !isReadable() ) { qWarning( "QStringBuffer::ungetch: Read operation not permitted" ); return -1; }#endif if ( ch != -1 ) { // something to do with eof if ( ioIndex ) ioIndex--; else ch = -1; } return ch;}/*! Constructs a text stream that operates on the Unicode QString, \a str, through an internal device. The \a filemode argument is passed to the device's open() function; see \l{QIODevice::mode()}. If you set an encoding or codec with setEncoding() or setCodec(), this setting is ignored for text streams that operate on QString. Example: \code QString str; QTextStream ts( &str, IO_WriteOnly ); ts << "pi = " << 3.14; // str == "pi = 3.14" \endcode Writing data to the text stream will modify the contents of the string. The string will be expanded when data is written beyond the end of the string. Note that the string will not be truncated: \code QString str = "pi = 3.14"; QTextStream ts( &str, IO_WriteOnly ); ts << "2+2 = " << 2+2; // str == "2+2 = 414" \endcode Note that because QString is Unicode, you should not use readRawBytes() or writeRawBytes() on such a stream.*/QTextStream::QTextStream( QString* str, int filemode ){ // TODO: optimize for this case as it becomes more common // (see QStringBuffer above) init(); dev = new QStringBuffer( str ); ((QStringBuffer *)dev)->open( filemode ); owndev = TRUE; setEncoding(RawUnicode); reset(); d->sourceType = QTextStreamPrivate::String;}/*! \obsolete This constructor is equivalent to the constructor taking a QString* parameter.*/QTextStream::QTextStream( QString& str, int filemode ){ init(); dev = new QStringBuffer( &str ); ((QStringBuffer *)dev)->open( filemode ); owndev = TRUE; setEncoding(RawUnicode); reset(); d->sourceType = QTextStreamPrivate::String;}/*! Constructs a text stream that operates on the byte array, \a a, through an internal QBuffer device. The \a mode argument is passed to the device's open() function; see \l{QIODevice::mode()}. Example: \code QByteArray array; QTextStream ts( array, IO_WriteOnly ); ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" \endcode Writing data to the text stream will modify the contents of the array. The array will be expanded when data is written beyond the end of the string. Same example, using a QBuffer: \code QByteArray array; QBuffer buf( array ); buf.open( IO_WriteOnly ); QTextStream ts( &buf ); ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" buf.close(); \endcode*/QTextStream::QTextStream( QByteArray a, int mode ){ init(); dev = new QBuffer( a ); ((QBuffer *)dev)->open( mode ); owndev = TRUE; setEncoding( Latin1 ); //### Locale??? reset(); d->sourceType = QTextStreamPrivate::ByteArray;}/*! Constructs a text stream that operates on an existing file handle \a fh through an internal QFile device. The \a mode argument is passed to the device's open() function; see \l{QIODevice::mode()}. Note that if you create a QTextStream \c cout or another name that is also used for another variable of a different type, some linkers may confuse the two variables, which will often cause crashes.*/QTextStream::QTextStream( FILE *fh, int mode ){ init(); setEncoding( Locale ); //### dev = new QFile; ((QFile *)dev)->open( mode, fh ); owndev = TRUE; reset(); d->sourceType = QTextStreamPrivate::File;}/*! Destroys the text stream. The destructor does not affect the current IO device.*/QTextStream::~QTextStream(){ if ( owndev ) delete dev; delete d;}/*! Positions the read pointer at the first non-whitespace character.*/void QTextStream::skipWhiteSpace(){ ts_ungetc( eat_ws() );}/*! Tries to read \a len characters from the stream and stores them in \a buf. Returns the number of characters really read. \warning There will no QEOF appended if the read reaches the end of the file. EOF is reached when the return value does not equal \a len.*/uint QTextStream::ts_getbuf( QChar* buf, uint len ){ if ( len < 1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -