OSDN Git Service

Debugger[New CDB]: Dump size of containers and QObject::ObjectName.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Fri, 3 Dec 2010 15:46:20 +0000 (16:46 +0100)
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>
Fri, 3 Dec 2010 15:46:20 +0000 (16:46 +0100)
Extend type checking for container templates. Add utility
function to obtain container size.

src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
src/libs/qtcreatorcdbext/symbolgroupvalue.h

index 6d6caa8..ebfe475 100644 (file)
@@ -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<int>((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;
index c2e4e0b..107f3f8 100644 (file)
@@ -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