diff --git a/src/libs/qtcreatorcdbext/symbolgroup.cpp b/src/libs/qtcreatorcdbext/symbolgroup.cpp index e63a2102d88a8bcbe9c3bcaac5a8680259d82530..c8ec41ff8271ac7db1c3cf798561d74cca7b169d 100644 --- a/src/libs/qtcreatorcdbext/symbolgroup.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroup.cpp @@ -496,6 +496,14 @@ std::string SymbolGroupNode::type() const return SUCCEEDED(hr) ? std::string(buf) : std::string(); } +unsigned SymbolGroupNode::size() const +{ + DEBUG_SYMBOL_ENTRY entry; + if (SUCCEEDED(m_symbolGroup->debugSymbolGroup()->GetSymbolEntryInformation(m_index, &entry))) + return entry.Size; + return 0; +} + ULONG64 SymbolGroupNode::address() const { ULONG64 address = 0; @@ -654,6 +662,8 @@ void SymbolGroupNode::debug(std::ostream &str, unsigned verbosity, unsigned dept str << " DumperFailed"; if (m_flags & ExpandedByDumper) str << " ExpandedByDumper"; + if (m_flags & AdditionalSymbol) + str << " AdditionalSymbol"; str << ' '; } if (verbosity) { @@ -745,33 +755,34 @@ static inline std::string msgCannotAddSymbol(const std::string &name, const std: } // For root nodes, only: Add a new symbol by name -bool SymbolGroupNode::addSymbolByName(const std::string &name, - const std::string &iname, - std::string *errorMessage) +SymbolGroupNode *SymbolGroupNode::addSymbolByName(const std::string &name, + const std::string &iname, + std::string *errorMessage) { ULONG index = DEBUG_ANY_ID; // Append HRESULT hr = m_symbolGroup->debugSymbolGroup()->AddSymbol(name.c_str(), &index); if (FAILED(hr)) { *errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("AddSymbol", hr)); - return false; + return 0; } SymbolParameterVector parameters(1, DEBUG_SYMBOL_PARAMETERS()); hr = m_symbolGroup->debugSymbolGroup()->GetSymbolParameters(index, 1, &(*parameters.begin())); if (FAILED(hr)) { // Should never fail *errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("GetSymbolParameters", hr)); - return false; + return 0; } // Paranoia: Check for cuckoo's eggs (which should not happen) if (parameters.front().ParentSymbol != m_index) { *errorMessage = msgCannotAddSymbol(name, "Parent id mismatch"); - return false; + return 0; } SymbolGroupNode *node = new SymbolGroupNode(m_symbolGroup, index, name, iname.empty() ? name : iname, this); node->parseParameters(0, 0, parameters); + node->addFlags(AdditionalSymbol); m_children.push_back(node); - return true; + return node; } static inline std::string msgNotFound(const std::string &nodeName) @@ -919,7 +930,7 @@ bool SymbolGroup::typeCast(const std::string &iname, const std::string &desiredT return node->typeCast(desiredType, errorMessage); } -bool SymbolGroup::addSymbol(const std::string &name, const std::string &iname, std::string *errorMessage) +SymbolGroupNode *SymbolGroup::addSymbol(const std::string &name, const std::string &iname, std::string *errorMessage) { return m_root->addSymbolByName(name, iname, errorMessage); } diff --git a/src/libs/qtcreatorcdbext/symbolgroup.h b/src/libs/qtcreatorcdbext/symbolgroup.h index 8fd886045fc3fe0d6f50ed3a928b2c2cd5fea82a..03ed8cbf08b810c0b8670fc4ef8f74e30c1e0a47 100644 --- a/src/libs/qtcreatorcdbext/symbolgroup.h +++ b/src/libs/qtcreatorcdbext/symbolgroup.h @@ -67,7 +67,8 @@ public: DumperOk = 0x4, // Internal dumper ran, value set DumperFailed = 0x8, // Internal dumper failed DumperMask = DumperNotApplicable|DumperOk|DumperFailed, - ExpandedByDumper = 0x10 + ExpandedByDumper = 0x10, + AdditionalSymbol = 0x20 // Introduced by addSymbol, should not be visible }; typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector; typedef std::vector<SymbolGroupNode *> SymbolGroupNodePtrVector; @@ -83,9 +84,9 @@ public: static SymbolGroupNode *create(SymbolGroup *sg, const std::string &name, const SymbolParameterVector &vec); // For root nodes, only: Add a new symbol by name - bool addSymbolByName(const std::string &name, // Expression like 'myarray[1]' - const std::string &iname, // Desired iname, defaults to name - std::string *errorMessage); + SymbolGroupNode *addSymbolByName(const std::string &name, // Expression like 'myarray[1]' + const std::string &iname, // Desired iname, defaults to name + std::string *errorMessage); const std::string &name() const { return m_name; } std::string fullIName() const; @@ -98,6 +99,7 @@ public: SymbolGroupNode *childByIName(const char *) const; const SymbolGroupNode *parent() const { return m_parent; } + SymbolGroup *symbolGroup() const { return m_symbolGroup; } // I/O: Gdbmi dump for Visitors void dump(std::ostream &str, const SymbolGroupValueContext &ctx); @@ -109,6 +111,7 @@ public: std::wstring displayValue(const SymbolGroupValueContext &ctx); std::string type() const; + unsigned size() const; // Size of value ULONG64 address() const; bool accept(SymbolGroupNodeVisitor &visitor, unsigned child, unsigned depth); @@ -223,9 +226,9 @@ public: // Cast an (unexpanded) node bool typeCast(const std::string &iname, const std::string &desiredType, std::string *errorMessage); // Add a symbol by name expression - bool addSymbol(const std::string &name, // Expression like 'myarray[1]' - const std::string &iname, // Desired iname, defaults to name - std::string *errorMessage); + SymbolGroupNode *addSymbol(const std::string &name, // Expression like 'myarray[1]' + const std::string &iname, // Desired iname, defaults to name + std::string *errorMessage); bool accept(SymbolGroupNodeVisitor &visitor) const; diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index b800c9d2f81eda3ec9331b45868ed03cd53d42f5..6d6caa825ba85ebd7eb048860ebc6b7694a8c6b5 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -87,6 +87,11 @@ std::string SymbolGroupValue::type() const return isValid() ? m_node->type() : std::string(); } +unsigned SymbolGroupValue::size() const +{ + return isValid() ? m_node->size() : 0; +} + std::wstring SymbolGroupValue::value() const { return isValid() ? m_node->symbolGroupFixedValue() : std::wstring(); @@ -147,6 +152,45 @@ unsigned char *SymbolGroupValue::pointerData(unsigned length) const return 0; } +ULONG64 SymbolGroupValue::address() const +{ + if (isValid()) + return m_node->address(); + return 0; +} + +// Temporary iname +static inline std::string additionalSymbolIname(const SymbolGroup *g) +{ + std::ostringstream str; + str << "__additional" << g->root()->children().size(); + return str.str(); +} + +SymbolGroupValue SymbolGroupValue::typeCast(const char *type) const +{ + return typeCastedValue(address(), type); +} + +SymbolGroupValue SymbolGroupValue::pointerTypeCast(const char *type) const +{ + return typeCastedValue(pointerValue(), type); +} + +SymbolGroupValue SymbolGroupValue::typeCastedValue(ULONG64 address, const char *type) const +{ + if (address) { + SymbolGroup *sg = m_node->symbolGroup(); + std::ostringstream str; + str << '(' << type << ")(" << std::showbase << std::hex << address << ')'; + if (SymbolGroupNode *node = sg->addSymbol(str.str(), + additionalSymbolIname(sg), + &m_errorMessage)) + return SymbolGroupValue(node, m_context); + } + return SymbolGroupValue(); +} + std::wstring SymbolGroupValue::wcharPointerData(unsigned charCount, unsigned maxCharCount) const { const bool truncated = charCount > maxCharCount; @@ -215,7 +259,7 @@ static inline void getDateFromJulianDay(unsigned julianDay, int *year, int *mont } // Convert and format Julian Date as used in QDate -static inline void formatJulianDate(std::wostringstream &str, unsigned julianDate) +static inline void formatJulianDate(std::wostream &str, unsigned julianDate) { int y, m, d; getDateFromJulianDay(julianDate, &y, &m, &d); @@ -223,7 +267,7 @@ static inline void formatJulianDate(std::wostringstream &str, unsigned julianDat } // Format time in milliseconds as "hh:dd:ss:mmm" -static inline void formatMilliSeconds(std::wostringstream &str, int milliSecs) +static inline void formatMilliSeconds(std::wostream &str, int milliSecs) { const int hourFactor = 1000 * 3600; const int hours = milliSecs / hourFactor; @@ -244,49 +288,122 @@ static const char stdStringTypeC[] = "class std::basic_string<char,std::char_tra static const char stdWStringTypeC[] = "class std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"; // Dump a QString. -static unsigned dumpQString(const std::string &type, const SymbolGroupValue &v, std::wstring *s) + +KnownType knownType(const std::string &type) { - if (!endsWith(type, "QString")) // namespaced Qt? - return SymbolGroupNode::DumperNotApplicable; + // Make sure this is 'class X' or 'struct X'. Strip that and pointer + if (type.empty() || (type.at(0) != 'c' && type.at(0) != 's')) + return KT_Unknown; + const bool isClass = type.compare(0, 6, "class ") != 0; + const bool isStruct = isClass ? false : type.compare(0, 7, "struct ") != 0; + if (!isClass && !isStruct) + return KT_Unknown; + // Strip pointer types. + const std::wstring::size_type compareLen = + endsWith(type, " *") ? type.size() -2 : type.size(); + // STL ? + if (!type.compare(0, 11, "class std::")) { + if (!type.compare(0, compareLen, stdStringTypeC)) + return KT_StdString; + if (!type.compare(0, compareLen, stdWStringTypeC)) + return KT_StdWString; + } + // Check for a 'Q' (beware of namespaced Qt: 'nsp::QString'). TODO: match QQuark as well? + const std::wstring::size_type qPos = type.rfind('Q'); + if (qPos == std::wstring::npos) + return KT_Unknown; + // Qt types (templates) + if (type.find("QFlags<") != std::wstring::npos) + return KT_QFlags; + // Remaining types: + switch (compareLen - qPos) { + case 5: + if (!type.compare(qPos, 5, "QChar")) + return KT_QChar; + if (!type.compare(qPos, 5, "QDate")) + return KT_QDate; + if (!type.compare(qPos, 5, "QTime")) + return KT_QTime; + if (!type.compare(qPos, 5, "QSize")) + return KT_QSize; + if (!type.compare(qPos, 5, "QLine")) + return KT_QLine; + if (!type.compare(qPos, 5, "QRect")) + return KT_QRect; + break; + case 6: + if (!type.compare(qPos, 6, "QColor")) + return KT_QColor; + if (!type.compare(qPos, 6, "QSizeF")) + return KT_QSizeF; + if (!type.compare(qPos, 6, "QPoint")) + return KT_QPoint; + if (!type.compare(qPos, 6, "QLineF")) + return KT_QLineF; + if (!type.compare(qPos, 6, "QRectF")) + return KT_QRectF; + break; + case 7: + if (!type.compare(qPos, 7, "QString")) + return KT_QString; + if (!type.compare(qPos, 7, "QPointF")) + return KT_QPointF; + break; + case 8: + if (!type.compare(qPos, 8, "QVariant")) + return KT_QVariant; + break; + case 10: + if (!type.compare(qPos, 10, "QAtomicInt")) + return KT_QAtomicInt; + if (!type.compare(qPos, 10, "QByteArray")) + return KT_QByteArray; + break; + case 15: + if (!type.compare(qPos, 15, "QBasicAtomicInt")) + return KT_QBasicAtomicInt; + break; + } + return KT_Unknown; +} - if (SymbolGroupValue d = v["d"]) { - if (SymbolGroupValue sizeValue = d["size"]) { +static inline bool dumpQString(const SymbolGroupValue &v, std::wostream &str) +{ + if (const SymbolGroupValue d = v["d"]) { + if (const SymbolGroupValue sizeValue = d["size"]) { const int size = sizeValue.intValue(); if (size >= 0) { - *s = d["data"].wcharPointerData(size); - return SymbolGroupNode::DumperOk; + str << d["data"].wcharPointerData(size); + return true; } } } - return SymbolGroupNode::DumperFailed; + return false; } // Dump QColor -static unsigned dumpQColor(const std::string &type, const SymbolGroupValue &v, std::wstring *s) +static bool dumpQColor(const SymbolGroupValue &v, std::wostream &str) { - if (!endsWith(type, "QColor")) // namespaced Qt? - return SymbolGroupNode::DumperNotApplicable; const SymbolGroupValue specV = v["cspec"]; if (!specV) - return SymbolGroupNode::DumperFailed; + return false; const int spec = specV.intValue(); if (spec == 0) { - *s = L"<Invalid color>"; - return SymbolGroupNode::DumperOk; + str << L"<Invalid color>"; + return true; } if (spec < 1 || spec > 4) - return SymbolGroupNode::DumperFailed; + return false; const SymbolGroupValue arrayV = v["ct"]["array"]; if (!arrayV) - return SymbolGroupNode::DumperFailed; + return false; const int a0 = arrayV["0"].intValue(); const int a1 = arrayV["1"].intValue(); const int a2 = arrayV["2"].intValue(); const int a3 = arrayV["3"].intValue(); const int a4 = arrayV["4"].intValue(); if (a0 < 0 || a1 < 0 || a2 < 0 || a3 < 0 || a4 < 0) - return SymbolGroupNode::DumperFailed; - std::wostringstream str; + return false; switch (spec) { case 1: // Rgb str << L"RGB alpha=" << (a0 / 0x101) << L", red=" << (a1 / 0x101) @@ -306,94 +423,93 @@ static unsigned dumpQColor(const std::string &type, const SymbolGroupValue &v, s << L", sat=" << (a2 / 0x101) << ", lightness=" << (a3 / 0x101); break; } - *s = str.str(); - return SymbolGroupNode::DumperOk; + return true; } // Dump Qt's core types -static unsigned dumpQtCoreTypes(const std::string &type, const SymbolGroupValue &v, std::wstring *s) + +static inline bool dumpQBasicAtomicInt(const SymbolGroupValue &v, std::wostream &str) { - if (endsWith(type, "QAtomicInt")) { // namespaced Qt? - if (SymbolGroupValue iValue = v[unsigned(0)]["_q_value"]) { - *s = iValue.value(); - return SymbolGroupNode::DumperOk; - } - return SymbolGroupNode::DumperFailed; + if (const SymbolGroupValue iValue = v["_q_value"]) { + str << iValue.value(); + return true; } + return false; +} - if (endsWith(type, "QChar")) { - if (SymbolGroupValue cValue = v["ucs"]) { - const int utf16 = cValue.intValue(); - if (utf16 >= 0) { - // Print code = character, - // exclude control characters and Pair indicator - std::wostringstream str; - str << utf16; - if (utf16 >= 32 && (utf16 < 0xD800 || utf16 > 0xDBFF)) - str << " '" << wchar_t(utf16) << '\''; - *s = str.str(); - } - return SymbolGroupNode::DumperOk; +static inline bool dumpQAtomicInt(const SymbolGroupValue &v, std::wostream &str) +{ + if (const SymbolGroupValue base = v[unsigned(0)]) + return dumpQBasicAtomicInt(base, str); + return false; +} + +static bool dumpQChar(const SymbolGroupValue &v, std::wostream &str) +{ + if (SymbolGroupValue cValue = v["ucs"]) { + const int utf16 = cValue.intValue(); + if (utf16 >= 0) { + // Print code = character, + // exclude control characters and Pair indicator + str << utf16; + if (utf16 >= 32 && (utf16 < 0xD800 || utf16 > 0xDBFF)) + str << " '" << wchar_t(utf16) << '\''; } - return SymbolGroupNode::DumperFailed; + return true; } + return false; +} - if (type.find("QFlags") != std::wstring::npos) { - if (SymbolGroupValue iV = v["i"]) { - const int i = iV.intValue(); - if (i >= 0) { - *s = toWString(i); - return SymbolGroupNode::DumperOk; - } +static inline bool dumpQFlags(const SymbolGroupValue &v, std::wostream &str) +{ + if (SymbolGroupValue iV = v["i"]) { + const int i = iV.intValue(); + if (i >= 0) { + str << i; + return true; } - return SymbolGroupNode::DumperFailed; } + return false; +} - if (endsWith(type, "QDate")) { - if (SymbolGroupValue julianDayV = v["jd"]) { - const int julianDay = julianDayV.intValue(); - if (julianDay > 0) { - std::wostringstream str; - formatJulianDate(str, julianDay); - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - return SymbolGroupNode::DumperFailed; +static inline bool dumpQDate(const SymbolGroupValue &v, std::wostream &str) +{ + if (const SymbolGroupValue julianDayV = v["jd"]) { + const int julianDay = julianDayV.intValue(); + if (julianDay > 0) { + formatJulianDate(str, julianDay); + return true; } } + return false; +} - if (endsWith(type, "QTime")) { - if (SymbolGroupValue milliSecsV = v["mds"]) { - int milliSecs = milliSecsV.intValue(); - if (milliSecs >= 0) { - std::wostringstream str; - formatMilliSeconds(str, milliSecs); - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - return SymbolGroupNode::DumperFailed; +static bool dumpQTime(const SymbolGroupValue &v, std::wostream &str) +{ + if (const SymbolGroupValue milliSecsV = v["mds"]) { + const int milliSecs = milliSecsV.intValue(); + if (milliSecs >= 0) { + formatMilliSeconds(str, milliSecs); + return true; } } - - return SymbolGroupNode::DumperNotApplicable; + return false; } // Dump a QByteArray -static unsigned dumpQByteArray(const std::string &type, const SymbolGroupValue &v, std::wstring *s) +static inline bool dumpQByteArray(const SymbolGroupValue &v, std::wostream &str) { - if (!endsWith(type, "QByteArray")) // namespaced Qt? - return SymbolGroupNode::DumperNotApplicable; // TODO: More sophisticated dumping of binary data? - if (SymbolGroupValue data = v["d"]["data"]) { - *s = data.value(); - return SymbolGroupNode::DumperOk; + if (const SymbolGroupValue data = v["d"]["data"]) { + str << data.value(); + return true; } - return SymbolGroupNode::DumperFailed; + return false; } // Dump a rectangle in X11 syntax template <class T> -inline void dumpRect(std::wostringstream &str, T x, T y, T width, T height) +inline void dumpRect(std::wostream &str, T x, T y, T width, T height) { str << width << 'x' << height; if (x >= 0) @@ -405,96 +521,264 @@ inline void dumpRect(std::wostringstream &str, T x, T y, T width, T height) } template <class T> -inline void dumpRectPoints(std::wostringstream &str, T x1, T y1, T x2, T y2) +inline void dumpRectPoints(std::wostream &str, T x1, T y1, T x2, T y2) { dumpRect(str, x1, y1, (x2 - x1), (y2 - y1)); } // Dump Qt's simple geometrical types -static unsigned dumpQtGeometryTypes(const std::string &type, const SymbolGroupValue &v, std::wstring *s) +static inline bool dumpQSize_F(const SymbolGroupValue &v, std::wostream &str) { - if (endsWith(type, "QSize") || endsWith(type, "QSizeF")) { // namespaced Qt? - std::wostringstream str; - str << '(' << v["wd"].value() << ", " << v["ht"].value() << ')'; - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - if (endsWith(type, "QPoint") || endsWith(type, "QPointF")) { // namespaced Qt? - std::wostringstream str; - str << '(' << v["xp"].value() << ", " << v["yp"].value() << ')'; - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - if (endsWith(type, "QLine") || endsWith(type, "QLineF")) { // namespaced Qt? - const SymbolGroupValue p1 = v["pt1"]; - const SymbolGroupValue p2 = v["pt2"]; - if (p1 && p2) { - std::wostringstream str; - str << '(' << p1["xp"].value() << ", " << p1["yp"].value() << ") (" - << p2["xp"].value() << ", " << p2["yp"].value() << ')'; - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - return SymbolGroupNode::DumperFailed; - } - if (endsWith(type, "QRect")) { - std::wostringstream str; - dumpRectPoints(str, v["x1"].intValue(), v["y1"].intValue(), v["x2"].intValue(), v["y2"].intValue()); - *s = str.str(); - return SymbolGroupNode::DumperOk; - } - if (endsWith(type, "QRectF")) { - std::wostringstream str; - dumpRect(str, v["xp"].floatValue(), v["yp"].floatValue(), v["w"].floatValue(), v["h"].floatValue()); - *s = str.str(); - return SymbolGroupNode::DumperOk; + str << '(' << v["wd"].value() << ", " << v["ht"].value() << ')'; + return true; +} + +static inline bool dumpQPoint_F(const SymbolGroupValue &v, std::wostream &str) +{ + str << '(' << v["xp"].value() << ", " << v["yp"].value() << ')'; + return true; +} + +static inline bool dumpQLine_F(const SymbolGroupValue &v, std::wostream &str) +{ + const SymbolGroupValue p1 = v["pt1"]; + const SymbolGroupValue p2 = v["pt2"]; + if (p1 && p2) { + str << '(' << p1["xp"].value() << ", " << p1["yp"].value() << ") (" + << p2["xp"].value() << ", " << p2["yp"].value() << ')'; + return true; } - return SymbolGroupNode::DumperNotApplicable; + return false; +} + +static inline bool dumpQRect(const SymbolGroupValue &v, std::wostream &str) +{ + dumpRectPoints(str, v["x1"].intValue(), v["y1"].intValue(), v["x2"].intValue(), v["y2"].intValue()); + return true; +} + +static inline bool dumpQRectF(const SymbolGroupValue &v, std::wostream &str) +{ + dumpRect(str, v["xp"].floatValue(), v["yp"].floatValue(), v["w"].floatValue(), v["h"].floatValue()); + return true; } // Dump a std::string. -static unsigned dumpStdString(const std::string &type, const SymbolGroupValue &v, std::wstring *s) +static bool dumpStd_W_String(const SymbolGroupValue &v, std::wostream &str) { - if (type != stdStringTypeC && type != stdWStringTypeC) - return SymbolGroupNode::DumperNotApplicable; // MSVC 2010: Access Bx/_Buf in base class SymbolGroupValue buf = v[unsigned(0)]["_Bx"]["_Buf"]; if (!buf) // MSVC2008: Bx/Buf are members buf = v["_Bx"]["_Buf"]; if (buf) { - *s = buf.value(); - return SymbolGroupNode::DumperOk; + str << buf.value(); + return true; + } + return false; +} + +// QVariant employs a template for storage where anything bigger than the data union +// is pointed to by data.shared.ptr, else it is put into the data struct (pointer size) +// itself (notably Qt types consisting of a d-ptr only). +// The layout can vary between 32 /64 bit for some types: QPoint/QSize (of 2 ints) is bigger +// as a pointer only on 32 bit. + +static inline SymbolGroupValue qVariantCast(const SymbolGroupValue &variantData, const char *type) +{ + const ULONG typeSize = SymbolGroupValue::sizeOf(type); + const std::string ptrType = std::string(type) + " *"; + if (typeSize > variantData.size()) + return variantData["shared"]["ptr"].pointerTypeCast(ptrType.c_str()); + return variantData.typeCast(ptrType.c_str()); +} + +static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str) +{ + const SymbolGroupValue dV = v["d"]; + if (!dV) + return false; + const SymbolGroupValue typeV = dV["type"]; + const SymbolGroupValue dataV = dV["data"]; + if (!typeV || !dataV) + return false; + const int typeId = typeV.intValue(); + if (typeId <= 0) { + str << L"<Invalid>"; + return true; + } + switch (typeId) { + case 1: // Bool + str << L"(bool) " << dataV["b"].value(); + break; + case 2: // Int + str << L"(int) " << dataV["i"].value(); + break; + case 3: // UInt + str << L"(unsigned) " << dataV["u"].value(); + break; + case 4: // LongLong + str << L"(long long) " << dataV["ll"].value(); + break; + case 5: // LongLong + str << L"(unsigned long long) " << dataV["ull"].value(); + break; + case 6: // Double + str << L"(double) " << dataV["d"].value(); + break; + case 7: // Char + str << L"(char) " << dataV["c"].value(); + break; + case 10: // String + str << L"(QString) \""; + if (const SymbolGroupValue sv = dataV.typeCast("QString *")) { + dumpQString(sv, str); + str << L'"'; + } + break; + case 12: //ByteArray + str << L"(QByteArray) "; + if (const SymbolGroupValue sv = dataV.typeCast("QByteArray *")) + dumpQByteArray(sv, str); + break; + case 13: // BitArray + str << L"(QBitArray)"; + break; + case 14: // Date + str << L"(QDate) "; + if (const SymbolGroupValue sv = dataV.typeCast("QDate *")) + dumpQDate(sv, str); + break; + case 15: // Time + str << L"(QTime) "; + if (const SymbolGroupValue sv = dataV.typeCast("QTime *")) + dumpQTime(sv, str); + break; + case 16: // DateTime + str << L"(QDateTime)"; + break; + case 17: // Url + str << L"(QUrl)"; + break; + case 18: // Locale + str << L"(QLocale)"; + break; + case 19: // Rect: + str << L"(QRect) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QRect *")) + dumpQRect(sv, str); + break; + case 20: // RectF + str << L"(QRectF) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QRectF *")) + dumpQRectF(sv, str); + break; + case 21: // Size + // Anything bigger than the data union is a pointer, else the data union is used + str << L"(QSize) "; + if (const SymbolGroupValue sv = qVariantCast(dataV, "QSize")) + dumpQSize_F(sv, str); + break; + case 22: // SizeF + str << L"(QSizeF) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QSizeF *")) + dumpQSize_F(sv, str); + break; + case 23: // Line + str << L"(QLine) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QLine *")) + dumpQLine_F(sv, str); + break; + case 24: // LineF + str << L"(QLineF) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QLineF *")) + dumpQLine_F(sv, str); + break; + case 25: // Point + str << L"(QPoint) "; + if (const SymbolGroupValue sv = qVariantCast(dataV, "QPoint")) + dumpQPoint_F(sv, str); + break; + case 26: // PointF + str << L"(QPointF) "; + if (const SymbolGroupValue sv = dataV["shared"]["ptr"].pointerTypeCast("QPointF *")) + dumpQPoint_F(sv, str); + break; + default: + str << L"Type " << typeId; + break; } - return SymbolGroupNode::DumperFailed; + return true; } // Dump builtin simple types using SymbolGroupValue expressions. unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s) { // Check for class types and strip pointer types (references appear as pointers as well) - std::string type = n->type(); - if (type.compare(0, 6, "class ") != 0) + s->clear(); + const KnownType kt = knownType(n->type()); + if (kt == KT_Unknown) return SymbolGroupNode::DumperNotApplicable; - if (endsWith(type, " *")) - type.erase(type.size() - 2, 2); + const SymbolGroupValue v(n, ctx); - unsigned rc = dumpQString(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; - rc = dumpQByteArray(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; - rc = dumpQtCoreTypes(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; - rc = dumpStdString(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; - rc = dumpQtGeometryTypes(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; - rc = dumpQColor(type, v, s); - if (rc != SymbolGroupNode::DumperNotApplicable) - return rc; + std::wostringstream str; + unsigned rc = SymbolGroupNode::DumperNotApplicable; + switch (kt) { + case KT_QChar: + rc = dumpQChar(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QByteArray: + rc = dumpQByteArray(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QString: + rc = dumpQString(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QColor: + rc = dumpQColor(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QFlags: + rc = dumpQFlags(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QDate: + rc = dumpQDate(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QTime: + rc = dumpQTime(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QPoint: + case KT_QPointF: + rc = dumpQPoint_F(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QSize: + case KT_QSizeF: + rc = dumpQSize_F(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QLine: + case KT_QLineF: + rc = dumpQLine_F(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QRect: + rc = dumpQRect(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QRectF: + rc = dumpQRectF(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QVariant: + rc = dumpQVariant(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QAtomicInt: + rc = dumpQAtomicInt(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QBasicAtomicInt: + rc = dumpQBasicAtomicInt(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_StdString: + case KT_StdWString: + rc = dumpStd_W_String(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + default: + break; + } + if (rc == SymbolGroupNode::DumperOk) + *s = str.str(); return rc; } diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h index b581d7d91ae209b1e493b7645dabeb15990095d8..c2e4e0b5d37fe1a4595b6867c6375bc0c5180d4c 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h @@ -61,12 +61,20 @@ public: // Access children by name or index (0-based) SymbolGroupValue operator[](const char *name) const; SymbolGroupValue operator[](unsigned) const; + // take address and cast to desired (pointer) type + SymbolGroupValue typeCast(const char *type) const; + // take pointer value and cast to desired (pointer) type + SymbolGroupValue pointerTypeCast(const char *type) const; std::string type() const; std::wstring value() const; + unsigned size() const; + static inline unsigned sizeOf(const char *type) { return GetTypeSize(type); } + int intValue(int defaultValue = -1) const; double floatValue(double defaultValue = -999) const; ULONG64 pointerValue(ULONG64 defaultValue = 0) const; + ULONG64 address() const; // Return allocated array of data pointed to unsigned char *pointerData(unsigned length) const; // Return data pointed to as wchar_t/std::wstring (UTF16) @@ -76,12 +84,43 @@ public: private: bool ensureExpanded() const; + SymbolGroupValue typeCastedValue(ULONG64 address, const char *type) const; SymbolGroupNode *m_node; SymbolGroupValueContext m_context; mutable std::string m_errorMessage; }; +// Helpers for detecting types +enum KnownType { + KT_Unknown =0, + KT_Qt_Type = 0x10000, + KT_STL_Type = 0x20000, + KT_ContainerType = 0x40000, + KT_QChar = KT_Qt_Type + 1, + KT_QByteArray = KT_Qt_Type + 2, + KT_QString = KT_Qt_Type + 3, + KT_QColor = KT_Qt_Type + 4, + KT_QFlags = KT_Qt_Type + 5, + KT_QDate = KT_Qt_Type + 6, + KT_QTime = KT_Qt_Type + 7, + KT_QPoint = KT_Qt_Type + 8, + KT_QPointF = KT_Qt_Type + 9, + KT_QSize = KT_Qt_Type + 11, + KT_QSizeF = KT_Qt_Type + 12, + KT_QLine = KT_Qt_Type + 13, + KT_QLineF = KT_Qt_Type + 14, + KT_QRect = KT_Qt_Type + 15, + KT_QRectF = KT_Qt_Type + 16, + KT_QVariant = KT_Qt_Type + 17, + KT_QBasicAtomicInt = KT_Qt_Type + 18, + KT_QAtomicInt = KT_Qt_Type + 19, + KT_StdString = KT_STL_Type + 1, + KT_StdWString = KT_STL_Type + 2 +}; + +KnownType knownType(const std::string &type); + // Dump builtin simple types using SymbolGroupValue expressions, // returning SymbolGroupNode dumper flags. unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s);