From: Friedemann Kleint Date: Fri, 3 Dec 2010 15:46:20 +0000 (+0100) Subject: Debugger[New CDB]: Dump size of containers and QObject::ObjectName. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=54c5692efc0a301fb16abbf6fb6551e9eecf7ffe;p=qt-creator-jp%2Fqt-creator-jp.git Debugger[New CDB]: Dump size of containers and QObject::ObjectName. Extend type checking for container templates. Add utility function to obtain container size. --- diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 6d6caa825b..ebfe475b55 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -215,6 +215,11 @@ std::string SymbolGroupValue::error() const return m_errorMessage; } +std::string SymbolGroupValue::stripPointerType(const std::string &t) +{ + return endsWith(t, " *") ? t.substr(0, t.size() - 2) : t; +} + // -------------------- Simple dumping helpers // Courtesy of qdatetime.cpp @@ -302,20 +307,76 @@ KnownType knownType(const std::string &type) const std::wstring::size_type compareLen = endsWith(type, " *") ? type.size() -2 : type.size(); // STL ? - if (!type.compare(0, 11, "class std::")) { + const std::wstring::size_type templatePos = type.find('<'); + static const std::wstring::size_type stlClassPos = 11; + if (!type.compare(0, stlClassPos, "class std::")) { + // STL containers + if (templatePos != std::string::npos) { + switch (templatePos - stlClassPos) { + case 3: + if (!type.compare(stlClassPos, 3, "set")) + return KT_StdSet; + if (!type.compare(stlClassPos, 3, "map")) + return KT_StdMap; + break; + case 4: + if (!type.compare(stlClassPos, 4, "list")) + return KT_StdList; + break; + case 6: + if (!type.compare(stlClassPos, 6, "vector")) + return KT_StdVector; + break; + case 8: + if (!type.compare(stlClassPos, 8, "multimap")) + return KT_StdMultiMap; + break; + } + } + // STL strings 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; + } // std::sth + // Check for a 'Q' past the last namespace (beware of namespaced Qt: + // 'nsp::QString'). + const std::wstring::size_type lastNameSpacePos = type.rfind(':'); + const std::wstring::size_type qPos = + lastNameSpacePos == std::string::npos ? type.find('Q') : lastNameSpacePos + 1; + if (qPos == std::string::npos || qPos >= type.size() || type.at(qPos) != 'Q') return KT_Unknown; // Qt types (templates) - if (type.find("QFlags<") != std::wstring::npos) - return KT_QFlags; - // Remaining types: + if (templatePos != std::string::npos) { + switch (templatePos - qPos) { + case 4: + if (!type.compare(qPos, 4, "QSet")) + return KT_QSet; + if (!type.compare(qPos, 4, "QMap")) + return KT_QMap; + break; + case 5: + if (!type.compare(qPos, 5, "QHash")) + return KT_QHash; + if (!type.compare(qPos, 5, "QList")) + return KT_QList; + break; + case 6: + if (!type.compare(qPos, 6, "QFlags")) + return KT_QFlags; + break; + case 7: + if (!type.compare(qPos, 7, "QVector")) + return KT_QVector; + break; + case 9: + if (!type.compare(qPos, 9, "QMultiMap")) + return KT_QMultiMap; + break; + } + } + // Remaining non-template types switch (compareLen - qPos) { case 5: if (!type.compare(qPos, 5, "QChar")) @@ -348,6 +409,10 @@ KnownType knownType(const std::string &type) return KT_QString; if (!type.compare(qPos, 7, "QPointF")) return KT_QPointF; + if (!type.compare(qPos, 7, "QObject")) + return KT_QObject; + if (!type.compare(qPos, 7, "QWidget")) + return KT_QWidget; break; case 8: if (!type.compare(qPos, 8, "QVariant")) @@ -359,6 +424,10 @@ KnownType knownType(const std::string &type) if (!type.compare(qPos, 10, "QByteArray")) return KT_QByteArray; break; + case 11: + if (!type.compare(qPos, 11, "QStringList")) + return KT_QStringList; + break; case 15: if (!type.compare(qPos, 15, "QBasicAtomicInt")) return KT_QBasicAtomicInt; @@ -563,6 +632,18 @@ static inline bool dumpQRectF(const SymbolGroupValue &v, std::wostream &str) return true; } +// Dump the object name +static inline bool dumpQObject(const SymbolGroupValue &v, std::wostream &str) +{ + if (SymbolGroupValue oName = v["d_ptr"]["d"].pointerTypeCast("QObjectPrivate *")["objectName"]) { + str << L'"'; + dumpQString(oName, str); + str << L'"'; + return true; + } + return false; +} + // Dump a std::string. static bool dumpStd_W_String(const SymbolGroupValue &v, std::wostream &str) { @@ -710,6 +791,107 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str) return true; } +// Return size of container or -1 + +int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx) +{ + if ((kt & KT_ContainerType) == 0) + return -1; + return containerSize(kt, SymbolGroupValue(n, ctx)); +} + +// Return size from an STL vector (last/first iterators). +static inline int msvcStdVectorSize(const SymbolGroupValue &v) +{ + if (const SymbolGroupValue myFirstPtrV = v["_Myfirst"]) { + if (const SymbolGroupValue myLastPtrV = v["_Mylast"]) { + const ULONG64 firstPtr = myFirstPtrV.pointerValue(); + const ULONG64 lastPtr = myLastPtrV.pointerValue(); + if (!firstPtr || lastPtr < firstPtr) + return -1; + if (lastPtr == firstPtr) + return 0; + // Subtract the pointers: We need to do the pointer arithmetics ourselves + // as we get char *pointers. + const std::string innerType = SymbolGroupValue::stripPointerType(myFirstPtrV.type()); + const size_t size = SymbolGroupValue::sizeOf(innerType.c_str()); + if (size == 0) + return -1; + return static_cast((lastPtr - firstPtr) / size); + } + } + return -1; +} + +int containerSize(KnownType kt, const SymbolGroupValue &v) +{ + switch (kt) { + case KT_QStringList: + if (const SymbolGroupValue base = v[unsigned(0)]) + return containerSize(KT_QList, base); + break; + case KT_QList: + if (const SymbolGroupValue dV = v["d"]) { + if (const SymbolGroupValue beginV = dV["begin"]) { + const int begin = beginV.intValue(); + const int end = dV["end"].intValue(); + if (begin >= 0 && end >= begin) + return end - begin; + } + } + break; + case KT_QHash: + case KT_QMap: + case KT_QVector: + if (const SymbolGroupValue sizeV = v["d"]["size"]) + return sizeV.intValue(); + break; + case KT_QSet: + if (const SymbolGroupValue base = v[unsigned(0)]) + return containerSize(KT_QHash, base); + break; + case KT_QMultiMap: + if (const SymbolGroupValue base = v[unsigned(0)]) + return containerSize(KT_QMap, base); + break; + case KT_StdVector: { + if (const SymbolGroupValue base = v[unsigned(0)]) { + const int msvc10Size = msvcStdVectorSize(base); + if (msvc10Size >= 0) + return msvc10Size; + } + const int msvc8Size = msvcStdVectorSize(v); + if (msvc8Size >= 0) + return msvc8Size; + } + break; + case KT_StdList: + if (const SymbolGroupValue sizeV = v["_Mysize"]) // VS 8 + return sizeV.intValue(); + if (const SymbolGroupValue sizeV = v[unsigned(0)][unsigned(0)]["_Mysize"]) // VS10 + return sizeV.intValue(); + break; + case KT_StdSet: + case KT_StdMap: + case KT_StdMultiMap: + if (const SymbolGroupValue baseV = v[unsigned(0)]) { + if (const SymbolGroupValue sizeV = baseV["_Mysize"]) // VS 8 + return sizeV.intValue(); + if (const SymbolGroupValue sizeV = baseV[unsigned(0)][unsigned(0)]["_Mysize"]) // VS 10 + return sizeV.intValue(); + } + break; + } + return -1; +} + +static inline std::wstring msgContainerSize(int s) +{ + std::wostringstream str; + str << L'<' << s << L" items>"; + return str.str(); +} + // Dump builtin simple types using SymbolGroupValue expressions. unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s) { @@ -720,6 +902,15 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, return SymbolGroupNode::DumperNotApplicable; const SymbolGroupValue v(n, ctx); + // Simple dump of size for containers + if (kt & KT_ContainerType) { + const int size = containerSize(kt, v); + if (size >= 0) { + *s = msgContainerSize(size); + return SymbolGroupNode::DumperOk; + } + return SymbolGroupNode::DumperFailed; + } std::wostringstream str; unsigned rc = SymbolGroupNode::DumperNotApplicable; switch (kt) { @@ -771,6 +962,12 @@ unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, case KT_QBasicAtomicInt: rc = dumpQBasicAtomicInt(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; break; + case KT_QObject: + rc = dumpQObject(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; + case KT_QWidget: + rc = dumpQObject(v[unsigned(0)], str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; + break; case KT_StdString: case KT_StdWString: rc = dumpStd_W_String(v, str) ? SymbolGroupNode::DumperOk : SymbolGroupNode::DumperFailed; diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h index c2e4e0b5d3..107f3f89e5 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h @@ -69,7 +69,6 @@ public: 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; @@ -82,6 +81,9 @@ public: std::string error() const; + static inline unsigned sizeOf(const char *type) { return GetTypeSize(type); } + static std::string stripPointerType(const std::string &); + private: bool ensureExpanded() const; SymbolGroupValue typeCastedValue(ULONG64 address, const char *type) const; @@ -97,6 +99,7 @@ enum KnownType { KT_Qt_Type = 0x10000, KT_STL_Type = 0x20000, KT_ContainerType = 0x40000, + // Qt Basic KT_QChar = KT_Qt_Type + 1, KT_QByteArray = KT_Qt_Type + 2, KT_QString = KT_Qt_Type + 3, @@ -115,8 +118,25 @@ enum KnownType { KT_QVariant = KT_Qt_Type + 17, KT_QBasicAtomicInt = KT_Qt_Type + 18, KT_QAtomicInt = KT_Qt_Type + 19, + KT_QObject = KT_Qt_Type + 20, + KT_QWidget = KT_Qt_Type + 21, + // Qt Containers + KT_QStringList = KT_Qt_Type + KT_ContainerType + 1, + KT_QList = KT_Qt_Type + KT_ContainerType + 2, + KT_QVector = KT_Qt_Type + KT_ContainerType + 3, + KT_QSet = KT_Qt_Type + KT_ContainerType + 4, + KT_QHash = KT_Qt_Type + KT_ContainerType + 5, + KT_QMap = KT_Qt_Type + KT_ContainerType + 6, + KT_QMultiMap = KT_Qt_Type + KT_ContainerType + 7, + // STL KT_StdString = KT_STL_Type + 1, - KT_StdWString = KT_STL_Type + 2 + KT_StdWString = KT_STL_Type + 2, + // STL containers + KT_StdVector = KT_STL_Type + KT_ContainerType + 1, + KT_StdList = KT_STL_Type + KT_ContainerType + 2, + KT_StdSet = KT_STL_Type + KT_ContainerType + 3, + KT_StdMap = KT_STL_Type + KT_ContainerType + 4, + KT_StdMultiMap = KT_STL_Type + KT_ContainerType + 5, }; KnownType knownType(const std::string &type); @@ -125,4 +145,8 @@ KnownType knownType(const std::string &type); // returning SymbolGroupNode dumper flags. unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s); +// Return size of container or -1 +int containerSize(KnownType ct, const SymbolGroupValue &v); +int containerSize(KnownType ct, SymbolGroupNode *n, const SymbolGroupValueContext &ctx); + #endif // SYMBOLGROUPVALUE_H