?? qtextstream.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************///#define QTEXTSTREAM_DEBUGstatic const int QTEXTSTREAM_BUFFERSIZE = 16384;/*! \class QTextStream \brief The QTextStream class provides a convenient interface for reading and writing text. \ingroup io \ingroup text \reentrant QTextStream can operate on a QIODevice, a QByteArray or a QString. Using QTextStream's streaming operators, you can conveniently read and write words, lines and numbers. For generating text, QTextStream supports formatting options for field padding and alignment, and formatting of numbers. Example: \code QFile data("output.txt"); if (data.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream out(&data); out << "Result: " << qSetFieldWidth(10) << left << 3.14 << 2.7 << endl; // writes "Result: 3.14 2.7 \n" } \endcode Besides using QTextStream's constructors, you can also set the device or string QTextStream operates on by calling setDevice() or setString(). You can seek to a position by calling seek(), and atEnd() will return true when there is no data left to be read. If you call flush(), QTextStream will empty all data from its write buffer into the device and call flush() on the device. Internally, QTextStream uses a Unicode based buffer, and QTextCodec is used by QTextStream to automatically support different character sets. By default, QTextCodec::codecForLocale() is used for reading and writing, but you can also set the codec by calling setCodec(). Automatic Unicode detection is also supported. When this feature is enabled (the default behavior), QTextStream will detect the UTF-16 BOM (Byte Order Mark) and switch to the appropriate UTF-16 codec when reading. QTextStream does not write a BOM by default, but you can enable this by calling setGenerateByteOrderMark(true). When QTextStream operates on a QString directly, the codec is disabled. There are three general ways to use QTextStream when reading text files: \list \o Chunk by chunk, by calling readLine() or readAll(). \o Word by word. QTextStream supports streaming into QStrings, QByteArrays and char* buffers. Words are delimited by space, and leading white space is automatically skipped. \o Character by character, by streaming into QChar or char types. This method is often used for convenient input handling when parsing files, independent of character encoding and end-of-line semantics. To skip white space, call skipWhiteSpace(). \endlist By default, when reading numbers from a stream of text, QTextStream will automatically detect the number's base representation. For example, if the number starts with "0x", it is assumed to be in hexadecimal form. If it starts with the digits 1-9, it is assumed to be in decimal form, and so on. You can set the integer base, thereby disabling the automatic detection, by calling setIntegerBase(). Example: \code QTextStream in("0x50 0x20"); int firstNumber, secondNumber; in >> firstNumber; // firstNumber == 80 in >> dec >> secondNumber; // secondNumber == 0 char ch; in >> ch; // ch == 'x' \endcode QTextStream supports many formatting options for generating text. You can set the field width and pad character by calling setFieldWidth() and setPadChar(). Use setFieldAlignment() to set the alignment within each field. For real numbers, call setRealNumberNotation() and setRealNumberPrecision() to set the notation (SmartNotation, ScientificNotation, FixedNotation) and precision in digits of the generated number. Some extra number formatting options are also available through setNumberFlags(). \keyword QTextStream manipulators Like \c <iostream> in the standard C++ library, QTextStream also defines several global manipulator functions: \table \header \o Manipulator \o Description \row \o \c bin \o Same as setIntegerBase(2). \row \o \c oct \o Same as setIntegerBase(8). \row \o \c dec \o Same as setIntegerBase(10). \row \o \c hex \o Same as setIntegerBase(16). \row \o \c showbase \o Same as setNumberFlags(numberFlags() | ShowBase). \row \o \c forcesign \o Same as setNumberFlags(numberFlags() | ForceSign). \row \o \c forcepoint \o Same as setNumberFlags(numberFlags() | ForcePoint). \row \o \c noshowbase \o Same as setNumberFlags(numberFlags() & ~ShowBase). \row \o \c noforcesign \o Same as setNumberFlags(numberFlags() & ~ForceSign). \row \o \c noforcepoint \o Same as setNumberFlags(numberFlags() & ~ForcePoint). \row \o \c uppercasebase \o Same as setNumberFlags(numberFlags() | UppercaseBase). \row \o \c uppercasedigits \o Same as setNumberFlags(numberFlags() | UppercaseDigits). \row \o \c lowercasebase \o Same as setNumberFlags(numberFlags() & ~UppercaseBase). \row \o \c lowercasedigits \o Same as setNumberFlags(numberFlags() & ~UppercaseDigits). \row \o \c fixed \o Same as setRealNumberNotation(FixedNotation). \row \o \c scientific \o Same as setRealNumberNotation(ScientificNotation). \row \o \c left \o Same as setFieldAlignment(AlignLeft). \row \o \c right \o Same as setFieldAlignment(AlignRight). \row \o \c center \o Same as setFieldAlignment(AlignCenter). \row \o \c endl \o Same as operator<<('\n') and flush(). \row \o \c flush \o Same as flush(). \row \o \c reset \o Same as reset(). \row \o \c ws \o Same as skipWhiteSpace(). \row \o \c bom \o Same as setGenerateByteOrderMark(true). \endtable In addition, Qt provides three global manipulators that take a parameter: qSetFieldWidth(), qSetPadChar(), and qSetRealNumberPrecision(). \sa QDataStream, QIODevice, QFile, QBuffer, QTcpSocket, {Codecs Example}*//*! \enum QTextStream::RealNumberNotation This enum specifies which notations to use for expressing \c float and \c double as strings. \value ScientificNotation Scientific notation (\c{printf()}'s \c %e flag). \value FixedNotation Fixed-point notation (\c{printf()}'s \c %f flag). \value SmartNotation Scientific or fixed-point notation, depending on which makes most sense (\c{printf()}'s \c %g flag). \sa setRealNumberNotation()*//*! \enum QTextStream::FieldAlignment This enum specifies how to align text in fields when the field is wider than the text that occupies it. \value AlignLeft Pad on the right side of fields. \value AlignRight Pad on the left side of fields. \value AlignCenter Pad on both sides of field. \value AlignAccountingStyle Same as AlignRight, except that the sign of a number is flush left. \sa setFieldAlignment()*//*! \enum QTextStream::NumberFlag This enum specifies various flags that can be set to affect the output of integers, \c{float}s, and \c{double}s. \value ShowBase Show the base as a prefix if the base is 16 ("0x"), 8 ("0"), or 2 ("0b"). \value ForcePoint Always put the decimal separator in numbers, even if there are no decimals. \value ForceSign Always put the sign in numbers, even for positive numbers. \value UppercaseBase Use uppercase versions of base prefixes ("0X", "0B"). \value UppercaseDigits Use uppercare letters for expressing digits 10 to 35 instead of lowercase. \sa setNumberFlags()*//*! \enum QTextStream::Status This enum describes the current status of the text stream. \value Ok The text stream is operating normally. \value ReadPastEnd The text stream has read past the end of the data in the underlying device. \value ReadCorruptData The text stream has read corrupt data. \sa status()*/#include "qtextstream.h"#include "qbuffer.h"#include "qfile.h"#ifndef QT_NO_TEXTCODEC#include "qtextcodec.h"#endif#ifndef Q_OS_TEMP#include <locale.h>#endif#include <stdlib.h>#if defined QTEXTSTREAM_DEBUG#include <ctype.h>// Returns a human readable representation of the first \a len// characters in \a data.static QByteArray qt_prettyDebug(const char *data, int len, int maxSize){ if (!data) return "(null)"; QByteArray out; for (int i = 0; i < len; ++i) { char c = data[i]; if (isprint(c)) { out += c; } else switch (c) { case '\n': out += "\\n"; break; case '\r': out += "\\r"; break; case '\t': out += "\\t"; break; default: QString tmp; tmp.sprintf("\\x%x", (unsigned int)(unsigned char)c); out += tmp.toLatin1(); } } if (len < maxSize) out += "..."; return out;}#endif// A precondition macro#define Q_VOID#define CHECK_VALID_STREAM(x) do { \ if (!d->string && !d->device) { \ qWarning("QTextStream: No device"); \ return x; \ } } while (0)// Base implementations of operator>> for ints and reals#define IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(type) do { \ Q_D(QTextStream); \ CHECK_VALID_STREAM(*this); \ qulonglong tmp; \ switch (d->getNumber(&tmp)) { \ case QTextStreamPrivate::npsOk: \ i = (type)tmp; \ break; \ case QTextStreamPrivate::npsMissingDigit: \ case QTextStreamPrivate::npsInvalidPrefix: \ i = (type)0; \ setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData); \ break; \ } \ return *this; } while (0)#define IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(type) do { \ Q_D(QTextStream); \ CHECK_VALID_STREAM(*this); \ double tmp; \ if (d->getReal(&tmp)) { \ f = (type)tmp; \ } else { \ f = (type)0; \ setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData); \ } \ return *this; } while (0)#ifndef QT_NO_QOBJECTclass QDeviceClosedNotifier : public QObject{ Q_OBJECTpublic: inline QDeviceClosedNotifier() { } inline void setupDevice(QTextStream *stream, QIODevice *device) { disconnect(); if (device) connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream())); this->stream = stream; }public slots: inline void flushStream() { stream->flush(); }private: QTextStream *stream;};#endif//-------------------------------------------------------------------class QTextStreamPrivate{ Q_DECLARE_PUBLIC(QTextStream)public: QTextStreamPrivate(QTextStream *q_ptr); ~QTextStreamPrivate(); void reset(); // device QIODevice *device;#ifndef QT_NO_QOBJECT QDeviceClosedNotifier deviceClosedNotifier;#endif bool deleteDevice; // string QString *string; int stringOffset; QIODevice::OpenMode stringOpenMode;#ifndef QT_NO_TEXTCODEC // codec QTextCodec *codec; QTextCodec::ConverterState readConverterState; QTextCodec::ConverterState writeConverterState; bool autoDetectUnicode;#endif // i/o enum TokenDelimiter { Space, NotSpace, EndOfLine, EndOfFile }; bool scan(const QChar **ptr, int *tokenLength, int maxlen, TokenDelimiter delimiter); inline const QChar *readPtr() const; inline void consumeLastToken(); inline void consume(int nchars); int lastTokenSize; // Return value type for getNumber() enum NumberParsingStatus { npsOk, npsMissingDigit, npsInvalidPrefix }; inline bool write(const QString &data); inline bool getChar(QChar *ch); inline void ungetChar(const QChar &ch); NumberParsingStatus getNumber(qulonglong *l); bool getReal(double *f); bool putNumber(qulonglong number, bool negative); inline bool putString(const QString &ch); // buffers bool fillReadBuffer(qint64 maxBytes = -1); bool flushWriteBuffer(); QString writeBuffer; QString readBuffer; int readBufferOffset; qint64 readBufferStartDevicePos; QString endOfBufferState;#ifndef QT_NO_TEXTCODEC QTextCodec::ConverterState readBufferStartReadConverterState;#endif QString readBufferStartEndOfBufferState; // streaming parameters int realNumberPrecision; int integerBase; int fieldWidth; QChar padChar; QTextStream::FieldAlignment fieldAlignment; QTextStream::RealNumberNotation realNumberNotation; QTextStream::NumberFlags numberFlags; // status QTextStream::Status status; QTextStream *q_ptr;};/*! \internal*/QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr){ this->q_ptr = q_ptr; reset();}/*! \internal*/QTextStreamPrivate::~QTextStreamPrivate(){ if (deleteDevice) delete device;}#ifndef QT_NO_TEXTCODECstatic void resetCodecConverterState(QTextCodec::ConverterState *state) { state->flags = QTextCodec::DefaultConversion; state->remainingChars = state->invalidChars = state->state_data[0] = state->state_data[1] = state->state_data[2] = 0; if (state->d) qFree(state->d); state->d = 0;}static void copyConverterState(QTextCodec::ConverterState *dest, const QTextCodec::ConverterState *src){ // ### QTextCodec::ConverterState's copy constructors and assignments are // private. This function copies the structure manually. dest->flags = src->flags; dest->invalidChars = src->invalidChars; dest->state_data[0] = src->state_data[0]; dest->state_data[1] = src->state_data[1]; dest->state_data[2] = src->state_data[2]; dest->d = src->d; // <- ### wrong?}#endif/*! \internal*/void QTextStreamPrivate::reset(){ realNumberPrecision = 6; integerBase = 0; fieldWidth = 0; padChar = QLatin1Char(' '); fieldAlignment = QTextStream::AlignRight; realNumberNotation = QTextStream::SmartNotation; numberFlags = 0; device = 0; deleteDevice = false; string = 0; stringOffset = 0; stringOpenMode = QIODevice::NotOpen; readBufferOffset = 0; readBufferStartDevicePos = 0; endOfBufferState.clear(); lastTokenSize = 0;#ifndef QT_NO_TEXTCODEC codec = QTextCodec::codecForLocale(); ::resetCodecConverterState(&readConverterState); ::resetCodecConverterState(&writeConverterState); ::resetCodecConverterState(&readBufferStartReadConverterState); writeConverterState.flags |= QTextCodec::IgnoreHeader; autoDetectUnicode = true;#endif}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -