Debugger: Debugger protocol maintenance

- Move DisplayFormat from watchhandler.h to debuggerprotocol.h
- Add/update a few comments about the use of the protocol enums
- Make decodeData take a DebuggerEncoding instead of an int

Change-Id: I50bed70a5da2e94da46e894bf9136bc14c9a1b23
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
hjk
2015-08-12 11:26:10 +02:00
parent fb387ea2af
commit eca5ccdd3e
6 changed files with 107 additions and 74 deletions

View File

@@ -59,7 +59,7 @@ StartRemoteProcess, \
= range(0, 9) = range(0, 9)
# Known special formats. Keep in sync with DisplayFormat in watchhandler.h # Known special formats. Keep in sync with DisplayFormat in debuggerprotocol.h
AutomaticFormat, \ AutomaticFormat, \
RawFormat, \ RawFormat, \
SimpleFormat, \ SimpleFormat, \
@@ -142,7 +142,7 @@ SpecialOptimizedOutValue, \
SpecialEmptyStructureValue, \ SpecialEmptyStructureValue, \
= range(40) = range(40)
# Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h # Display modes. Keep that synchronized with DebuggerDisplay in debuggerprotocol.h
StopDisplay, \ StopDisplay, \
DisplayImageData, \ DisplayImageData, \
DisplayUtf16String, \ DisplayUtf16String, \

View File

@@ -558,7 +558,7 @@ static void getDateTime(qint64 msecs, int status, QDate *date, QTime *time)
*time = (status & NullTime) ? QTime() : QTime::fromMSecsSinceStartOfDay(ds); *time = (status & NullTime) ? QTime() : QTime::fromMSecsSinceStartOfDay(ds);
} }
QString decodeData(const QByteArray &ba, int encoding) QString decodeData(const QByteArray &ba, DebuggerEncoding encoding)
{ {
switch (encoding) { switch (encoding) {
case Unencoded8Bit: // 0 case Unencoded8Bit: // 0
@@ -657,17 +657,39 @@ QString decodeData(const QByteArray &ba, int encoding)
const QDate date = dateFromData(ba.toInt()); const QDate date = dateFromData(ba.toInt());
return date.isValid() ? date.toString(Qt::TextDate) : QLatin1String("(invalid)"); return date.isValid() ? date.toString(Qt::TextDate) : QLatin1String("(invalid)");
} }
case MillisecondsSinceMidnight: { case MillisecondsSinceMidnight: { // 15
const QTime time = timeFromData(ba.toInt()); const QTime time = timeFromData(ba.toInt());
return time.isValid() ? time.toString(Qt::TextDate) : QLatin1String("(invalid)"); return time.isValid() ? time.toString(Qt::TextDate) : QLatin1String("(invalid)");
} }
case JulianDateAndMillisecondsSinceMidnight: { case JulianDateAndMillisecondsSinceMidnight: { // 16
const int p = ba.indexOf('/'); const int p = ba.indexOf('/');
const QDate date = dateFromData(ba.left(p).toInt()); const QDate date = dateFromData(ba.left(p).toInt());
const QTime time = timeFromData(ba.mid(p + 1 ).toInt()); const QTime time = timeFromData(ba.mid(p + 1 ).toInt());
const QDateTime dateTime = QDateTime(date, time); const QDateTime dateTime = QDateTime(date, time);
return dateTime.isValid() ? dateTime.toString(Qt::TextDate) : QLatin1String("(invalid)"); 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
qDebug("not implemented"); // Only used in Arrays, see watchdata.cpp
return QString();
case Hex2EncodedFloat4: { // 25
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);
}
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 IPv6AddressAndHexScopeId: { // 27, 16 hex-encoded bytes, "%" and the string-encoded scope
const int p = ba.indexOf('%'); const int p = ba.indexOf('%');
QHostAddress ip6(QString::fromLatin1(p == -1 ? ba : ba.left(p))); QHostAddress ip6(QString::fromLatin1(p == -1 ? ba : ba.left(p)));
@@ -716,46 +738,34 @@ QString decodeData(const QByteArray &ba, int encoding)
} }
return dateTime.toString(); return dateTime.toString();
} }
case Hex2EncodedFloat4: { case SpecialEmptyValue: { // 30
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);
}
case Hex2EncodedFloat8: {
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 SpecialEmptyValue: {
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<empty>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<empty>");
} }
case SpecialUninitializedValue: { case SpecialUninitializedValue: { // 31
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<uninitialized>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<uninitialized>");
} }
case SpecialInvalidValue: { case SpecialInvalidValue: { // 32
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<invalid>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<invalid>");
} }
case SpecialNotAccessibleValue: { case SpecialNotAccessibleValue: { // 33
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not accessible>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not accessible>");
} }
case SpecialItemCountValue: { case SpecialItemCountValue: { // 34
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<%n items>", 0, ba.toInt()); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<%n items>", 0, ba.toInt());
} }
case SpecialMinimumItemCountValue: { case SpecialMinimumItemCountValue: { // 35
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<at least %n items>", 0, ba.toInt()); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<at least %n items>", 0, ba.toInt());
} }
case SpecialNotCallableValue: { case SpecialNotCallableValue: { // 36
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not callable>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<not callable>");
} }
case SpecialNullReferenceValue: { case SpecialNullReferenceValue: { // 37
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<null reference>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<null reference>");
} }
case SpecialOptimizedOutValue: { case SpecialOptimizedOutValue: { // 38
return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<optimized out>"); return QCoreApplication::translate("Debugger::Internal::WatchHandler", "<optimized out>");
} }
case SpecialEmptyStructureValue: { case SpecialEmptyStructureValue: { // 39
return QLatin1String("{...}"); return QLatin1String("{...}");
} }
} }

View File

@@ -208,7 +208,13 @@ public:
void extractGdbVersion(const QString &msg, void extractGdbVersion(const QString &msg,
int *gdbVersion, int *gdbBuildVersion, bool *isMacGdb, bool *isQnxGdb); int *gdbVersion, int *gdbBuildVersion, bool *isMacGdb, bool *isQnxGdb);
// These enum values correspond to encodings produced by the dumpers
// and consumed by \c decodeData(const QByteArray &baIn, DebuggerEncoding encoding);
// They are never stored in settings.
//
// Keep in sync with dumper.py // Keep in sync with dumper.py
enum DebuggerEncoding enum DebuggerEncoding
{ {
Unencoded8Bit = 0, Unencoded8Bit = 0,
@@ -253,8 +259,68 @@ enum DebuggerEncoding
SpecialEmptyStructureValue = 39 SpecialEmptyStructureValue = 39
}; };
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, DebuggerEncoding encoding);
// These enum values correspond to possible value display format requests,
// typically selected by the user using the L&E context menu, under
// "Change Value Display Format". They are passed from the frontend to
// the dumpers.
//
// Keep in sync with dumper.py.
//
// \note Add new enum values only at the end, as the numeric values are
// persisted in user settings.
enum DisplayFormat
{
AutomaticFormat = 0, // Based on type for individuals, dumper default for types.
// Could be anything reasonably cheap.
RawFormat = 1, // No formatting at all.
SimpleFormat = 2, // Typical simple format (e.g. for QModelIndex row/column)
EnhancedFormat = 3, // Enhanced format (e.g. for QModelIndex with resolved display)
SeparateFormat = 4, // Display in separate Window
Latin1StringFormat = 5,
SeparateLatin1StringFormat = 6,
Utf8StringFormat = 7,
SeparateUtf8StringFormat = 8,
Local8BitStringFormat = 9,
Utf16StringFormat = 10,
Ucs4StringFormat = 11,
Array10Format = 12,
Array100Format = 13,
Array1000Format = 14,
Array10000Format = 15,
ArrayPlotFormat = 16,
CompactMapFormat = 17,
DirectQListStorageFormat = 18,
IndirectQListStorageFormat = 19,
BoolTextFormat = 20, // Bools as "true" or "false" - Frontend internal only.
BoolIntegerFormat = 21, // Bools as "0" or "1" - Frontend internal only
DecimalIntegerFormat = 22, // Frontend internal only
HexadecimalIntegerFormat = 23, // Frontend internal only
BinaryIntegerFormat = 24, // Frontend internal only
OctalIntegerFormat = 25, // Frontend internal only
CompactFloatFormat = 26, // Frontend internal only
ScientificFloatFormat = 27 // Frontend internal only
};
// These enum values are passed from the dumper to the frontend,
// typically as a result of passing a related DisplayFormat value.
// They are never stored in settings.
// Keep in sync with dumper.py, symbolgroupvalue.cpp of CDB // Keep in sync with dumper.py, symbolgroupvalue.cpp of CDB
enum DebuggerDisplay { enum DebuggerDisplay
{
StopDisplay = 0, StopDisplay = 0,
DisplayImageData = 1, DisplayImageData = 1,
DisplayUtf16String = 2, DisplayUtf16String = 2,
@@ -263,8 +329,6 @@ enum DebuggerDisplay {
DisplayUtf8String = 5, DisplayUtf8String = 5,
DisplayPlotData = 6 DisplayPlotData = 6
}; };
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -3498,7 +3498,7 @@ void GdbEngine::handleThreadNames(const DebuggerResponse &response)
ThreadData thread; ThreadData thread;
thread.id = ThreadId(name["id"].toInt()); thread.id = ThreadId(name["id"].toInt());
thread.name = decodeData(name["value"].data(), thread.name = decodeData(name["value"].data(),
name["valueencoded"].toInt()); DebuggerEncoding(name["valueencoded"].toInt()));
handler->updateThread(thread); handler->updateThread(thread);
} }
updateViews(); updateViews();

View File

@@ -393,7 +393,7 @@ void WatchData::updateValue(const GdbMi &item)
GdbMi value = item["value"]; GdbMi value = item["value"];
if (value.isValid()) { if (value.isValid()) {
int encoding = item["valueencoded"].toInt(); int encoding = item["valueencoded"].toInt();
setValue(decodeData(value.data(), encoding)); setValue(decodeData(value.data(), DebuggerEncoding(encoding)));
} else { } else {
setValueNeeded(); setValueNeeded();
} }
@@ -620,7 +620,7 @@ void parseChildrenData(const WatchData &data0, const GdbMi &item,
QByteArray key = child["key"].data(); QByteArray key = child["key"].data();
if (!key.isEmpty()) { if (!key.isEmpty()) {
int encoding = child["keyencoded"].toInt(); int encoding = child["keyencoded"].toInt();
data1.name = decodeData(key, encoding); data1.name = decodeData(key, DebuggerEncoding(encoding));
} }
childHandler(data1, child); childHandler(data1, child);
} }

View File

@@ -44,47 +44,6 @@ class DebuggerCommand;
class DebuggerEngine; class DebuggerEngine;
class WatchModel; class WatchModel;
// Special formats. Keep in sync with dumper.py.
enum DisplayFormat
{
AutomaticFormat, // Based on type for individuals, dumper default for types.
RawFormat,
SimpleFormat, // Typical simple format (e.g. for QModelIndex row/column)
EnhancedFormat, // Enhanced format (e.g. for QModelIndex with resolved display)
SeparateFormat, // Display in separate Window
Latin1StringFormat,
SeparateLatin1StringFormat,
Utf8StringFormat,
SeparateUtf8StringFormat,
Local8BitStringFormat,
Utf16StringFormat,
Ucs4StringFormat,
Array10Format,
Array100Format,
Array1000Format,
Array10000Format,
ArrayPlotFormat,
CompactMapFormat,
DirectQListStorageFormat,
IndirectQListStorageFormat,
// Not used in *.py.
BoolTextFormat,
BoolIntegerFormat,
DecimalIntegerFormat,
HexadecimalIntegerFormat,
BinaryIntegerFormat,
OctalIntegerFormat,
CompactFloatFormat,
ScientificFloatFormat,
};
typedef QVector<DisplayFormat> DisplayFormats; typedef QVector<DisplayFormat> DisplayFormats;
class WatchItem : public Utils::TreeItem, public WatchData class WatchItem : public Utils::TreeItem, public WatchData