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 <thiago.macieira@intel.com>
(cherry picked from commit e579cdceb8b54fea02c1ed9bfae8b5ef74902270)
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Mårten Nordheim 2023-10-30 17:35:10 +01:00
parent d6cdaa1c6b
commit d3def622ea

View File

@ -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<wchar_t *>(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<int>::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<wchar_t *>(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