Debugger: Correctly display > 2 byte characters in strings

The "escapeUnprintable" function previously iterated through the
QString QChar by QChar. Since QChar only represents UTF-16 it would
erroneously split 4 byte characters into two characters that were
no longer printable.

To workaround, we first convert the QString to a UTF32 ByteArray
and iterate over each of the characters. This allows us to
correctly distinguish between non- printable characters.

Change-Id: I5552a79a91678994868441e67f967c68329aa1ce
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-08-09 16:12:23 +02:00
parent cd919e6f61
commit a1fd70c1a4

View File

@@ -30,6 +30,8 @@
#include "watchdata.h" #include "watchdata.h"
#include <QDebug> #include <QDebug>
#include <QStringEncoder>
#include <QStringDecoder>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@@ -242,35 +244,40 @@ QString formatToolTipAddress(quint64 a)
QString escapeUnprintable(const QString &str, int unprintableBase) QString escapeUnprintable(const QString &str, int unprintableBase)
{ {
if (unprintableBase == 0) QStringEncoder toUtf32(QStringEncoder::Utf32);
return str; QStringDecoder toQString(QStringDecoder::Utf32);
QByteArray arr = toUtf32(str);
QByteArrayView arrayView(arr);
QString encoded; QString encoded;
if (unprintableBase == -1) {
for (const QChar c : str) { while (arrayView.size() >= 4) {
int u = c.unicode(); char32_t c;
if (c.isPrint()) memcpy(&c, arrayView.constData(), sizeof(char32_t));
encoded += c;
else if (u == '\r') if (QChar::isPrint(c))
encoded += "\\r"; encoded += toQString(arrayView.sliced(0, 4));
else if (u == '\t') else {
encoded += "\\t"; if (unprintableBase == -1) {
else if (u == '\n') if (c == '\r')
encoded += "\\n"; encoded += "\\r";
else else if (c == '\t')
encoded += QString("\\%1").arg(u, 3, 8, QLatin1Char('0')); encoded += "\\t";
else if (c == '\n')
encoded += "\\n";
else
encoded += QString("\\%1").arg(c, 3, 8, QLatin1Char('0'));
} else if (unprintableBase == 8) {
encoded += QString("\\%1").arg(c, 3, 8, QLatin1Char('0'));
} else {
encoded += QString("\\u%1").arg(c, 4, 16, QLatin1Char('0'));
}
} }
return encoded;
arrayView = arrayView.sliced(4);
} }
for (const QChar c : str) {
if (c.isPrint())
encoded += c;
else if (unprintableBase == 8)
encoded += QString("\\%1").arg(c.unicode(), 3, 8, QLatin1Char('0'));
else
encoded += QString("\\u%1").arg(c.unicode(), 4, 16, QLatin1Char('0'));
}
return encoded; return encoded;
} }