summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qtextstream.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/corelib/io/qtextstream.cpp
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/corelib/io/qtextstream.cpp')
-rw-r--r--src/corelib/io/qtextstream.cpp3413
1 files changed, 3413 insertions, 0 deletions
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
new file mode 100644
index 0000000000..a5837cbeb5
--- /dev/null
+++ b/src/corelib/io/qtextstream.cpp
@@ -0,0 +1,3413 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QTEXTSTREAM_DEBUG
+static const int QTEXTSTREAM_BUFFERSIZE = 16384;
+
+/*!
+ \class QTextStream
+
+ \brief The QTextStream class provides a convenient interface for
+ reading and writing text.
+
+ \ingroup io
+ \ingroup string-processing
+ \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:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 0
+
+ It's also common to use QTextStream to read console input and write
+ console output. QTextStream is locale aware, and will automatically decode
+ standard input using the correct codec. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 1
+
+ Note that you cannot use QTextStream::atEnd(), which returns true when you
+ have reached the end of the data stream, with stdin. The reason for this is
+ that as long as stdin doesn't give any input to the QTextStream, \c atEnd()
+ will return true even if the stdin is open and waiting for more characters.
+
+ 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 or the UTF-32 BOM (Byte Order Mark) and
+ switch to the appropriate UTF 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
+
+ Since the text stream uses a buffer, you should not read from
+ the stream using the implementation of a superclass. For instance,
+ if you have a QFile and read from it directly using
+ QFile::readLine() instead of using the stream, the text stream's
+ internal position will be out of sync with the file's position.
+
+ 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:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 2
+
+ 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 uppercase 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.
+ \value WriteFailed The text stream cannot write to the underlying device.
+
+ \sa status()
+*/
+
+#include "qtextstream.h"
+#include "qbuffer.h"
+#include "qfile.h"
+#include "qnumeric.h"
+#ifndef QT_NO_TEXTCODEC
+#include "qtextcodec.h"
+#endif
+#ifndef Q_OS_WINCE
+#include <locale.h>
+#endif
+#include "private/qlocale_p.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <new>
+
+#if defined QTEXTSTREAM_DEBUG
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+// 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(int(uchar(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;
+}
+QT_END_NAMESPACE
+
+#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)
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QOBJECT
+class QDeviceClosedNotifier : public QObject
+{
+ Q_OBJECT
+public:
+ inline QDeviceClosedNotifier()
+ { }
+
+ inline void setupDevice(QTextStream *stream, QIODevice *device)
+ {
+ disconnect();
+ if (device)
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
+ this->stream = stream;
+ }
+
+public Q_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;
+ QTextCodec::ConverterState *readConverterSavedState;
+ bool autoDetectUnicode;
+#endif
+
+ // i/o
+ enum TokenDelimiter {
+ Space,
+ NotSpace,
+ EndOfLine
+ };
+
+ QString read(int maxlen);
+ bool scan(const QChar **ptr, int *tokenLength,
+ int maxlen, TokenDelimiter delimiter);
+ inline const QChar *readPtr() const;
+ inline void consumeLastToken();
+ inline void consume(int nchars);
+ void saveConverterState(qint64 newPos);
+ void restoreToSavedConverterState();
+ int lastTokenSize;
+
+ // Return value type for getNumber()
+ enum NumberParsingStatus {
+ npsOk,
+ npsMissingDigit,
+ npsInvalidPrefix
+ };
+
+ inline bool getChar(QChar *ch);
+ inline void ungetChar(const QChar &ch);
+ NumberParsingStatus getNumber(qulonglong *l);
+ bool getReal(double *f);
+
+ inline void write(const QString &data);
+ inline void putString(const QString &ch, bool number = false);
+ void putNumber(qulonglong number, bool negative);
+
+ // buffers
+ bool fillReadBuffer(qint64 maxBytes = -1);
+ void resetReadBuffer();
+ void flushWriteBuffer();
+ QString writeBuffer;
+ QString readBuffer;
+ int readBufferOffset;
+ int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
+ qint64 readBufferStartDevicePos;
+
+ // streaming parameters
+ int realNumberPrecision;
+ int integerBase;
+ int fieldWidth;
+ QChar padChar;
+ QTextStream::FieldAlignment fieldAlignment;
+ QTextStream::RealNumberNotation realNumberNotation;
+ QTextStream::NumberFlags numberFlags;
+
+ // status
+ QTextStream::Status status;
+
+ QLocale locale;
+
+ QTextStream *q_ptr;
+};
+
+/*! \internal
+*/
+QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
+ :
+#ifndef QT_NO_TEXTCODEC
+ readConverterSavedState(0),
+#endif
+ readConverterSavedStateOffset(0),
+ locale(QLocale::c())
+{
+ this->q_ptr = q_ptr;
+ reset();
+}
+
+/*! \internal
+*/
+QTextStreamPrivate::~QTextStreamPrivate()
+{
+ if (deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ device->blockSignals(true);
+#endif
+ delete device;
+ }
+#ifndef QT_NO_TEXTCODEC
+ delete readConverterSavedState;
+#endif
+}
+
+#ifndef QT_NO_TEXTCODEC
+static void resetCodecConverterStateHelper(QTextCodec::ConverterState *state)
+{
+ state->~ConverterState();
+ new (state) QTextCodec::ConverterState;
+}
+
+static void copyConverterStateHelper(QTextCodec::ConverterState *dest,
+ const QTextCodec::ConverterState *src)
+{
+ // ### QTextCodec::ConverterState's copy constructors and assignments are
+ // private. This function copies the structure manually.
+ Q_ASSERT(!src->d);
+ 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];
+}
+#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;
+ lastTokenSize = 0;
+
+#ifndef QT_NO_TEXTCODEC
+ codec = QTextCodec::codecForLocale();
+ resetCodecConverterStateHelper(&readConverterState);
+ resetCodecConverterStateHelper(&writeConverterState);
+ delete readConverterSavedState;
+ readConverterSavedState = 0;
+ writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ autoDetectUnicode = true;
+#endif
+}
+
+/*! \internal
+*/
+bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
+{
+ // no buffer next to the QString itself; this function should only
+ // be called internally, for devices.
+ Q_ASSERT(!string);
+ Q_ASSERT(device);
+
+ // handle text translation and bypass the Text flag in the device.
+ bool textModeEnabled = device->isTextModeEnabled();
+ if (textModeEnabled)
+ device->setTextModeEnabled(false);
+
+ // read raw data into a temporary buffer
+ char buf[QTEXTSTREAM_BUFFERSIZE];
+ qint64 bytesRead = 0;
+#if defined(Q_OS_WIN)
+ // On Windows, there is no non-blocking stdin - so we fall back to reading
+ // lines instead. If there is no QOBJECT, we read lines for all sequential
+ // devices; otherwise, we read lines only for stdin.
+ QFile *file = 0;
+ Q_UNUSED(file);
+ if (device->isSequential()
+#if !defined(QT_NO_QOBJECT)
+ && (file = qobject_cast<QFile *>(device)) && file->handle() == 0
+#endif
+ ) {
+ if (maxBytes != -1)
+ bytesRead = device->readLine(buf, qMin<qint64>(sizeof(buf), maxBytes));
+ else
+ bytesRead = device->readLine(buf, sizeof(buf));
+ } else
+#endif
+ {
+ if (maxBytes != -1)
+ bytesRead = device->read(buf, qMin<qint64>(sizeof(buf), maxBytes));
+ else
+ bytesRead = device->read(buf, sizeof(buf));
+ }
+
+#ifndef QT_NO_TEXTCODEC
+ // codec auto detection, explicitly defaults to locale encoding if the
+ // codec has been set to 0.
+ if (!codec || autoDetectUnicode) {
+ autoDetectUnicode = false;
+
+ codec = QTextCodec::codecForUtfText(QByteArray::fromRawData(buf, bytesRead), codec);
+ if (!codec) {
+ codec = QTextCodec::codecForLocale();
+ writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ }
+ }
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::fillReadBuffer(), using %s codec",
+ codec->name().constData());
+#endif
+#endif
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d",
+ qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), sizeof(buf), int(bytesRead));
+#endif
+
+ if (bytesRead <= 0)
+ return false;
+
+ int oldReadBufferSize = readBuffer.size();
+#ifndef QT_NO_TEXTCODEC
+ // convert to unicode
+ readBuffer += codec->toUnicode(buf, bytesRead, &readConverterState);
+#else
+ readBuffer += QString::fromLatin1(QByteArray(buf, bytesRead).constData());
+#endif
+
+ // reset the Text flag.
+ if (textModeEnabled)
+ device->setTextModeEnabled(true);
+
+ // remove all '\r\n' in the string.
+ if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
+ QChar CR = QLatin1Char('\r');
+ QChar *writePtr = readBuffer.data() + oldReadBufferSize;
+ QChar *readPtr = readBuffer.data() + oldReadBufferSize;
+ QChar *endPtr = readBuffer.data() + readBuffer.size();
+
+ int n = oldReadBufferSize;
+ if (readPtr < endPtr) {
+ // Cut-off to avoid unnecessary self-copying.
+ while (*readPtr++ != CR) {
+ ++n;
+ if (++writePtr == endPtr)
+ break;
+ }
+ }
+ while (readPtr < endPtr) {
+ QChar ch = *readPtr++;
+ if (ch != CR) {
+ *writePtr++ = ch;
+ } else {
+ if (n < readBufferOffset)
+ --readBufferOffset;
+ --bytesRead;
+ }
+ ++n;
+ }
+ readBuffer.resize(writePtr - readBuffer.data());
+ }
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::fillReadBuffer() read %d bytes from device. readBuffer = [%s]", int(bytesRead),
+ qt_prettyDebug(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).data());
+#endif
+ return true;
+}
+
+/*! \internal
+*/
+void QTextStreamPrivate::resetReadBuffer()
+{
+ readBuffer.clear();
+ readBufferOffset = 0;
+ readBufferStartDevicePos = (device ? device->pos() : 0);
+}
+
+/*! \internal
+*/
+void QTextStreamPrivate::flushWriteBuffer()
+{
+ // no buffer next to the QString itself; this function should only
+ // be called internally, for devices.
+ if (string || !device)
+ return;
+
+ // Stream went bye-bye already. Appending further data may succeed again,
+ // but would create a corrupted stream anyway.
+ if (status != QTextStream::Ok)
+ return;
+
+ if (writeBuffer.isEmpty())
+ return;
+
+#if defined (Q_OS_WIN)
+ // handle text translation and bypass the Text flag in the device.
+ bool textModeEnabled = device->isTextModeEnabled();
+ if (textModeEnabled) {
+ device->setTextModeEnabled(false);
+ writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ }
+#endif
+
+#ifndef QT_NO_TEXTCODEC
+ if (!codec)
+ codec = QTextCodec::codecForLocale();
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::flushWriteBuffer(), using %s codec (%s generating BOM)",
+ codec->name().constData(), writeConverterState.flags & QTextCodec::IgnoreHeader ? "not" : "");
+#endif
+
+ // convert from unicode to raw data
+ QByteArray data = codec->fromUnicode(writeBuffer.data(), writeBuffer.size(), &writeConverterState);
+#else
+ QByteArray data = writeBuffer.toLocal8Bit();
+#endif
+ writeBuffer.clear();
+
+ // write raw data to the device
+ qint64 bytesWritten = device->write(data);
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d",
+ qt_prettyDebug(data.constData(), qMin(data.size(),32), data.size()).constData(), int(bytesWritten));
+#endif
+ if (bytesWritten <= 0) {
+ status = QTextStream::WriteFailed;
+ return;
+ }
+
+#if defined (Q_OS_WIN)
+ // replace the text flag
+ if (textModeEnabled)
+ device->setTextModeEnabled(true);
+#endif
+
+ // flush the file
+#ifndef QT_NO_QOBJECT
+ QFile *file = qobject_cast<QFile *>(device);
+ bool flushed = !file || file->flush();
+#else
+ bool flushed = true;
+#endif
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::flushWriteBuffer() wrote %d bytes",
+ int(bytesWritten));
+#endif
+ if (!flushed || bytesWritten != qint64(data.size()))
+ status = QTextStream::WriteFailed;
+}
+
+QString QTextStreamPrivate::read(int maxlen)
+{
+ QString ret;
+ if (string) {
+ lastTokenSize = qMin(maxlen, string->size() - stringOffset);
+ ret = string->mid(stringOffset, lastTokenSize);
+ } else {
+ while (readBuffer.size() - readBufferOffset < maxlen && fillReadBuffer()) ;
+ lastTokenSize = qMin(maxlen, readBuffer.size() - readBufferOffset);
+ ret = readBuffer.mid(readBufferOffset, lastTokenSize);
+ }
+ consumeLastToken();
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::read() maxlen = %d, token length = %d", maxlen, ret.length());
+#endif
+ return ret;
+}
+
+/*! \internal
+
+ Scans no more than \a maxlen QChars in the current buffer for the
+ first \a delimiter. Stores a pointer to the start offset of the
+ token in \a ptr, and the length in QChars in \a length.
+*/
+bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenDelimiter delimiter)
+{
+ int totalSize = 0;
+ int delimSize = 0;
+ bool consumeDelimiter = false;
+ bool foundToken = false;
+ int startOffset = device ? readBufferOffset : stringOffset;
+ QChar lastChar;
+
+ bool canStillReadFromDevice = true;
+ do {
+ int endOffset;
+ const QChar *chPtr;
+ if (device) {
+ chPtr = readBuffer.constData();
+ endOffset = readBuffer.size();
+ } else {
+ chPtr = string->constData();
+ endOffset = string->size();
+ }
+ chPtr += startOffset;
+
+ for (; !foundToken && startOffset < endOffset && (!maxlen || totalSize < maxlen); ++startOffset) {
+ const QChar ch = *chPtr++;
+ ++totalSize;
+
+ switch (delimiter) {
+ case Space:
+ if (ch.isSpace()) {
+ foundToken = true;
+ delimSize = 1;
+ }
+ break;
+ case NotSpace:
+ if (!ch.isSpace()) {
+ foundToken = true;
+ delimSize = 1;
+ }
+ break;
+ case EndOfLine:
+ if (ch == QLatin1Char('\n')) {
+ foundToken = true;
+ delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1;
+ consumeDelimiter = true;
+ }
+ lastChar = ch;
+ break;
+ }
+ }
+ } while (!foundToken
+ && (!maxlen || totalSize < maxlen)
+ && (device && (canStillReadFromDevice = fillReadBuffer())));
+
+ // if the token was not found, but we reached the end of input,
+ // then we accept what we got. if we are not at the end of input,
+ // we return false.
+ if (!foundToken && (!maxlen || totalSize < maxlen)
+ && (totalSize == 0
+ || (string && stringOffset + totalSize < string->size())
+ || (device && !device->atEnd() && canStillReadFromDevice))) {
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::scan() did not find the token.");
+#endif
+ return false;
+ }
+
+ // if we find a '\r' at the end of the data when reading lines,
+ // don't make it part of the line.
+ if (delimiter == EndOfLine && totalSize > 0 && !foundToken) {
+ if (((string && stringOffset + totalSize == string->size()) || (device && device->atEnd()))
+ && lastChar == QLatin1Char('\r')) {
+ consumeDelimiter = true;
+ ++delimSize;
+ }
+ }
+
+ // set the read offset and length of the token
+ if (length)
+ *length = totalSize - delimSize;
+ if (ptr)
+ *ptr = readPtr();
+
+ // update last token size. the callee will call consumeLastToken() when
+ // done.
+ lastTokenSize = totalSize;
+ if (!consumeDelimiter)
+ lastTokenSize -= delimSize;
+
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::scan(%p, %p, %d, %x) token length = %d, delimiter = %d",
+ ptr, length, maxlen, (int)delimiter, totalSize - delimSize, delimSize);
+#endif
+ return true;
+}
+
+/*! \internal
+*/
+inline const QChar *QTextStreamPrivate::readPtr() const
+{
+ Q_ASSERT(readBufferOffset <= readBuffer.size());
+ if (string)
+ return string->constData() + stringOffset;
+ return readBuffer.constData() + readBufferOffset;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::consumeLastToken()
+{
+ if (lastTokenSize)
+ consume(lastTokenSize);
+ lastTokenSize = 0;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::consume(int size)
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStreamPrivate::consume(%d)", size);
+#endif
+ if (string) {
+ stringOffset += size;
+ if (stringOffset > string->size())
+ stringOffset = string->size();
+ } else {
+ readBufferOffset += size;
+ if (readBufferOffset >= readBuffer.size()) {
+ readBufferOffset = 0;
+ readBuffer.clear();
+ saveConverterState(device->pos());
+ } else if (readBufferOffset > QTEXTSTREAM_BUFFERSIZE) {
+ readBuffer = readBuffer.remove(0,readBufferOffset);
+ readConverterSavedStateOffset += readBufferOffset;
+ readBufferOffset = 0;
+ }
+ }
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (readConverterState.d) {
+ // converter cannot be copied, so don't save anything
+ // don't update readBufferStartDevicePos either
+ return;
+ }
+
+ if (!readConverterSavedState)
+ readConverterSavedState = new QTextCodec::ConverterState;
+ copyConverterStateHelper(readConverterSavedState, &readConverterState);
+#endif
+
+ readBufferStartDevicePos = newPos;
+ readConverterSavedStateOffset = 0;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::restoreToSavedConverterState()
+{
+#ifndef QT_NO_TEXTCODEC
+ if (readConverterSavedState) {
+ // we have a saved state
+ // that means the converter can be copied
+ copyConverterStateHelper(&readConverterState, readConverterSavedState);
+ } else {
+ // the only state we could save was the initial
+ // so reset to that
+ resetCodecConverterStateHelper(&readConverterState);
+ }
+#endif
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::write(const QString &data)
+{
+ if (string) {
+ // ### What about seek()??
+ string->append(data);
+ } else {
+ writeBuffer += data;
+ if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE)
+ flushWriteBuffer();
+ }
+}
+
+/*! \internal
+*/
+inline bool QTextStreamPrivate::getChar(QChar *ch)
+{
+ if ((string && stringOffset == string->size())
+ || (device && readBuffer.isEmpty() && !fillReadBuffer())) {
+ if (ch)
+ *ch = 0;
+ return false;
+ }
+ if (ch)
+ *ch = *readPtr();
+ consume(1);
+ return true;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::ungetChar(const QChar &ch)
+{
+ if (string) {
+ if (stringOffset == 0)
+ string->prepend(ch);
+ else
+ (*string)[--stringOffset] = ch;
+ return;
+ }
+
+ if (readBufferOffset == 0) {
+ readBuffer.prepend(ch);
+ return;
+ }
+
+ readBuffer[--readBufferOffset] = ch;
+}
+
+/*! \internal
+*/
+inline void QTextStreamPrivate::putString(const QString &s, bool number)
+{
+ QString tmp = s;
+
+ // handle padding
+ int padSize = fieldWidth - s.size();
+ if (padSize > 0) {
+ QString pad(padSize, padChar);
+ if (fieldAlignment == QTextStream::AlignLeft) {
+ tmp.append(QString(padSize, padChar));
+ } else if (fieldAlignment == QTextStream::AlignRight
+ || fieldAlignment == QTextStream::AlignAccountingStyle) {
+ tmp.prepend(QString(padSize, padChar));
+ if (fieldAlignment == QTextStream::AlignAccountingStyle && number) {
+ const QChar sign = s.size() > 0 ? s.at(0) : QChar();
+ if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
+ QChar *data = tmp.data();
+ data[padSize] = tmp.at(0);
+ data[0] = sign;
+ }
+ }
+ } else if (fieldAlignment == QTextStream::AlignCenter) {
+ tmp.prepend(QString(padSize/2, padChar));
+ tmp.append(QString(padSize - padSize/2, padChar));
+ }
+ }
+
+#if defined (QTEXTSTREAM_DEBUG)
+ QByteArray a = s.toUtf8();
+ QByteArray b = tmp.toUtf8();
+ qDebug("QTextStreamPrivate::putString(\"%s\") calls write(\"%s\")",
+ qt_prettyDebug(a.constData(), a.size(), qMax(16, a.size())).constData(),
+ qt_prettyDebug(b.constData(), b.size(), qMax(16, b.size())).constData());
+#endif
+ write(tmp);
+}
+
+/*!
+ Constructs a QTextStream. Before you can use it for reading or
+ writing, you must assign a device or a string.
+
+ \sa setDevice(), setString()
+*/
+QTextStream::QTextStream()
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream()");
+#endif
+ Q_D(QTextStream);
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a device.
+*/
+QTextStream::QTextStream(QIODevice *device)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QIODevice *device == *%p)",
+ device);
+#endif
+ Q_D(QTextStream);
+ d->device = device;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a string, using \a
+ openMode to define the open mode.
+*/
+QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QString *string == *%p, openMode = %d)",
+ string, int(openMode));
+#endif
+ Q_D(QTextStream);
+ d->string = string;
+ d->stringOpenMode = openMode;
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a array, using \a
+ openMode to define the open mode. Internally, the array is wrapped
+ by a QBuffer.
+*/
+QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(QByteArray *array == *%p, openMode = %d)",
+ array, int(openMode));
+#endif
+ Q_D(QTextStream);
+ d->device = new QBuffer(array);
+ d->device->open(openMode);
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a array, using \a
+ openMode to define the open mode. The array is accessed as
+ read-only, regardless of the values in \a openMode.
+
+ This constructor is convenient for working on constant
+ strings. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 3
+*/
+QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(const QByteArray &array == *(%p), openMode = %d)",
+ &array, int(openMode));
+#endif
+ QBuffer *buffer = new QBuffer;
+ buffer->setData(array);
+ buffer->open(openMode);
+
+ Q_D(QTextStream);
+ d->device = buffer;
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Constructs a QTextStream that operates on \a fileHandle, using \a
+ openMode to define the open mode. Internally, a QFile is created
+ to handle the FILE pointer.
+
+ This constructor is useful for working directly with the common
+ FILE based input and output streams: stdin, stdout and stderr. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 4
+*/
+
+QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
+ : d_ptr(new QTextStreamPrivate(this))
+{
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::QTextStream(FILE *fileHandle = %p, openMode = %d)",
+ fileHandle, int(openMode));
+#endif
+ QFile *file = new QFile;
+ file->open(fileHandle, openMode);
+
+ Q_D(QTextStream);
+ d->device = file;
+ d->deleteDevice = true;
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+ d->status = Ok;
+}
+
+/*!
+ Destroys the QTextStream.
+
+ If the stream operates on a device, flush() will be called
+ implicitly. Otherwise, the device is unaffected.
+*/
+QTextStream::~QTextStream()
+{
+ Q_D(QTextStream);
+#if defined (QTEXTSTREAM_DEBUG)
+ qDebug("QTextStream::~QTextStream()");
+#endif
+ if (!d->writeBuffer.isEmpty())
+ d->flushWriteBuffer();
+}
+
+/*!
+ Resets QTextStream's formatting options, bringing it back to its
+ original constructed state. The device, string and any buffered
+ data is left untouched.
+*/
+void QTextStream::reset()
+{
+ Q_D(QTextStream);
+
+ d->realNumberPrecision = 6;
+ d->integerBase = 0;
+ d->fieldWidth = 0;
+ d->padChar = QLatin1Char(' ');
+ d->fieldAlignment = QTextStream::AlignRight;
+ d->realNumberNotation = QTextStream::SmartNotation;
+ d->numberFlags = 0;
+}
+
+/*!
+ Flushes any buffered data waiting to be written to the device.
+
+ If QTextStream operates on a string, this function does nothing.
+*/
+void QTextStream::flush()
+{
+ Q_D(QTextStream);
+ d->flushWriteBuffer();
+}
+
+/*!
+ Seeks to the position \a pos in the device. Returns true on
+ success; otherwise returns false.
+*/
+bool QTextStream::seek(qint64 pos)
+{
+ Q_D(QTextStream);
+ d->lastTokenSize = 0;
+
+ if (d->device) {
+ // Empty the write buffer
+ d->flushWriteBuffer();
+ if (!d->device->seek(pos))
+ return false;
+ d->resetReadBuffer();
+
+#ifndef QT_NO_TEXTCODEC
+ // Reset the codec converter states.
+ resetCodecConverterStateHelper(&d->readConverterState);
+ resetCodecConverterStateHelper(&d->writeConverterState);
+ delete d->readConverterSavedState;
+ d->readConverterSavedState = 0;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+#endif
+ return true;
+ }
+
+ // string
+ if (d->string && pos <= d->string->size()) {
+ d->stringOffset = int(pos);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \since 4.2
+
+ Returns the device position corresponding to the current position of the
+ stream, or -1 if an error occurs (e.g., if there is no device or string,
+ or if there's a device error).
+
+ Because QTextStream is buffered, this function may have to
+ seek the device to reconstruct a valid device position. This
+ operation can be expensive, so you may want to avoid calling this
+ function in a tight loop.
+
+ \sa seek()
+*/
+qint64 QTextStream::pos() const
+{
+ Q_D(const QTextStream);
+ if (d->device) {
+ // Cutoff
+ if (d->readBuffer.isEmpty())
+ return d->device->pos();
+ if (d->device->isSequential())
+ return 0;
+
+ // Seek the device
+ if (!d->device->seek(d->readBufferStartDevicePos))
+ return qint64(-1);
+
+ // Reset the read buffer
+ QTextStreamPrivate *thatd = const_cast<QTextStreamPrivate *>(d);
+ thatd->readBuffer.clear();
+
+#ifndef QT_NO_TEXTCODEC
+ thatd->restoreToSavedConverterState();
+ if (d->readBufferStartDevicePos == 0)
+ thatd->autoDetectUnicode = true;
+#endif
+
+ // Rewind the device to get to the current position Ensure that
+ // readBufferOffset is unaffected by fillReadBuffer()
+ int oldReadBufferOffset = d->readBufferOffset + d->readConverterSavedStateOffset;
+ while (d->readBuffer.size() < oldReadBufferOffset) {
+ if (!thatd->fillReadBuffer(1))
+ return qint64(-1);
+ }
+ thatd->readBufferOffset = oldReadBufferOffset;
+ thatd->readConverterSavedStateOffset = 0;
+
+ // Return the device position.
+ return d->device->pos();
+ }
+
+ if (d->string)
+ return d->stringOffset;
+
+ qWarning("QTextStream::pos: no device");
+ return qint64(-1);
+}
+
+/*!
+ Reads and discards whitespace from the stream until either a
+ non-space character is detected, or until atEnd() returns
+ true. This function is useful when reading a stream character by
+ character.
+
+ Whitespace characters are all characters for which
+ QChar::isSpace() returns true.
+
+ \sa operator>>()
+*/
+void QTextStream::skipWhiteSpace()
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(Q_VOID);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+}
+
+/*!
+ Sets the current device to \a device. If a device has already been
+ assigned, QTextStream will call flush() before the old device is
+ replaced.
+
+ \note This function resets locale to the default locale ('C')
+ and codec to the default codec, QTextCodec::codecForLocale().
+
+ \sa device(), setString()
+*/
+void QTextStream::setDevice(QIODevice *device)
+{
+ Q_D(QTextStream);
+ flush();
+ if (d->deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.disconnect();
+#endif
+ delete d->device;
+ d->deleteDevice = false;
+ }
+
+ d->reset();
+ d->status = Ok;
+ d->device = device;
+ d->resetReadBuffer();
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.setupDevice(this, d->device);
+#endif
+}
+
+/*!
+ Returns the current device associated with the QTextStream,
+ or 0 if no device has been assigned.
+
+ \sa setDevice(), string()
+*/
+QIODevice *QTextStream::device() const
+{
+ Q_D(const QTextStream);
+ return d->device;
+}
+
+/*!
+ Sets the current string to \a string, using the given \a
+ openMode. If a device has already been assigned, QTextStream will
+ call flush() before replacing it.
+
+ \sa string(), setDevice()
+*/
+void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
+{
+ Q_D(QTextStream);
+ flush();
+ if (d->deleteDevice) {
+#ifndef QT_NO_QOBJECT
+ d->deviceClosedNotifier.disconnect();
+ d->device->blockSignals(true);
+#endif
+ delete d->device;
+ d->deleteDevice = false;
+ }
+
+ d->reset();
+ d->status = Ok;
+ d->string = string;
+ d->stringOpenMode = openMode;
+}
+
+/*!
+ Returns the current string assigned to the QTextStream, or 0 if no
+ string has been assigned.
+
+ \sa setString(), device()
+*/
+QString *QTextStream::string() const
+{
+ Q_D(const QTextStream);
+ return d->string;
+}
+
+/*!
+ Sets the field alignment to \a mode. When used together with
+ setFieldWidth(), this function allows you to generate formatted
+ output with text aligned to the left, to the right or center
+ aligned.
+
+ \sa fieldAlignment(), setFieldWidth()
+*/
+void QTextStream::setFieldAlignment(FieldAlignment mode)
+{
+ Q_D(QTextStream);
+ d->fieldAlignment = mode;
+}
+
+/*!
+ Returns the current field alignment.
+
+ \sa setFieldAlignment(), fieldWidth()
+*/
+QTextStream::FieldAlignment QTextStream::fieldAlignment() const
+{
+ Q_D(const QTextStream);
+ return d->fieldAlignment;
+}
+
+/*!
+ Sets the pad character to \a ch. The default value is the ASCII
+ space character (' '), or QChar(0x20). This character is used to
+ fill in the space in fields when generating text.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 5
+
+ The string \c s contains:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 6
+
+ \sa padChar(), setFieldWidth()
+*/
+void QTextStream::setPadChar(QChar ch)
+{
+ Q_D(QTextStream);
+ d->padChar = ch;
+}
+
+/*!
+ Returns the current pad character.
+
+ \sa setPadChar(), setFieldWidth()
+*/
+QChar QTextStream::padChar() const
+{
+ Q_D(const QTextStream);
+ return d->padChar;
+}
+
+/*!
+ Sets the current field width to \a width. If \a width is 0 (the
+ default), the field width is equal to the length of the generated
+ text.
+
+ \note The field width applies to every element appended to this
+ stream after this function has been called (e.g., it also pads
+ endl). This behavior is different from similar classes in the STL,
+ where the field width only applies to the next element.
+
+ \sa fieldWidth(), setPadChar()
+*/
+void QTextStream::setFieldWidth(int width)
+{
+ Q_D(QTextStream);
+ d->fieldWidth = width;
+}
+
+/*!
+ Returns the current field width.
+
+ \sa setFieldWidth()
+*/
+int QTextStream::fieldWidth() const
+{
+ Q_D(const QTextStream);
+ return d->fieldWidth;
+}
+
+/*!
+ Sets the current number flags to \a flags. \a flags is a set of
+ flags from the NumberFlag enum, and describes options for
+ formatting generated code (e.g., whether or not to always write
+ the base or sign of a number).
+
+ \sa numberFlags(), setIntegerBase(), setRealNumberNotation()
+*/
+void QTextStream::setNumberFlags(NumberFlags flags)
+{
+ Q_D(QTextStream);
+ d->numberFlags = flags;
+}
+
+/*!
+ Returns the current number flags.
+
+ \sa setNumberFlags(), integerBase(), realNumberNotation()
+*/
+QTextStream::NumberFlags QTextStream::numberFlags() const
+{
+ Q_D(const QTextStream);
+ return d->numberFlags;
+}
+
+/*!
+ Sets the base of integers to \a base, both for reading and for
+ generating numbers. \a base can be either 2 (binary), 8 (octal),
+ 10 (decimal) or 16 (hexadecimal). If \a base is 0, QTextStream
+ will attempt to detect the base by inspecting the data on the
+ stream. When generating numbers, QTextStream assumes base is 10
+ unless the base has been set explicitly.
+
+ \sa integerBase(), QString::number(), setNumberFlags()
+*/
+void QTextStream::setIntegerBase(int base)
+{
+ Q_D(QTextStream);
+ d->integerBase = base;
+}
+
+/*!
+ Returns the current base of integers. 0 means that the base is
+ detected when reading, or 10 (decimal) when generating numbers.
+
+ \sa setIntegerBase(), QString::number(), numberFlags()
+*/
+int QTextStream::integerBase() const
+{
+ Q_D(const QTextStream);
+ return d->integerBase;
+}
+
+/*!
+ Sets the real number notation to \a notation (SmartNotation,
+ FixedNotation, ScientificNotation). When reading and generating
+ numbers, QTextStream uses this value to detect the formatting of
+ real numbers.
+
+ \sa realNumberNotation(), setRealNumberPrecision(), setNumberFlags(), setIntegerBase()
+*/
+void QTextStream::setRealNumberNotation(RealNumberNotation notation)
+{
+ Q_D(QTextStream);
+ d->realNumberNotation = notation;
+}
+
+/*!
+ Returns the current real number notation.
+
+ \sa setRealNumberNotation(), realNumberPrecision(), numberFlags(), integerBase()
+*/
+QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
+{
+ Q_D(const QTextStream);
+ return d->realNumberNotation;
+}
+
+/*!
+ Sets the precision of real numbers to \a precision. This value
+ describes the number of fraction digits QTextStream should
+ write when generating real numbers.
+
+ The precision cannot be a negative value. The default value is 6.
+
+ \sa realNumberPrecision(), setRealNumberNotation()
+*/
+void QTextStream::setRealNumberPrecision(int precision)
+{
+ Q_D(QTextStream);
+ if (precision < 0) {
+ qWarning("QTextStream::setRealNumberPrecision: Invalid precision (%d)", precision);
+ d->realNumberPrecision = 6;
+ return;
+ }
+ d->realNumberPrecision = precision;
+}
+
+/*!
+ Returns the current real number precision, or the number of fraction
+ digits QTextStream will write when generating real numbers.
+
+ \sa setRealNumberNotation(), realNumberNotation(), numberFlags(), integerBase()
+*/
+int QTextStream::realNumberPrecision() const
+{
+ Q_D(const QTextStream);
+ return d->realNumberPrecision;
+}
+
+/*!
+ Returns the status of the text stream.
+
+ \sa QTextStream::Status, setStatus(), resetStatus()
+*/
+
+QTextStream::Status QTextStream::status() const
+{
+ Q_D(const QTextStream);
+ return d->status;
+}
+
+/*!
+ \since 4.1
+
+ Resets the status of the text stream.
+
+ \sa QTextStream::Status, status(), setStatus()
+*/
+void QTextStream::resetStatus()
+{
+ Q_D(QTextStream);
+ d->status = Ok;
+}
+
+/*!
+ \since 4.1
+
+ Sets the status of the text stream to the \a status given.
+
+ Subsequent calls to setStatus() are ignored until resetStatus()
+ is called.
+
+ \sa Status status() resetStatus()
+*/
+void QTextStream::setStatus(Status status)
+{
+ Q_D(QTextStream);
+ if (d->status == Ok)
+ d->status = status;
+}
+
+/*!
+ Returns true if there is no more data to be read from the
+ QTextStream; otherwise returns false. This is similar to, but not
+ the same as calling QIODevice::atEnd(), as QTextStream also takes
+ into account its internal Unicode buffer.
+*/
+bool QTextStream::atEnd() const
+{
+ Q_D(const QTextStream);
+ CHECK_VALID_STREAM(true);
+
+ if (d->string)
+ return d->string->size() == d->stringOffset;
+ return d->readBuffer.isEmpty() && d->device->atEnd();
+}
+
+/*!
+ Reads the entire content of the stream, and returns it as a
+ QString. Avoid this function when working on large files, as it
+ will consume a significant amount of memory.
+
+ Calling readLine() is better if you do not know how much data is
+ available.
+
+ \sa readLine()
+*/
+QString QTextStream::readAll()
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ return d->read(INT_MAX);
+}
+
+/*!
+ Reads one line of text from the stream, and returns it as a
+ QString. The maximum allowed line length is set to \a maxlen. If
+ the stream contains lines longer than this, then the lines will be
+ split after \a maxlen characters and returned in parts.
+
+ If \a maxlen is 0, the lines can be of any length. A common value
+ for \a maxlen is 75.
+
+ The returned line has no trailing end-of-line characters ("\\n"
+ or "\\r\\n"), so calling QString::trimmed() is unnecessary.
+
+ If the stream has read to the end of the file, readLine() will return a
+ null QString. For strings, or for devices that support it, you can
+ explicitly test for the end of the stream using atEnd().
+
+ \sa readAll(), QIODevice::readLine()
+*/
+QString QTextStream::readLine(qint64 maxlen)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ const QChar *readPtr;
+ int length;
+ if (!d->scan(&readPtr, &length, int(maxlen), QTextStreamPrivate::EndOfLine))
+ return QString();
+
+ QString tmp = QString(readPtr, length);
+ d->consumeLastToken();
+ return tmp;
+}
+
+/*!
+ \since 4.1
+
+ Reads at most \a maxlen characters from the stream, and returns the data
+ read as a QString.
+
+ \sa readAll(), readLine(), QIODevice::read()
+*/
+QString QTextStream::read(qint64 maxlen)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(QString());
+
+ if (maxlen <= 0)
+ return QString::fromLatin1(""); // empty, not null
+
+ return d->read(int(maxlen));
+}
+
+/*! \internal
+*/
+QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong *ret)
+{
+ scan(0, 0, 0, NotSpace);
+ consumeLastToken();
+
+ // detect int encoding
+ int base = integerBase;
+ if (base == 0) {
+ QChar ch;
+ if (!getChar(&ch))
+ return npsInvalidPrefix;
+ if (ch == QLatin1Char('0')) {
+ QChar ch2;
+ if (!getChar(&ch2)) {
+ // Result is the number 0
+ *ret = 0;
+ return npsOk;
+ }
+ ch2 = ch2.toLower();
+
+ if (ch2 == QLatin1Char('x')) {
+ base = 16;
+ } else if (ch2 == QLatin1Char('b')) {
+ base = 2;
+ } else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) {
+ base = 8;
+ } else {
+ base = 10;
+ }
+ ungetChar(ch2);
+ } else if (ch == locale.negativeSign() || ch == locale.positiveSign() || ch.isDigit()) {
+ base = 10;
+ } else {
+ ungetChar(ch);
+ return npsInvalidPrefix;
+ }
+ ungetChar(ch);
+ // State of the stream is now the same as on entry
+ // (cursor is at prefix),
+ // and local variable 'base' has been set appropriately.
+ }
+
+ qulonglong val=0;
+ switch (base) {
+ case 2: {
+ QChar pf1, pf2, dig;
+ // Parse prefix '0b'
+ if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('b'))
+ return npsInvalidPrefix;
+ // Parse digits
+ int ndigits = 0;
+ while (getChar(&dig)) {
+ int n = dig.toLower().unicode();
+ if (n == '0' || n == '1') {
+ val <<= 1;
+ val += n - '0';
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ // Unwind the prefix and abort
+ ungetChar(pf2);
+ ungetChar(pf1);
+ return npsMissingDigit;
+ }
+ break;
+ }
+ case 8: {
+ QChar pf, dig;
+ // Parse prefix '0'
+ if (!getChar(&pf) || pf != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ // Parse digits
+ int ndigits = 0;
+ while (getChar(&dig)) {
+ int n = dig.toLower().unicode();
+ if (n >= '0' && n <= '7') {
+ val *= 8;
+ val += n - '0';
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ // Unwind the prefix and abort
+ ungetChar(pf);
+ return npsMissingDigit;
+ }
+ break;
+ }
+ case 10: {
+ // Parse sign (or first digit)
+ QChar sign;
+ int ndigits = 0;
+ if (!getChar(&sign))
+ return npsMissingDigit;
+ if (sign != locale.negativeSign() && sign != locale.positiveSign()) {
+ if (!sign.isDigit()) {
+ ungetChar(sign);
+ return npsMissingDigit;
+ }
+ val += sign.digitValue();
+ ndigits++;
+ }
+ // Parse digits
+ QChar ch;
+ while (getChar(&ch)) {
+ if (ch.isDigit()) {
+ val *= 10;
+ val += ch.digitValue();
+ } else if (locale != QLocale::c() && ch == locale.groupSeparator()) {
+ continue;
+ } else {
+ ungetChar(ch);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0)
+ return npsMissingDigit;
+ if (sign == locale.negativeSign()) {
+ qlonglong ival = qlonglong(val);
+ if (ival > 0)
+ ival = -ival;
+ val = qulonglong(ival);
+ }
+ break;
+ }
+ case 16: {
+ QChar pf1, pf2, dig;
+ // Parse prefix ' 0x'
+ if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ return npsInvalidPrefix;
+ if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('x'))
+ return npsInvalidPrefix;
+ // Parse digits
+ int ndigits = 0;
+ while (getChar(&dig)) {
+ int n = dig.toLower().unicode();
+ if (n >= '0' && n <= '9') {
+ val <<= 4;
+ val += n - '0';
+ } else if (n >= 'a' && n <= 'f') {
+ val <<= 4;
+ val += 10 + (n - 'a');
+ } else {
+ ungetChar(dig);
+ break;
+ }
+ ndigits++;
+ }
+ if (ndigits == 0) {
+ return npsMissingDigit;
+ }
+ break;
+ }
+ default:
+ // Unsupported integerBase
+ return npsInvalidPrefix;
+ }
+
+ if (ret)
+ *ret = val;
+ return npsOk;
+}
+
+/*! \internal
+ (hihi)
+*/
+bool QTextStreamPrivate::getReal(double *f)
+{
+ // We use a table-driven FSM to parse floating point numbers
+ // strtod() cannot be used directly since we may be reading from a
+ // QIODevice.
+ enum ParserState {
+ Init = 0,
+ Sign = 1,
+ Mantissa = 2,
+ Dot = 3,
+ Abscissa = 4,
+ ExpMark = 5,
+ ExpSign = 6,
+ Exponent = 7,
+ Nan1 = 8,
+ Nan2 = 9,
+ Inf1 = 10,
+ Inf2 = 11,
+ NanInf = 12,
+ Done = 13
+ };
+ enum InputToken {
+ None = 0,
+ InputSign = 1,
+ InputDigit = 2,
+ InputDot = 3,
+ InputExp = 4,
+ InputI = 5,
+ InputN = 6,
+ InputF = 7,
+ InputA = 8,
+ InputT = 9
+ };
+
+ static const uchar table[13][10] = {
+ // None InputSign InputDigit InputDot InputExp InputI InputN InputF InputA InputT
+ { 0, Sign, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 }, // 0 Init
+ { 0, 0, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 }, // 1 Sign
+ { Done, Done, Mantissa, Dot, ExpMark, 0, 0, 0, 0, 0 }, // 2 Mantissa
+ { 0, 0, Abscissa, 0, 0, 0, 0, 0, 0, 0 }, // 3 Dot
+ { Done, Done, Abscissa, Done, ExpMark, 0, 0, 0, 0, 0 }, // 4 Abscissa
+ { 0, ExpSign, Exponent, 0, 0, 0, 0, 0, 0, 0 }, // 5 ExpMark
+ { 0, 0, Exponent, 0, 0, 0, 0, 0, 0, 0 }, // 6 ExpSign
+ { Done, Done, Exponent, Done, Done, 0, 0, 0, 0, 0 }, // 7 Exponent
+ { 0, 0, 0, 0, 0, 0, 0, 0, Nan2, 0 }, // 8 Nan1
+ { 0, 0, 0, 0, 0, 0, NanInf, 0, 0, 0 }, // 9 Nan2
+ { 0, 0, 0, 0, 0, 0, Inf2, 0, 0, 0 }, // 10 Inf1
+ { 0, 0, 0, 0, 0, 0, 0, NanInf, 0, 0 }, // 11 Inf2
+ { Done, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 11 NanInf
+ };
+
+ ParserState state = Init;
+ InputToken input = None;
+
+ scan(0, 0, 0, NotSpace);
+ consumeLastToken();
+
+ const int BufferSize = 128;
+ char buf[BufferSize];
+ int i = 0;
+
+ QChar c;
+ while (getChar(&c)) {
+ switch (c.unicode()) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ input = InputDigit;
+ break;
+ case 'i': case 'I':
+ input = InputI;
+ break;
+ case 'n': case 'N':
+ input = InputN;
+ break;
+ case 'f': case 'F':
+ input = InputF;
+ break;
+ case 'a': case 'A':
+ input = InputA;
+ break;
+ case 't': case 'T':
+ input = InputT;
+ break;
+ default: {
+ QChar lc = c.toLower();
+ if (lc == locale.decimalPoint().toLower())
+ input = InputDot;
+ else if (lc == locale.exponential().toLower())
+ input = InputExp;
+ else if (lc == locale.negativeSign().toLower()
+ || lc == locale.positiveSign().toLower())
+ input = InputSign;
+ else if (locale != QLocale::c() // backward-compatibility
+ && lc == locale.groupSeparator().toLower())
+ input = InputDigit; // well, it isn't a digit, but no one cares.
+ else
+ input = None;
+ }
+ break;
+ }
+
+ state = ParserState(table[state][input]);
+
+ if (state == Init || state == Done || i > (BufferSize - 5)) {
+ ungetChar(c);
+ if (i > (BufferSize - 5)) { // ignore rest of digits
+ while (getChar(&c)) {
+ if (!c.isDigit()) {
+ ungetChar(c);
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ buf[i++] = c.toLatin1();
+ }
+
+ if (i == 0)
+ return false;
+ if (!f)
+ return true;
+ buf[i] = '\0';
+
+ // backward-compatibility. Old implementation supported +nan/-nan
+ // for some reason. QLocale only checks for lower-case
+ // nan/+inf/-inf, so here we also check for uppercase and mixed
+ // case versions.
+ if (!qstricmp(buf, "nan") || !qstricmp(buf, "+nan") || !qstricmp(buf, "-nan")) {
+ *f = qSNaN();
+ return true;
+ } else if (!qstricmp(buf, "+inf") || !qstricmp(buf, "inf")) {
+ *f = qInf();
+ return true;
+ } else if (!qstricmp(buf, "-inf")) {
+ *f = -qInf();
+ return true;
+ }
+ bool ok;
+ *f = locale.toDouble(QString::fromLatin1(buf), &ok);
+ return ok;
+}
+
+/*!
+ Reads a character from the stream and stores it in \a c. Returns a
+ reference to the QTextStream, so several operators can be
+ nested. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 7
+
+ Whitespace is \e not skipped.
+*/
+
+QTextStream &QTextStream::operator>>(QChar &c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ if (!d->getChar(&c))
+ setStatus(ReadPastEnd);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Reads a character from the stream and stores it in \a c. The
+ character from the stream is converted to ISO-5589-1 before it is
+ stored.
+
+ \sa QChar::toLatin1()
+*/
+QTextStream &QTextStream::operator>>(char &c)
+{
+ QChar ch;
+ *this >> ch;
+ c = ch.toLatin1();
+ return *this;
+}
+
+/*!
+ Reads an integer from the stream and stores it in \a i, then
+ returns a reference to the QTextStream. The number is cast to
+ the correct type before it is stored. If no number was detected on
+ the stream, \a i is set to 0.
+
+ By default, QTextStream will attempt to detect the base of the
+ number using the following rules:
+
+ \table
+ \header \o Prefix \o Base
+ \row \o "0b" or "0B" \o 2 (binary)
+ \row \o "0" followed by "0-7" \o 8 (octal)
+ \row \o "0" otherwise \o 10 (decimal)
+ \row \o "0x" or "0X" \o 16 (hexadecimal)
+ \row \o "1" to "9" \o 10 (decimal)
+ \endtable
+
+ By calling setIntegerBase(), you can specify the integer base
+ explicitly. This will disable the auto-detection, and speed up
+ QTextStream slightly.
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(signed short &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed short);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned short \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned short &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned short);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the signed int \a i.
+*/
+QTextStream &QTextStream::operator>>(signed int &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed int);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned int \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned int &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned int);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the signed long \a i.
+*/
+QTextStream &QTextStream::operator>>(signed long &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(signed long);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the unsigned long \a i.
+*/
+QTextStream &QTextStream::operator>>(unsigned long &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(unsigned long);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the qlonglong \a i.
+*/
+QTextStream &QTextStream::operator>>(qlonglong &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(qlonglong);
+}
+
+/*!
+ \overload
+
+ Stores the integer in the qulonglong \a i.
+*/
+QTextStream &QTextStream::operator>>(qulonglong &i)
+{
+ IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(qulonglong);
+}
+
+/*!
+ Reads a real number from the stream and stores it in \a f, then
+ returns a reference to the QTextStream. The number is cast to
+ the correct type. If no real number is detect on the stream, \a f
+ is set to 0.0.
+
+ As a special exception, QTextStream allows the strings "nan" and "inf" to
+ represent NAN and INF floats or doubles.
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(float &f)
+{
+ IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(float);
+}
+
+/*!
+ \overload
+
+ Stores the real number in the double \a f.
+*/
+QTextStream &QTextStream::operator>>(double &f)
+{
+ IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(double);
+}
+
+/*!
+ Reads a word from the stream and stores it in \a str, then returns
+ a reference to the stream. Words are separated by whitespace
+ (i.e., all characters for which QChar::isSpace() returns true).
+
+ Leading whitespace is skipped.
+*/
+QTextStream &QTextStream::operator>>(QString &str)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ str.clear();
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ str = QString(ptr, length);
+ d->consumeLastToken();
+ return *this;
+}
+
+/*!
+ \overload
+
+ Converts the word to ISO-8859-1, then stores it in \a array.
+
+ \sa QString::toLatin1()
+*/
+QTextStream &QTextStream::operator>>(QByteArray &array)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ array.clear();
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ for (int i = 0; i < length; ++i)
+ array += ptr[i].toLatin1();
+
+ d->consumeLastToken();
+ return *this;
+}
+
+/*!
+ \overload
+
+ Stores the word in \a c, terminated by a '\0' character. If no word is
+ available, only the '\0' character is stored.
+
+ Warning: Although convenient, this operator is dangerous and must
+ be used with care. QTextStream assumes that \a c points to a
+ buffer with enough space to hold the word. If the buffer is too
+ small, your application may crash.
+
+ If possible, use the QByteArray operator instead.
+*/
+QTextStream &QTextStream::operator>>(char *c)
+{
+ Q_D(QTextStream);
+ *c = 0;
+ CHECK_VALID_STREAM(*this);
+ d->scan(0, 0, 0, QTextStreamPrivate::NotSpace);
+ d->consumeLastToken();
+
+ const QChar *ptr;
+ int length;
+ if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
+ setStatus(ReadPastEnd);
+ return *this;
+ }
+
+ for (int i = 0; i < length; ++i)
+ *c++ = ptr[i].toLatin1();
+ *c = '\0';
+ d->consumeLastToken();
+ return *this;
+}
+
+/*! \internal
+ */
+void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
+{
+ QString result;
+
+ unsigned flags = 0;
+ if (numberFlags & QTextStream::ShowBase)
+ flags |= QLocalePrivate::ShowBase;
+ if (numberFlags & QTextStream::ForceSign)
+ flags |= QLocalePrivate::AlwaysShowSign;
+ if (numberFlags & QTextStream::UppercaseBase)
+ flags |= QLocalePrivate::UppercaseBase;
+ if (numberFlags & QTextStream::UppercaseDigits)
+ flags |= QLocalePrivate::CapitalEorX;
+
+ // add thousands group separators. For backward compatibility we
+ // don't add a group separator for C locale.
+ if (locale != QLocale::c())
+ flags |= QLocalePrivate::ThousandsGroup;
+
+ const QLocalePrivate *dd = locale.d();
+ int base = integerBase ? integerBase : 10;
+ if (negative && base == 10) {
+ result = dd->longLongToString(-static_cast<qlonglong>(number), -1,
+ base, -1, flags);
+ } else if (negative) {
+ // Workaround for backward compatibility for writing negative
+ // numbers in octal and hex:
+ // QTextStream(result) << showbase << hex << -1 << oct << -1
+ // should output: -0x1 -0b1
+ result = dd->unsLongLongToString(number, -1, base, -1, flags);
+ result.prepend(locale.negativeSign());
+ } else {
+ result = dd->unsLongLongToString(number, -1, base, -1, flags);
+ // workaround for backward compatibility - in octal form with
+ // ShowBase flag set zero should be written as '00'
+ if (number == 0 && base == 8 && numberFlags & QTextStream::ShowBase
+ && result == QLatin1String("0")) {
+ result.prepend(QLatin1Char('0'));
+ }
+ }
+ putString(result, true);
+}
+
+/*!
+ \internal
+ \overload
+*/
+QTextStream &QTextStream::operator<<(QBool b)
+{
+ return *this << bool(b);
+}
+
+/*!
+ Writes the character \a c to the stream, then returns a reference
+ to the QTextStream.
+
+ \sa setFieldWidth()
+*/
+QTextStream &QTextStream::operator<<(QChar c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString(c));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Converts \a c from ASCII to a QChar, then writes it to the stream.
+*/
+QTextStream &QTextStream::operator<<(char c)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString(QChar::fromAscii(c)));
+ return *this;
+}
+
+/*!
+ Writes the integer number \a i to the stream, then returns a
+ reference to the QTextStream. By default, the number is stored in
+ decimal form, but you can also set the base by calling
+ setIntegerBase().
+
+ \sa setFieldWidth(), setNumberFlags()
+*/
+QTextStream &QTextStream::operator<<(signed short i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned short \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned short i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the signed int \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(signed int i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned int \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned int i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the signed long \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(signed long i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(qlonglong(i)), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the unsigned long \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(unsigned long i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)i, false);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the qlonglong \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(qlonglong i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber((qulonglong)qAbs(i), i < 0);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the qulonglong \a i to the stream.
+*/
+QTextStream &QTextStream::operator<<(qulonglong i)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putNumber(i, false);
+ return *this;
+}
+
+/*!
+ Writes the real number \a f to the stream, then returns a
+ reference to the QTextStream. By default, QTextStream stores it
+ using SmartNotation, with up to 6 digits of precision. You can
+ change the textual representation QTextStream will use for real
+ numbers by calling setRealNumberNotation(),
+ setRealNumberPrecision() and setNumberFlags().
+
+ \sa setFieldWidth(), setRealNumberNotation(),
+ setRealNumberPrecision(), setNumberFlags()
+*/
+QTextStream &QTextStream::operator<<(float f)
+{
+ return *this << double(f);
+}
+
+/*!
+ \overload
+
+ Writes the double \a f to the stream.
+*/
+QTextStream &QTextStream::operator<<(double f)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+
+ QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
+ switch (realNumberNotation()) {
+ case FixedNotation:
+ form = QLocalePrivate::DFDecimal;
+ break;
+ case ScientificNotation:
+ form = QLocalePrivate::DFExponent;
+ break;
+ case SmartNotation:
+ form = QLocalePrivate::DFSignificantDigits;
+ break;
+ }
+
+ uint flags = 0;
+ if (numberFlags() & ShowBase)
+ flags |= QLocalePrivate::ShowBase;
+ if (numberFlags() & ForceSign)
+ flags |= QLocalePrivate::AlwaysShowSign;
+ if (numberFlags() & UppercaseBase)
+ flags |= QLocalePrivate::UppercaseBase;
+ if (numberFlags() & UppercaseDigits)
+ flags |= QLocalePrivate::CapitalEorX;
+ if (numberFlags() & ForcePoint)
+ flags |= QLocalePrivate::Alternate;
+
+ const QLocalePrivate *dd = d->locale.d();
+ QString num = dd->doubleToString(f, d->realNumberPrecision, form, -1, flags);
+ d->putString(num, true);
+ return *this;
+}
+
+/*!
+ Writes the string \a string to the stream, and returns a reference
+ to the QTextStream. The string is first encoded using the assigned
+ codec (the default codec is QTextCodec::codecForLocale()) before
+ it is written to the stream.
+
+ \sa setFieldWidth(), setCodec()
+*/
+QTextStream &QTextStream::operator<<(const QString &string)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(string);
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes \a array to the stream. The contents of \a array are
+ converted with QString::fromAscii().
+*/
+QTextStream &QTextStream::operator<<(const QByteArray &array)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QString::fromAscii(array.constData(), array.length()));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes the constant string pointed to by \a string to the stream. \a
+ string is assumed to be in ISO-8859-1 encoding. This operator
+ is convenient when working with constant string data. Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 8
+
+ Warning: QTextStream assumes that \a string points to a string of
+ text, terminated by a '\0' character. If there is no terminating
+ '\0' character, your application may crash.
+*/
+QTextStream &QTextStream::operator<<(const char *string)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(QLatin1String(string));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes \a ptr to the stream as a hexadecimal number with a base.
+*/
+
+QTextStream &QTextStream::operator<<(const void *ptr)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ int oldBase = d->integerBase;
+ NumberFlags oldFlags = d->numberFlags;
+ d->integerBase = 16;
+ d->numberFlags |= ShowBase;
+ d->putNumber(reinterpret_cast<quintptr>(ptr), false);
+ d->integerBase = oldBase;
+ d->numberFlags = oldFlags;
+ return *this;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(2) on \a stream and returns \a
+ stream.
+
+ \sa oct(), dec(), hex(), {QTextStream manipulators}
+*/
+QTextStream &bin(QTextStream &stream)
+{
+ stream.setIntegerBase(2);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(8) on \a stream and returns \a
+ stream.
+
+ \sa bin(), dec(), hex(), {QTextStream manipulators}
+*/
+QTextStream &oct(QTextStream &stream)
+{
+ stream.setIntegerBase(8);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(10) on \a stream and returns \a
+ stream.
+
+ \sa bin(), oct(), hex(), {QTextStream manipulators}
+*/
+QTextStream &dec(QTextStream &stream)
+{
+ stream.setIntegerBase(10);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setIntegerBase(16) on \a stream and returns \a
+ stream.
+
+ \note The hex modifier can only be used for writing to streams.
+ \sa bin(), oct(), dec(), {QTextStream manipulators}
+*/
+QTextStream &hex(QTextStream &stream)
+{
+ stream.setIntegerBase(16);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ShowBase) on \a stream and returns \a stream.
+
+ \sa noshowbase(), forcesign(), forcepoint(), {QTextStream manipulators}
+*/
+QTextStream &showbase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ShowBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ForceSign) on \a stream and returns \a stream.
+
+ \sa noforcesign(), forcepoint(), showbase(), {QTextStream manipulators}
+*/
+QTextStream &forcesign(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ForceSign);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::ForcePoint) on \a stream and returns \a stream.
+
+ \sa noforcepoint(), forcesign(), showbase(), {QTextStream manipulators}
+*/
+QTextStream &forcepoint(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::ForcePoint);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ShowBase) on \a stream and returns \a stream.
+
+ \sa showbase(), noforcesign(), noforcepoint(), {QTextStream manipulators}
+*/
+QTextStream &noshowbase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ShowBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ForceSign) on \a stream and returns \a stream.
+
+ \sa forcesign(), noforcepoint(), noshowbase(), {QTextStream manipulators}
+*/
+QTextStream &noforcesign(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ForceSign);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::ForcePoint) on \a stream and returns \a stream.
+
+ \sa forcepoint(), noforcesign(), noshowbase(), {QTextStream manipulators}
+*/
+QTextStream &noforcepoint(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() &= ~QTextStream::ForcePoint);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::UppercaseBase) on \a stream and returns \a stream.
+
+ \sa lowercasebase(), uppercasedigits(), {QTextStream manipulators}
+*/
+QTextStream &uppercasebase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::UppercaseBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
+ QTextStream::UppercaseDigits) on \a stream and returns \a stream.
+
+ \sa lowercasedigits(), uppercasebase(), {QTextStream manipulators}
+*/
+QTextStream &uppercasedigits(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() | QTextStream::UppercaseDigits);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::UppercaseBase) on \a stream and returns \a stream.
+
+ \sa uppercasebase(), lowercasedigits(), {QTextStream manipulators}
+*/
+QTextStream &lowercasebase(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() & ~QTextStream::UppercaseBase);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
+ ~QTextStream::UppercaseDigits) on \a stream and returns \a stream.
+
+ \sa uppercasedigits(), lowercasebase(), {QTextStream manipulators}
+*/
+QTextStream &lowercasedigits(QTextStream &stream)
+{
+ stream.setNumberFlags(stream.numberFlags() & ~QTextStream::UppercaseDigits);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation)
+ on \a stream and returns \a stream.
+
+ \sa scientific(), {QTextStream manipulators}
+*/
+QTextStream &fixed(QTextStream &stream)
+{
+ stream.setRealNumberNotation(QTextStream::FixedNotation);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setRealNumberNotation(QTextStream::ScientificNotation)
+ on \a stream and returns \a stream.
+
+ \sa fixed(), {QTextStream manipulators}
+*/
+QTextStream &scientific(QTextStream &stream)
+{
+ stream.setRealNumberNotation(QTextStream::ScientificNotation);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft)
+ on \a stream and returns \a stream.
+
+ \sa right(), center(), {QTextStream manipulators}
+*/
+QTextStream &left(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignLeft);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignRight)
+ on \a stream and returns \a stream.
+
+ \sa left(), center(), {QTextStream manipulators}
+*/
+QTextStream &right(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignRight);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter)
+ on \a stream and returns \a stream.
+
+ \sa left(), right(), {QTextStream manipulators}
+*/
+QTextStream &center(QTextStream &stream)
+{
+ stream.setFieldAlignment(QTextStream::AlignCenter);
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Writes '\n' to the \a stream and flushes the stream.
+
+ Equivalent to
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 9
+
+ Note: On Windows, all '\n' characters are written as '\r\n' if
+ QTextStream's device or string is opened using the QIODevice::Text flag.
+
+ \sa flush(), reset(), {QTextStream manipulators}
+*/
+QTextStream &endl(QTextStream &stream)
+{
+ return stream << QLatin1Char('\n') << flush;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::flush() on \a stream and returns \a stream.
+
+ \sa endl(), reset(), {QTextStream manipulators}
+*/
+QTextStream &flush(QTextStream &stream)
+{
+ stream.flush();
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls QTextStream::reset() on \a stream and returns \a stream.
+
+ \sa flush(), {QTextStream manipulators}
+*/
+QTextStream &reset(QTextStream &stream)
+{
+ stream.reset();
+ return stream;
+}
+
+/*!
+ \relates QTextStream
+
+ Calls skipWhiteSpace() on \a stream and returns \a stream.
+
+ \sa {QTextStream manipulators}
+*/
+QTextStream &ws(QTextStream &stream)
+{
+ stream.skipWhiteSpace();
+ return stream;
+}
+
+/*!
+ \fn QTextStreamManipulator qSetFieldWidth(int width)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setFieldWidth(\a width).
+*/
+
+/*!
+ \fn QTextStreamManipulator qSetPadChar(QChar ch)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setPadChar(\a ch).
+*/
+
+/*!
+ \fn QTextStreamManipulator qSetRealNumberPrecision(int precision)
+ \relates QTextStream
+
+ Equivalent to QTextStream::setRealNumberPrecision(\a precision).
+*/
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+ \relates QTextStream
+
+ Toggles insertion of the Byte Order Mark on \a stream when QTextStream is
+ used with a UTF codec.
+
+ \sa QTextStream::setGenerateByteOrderMark(), {QTextStream manipulators}
+*/
+QTextStream &bom(QTextStream &stream)
+{
+ stream.setGenerateByteOrderMark(true);
+ return stream;
+}
+
+/*!
+ Sets the codec for this stream to \a codec. The codec is used for
+ decoding any data that is read from the assigned device, and for
+ encoding any data that is written. By default,
+ QTextCodec::codecForLocale() is used, and automatic unicode
+ detection is enabled.
+
+ If QTextStream operates on a string, this function does nothing.
+
+ \warning If you call this function while the text stream is reading
+ from an open sequential socket, the internal buffer may still contain
+ text decoded using the old codec.
+
+ \sa codec(), setAutoDetectUnicode(), setLocale()
+*/
+void QTextStream::setCodec(QTextCodec *codec)
+{
+ Q_D(QTextStream);
+ qint64 seekPos = -1;
+ if (!d->readBuffer.isEmpty()) {
+ if (!d->device->isSequential()) {
+ seekPos = pos();
+ }
+ }
+ d->codec = codec;
+ if (seekPos >=0 && !d->readBuffer.isEmpty())
+ seek(seekPos);
+}
+
+/*!
+ Sets the codec for this stream to the QTextCodec for the encoding
+ specified by \a codecName. Common values for \c codecName include
+ "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
+ recognized, nothing happens.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qtextstream.cpp 10
+
+ \sa QTextCodec::codecForName(), setLocale()
+*/
+void QTextStream::setCodec(const char *codecName)
+{
+ QTextCodec *codec = QTextCodec::codecForName(codecName);
+ if (codec)
+ setCodec(codec);
+}
+
+/*!
+ Returns the codec that is current assigned to the stream.
+
+ \sa setCodec(), setAutoDetectUnicode(), locale()
+*/
+QTextCodec *QTextStream::codec() const
+{
+ Q_D(const QTextStream);
+ return d->codec;
+}
+
+/*!
+ If \a enabled is true, QTextStream will attempt to detect Unicode
+ encoding by peeking into the stream data to see if it can find the
+ UTF-16 or UTF-32 BOM (Byte Order Mark). If this mark is found, QTextStream
+ will replace the current codec with the UTF codec.
+
+ This function can be used together with setCodec(). It is common
+ to set the codec to UTF-8, and then enable UTF-16 detection.
+
+ \sa autoDetectUnicode(), setCodec()
+*/
+void QTextStream::setAutoDetectUnicode(bool enabled)
+{
+ Q_D(QTextStream);
+ d->autoDetectUnicode = enabled;
+}
+
+/*!
+ Returns true if automatic Unicode detection is enabled, otherwise
+ returns false. Automatic Unicode detection is enabled by default.
+
+ \sa setAutoDetectUnicode(), setCodec()
+*/
+bool QTextStream::autoDetectUnicode() const
+{
+ Q_D(const QTextStream);
+ return d->autoDetectUnicode;
+}
+
+/*!
+ If \a generate is true and a UTF codec is used, QTextStream will insert
+ the BOM (Byte Order Mark) before any data has been written to the
+ device. If \a generate is false, no BOM will be inserted. This function
+ must be called before any data is written. Otherwise, it does nothing.
+
+ \sa generateByteOrderMark(), bom()
+*/
+void QTextStream::setGenerateByteOrderMark(bool generate)
+{
+ Q_D(QTextStream);
+ if (d->writeBuffer.isEmpty()) {
+ if (generate)
+ d->writeConverterState.flags &= ~QTextCodec::IgnoreHeader;
+ else
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ }
+}
+
+/*!
+ Returns true if QTextStream is set to generate the UTF BOM (Byte Order
+ Mark) when using a UTF codec; otherwise returns false. UTF BOM generation is
+ set to false by default.
+
+ \sa setGenerateByteOrderMark()
+*/
+bool QTextStream::generateByteOrderMark() const
+{
+ Q_D(const QTextStream);
+ return (d->writeConverterState.flags & QTextCodec::IgnoreHeader) == 0;
+}
+
+#endif
+
+/*!
+ \since 4.5
+
+ Sets the locale for this stream to \a locale. The specified locale is
+ used for conversions between numbers and their string representations.
+
+ The default locale is C and it is a special case - the thousands
+ group separator is not used for backward compatibility reasons.
+
+ \sa locale()
+*/
+void QTextStream::setLocale(const QLocale &locale)
+{
+ Q_D(QTextStream);
+ d->locale = locale;
+}
+
+/*!
+ \since 4.5
+
+ Returns the locale for this stream. The default locale is C.
+
+ \sa setLocale()
+*/
+QLocale QTextStream::locale() const
+{
+ Q_D(const QTextStream);
+ return d->locale;
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \class QTextIStream
+ \brief The QTextIStream class is a convenience class for input streams.
+
+ \compat
+ \reentrant
+
+ Use QTextStream instead.
+*/
+
+/*!
+ \fn QTextIStream::QTextIStream(const QString *string)
+
+ Use QTextStream(&\a{string}, QIODevice::ReadOnly) instead.
+*/
+/*!
+ \fn QTextIStream::QTextIStream(QByteArray *byteArray)
+
+ Use QTextStream(&\a{byteArray}, QIODevice::ReadOnly) instead.
+*/
+/*!
+ \fn QTextIStream::QTextIStream(FILE *file)
+
+ Use QTextStream(\a{file}, QIODevice::ReadOnly) instead.
+*/
+
+/*!
+ \class QTextOStream
+ \brief The QTextOStream class is a convenience class for output streams.
+
+ \compat
+ \reentrant
+
+ Use QTextStream instead.
+*/
+
+/*!
+ \fn QTextOStream::QTextOStream(QString *string)
+
+ Use QTextStream(&\a{string}, QIODevice::WriteOnly) instead.
+*/
+/*!
+ \fn QTextOStream::QTextOStream(QByteArray *byteArray)
+
+ Use QTextStream(&\a{byteArray}, QIODevice::WriteOnly) instead.
+*/
+/*!
+ \fn QTextOStream::QTextOStream(FILE *file)
+
+ Use QTextStream(\a{file}, QIODevice::WriteOnly) instead.
+*/
+
+/*! \internal
+*/
+int QTextStream::flagsInternal() const
+{
+ Q_D(const QTextStream);
+
+ int f = 0;
+ switch (d->fieldAlignment) {
+ case AlignLeft: f |= left; break;
+ case AlignRight: f |= right; break;
+ case AlignCenter: f |= internal; break;
+ default:
+ break;
+ }
+ switch (d->integerBase) {
+ case 2: f |= bin; break;
+ case 8: f |= oct; break;
+ case 10: f |= dec; break;
+ case 16: f |= hex; break;
+ default:
+ break;
+ }
+ switch (d->realNumberNotation) {
+ case FixedNotation: f |= fixed; break;
+ case ScientificNotation: f |= scientific; break;
+ default:
+ break;
+ }
+ if (d->numberFlags & ShowBase)
+ f |= showbase;
+ if (d->numberFlags & ForcePoint)
+ f |= showpoint;
+ if (d->numberFlags & ForceSign)
+ f |= showpos;
+ if (d->numberFlags & UppercaseBase)
+ f |= uppercase;
+ return f;
+}
+
+/*! \internal
+*/
+int QTextStream::flagsInternal(int newFlags)
+{
+ int oldFlags = flagsInternal();
+
+ if (newFlags & left)
+ setFieldAlignment(AlignLeft);
+ else if (newFlags & right)
+ setFieldAlignment(AlignRight);
+ else if (newFlags & internal)
+ setFieldAlignment(AlignCenter);
+
+ if (newFlags & bin)
+ setIntegerBase(2);
+ else if (newFlags & oct)
+ setIntegerBase(8);
+ else if (newFlags & dec)
+ setIntegerBase(10);
+ else if (newFlags & hex)
+ setIntegerBase(16);
+
+ if (newFlags & showbase)
+ setNumberFlags(numberFlags() | ShowBase);
+ if (newFlags & showpos)
+ setNumberFlags(numberFlags() | ForceSign);
+ if (newFlags & showpoint)
+ setNumberFlags(numberFlags() | ForcePoint);
+ if (newFlags & uppercase)
+ setNumberFlags(numberFlags() | UppercaseBase);
+
+ if (newFlags & fixed)
+ setRealNumberNotation(FixedNotation);
+ else if (newFlags & scientific)
+ setRealNumberNotation(ScientificNotation);
+
+ return oldFlags;
+}
+
+#ifndef QT_NO_TEXTCODEC
+/*!
+ Use setCodec() and setAutoDetectUnicode() instead.
+*/
+void QTextStream::setEncoding(Encoding encoding)
+{
+ Q_D(QTextStream);
+ resetCodecConverterStateHelper(&d->readConverterState);
+ resetCodecConverterStateHelper(&d->writeConverterState);
+
+ switch (encoding) {
+ case Locale:
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForLocale());
+ d->autoDetectUnicode = true;
+ break;
+ case Latin1:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("ISO-8859-1"));
+ d->autoDetectUnicode = false;
+ break;
+ case Unicode:
+ setCodec(QTextCodec::codecForName("UTF-16"));
+ d->autoDetectUnicode = false;
+ break;
+ case RawUnicode:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeNetworkOrder:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16BE"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeReverse:
+ d->readConverterState.flags |= QTextCodec::IgnoreHeader;
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-16LE"));
+ d->autoDetectUnicode = false;
+ break;
+ case UnicodeUTF8:
+ d->writeConverterState.flags |= QTextCodec::IgnoreHeader;
+ setCodec(QTextCodec::codecForName("UTF-8"));
+ d->autoDetectUnicode = true;
+ break;
+ }
+}
+#endif
+
+/*!
+ \enum QTextStream::Encoding
+ \compat
+
+ \value Latin1 Use setCodec(QTextCodec::codecForName("ISO-8859-1")) instead.
+ \value Locale Use setCodec(QTextCodec::codecForLocale()) instead.
+ \value RawUnicode Use setCodec(QTextCodec::codecForName("UTF-16")) instead.
+ \value Unicode Use setCodec(QTextCodec::codecForName("UTF-16")) instead.
+ \value UnicodeNetworkOrder Use setCodec(QTextCodec::codecForName("UTF-16BE")) instead.
+ \value UnicodeReverse Use setCodec(QTextCodec::codecForName("UTF-16LE")) instead.
+ \value UnicodeUTF8 Use setCodec(QTextCodec::codecForName("UTF-8")) instead.
+
+ Also, for all encodings except QTextStream::Latin1 and
+ QTextStream::UTF8, you need to call setAutoDetectUnicode(false)
+ to obtain the Qt 3 behavior in addition to the setCodec() call.
+
+ \sa setCodec(), setAutoDetectUnicode()
+*/
+
+/*!
+ \fn int QTextStream::flags() const
+
+ Use fieldAlignment(), padChar(), fieldWidth(), numberFlags(),
+ integerBase(), realNumberNotation(), and realNumberNotation
+ instead.
+*/
+
+/*!
+ \fn int QTextStream::flags(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::setf(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::setf(int, int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::unsetf(int)
+
+ Use setFieldAlignment(), setPadChar(), setFieldWidth(),
+ setNumberFlags(), setIntegerBase(), setRealNumberNotation(), and
+ setRealNumberNotation instead.
+*/
+
+/*!
+ \fn int QTextStream::width(int)
+
+ Use setFieldWidth() instead.
+*/
+
+/*!
+ \fn int QTextStream::fill(int)
+
+ Use setPadChar() instead.
+*/
+
+/*!
+ \fn int QTextStream::precision(int)
+
+ Use setRealNumberPrecision() instead.
+*/
+
+/*!
+ \fn int QTextStream::read()
+
+ Use readAll() or readLine() instead.
+*/
+
+/*!
+ \fn int QTextStream::unsetDevice()
+
+ Use setDevice(0) instead.
+*/
+
+/*!
+ \variable QTextStream::skipws
+ \variable QTextStream::left
+ \variable QTextStream::right
+ \variable QTextStream::internal
+ \variable QTextStream::bin
+ \variable QTextStream::oct
+ \variable QTextStream::dec
+ \variable QTextStream::hex
+ \variable QTextStream::showbase
+ \variable QTextStream::showpoint
+ \variable QTextStream::uppercase
+ \variable QTextStream::showpos
+ \variable QTextStream::scientific
+ \variable QTextStream::fixed
+ \variable QTextStream::basefield
+ \variable QTextStream::adjustfield
+ \variable QTextStream::floatfield
+ \compat
+
+ Use the new \l{QTextStream manipulators} instead.
+*/
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_QOBJECT
+#include "qtextstream.moc"
+#endif
+