From e579cdceb8b54fea02c1ed9bfae8b5ef74902270 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: 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.6 6.5 Task-number: QTBUG-105105 Change-Id: Ibe49cc661f582fd54ce36ad466cf798a62b5c4c6 Reviewed-by: Thiago Macieira --- src/corelib/text/qstringconverter.cpp | 62 ++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'src/corelib/text/qstringconverter.cpp') diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp index 731b9fa4e4..9ac290b0c1 100644 --- a/src/corelib/text/qstringconverter.cpp +++ b/src/corelib/text/qstringconverter.cpp @@ -1333,35 +1333,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 -- cgit v1.2.3