Debugger: Split DebuggerEncoding enum

... into a string specifying a kind of encoding (utf8, latin1),
an optional bytesize (2-byte integers, 4-byte integers) and a
flag whether the displayed value should get "..." around it.

Scales better than adding an enum value for each new combination.

Change-Id: Iffcb1e2f148f12da96e165559a976bd34026c649
Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
hjk
2015-12-11 13:28:21 +01:00
parent 74b33929d8
commit c2bf384ac2
19 changed files with 404 additions and 570 deletions

View File

@@ -560,139 +560,101 @@ static void getDateTime(qint64 msecs, int status, QDate *date, QTime *time)
*time = (status & NullTime) ? QTime() : QTime::fromMSecsSinceStartOfDay(ds);
}
QString decodeData(const QByteArray &ba, DebuggerEncoding encoding)
QString decodeData(const QByteArray &ba, const QByteArray &encoding)
{
switch (encoding) {
case Unencoded8Bit: // 0
return quoteUnprintableLatin1(ba);
case Base64Encoded8BitWithQuotes: { // 1, used for QByteArray
const QChar doubleQuote(QLatin1Char('"'));
QString rc = doubleQuote;
rc += quoteUnprintableLatin1(QByteArray::fromBase64(ba));
rc += doubleQuote;
return rc;
if (encoding.isEmpty())
return quoteUnprintableLatin1(ba); // The common case.
if (encoding == "empty")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<empty>");
if (encoding == "minimumitemcount")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<at least %n items>", 0, ba.toInt());
if (encoding == "undefined")
return QLatin1String("Undefined");
if (encoding == "null")
return QLatin1String("Null");
if (encoding == "itemcount")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<%n items>", 0, ba.toInt());
if (encoding == "notaccessible")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not accessible>");
if (encoding == "optimizedout")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<optimized out>");
if (encoding == "nullreference")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<null reference>");
if (encoding == "emptystructure")
return QLatin1String("{...}");
if (encoding == "uninitialized")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<uninitialized>");
if (encoding == "invalid")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<invalid>");
if (encoding == "notcallable")
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not callable>");
DebuggerEncoding enc(encoding);
QString result;
switch (enc.type) {
case DebuggerEncoding::Unencoded: {
result = quoteUnprintableLatin1(ba);
break;
}
case Base64Encoded16BitWithQuotes: { // 2, used for QString
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromBase64(ba);
QString rc = doubleQuote;
rc += QString::fromUtf16(reinterpret_cast<const ushort *>
case DebuggerEncoding::HexEncodedLocal8Bit: {
const QByteArray decodedBa = QByteArray::fromHex(ba);
result = QString::fromLocal8Bit(decodedBa.data(), decodedBa.size());
break;
}
case DebuggerEncoding::HexEncodedLatin1: {
const QByteArray decodedBa = QByteArray::fromHex(ba);
result = QString::fromLatin1(decodedBa.data(), decodedBa.size());
break;
}
case DebuggerEncoding::HexEncodedUtf8: {
const QByteArray decodedBa = QByteArray::fromHex(ba);
result = QString::fromUtf8(decodedBa.data(), decodedBa.size());
break;
}
case DebuggerEncoding::HexEncodedUtf16: {
const QByteArray decodedBa = QByteArray::fromHex(ba);
result = QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2);
rc += doubleQuote;
return rc;
break;
}
case Base64Encoded32BitWithQuotes: { // 3
const QByteArray decodedBa = QByteArray::fromBase64(ba);
const QChar doubleQuote(QLatin1Char('"'));
QString rc = doubleQuote;
rc += QString::fromUcs4(reinterpret_cast<const uint *>
case DebuggerEncoding::HexEncodedUcs4: {
const QByteArray decodedBa = QByteArray::fromHex(ba);
result = QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4);
rc += doubleQuote;
return rc;
break;
}
case Base64Encoded16Bit: { // 4, without quotes (see 2)
const QByteArray decodedBa = QByteArray::fromBase64(ba);
return QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2);
}
case Base64Encoded8Bit: { // 5, without quotes (see 1)
return quoteUnprintableLatin1(QByteArray::fromBase64(ba));
}
case Hex2EncodedLatin1WithQuotes: { // 6, %02x encoded 8 bit Latin1 data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
return doubleQuote + QString::fromLatin1(decodedBa, decodedBa.size()) + doubleQuote;
}
case Hex4EncodedLittleEndianWithQuotes: { // 7, %04x encoded 16 bit data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
return doubleQuote + QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2) + doubleQuote;
}
case Hex8EncodedLittleEndianWithQuotes: { // 8, %08x encoded 32 bit data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
}
case Hex2EncodedUtf8WithQuotes: { // 9, %02x encoded 8 bit UTF-8 data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
return doubleQuote + QString::fromUtf8(decodedBa) + doubleQuote;
}
case Hex8EncodedBigEndian: { // 10, %08x encoded 32 bit data
const QChar doubleQuote(QLatin1Char('"'));
QByteArray decodedBa = QByteArray::fromHex(ba);
for (int i = 0; i < decodedBa.size() - 3; i += 4) {
char c = decodedBa.at(i);
decodedBa[i] = decodedBa.at(i + 3);
decodedBa[i + 3] = c;
c = decodedBa.at(i + 1);
decodedBa[i + 1] = decodedBa.at(i + 2);
decodedBa[i + 2] = c;
}
return doubleQuote + QString::fromUcs4(reinterpret_cast<const uint *>
(decodedBa.data()), decodedBa.size() / 4) + doubleQuote;
}
case Hex4EncodedBigEndianWithQuotes: { // 11, %04x encoded 16 bit data
const QChar doubleQuote(QLatin1Char('"'));
QByteArray decodedBa = QByteArray::fromHex(ba);
for (int i = 0; i < decodedBa.size(); i += 2) {
char c = decodedBa.at(i);
decodedBa[i] = decodedBa.at(i + 1);
decodedBa[i + 1] = c;
}
return doubleQuote + QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2) + doubleQuote;
}
case Hex4EncodedLittleEndianWithoutQuotes: { // 12, see 7, without quotes
const QByteArray decodedBa = QByteArray::fromHex(ba);
return QString::fromUtf16(reinterpret_cast<const ushort *>
(decodedBa.data()), decodedBa.size() / 2);
}
case Hex2EncodedLocal8BitWithQuotes: { // 13, %02x encoded 8 bit UTF-8 data
const QChar doubleQuote(QLatin1Char('"'));
const QByteArray decodedBa = QByteArray::fromHex(ba);
return doubleQuote + QString::fromLocal8Bit(decodedBa) + doubleQuote;
}
case JulianDate: { // 14, an integer count
case DebuggerEncoding::JulianDate: {
const QDate date = dateFromData(ba.toInt());
return date.isValid() ? date.toString(Qt::TextDate) : QLatin1String("(invalid)");
}
case MillisecondsSinceMidnight: { // 15
case DebuggerEncoding::MillisecondsSinceMidnight: {
const QTime time = timeFromData(ba.toInt());
return time.isValid() ? time.toString(Qt::TextDate) : QLatin1String("(invalid)");
}
case JulianDateAndMillisecondsSinceMidnight: { // 16
case DebuggerEncoding::JulianDateAndMillisecondsSinceMidnight: {
const int p = ba.indexOf('/');
const QDate date = dateFromData(ba.left(p).toInt());
const QTime time = timeFromData(ba.mid(p + 1 ).toInt());
const QDateTime dateTime = QDateTime(date, time);
return dateTime.isValid() ? dateTime.toString(Qt::TextDate) : QLatin1String("(invalid)");
}
case Hex2EncodedInt1: // 17
case Hex2EncodedInt2: // 18
case Hex2EncodedInt4: // 19
case Hex2EncodedInt8: // 20
case Hex2EncodedUInt1: // 21
case Hex2EncodedUInt2: // 22
case Hex2EncodedUInt4: // 23
case Hex2EncodedUInt8: // 24
case DebuggerEncoding::HexEncodedUnsignedInteger:
case DebuggerEncoding::HexEncodedSignedInteger:
qDebug("not implemented"); // Only used in Arrays, see watchdata.cpp
return QString();
case Hex2EncodedFloat4: { // 25
case DebuggerEncoding::HexEncodedFloat: {
const QByteArray s = QByteArray::fromHex(ba);
QTC_ASSERT(s.size() == 4, break);
union { char c[4]; float f; } u = { { s[3], s[2], s[1], s[0] } };
return QString::number(u.f);
if (enc.size == 4) {
union { char c[4]; float f; } u = { { s[3], s[2], s[1], s[0] } };
return QString::number(u.f);
}
if (enc.size == 8) {
union { char c[8]; double d; } u = { { s[7], s[6], s[5], s[4], s[3], s[2], s[1], s[0] } };
return QString::number(u.d);
}
}
case Hex2EncodedFloat8: { // 26
const QByteArray s = QByteArray::fromHex(ba);
QTC_ASSERT(s.size() == 8, break);
union { char c[8]; double d; } u = { { s[7], s[6], s[5], s[4], s[3], s[2], s[1], s[0] } };
return QString::number(u.d);
}
case IPv6AddressAndHexScopeId: { // 27, 16 hex-encoded bytes, "%" and the string-encoded scope
case DebuggerEncoding::IPv6AddressAndHexScopeId: { // 16 hex-encoded bytes, "%" and the string-encoded scope
const int p = ba.indexOf('%');
QHostAddress ip6(QString::fromLatin1(p == -1 ? ba : ba.left(p)));
if (ip6.isNull())
@@ -704,11 +666,7 @@ QString decodeData(const QByteArray &ba, DebuggerEncoding encoding)
scopeId.length() / 2));
return ip6.toString();
}
case Hex2EncodedUtf8WithoutQuotes: { // 28, %02x encoded 8 bit UTF-8 data without quotes
const QByteArray decodedBa = QByteArray::fromHex(ba);
return QString::fromUtf8(decodedBa);
}
case DateTimeInternal: { // 29, DateTimeInternal: msecs, spec, offset, tz, status
case DebuggerEncoding::DateTimeInternal: { // DateTimeInternal: msecs, spec, offset, tz, status
int p0 = ba.indexOf('/');
int p1 = ba.indexOf('/', p0 + 1);
int p2 = ba.indexOf('/', p1 + 1);
@@ -740,45 +698,15 @@ QString decodeData(const QByteArray &ba, DebuggerEncoding encoding)
}
return dateTime.toString();
}
case SpecialEmptyValue: { // 30
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<empty>");
}
case SpecialUninitializedValue: { // 31
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<uninitialized>");
}
case SpecialInvalidValue: { // 32
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<invalid>");
}
case SpecialNotAccessibleValue: { // 33
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not accessible>");
}
case SpecialItemCountValue: { // 34
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<%n items>", 0, ba.toInt());
}
case SpecialMinimumItemCountValue: { // 35
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<at least %n items>", 0, ba.toInt());
}
case SpecialNotCallableValue: { // 36
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not callable>");
}
case SpecialNullReferenceValue: { // 37
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<null reference>");
}
case SpecialOptimizedOutValue: { // 38
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<optimized out>");
}
case SpecialEmptyStructureValue: { // 39
return QLatin1String("{...}");
}
case SpecialUndefinedValue: { // 40
return QLatin1String("Undefined");
}
case SpecialNullValue: { // 41
return QLatin1String("Null");
}
qDebug() << "ENCODING ERROR: " << enc.type;
return QCoreApplication::translate("Debugger", "<Encoding error>");
}
qDebug() << "ENCODING ERROR: " << encoding;
return QCoreApplication::translate("Debugger", "<Encoding error>");
if (enc.quotes) {
const QChar doubleQuote(QLatin1Char('"'));
result = doubleQuote + result + doubleQuote;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////
@@ -897,23 +825,61 @@ QByteArray DebuggerCommand::argsToString() const
return args.toString().toLatin1();
}
DebuggerEncoding debuggerEncoding(const QByteArray &data)
DebuggerEncoding::DebuggerEncoding(const QByteArray &data)
{
if (data == "utf16")
return Hex4EncodedLittleEndianWithQuotes;
if (data == "empty")
return SpecialEmptyValue;
if (data == "minimumitemcount")
return SpecialMinimumItemCountValue;
if (data == "undefined")
return SpecialUndefinedValue;
if (data == "null")
return SpecialNullValue;
if (data == "itemcount")
return SpecialItemCountValue;
if (data == "notaccessible")
return SpecialNotAccessibleValue;
return DebuggerEncoding(data.toInt());
const QByteArrayList l = data.split(':');
const QByteArray &t = l.at(0);
if (t == "latin1") {
type = HexEncodedLatin1;
size = 1;
quotes = true;
} else if (t == "local8bit") {
type = HexEncodedLocal8Bit;
size = 1;
quotes = true;
} else if (t == "utf8") {
type = HexEncodedUtf8;
size = 1;
quotes = true;
} else if (t == "utf16") {
type = HexEncodedUtf16;
size = 2;
quotes = true;
} else if (t == "ucs4") {
type = HexEncodedUcs4;
size = 4;
quotes = true;
} else if (t == "int") {
type = HexEncodedSignedInteger;
} else if (t == "uint") {
type = HexEncodedUnsignedInteger;
} else if (t == "float") {
type = HexEncodedFloat;
} else if (t == "juliandate") {
type = JulianDate;
} else if (t == "juliandateandmillisecondssincemidnight") {
type = JulianDateAndMillisecondsSinceMidnight;
} else if (t == "millisecondssincemidnight") {
type = MillisecondsSinceMidnight;
} else if (t == "ipv6addressandhexscopeid") {
type = IPv6AddressAndHexScopeId;
} else if (t == "datetimeinternal") {
type = DateTimeInternal;
} else if (!t.isEmpty()) {
qDebug() << "CANNOT DECODE ENCODING" << data;
}
if (l.size() >= 2)
size = l.at(1).toInt();
if (l.size() >= 3)
quotes = bool(l.at(2).toInt());
}
QString DebuggerEncoding::toString() const
{
return QString::fromLatin1("%1:%2:%3").arg(type).arg(size).arg(quotes);
}
} // namespace Internal