From d3def622ead7127d54c6f91010f624526abf33fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 30 Oct 2023 17:35:10 +0100 Subject: [PATCH] QLocal8Bit::convertToUnicode[win]: Pre-2Gi changes Prepare the code for the upcoming changes to support strings longer than 2GiB. We will have to loop from start to end, and increment the pointer whenever we succeed, rather than assuming there is a single success before we return. This also means the error-handling code goes into an else-branch and gets indented. Pick-to: 6.5 Task-number: QTBUG-105105 Change-Id: Ibe49cc661f582fd54ce36ad466cf798a62b5c4c6 Reviewed-by: Thiago Macieira (cherry picked from commit e579cdceb8b54fea02c1ed9bfae8b5ef74902270) Reviewed-by: Edward Welbourne --- src/corelib/text/qstringconverter.cpp | 62 ++++++++++++++++----------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp index 65f2b64e3f9..65a365870cb 100644 --- a/src/corelib/text/qstringconverter.cpp +++ b/src/corelib/text/qstringconverter.cpp @@ -1332,35 +1332,45 @@ QString QLocal8Bit::convertToUnicode_sys(QByteArrayView in, quint32 codePage, Q_ASSERT(mblen > 0); Q_ASSERT(!state || state->remainingChars == 0); - while (!(len = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, mb, mblen, out, - int(outlen)))) { - int r = GetLastError(); - if (r == ERROR_INSUFFICIENT_BUFFER) { - Q_ASSERT(QtPrivate::q_points_into_range(out, buf.data(), buf.data() + buf.size())); - const int wclen = MultiByteToWideChar(codePage, 0, mb, mblen, 0, 0); - const qsizetype offset = qsizetype(out - buf.data()); - sp.resize(offset + wclen); - auto it = reinterpret_cast(sp.data()); - it = std::copy_n(buf.data(), offset, it); - out = it; - outlen = wclen; - } else if (r == ERROR_NO_UNICODE_TRANSLATION && state - && state->remainingChars < q20::ssize(state->state_data)) { - ++state->remainingChars; - --mblen; - for (qsizetype i = 0; i < state->remainingChars; ++i) - state->state_data[i] = mb[mblen + i]; - if (mblen == 0) - break; + constexpr int MaxStep = std::numeric_limits::max(); + const char *end = mb + mblen; + while (mb != end) { + const int nextIn = int(std::min(qsizetype(mblen), qsizetype(MaxStep))); + const int nextOut = int(std::min(outlen, qsizetype(MaxStep))); + len = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, mb, nextIn, out, nextOut); + if (len) { + mb += nextIn; + mblen -= nextIn; + out += len; + outlen -= len; } else { - // Fail. - qWarning("MultiByteToWideChar: Cannot convert multibyte text"); - break; + int r = GetLastError(); + if (r == ERROR_INSUFFICIENT_BUFFER) { + Q_ASSERT(QtPrivate::q_points_into_range(out, buf.data(), buf.data() + buf.size())); + const int wclen = MultiByteToWideChar(codePage, 0, mb, nextIn, 0, 0); + auto begin = buf.data(); + const qsizetype offset = qsizetype(std::distance(begin, out)); + qsizetype newSize = offset + wclen; + sp.resize(newSize); + auto it = reinterpret_cast(sp.data()); + it = std::copy_n(buf.data(), offset, it); + out = it; + outlen = wclen; + } else if (r == ERROR_NO_UNICODE_TRANSLATION && state + && state->remainingChars < q20::ssize(state->state_data)) { + ++state->remainingChars; + --mblen; + for (qsizetype i = 0; i < state->remainingChars; ++i) + state->state_data[i] = mb[mblen + i]; + if (mblen == 0) + break; + } else { + // Fail. + qWarning("MultiByteToWideChar: Cannot convert multibyte text"); + break; + } } } - out += len; - if (len) - mblen = 0; if (sp.isEmpty()) { // We must have only used the stack buffer