📄 qtextstream.cpp
字号:
/****************************************************************************** $Id: qt/src/tools/qtextstream.cpp 2.2.3 edited 2000-10-25 $**** Implementation of QTextStream class**** Created : 940922**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the tools module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** 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#include "qtextcodec.h"#include "qregexp.h"#include "qbuffer.h"#include "qfile.h"#include <stdio.h>#include <ctype.h>#include <stdlib.h>#if defined(_OS_WIN32_)#include <windows.h>#endif// NOT REVISED/*! \class QTextStream qtextstream.h \brief The QTextStream class provides basic functions for reading and writing text using a QIODevice. \ingroup io \define endl \define bin \define oct \define dec \define hex \define flush \define ws The text stream class has a functional interface that is very similar to that of the standard C++ iostream class. The difference between iostream and QTextStream is that our stream operates on a QIODevice, which is easily subclassed, while iostream operates on FILE * pointers, which can not be subclassed. Qt provides several global functions similar to the ones in iostream: <ul> <li> \c bin sets the QTextStream to read/write binary numbers <li> \c oct sets the QTextStream to read/write octal numbers <li> \c dec sets the QTextStream to read/write decimal numbers <li> \c hex sets the QTextStream to read/write hexadecimal numbers <li> \c endl forces a line break <li> \c flush forces the QIODevice to flush any buffered data <li> \c ws eats any available white space (on input) <li> \c reset resets the QTextStream to its default mode (see reset()). </ul> \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, ie. the sequence "0100" will be interpreted as 64. The QTextStream class reads and writes text and it is not appropriate for dealing with binary data (but QDataStream is). By default output of Unicode text (ie. 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, but otherwise the local 8-bit encoding is used. \sa QDataStream*//* \class QTSManip qtextstream.h \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(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.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 ), sourceType( NotSet ) {} ~QTextStreamPrivate() { delete decoder; } QTextDecoder *decoder; //???#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; // no device set fstrm = owndev = FALSE; mapper = 0; d = new QTextStreamPrivate; doUnicodeHeader = TRUE; //default to autodetect latin1 = TRUE; // ### should use local? internalOrder = QChar::networkOrdered(); //default to network order}/*! 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; // set device 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(); uint size() const; int at() const; bool at( int pos ); int readBlock( char *p, uint len ); int writeBlock( const char *p, uint len ); int getch(); int putch( int ch ); int ungetch( int ch );protected: QString* s;private: // Disabled copy constructor and operator= QStringBuffer( const QStringBuffer & ); QStringBuffer &operator=( const QStringBuffer & );};QStringBuffer::QStringBuffer( QString* str ){ s = str;}QStringBuffer::~QStringBuffer(){}bool QStringBuffer::open( int m ){ if ( !s ) {#if defined(CHECK_STATE) qWarning( "QStringBuffer::open: No string" );#endif return FALSE; } if ( isOpen() ) { // buffer already open#if defined(CHECK_STATE) qWarning( "QStringBuffer::open: Buffer already open" );#endif return FALSE; } setMode( m ); if ( m & IO_Truncate ) { // truncate buffer s->truncate( 0 ); } if ( m & IO_Append ) { // append to end of buffer ioIndex = s->length()*sizeof(QChar); } else { ioIndex = 0; } setState( IO_Open ); setStatus( 0 ); return TRUE;}void QStringBuffer::close(){ if ( isOpen() ) { setFlags( IO_Direct ); ioIndex = 0; }}void QStringBuffer::flush(){}uint QStringBuffer::size() const{ return s ? s->length()*sizeof(QChar) : 0;}int QStringBuffer::at() const{ return ioIndex;}bool QStringBuffer::at( int pos ){#if defined(CHECK_STATE) if ( !isOpen() ) { qWarning( "QStringBuffer::at: Buffer is not open" ); return FALSE; }#endif if ( (uint)pos >= s->length()*2 ) {#if defined(CHECK_RANGE) qWarning( "QStringBuffer::at: Index %d out of range", pos );#endif return FALSE; } ioIndex = pos; return TRUE;}int QStringBuffer::readBlock( char *p, uint len ){#if defined(CHECK_STATE) CHECK_PTR( p ); if ( !isOpen() ) { // buffer not open qWarning( "QStringBuffer::readBlock: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QStringBuffer::readBlock: Read operation not permitted" ); return -1; }#endif if ( (uint)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;}int QStringBuffer::writeBlock( const char *p, uint len ){#if defined(CHECK_NULL) if ( p == 0 && len != 0 ) qWarning( "QStringBuffer::writeBlock: Null pointer error" );#endif#if defined(CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QStringBuffer::writeBlock: Buffer not open" ); return -1; } if ( !isWritable() ) { // writing not permitted 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(CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QStringBuffer::getch: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QStringBuffer::getch: Read operation not permitted" ); return -1; }#endif if ( (uint)ioIndex >= s->length()*2 ) { // overflow setStatus( IO_ReadError ); return -1; } return *((char*)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(CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QStringBuffer::ungetch: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted 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 a Unicode QString through an internal device. 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 since 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 a byte array through an internal QBuffer device. 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -