From 618620bc5d82619789c9f3914f0ca3f0b1752e39 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 21 Apr 2020 15:55:50 +0200 Subject: [PATCH] Ensure the conversion methods in qstringconverter always get a valid state Make sure that the conversion methods always get a valid state. This is already the ecase then using the new QStringConverter API, ensure the old QTextCodec API also passes in a valid state. This helps simplify the logic inside those methods. Change-Id: I1945e98cdefd46bf1427e11984337f1d62abcaa2 Reviewed-by: Thiago Macieira Reviewed-by: Alex Blasche --- src/corelib/codecs/qutfcodec.cpp | 21 ++++++++++++++ src/corelib/codecs/qwindowscodec.cpp | 6 ++++ src/corelib/text/qstring.cpp | 12 +++++--- src/corelib/text/qstringconverter.cpp | 42 ++++++++++++++++++++++++++- src/corelib/text/qstringconverter.h | 9 +++--- 5 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index c518ab1d9c..d5dbd8758c 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -56,16 +56,25 @@ QUtf8Codec::~QUtf8Codec() QByteArray QUtf8Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf8::convertFromUnicode(uc, len, state); } void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; *target += QUtf8::convertToUnicode(chars, len, state); } QString QUtf8Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf8::convertToUnicode(chars, len, state); } @@ -85,11 +94,17 @@ QUtf16Codec::~QUtf16Codec() QByteArray QUtf16Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf16::convertFromUnicode(uc, len, state, e); } QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf16::convertToUnicode(chars, len, state, e); } @@ -146,11 +161,17 @@ QUtf32Codec::~QUtf32Codec() QByteArray QUtf32Codec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf32::convertFromUnicode(uc, len, state, e); } QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QUtf32::convertToUnicode(chars, len, state, e); } diff --git a/src/corelib/codecs/qwindowscodec.cpp b/src/corelib/codecs/qwindowscodec.cpp index d8a0088d6a..4a4e9dca5b 100644 --- a/src/corelib/codecs/qwindowscodec.cpp +++ b/src/corelib/codecs/qwindowscodec.cpp @@ -52,11 +52,17 @@ QWindowsLocalCodec::~QWindowsLocalCodec() QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QLocal8Bit::convertToUnicode(chars, length, state); } QByteArray QWindowsLocalCodec::convertFromUnicode(const QChar *ch, int uclen, ConverterState *state) const { + ConverterState s(QStringConverter::Flag::Stateless); + if (!state) + state = &s; return QLocal8Bit::convertFromUnicode(ch, uclen, state); } diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 21ca6f5eb2..7753ce5f00 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -5206,7 +5206,8 @@ static QByteArray qt_convert_to_local_8bit(QStringView string) { if (string.isNull()) return QByteArray(); - return QLocal8Bit::convertFromUnicode(string.data(), string.length(), nullptr); + QStringEncoder fromUtf16(QStringEncoder::Locale, QStringEncoder::Flag::Stateless); + return fromUtf16(string); } /*! @@ -5391,7 +5392,8 @@ QString QString::fromLocal8Bit_helper(const char *str, int size) QString::DataPointer empty = { pair.first, pair.second, 0 }; return QString(empty); } - return QLocal8Bit::convertToUnicode(str, size, nullptr); + QStringDecoder toUtf16(QStringDecoder::Locale, QStringDecoder::Flag::Stateless); + return toUtf16(str, size); } /*! \fn QString QString::fromUtf8(const char *str, int size) @@ -5458,7 +5460,8 @@ QString QString::fromUtf16(const char16_t *unicode, int size) while (unicode[size] != 0) ++size; } - return QUtf16::convertToUnicode((const char *)unicode, size*2, nullptr); + QStringDecoder toUtf16(QStringDecoder::Utf16, QStringDecoder::Flag::Stateless); + return toUtf16(reinterpret_cast(unicode), size*2); } /*! @@ -5495,7 +5498,8 @@ QString QString::fromUcs4(const char32_t *unicode, int size) while (unicode[size] != 0) ++size; } - return QUtf32::convertToUnicode((const char *)unicode, size*4, nullptr); + QStringDecoder toUtf16(QStringDecoder::Utf32, QStringDecoder::Flag::Stateless); + return toUtf16(reinterpret_cast(unicode), size*4); } diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp index fd716da15a..31a4d043a2 100644 --- a/src/corelib/text/qstringconverter.cpp +++ b/src/corelib/text/qstringconverter.cpp @@ -404,6 +404,10 @@ QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len) QByteArray QUtf8::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverter::State *state) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + uchar replacement = '?'; qsizetype rlen = 3*len; int surrogate_high = -1; @@ -549,6 +553,10 @@ QChar *QUtf8::convertToUnicode(QChar *buffer, const char *chars, qsizetype len) QString QUtf8::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + bool headerdone = state && state->internalState & HeaderDone; ushort replacement = QChar::ReplacementCharacter; int invalid = 0; @@ -754,6 +762,10 @@ int QUtf8::compareUtf8(const char *utf8, qsizetype u8len, QLatin1String s) QByteArray QUtf16::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverter::State *state, DataEndianness endian) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + bool writeBom = state && !(state->internalState & HeaderDone) && state->flags & QStringConverter::Flag::WriteBom; qsizetype length = 2*len; if (writeBom) @@ -787,6 +799,10 @@ QByteArray QUtf16::convertFromUnicode(const QChar *uc, qsizetype len, QStringCon QString QUtf16::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + bool half = false; uchar buf = 0; bool headerdone = state && state->internalState & HeaderDone; @@ -862,6 +878,10 @@ QString QUtf16::convertToUnicode(const char *chars, qsizetype len, QStringConver QByteArray QUtf32::convertFromUnicode(const QChar *uc, qsizetype len, QStringConverter::State *state, DataEndianness endian) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + bool writeBom = state && !(state->internalState & HeaderDone) && state->flags & QStringConverter::Flag::WriteBom; qsizetype length = 4*len; if (writeBom) @@ -911,6 +931,10 @@ QByteArray QUtf32::convertFromUnicode(const QChar *uc, qsizetype len, QStringCon QString QUtf32::convertToUnicode(const char *chars, qsizetype len, QStringConverter::State *state, DataEndianness endian) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + uchar tuple[4]; int num = 0; bool headerdone = state && state->internalState & HeaderDone; @@ -995,6 +1019,10 @@ QString qFromUtfEncoded(const QByteArray &ba) #if defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED) static QString convertToUnicodeCharByChar(const char *chars, qsizetype length, QStringConverter::State *state) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + if (!chars || !length) return QString(); @@ -1144,6 +1172,11 @@ QString QLocal8Bit::convertToUnicode(const char *chars, qsizetype length, QStrin QByteArray QLocal8Bit::convertFromUnicode(const QChar *ch, qsizetype uclen, QStringConverter::State *state) { Q_ASSERT(uclen < INT_MAX); // ### FIXME + Q_ASSERT(state); + Q_UNUSED(state); // ### Fixme + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + if (!ch) return QByteArray(); if (uclen == 0) @@ -1307,8 +1340,11 @@ static char *toUtf32LE(char *out, QStringView in, QStringConverter::State *state void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept; -static QChar *fromLatin1(QChar *out, const char *chars, qsizetype len, QStringConverter::State *) +static QChar *fromLatin1(QChar *out, const char *chars, qsizetype len, QStringConverter::State *state) { + Q_ASSERT(state); + Q_UNUSED(state); + qt_from_latin1(reinterpret_cast(out), chars, size_t(len)); return out + len; } @@ -1316,6 +1352,10 @@ static QChar *fromLatin1(QChar *out, const char *chars, qsizetype len, QStringCo static char *toLatin1(char *out, QStringView in, QStringConverter::State *state) { + Q_ASSERT(state); + if (state->flags & QStringConverter::Flag::Stateless) // temporary + state = nullptr; + const char replacement = (state && state->flags & QStringConverter::Flag::ConvertInvalidToNull) ? 0 : '?'; int invalid = 0; for (qsizetype i = 0; i < in.length(); ++i) { diff --git a/src/corelib/text/qstringconverter.h b/src/corelib/text/qstringconverter.h index 3f657c9935..1e46cbe72e 100644 --- a/src/corelib/text/qstringconverter.h +++ b/src/corelib/text/qstringconverter.h @@ -200,13 +200,12 @@ public: qsizetype requiredSpace(qsizetype inputLength) const { return iface->fromUtf16Len(inputLength); } char *decodeIntoBuffer(char *out, const QChar *in, qsizetype length) - { return iface->fromUtf16(out, QStringView(in, length), state.flags & Flag::Stateless ? nullptr : &state); } + { return iface->fromUtf16(out, QStringView(in, length), &state); } QByteArray encode(QStringView in) { QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized); char *out = result.data(); - // ### Fixme: needs to be moved into the conversion methods to honor the other flags - out = iface->fromUtf16(out, in, state.flags & Flag::Stateless ? nullptr : &state); + out = iface->fromUtf16(out, in, &state); result.truncate(out - result.constData()); return result; } @@ -259,13 +258,13 @@ public: qsizetype requiredSpace(qsizetype inputLength) const { return iface->toUtf16Len(inputLength); } QChar *decodeIntoBuffer(QChar *out, const char *in, qsizetype length) - { return iface->toUtf16(out, in, length, state.flags & Flag::Stateless ? nullptr : &state); } + { return iface->toUtf16(out, in, length, &state); } QString decode(const char *in, qsizetype length) { QString result(iface->toUtf16Len(length), Qt::Uninitialized); QChar *out = result.data(); // ### Fixme: state handling needs to be moved into the conversion methods - out = iface->toUtf16(out, in, length, state.flags & Flag::Stateless ? nullptr : &state); + out = iface->toUtf16(out, in, length, &state); result.truncate(out - result.constData()); return result; }