summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qstringconverter.cpp
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2023-10-30 17:35:10 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2023-11-06 18:23:19 +0100
commite579cdceb8b54fea02c1ed9bfae8b5ef74902270 (patch)
treefc4a65f010498a81a0697f1e66a24011b92c7e73 /src/corelib/text/qstringconverter.cpp
parent6f4823348220780a2e926c7885f2249f89f7e16d (diff)
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 <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/text/qstringconverter.cpp')
-rw-r--r--src/corelib/text/qstringconverter.cpp62
1 files changed, 36 insertions, 26 deletions
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<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