diff options
Diffstat (limited to 'src/corelib/serialization/qtextstream.cpp')
-rw-r--r-- | src/corelib/serialization/qtextstream.cpp | 204 |
1 files changed, 77 insertions, 127 deletions
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index 137d736b30..e9d650b3e2 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only //#define QTEXTSTREAM_DEBUG static const int QTEXTSTREAM_BUFFERSIZE = 16384; @@ -50,6 +14,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; \ingroup io \ingroup string-processing + \ingroup qtserialization \reentrant QTextStream can operate on a QIODevice, a QByteArray or a @@ -230,6 +195,9 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; #include "qfile.h" #include "qnumeric.h" #include "qvarlengtharray.h" +#include <private/qdebug_p.h> +#include <private/qnumeric_p.h> +#include <private/qtools_p.h> #include <locale.h> #include "private/qlocale_p.h" @@ -239,48 +207,6 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; #include <limits.h> #include <new> -#if defined QTEXTSTREAM_DEBUG -#include <ctype.h> -#include "private/qtools_p.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: { - const char buf[] = { - '\\', - 'x', - QtMiscUtils::toHexLower(uchar(c) / 16), - QtMiscUtils::toHexLower(uchar(c) % 16), - 0 - }; - out += buf; - } - } - } - - if (len < maxSize) - out += "..."; - - return out; -} -QT_END_NAMESPACE - -#endif - // A precondition macro #define Q_VOID #define CHECK_VALID_STREAM(x) do { \ @@ -320,6 +246,9 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; +using namespace QtMiscUtils; + //------------------------------------------------------------------- /*! @@ -351,7 +280,7 @@ void QTextStreamPrivate::Params::reset() realNumberPrecision = 6; integerBase = 0; fieldWidth = 0; - padChar = QLatin1Char(' '); + padChar = u' '; fieldAlignment = QTextStream::AlignRight; realNumberNotation = QTextStream::SmartNotation; numberFlags = { }; @@ -431,6 +360,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes) if (bytesRead <= 0) return false; +#ifndef QT_BOOTSTRAPPED if (autoDetectUnicode) { autoDetectUnicode = false; @@ -445,10 +375,11 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes) #if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::fillReadBuffer(), using %s encoding", QStringConverter::nameForEncoding(encoding)); #endif +#endif #if defined (QTEXTSTREAM_DEBUG) qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d", - qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), int(sizeof(buf)), int(bytesRead)); + QtDebugUtils::toPrintable(buf, bytesRead, 32).constData(), int(sizeof(buf)), int(bytesRead)); #endif int oldReadBufferSize = readBuffer.size(); @@ -456,7 +387,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes) // remove all '\r\n' in the string. if (readBuffer.size() > oldReadBufferSize && textModeEnabled) { - QChar CR = QLatin1Char('\r'); + QChar CR = u'\r'; QChar *writePtr = readBuffer.data() + oldReadBufferSize; QChar *readPtr = readBuffer.data() + oldReadBufferSize; QChar *endPtr = readBuffer.data() + readBuffer.size(); @@ -486,7 +417,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes) #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()); + QtDebugUtils::toPrintable(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).constData()); #endif return true; } @@ -524,7 +455,7 @@ void QTextStreamPrivate::flushWriteBuffer() bool textModeEnabled = device->isTextModeEnabled(); if (textModeEnabled) { device->setTextModeEnabled(false); - writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n")); + writeBuffer.replace(u'\n', "\r\n"_L1); } #endif @@ -536,7 +467,7 @@ void QTextStreamPrivate::flushWriteBuffer() 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)); + QtDebugUtils::toPrintable(data.constData(), data.size(), 32).constData(), int(bytesWritten)); #endif #if defined (Q_OS_WIN) @@ -601,7 +532,6 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD int startOffset = device ? readBufferOffset : stringOffset; QChar lastChar; - bool canStillReadFromDevice = true; do { int endOffset; const QChar *chPtr; @@ -632,9 +562,9 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD } break; case EndOfLine: - if (ch == QLatin1Char('\n')) { + if (ch == u'\n') { foundToken = true; - delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1; + delimSize = (lastChar == u'\r') ? 2 : 1; consumeDelimiter = true; } lastChar = ch; @@ -643,7 +573,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD } } while (!foundToken && (!maxlen || totalSize < maxlen) - && (device && (canStillReadFromDevice = fillReadBuffer()))); + && device && fillReadBuffer()); if (totalSize == 0) { #if defined (QTEXTSTREAM_DEBUG) @@ -656,7 +586,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD // 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')) { + && lastChar == u'\r') { consumeDelimiter = true; ++delimSize; } @@ -754,7 +684,7 @@ inline void QTextStreamPrivate::restoreToSavedConverterState() /*! \internal */ -void QTextStreamPrivate::write(const QChar *data, int len) +void QTextStreamPrivate::write(const QChar *data, qsizetype len) { if (string) { // ### What about seek()?? @@ -784,7 +714,7 @@ inline void QTextStreamPrivate::write(QChar ch) /*! \internal */ -void QTextStreamPrivate::write(QLatin1String data) +void QTextStreamPrivate::write(QLatin1StringView data) { if (string) { // ### What about seek()?? @@ -799,7 +729,7 @@ void QTextStreamPrivate::write(QLatin1String data) /*! \internal */ -void QTextStreamPrivate::writePadding(int len) +void QTextStreamPrivate::writePadding(qsizetype len) { if (string) { // ### What about seek()?? @@ -864,7 +794,7 @@ inline void QTextStreamPrivate::putChar(QChar ch) /*! \internal */ -QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const +QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(qsizetype len) const { Q_ASSERT(params.fieldWidth > len); // calling padding() when no padding is needed is an error @@ -891,7 +821,7 @@ QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const /*! \internal */ -void QTextStreamPrivate::putString(const QChar *data, int len, bool number) +void QTextStreamPrivate::putString(const QChar *data, qsizetype len, bool number) { if (Q_UNLIKELY(params.fieldWidth > len)) { @@ -920,7 +850,7 @@ void QTextStreamPrivate::putString(const QChar *data, int len, bool number) /*! \internal */ -void QTextStreamPrivate::putString(QLatin1String data, bool number) +void QTextStreamPrivate::putString(QLatin1StringView data, bool number) { if (Q_UNLIKELY(params.fieldWidth > data.size())) { @@ -933,7 +863,7 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number) if (sign == locale.negativeSign() || sign == locale.positiveSign()) { // write the sign before the padding, then skip it later write(&sign, 1); - data = QLatin1String(data.data() + 1, data.size() - 1); + data = QLatin1StringView(data.data() + 1, data.size() - 1); } } @@ -1072,7 +1002,10 @@ QTextStream::QTextStream(FILE *fileHandle, OpenMode openMode) fileHandle, int(openMode)); #endif QFile *file = new QFile; - file->open(fileHandle, openMode); + // Discarding the return value of open; even if it failed + // (and the file is not open), QTextStream still reports `Ok` + // for closed QIODevices, so there's nothing really to do here. + (void)file->open(fileHandle, openMode); Q_D(QTextStream); d->device = file; @@ -1475,7 +1408,8 @@ QTextStream::RealNumberNotation QTextStream::realNumberNotation() const /*! Sets the precision of real numbers to \a precision. This value describes the number of fraction digits QTextStream should - write when generating real numbers. + write when generating real numbers (FixedNotation, ScientificNotation), or + the maximum number of significant digits (SmartNotation). The precision cannot be a negative value. The default value is 6. @@ -1494,7 +1428,9 @@ void QTextStream::setRealNumberPrecision(int precision) /*! Returns the current real number precision, or the number of fraction - digits QTextStream will write when generating real numbers. + digits QTextStream will write when generating real numbers + (FixedNotation, ScientificNotation), or the maximum number of significant + digits (SmartNotation). \sa setRealNumberNotation(), realNumberNotation(), numberFlags(), integerBase() */ @@ -1688,7 +1624,7 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong QChar ch; if (!getChar(&ch)) return npsInvalidPrefix; - if (ch == QLatin1Char('0')) { + if (ch == u'0') { QChar ch2; if (!getChar(&ch2)) { // Result is the number 0 @@ -1697,9 +1633,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong } ch2 = ch2.toLower(); - if (ch2 == QLatin1Char('x')) { + if (ch2 == u'x') { base = 16; - } else if (ch2 == QLatin1Char('b')) { + } else if (ch2 == u'b') { base = 2; } else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) { base = 8; @@ -1724,9 +1660,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong case 2: { QChar pf1, pf2, dig; // Parse prefix '0b' - if (!getChar(&pf1) || pf1 != QLatin1Char('0')) + if (!getChar(&pf1) || pf1 != u'0') return npsInvalidPrefix; - if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('b')) + if (!getChar(&pf2) || pf2.toLower() != u'b') return npsInvalidPrefix; // Parse digits int ndigits = 0; @@ -1752,13 +1688,13 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong case 8: { QChar pf, dig; // Parse prefix '0' - if (!getChar(&pf) || pf != QLatin1Char('0')) + if (!getChar(&pf) || pf != u'0') return npsInvalidPrefix; // Parse digits int ndigits = 0; while (getChar(&dig)) { int n = dig.toLower().unicode(); - if (n >= '0' && n <= '7') { + if (isOctalDigit(n)) { val *= 8; val += n - '0'; } else { @@ -1815,20 +1751,17 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong case 16: { QChar pf1, pf2, dig; // Parse prefix ' 0x' - if (!getChar(&pf1) || pf1 != QLatin1Char('0')) + if (!getChar(&pf1) || pf1 != u'0') return npsInvalidPrefix; - if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('x')) + if (!getChar(&pf2) || pf2.toLower() != u'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') { + const int h = fromHex(dig.unicode()); + if (h != -1) { val <<= 4; - val += 10 + (n - 'a'); + val += h; } else { ungetChar(dig); break; @@ -1984,13 +1917,13 @@ bool QTextStreamPrivate::getReal(double *f) // 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 = qQNaN(); + *f = qt_qnan(); return true; } else if (!qstricmp(buf, "+inf") || !qstricmp(buf, "inf")) { - *f = qInf(); + *f = qt_inf(); return true; } else if (!qstricmp(buf, "-inf")) { - *f = -qInf(); + *f = -qt_inf(); return true; } bool ok; @@ -2022,7 +1955,7 @@ QTextStream &QTextStream::operator>>(QChar &c) \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 + character from the stream is converted to ISO-8859-1 before it is stored. \sa QChar::toLatin1() @@ -2036,6 +1969,14 @@ QTextStream &QTextStream::operator>>(char &c) } /*! + \fn QTextStream &QTextStream::operator>>(char16_t &c) + \overload + \since 6.4 + + Reads a character from the stream and stores it in \a c. +*/ + +/*! 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 @@ -2293,8 +2234,8 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative) // workaround for backward compatibility - in octal form with // ShowBase flag set zero should be written as '00' if (number == 0 && base == 8 && params.numberFlags & QTextStream::ShowBase - && result == QLatin1String("0")) { - result.prepend(QLatin1Char('0')); + && result == "0"_L1) { + result.prepend(u'0'); } } putString(result, true); @@ -2328,6 +2269,15 @@ QTextStream &QTextStream::operator<<(char c) } /*! + \fn QTextStream &QTextStream::operator<<(char16_t c) + \overload + \since 6.3.1 + + Writes the Unicode character \a c to the stream, then returns a + reference to the QTextStream. +*/ + +/*! 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 @@ -2538,7 +2488,7 @@ QTextStream &QTextStream::operator<<(QStringView string) Writes \a string to the stream, and returns a reference to the QTextStream. */ -QTextStream &QTextStream::operator<<(QLatin1String string) +QTextStream &QTextStream::operator<<(QLatin1StringView string) { Q_D(QTextStream); CHECK_VALID_STREAM(*this); @@ -2556,7 +2506,7 @@ QTextStream &QTextStream::operator<<(const QByteArray &array) { Q_D(QTextStream); CHECK_VALID_STREAM(*this); - d->putString(QString::fromUtf8(array.constData(), array.length())); + d->putString(QString::fromUtf8(array.constData(), array.size())); return *this; } @@ -2886,7 +2836,7 @@ QTextStream ¢er(QTextStream &stream) */ QTextStream &endl(QTextStream &stream) { - return stream << QLatin1Char('\n') << Qt::flush; + return stream << '\n'_L1 << Qt::flush; } /*! @@ -3000,7 +2950,7 @@ void QTextStream::setEncoding(QStringConverter::Encoding encoding) d->encoding = encoding; d->toUtf16 = QStringDecoder(d->encoding); - bool generateBOM = d->hasWrittenData && d->generateBOM; + bool generateBOM = !d->hasWrittenData && d->generateBOM; d->fromUtf16 = QStringEncoder(d->encoding, generateBOM ? QStringEncoder::Flag::WriteBom : QStringEncoder::Flag::Default); |