OSDN Git Service

Debugger[New CDB]: Work on QList.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Mon, 13 Dec 2010 15:25:54 +0000 (16:25 +0100)
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>
Mon, 13 Dec 2010 15:30:29 +0000 (16:30 +0100)
Move container size code to container.cpp/h and known type
enumeration to separate knowntype.h.
Add some more types. Change type detection to work without
'class '/'struct ' prefixes for inner types. Add Qt types with
Movable/Primitive flags. Add QStack/QQueue, size for std::deque
and std::stack. Add infrastructure for linked-list type containers
and std::list. Implement QList specialisations depending on type.

src/libs/qtcreatorcdbext/containers.cpp
src/libs/qtcreatorcdbext/containers.h
src/libs/qtcreatorcdbext/knowntype.h [new file with mode: 0644]
src/libs/qtcreatorcdbext/qtcreatorcdbext_build.pro
src/libs/qtcreatorcdbext/stringutils.h
src/libs/qtcreatorcdbext/symbolgroup.cpp
src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
src/libs/qtcreatorcdbext/symbolgroupvalue.h

index 3df9514..ad8ae66 100644 (file)
 #include "symbolgroup.h"
 #include "stringutils.h"
 
+#include <functional>
+
 typedef SymbolGroupNode::SymbolGroupNodePtrVector SymbolGroupNodePtrVector;
 
+// 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;
+}
+
+// Determine size of containers
+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_QLinkedList:
+    case KT_QHash:
+    case KT_QMap:
+    case KT_QVector:
+        if (const SymbolGroupValue sizeV = v["d"]["size"])
+            return sizeV.intValue();
+        break;
+    case KT_QQueue:
+        if (const SymbolGroupValue qList= v[unsigned(0)])
+            return containerSize(KT_QList, qList);
+        break;
+    case KT_QStack:
+        if (const SymbolGroupValue qVector = v[unsigned(0)])
+            return containerSize(KT_QVector, qVector);
+        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_StdDeque:
+        if (const SymbolGroupValue sizeV =  v[unsigned(0)]["_Mysize"])
+            return sizeV.intValue();
+        break;
+    case KT_StdStack:
+        if (const SymbolGroupValue deque =  v[unsigned(0)])
+            return containerSize(KT_StdDeque, deque);
+        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;
+}
+
+/* Generate a list of children by invoking the functions to obtain the value
+ * and the next link */
+template <class ValueFunction, class NextFunction>
+SymbolGroupNodePtrVector linkedListChildList(SymbolGroupValue headNode,
+                                             int count,
+                                             ValueFunction valueFunc,
+                                             NextFunction nextFunc)
+{
+    SymbolGroupNodePtrVector rc;
+    rc.reserve(count);
+    for (int i =0; i < count && headNode; i++) {
+        if (const SymbolGroupValue value = valueFunc(headNode)) {
+            rc.push_back(value.node());
+            headNode = nextFunc(headNode);
+        } else {
+            break;
+        }
+    }
+    return rc;
+}
+
+// Helper function for linkedListChildList that returns a member by name
+class MemberByName : public std::unary_function<const SymbolGroupValue &, SymbolGroupValue> {
+public:
+    explicit MemberByName(const char *name) : m_name(name) {}
+    SymbolGroupValue operator()(const SymbolGroupValue &v) { return v[m_name]; }
+
+private:
+    const char *m_name;
+};
+
+// std::list<T>: Dummy head node and then a linked list of "_Next", "_Myval".
+static inline SymbolGroupNodePtrVector stdListChildList(SymbolGroupNode *n, int count,
+                                                        const SymbolGroupValueContext &ctx)
+{
+    if (count)
+        if (const SymbolGroupValue head = SymbolGroupValue(n, ctx)[unsigned(0)][unsigned(0)]["_Myhead"]["_Next"])
+            return linkedListChildList(head, count, MemberByName("_Myval"), MemberByName("_Next"));
+    return SymbolGroupNodePtrVector();
+}
+
+// QLinkedList<T>: Dummy head node and then a linked list of "n", "t".
+static inline SymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupNode *n, int count,
+                                                        const SymbolGroupValueContext &ctx)
+{
+    if (count)
+        if (const SymbolGroupValue head = SymbolGroupValue(n, ctx)["e"]["n"])
+            return linkedListChildList(head, count, MemberByName("t"), MemberByName("n"));
+    return SymbolGroupNodePtrVector();
+}
+
 /* Helper for array-type containers:
  * Add a series of "*(innertype *)0x (address + n * size)" fake child symbols. */
 static SymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, ULONG64 address,
-                                               int count, const std::string &innerType)
+                                               const std::string &innerType,
+                                               ULONG64 innerTypeSize,
+                                               int count)
 {
     SymbolGroupNodePtrVector rc;
-    const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str());
-    if (!innerTypeSize)
+    if (!count || !address || !innerTypeSize)
         return rc;
-
     std::string errorMessage;
     rc.reserve(count);
     for (int i = 0; i < count; i++, address += innerTypeSize) {
         std::ostringstream str;
-        str << "*(" << innerType << " *)" << std::showbase << std::hex << address;
+        str << "*(" << innerType;
+        if (!endsWith(innerType, '*'))
+            str << ' ';
+        str << "*)" << std::showbase << std::hex << address;
         if (SymbolGroupNode *child = sg->addSymbol(str.str(), toString(i), &errorMessage)) {
             rc.push_back(child);
         } else {
@@ -58,6 +225,16 @@ static SymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, ULONG64 address,
     return rc;
 }
 
+// Convenience overload that determines the inner size
+static inline SymbolGroupNodePtrVector arrayChildList(SymbolGroup *sg, ULONG64 address,
+                                                      const std::string &innerType,
+                                                      int count)
+{
+    if (const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str()))
+        return arrayChildList(sg, address, innerType, innerTypeSize, count);
+    return SymbolGroupNodePtrVector();
+}
+
 // std::vector<T>
 static inline SymbolGroupNodePtrVector
     stdVectorChildList(SymbolGroupNode *n, int count, const SymbolGroupValueContext &ctx)
@@ -71,8 +248,9 @@ static inline SymbolGroupNodePtrVector
             myFirst = vec["_Myfirst"]; // MSVC2008
         if (myFirst)
             if (const ULONG64 address = myFirst.pointerValue())
-                return arrayChildList(n->symbolGroup(), address, count,
-                                      SymbolGroupValue::stripPointerType(myFirst.type()));
+                return arrayChildList(n->symbolGroup(), address,
+                                      SymbolGroupValue::stripPointerType(myFirst.type()),
+                                      count);
     }
     return SymbolGroupNodePtrVector();
 }
@@ -87,28 +265,62 @@ static inline SymbolGroupNodePtrVector
         const SymbolGroupValue vec(n, ctx);
         if (const SymbolGroupValue firstElementV = vec["p"]["array"][unsigned(0)])
             if (const ULONG64 arrayAddress = firstElementV.address())
-                return arrayChildList(n->symbolGroup(), arrayAddress, count,
-                                      firstElementV.type());
+                return arrayChildList(n->symbolGroup(), arrayAddress,
+                                      firstElementV.type(), count);
     }
     return SymbolGroupNodePtrVector();
 }
 
-// QList<> of type array
+// QList<> of type array: Applicable for POD/pointer types and movable Qt types.
 static inline SymbolGroupNodePtrVector
-    qListOfArraryTypeChildren(SymbolGroup *sg, const SymbolGroupValue &v, int count)
+    qListChildList(const SymbolGroupValue &v, int count)
 {
     // QList<T>: d/array is declared as array of void *[]. Dereference first
     // element to obtain address.
-    if (count) {
-        if (const SymbolGroupValue firstElementV = v["d"]["array"][unsigned(0)])
-            if (const ULONG64 arrayAddress = firstElementV.address()) {
-                const std::vector<std::string> innerTypes = v.innerTypes();
-                if (innerTypes.size() == 1)
-                    return arrayChildList(sg, arrayAddress,
-                                          count, innerTypes.front());
-            }
-    }
-    return SymbolGroupNodePtrVector();
+    if (!count)
+        return SymbolGroupNodePtrVector();
+    const SymbolGroupValue dV = v["d"];
+    if (!dV)
+        return SymbolGroupNodePtrVector();
+    const int begin = dV["begin"].intValue();
+    if (begin < 0)
+        return SymbolGroupNodePtrVector();
+    const SymbolGroupValue firstElementV = dV["array"][unsigned(0)];
+    if (!firstElementV)
+        return SymbolGroupNodePtrVector();
+     const ULONG64 arrayAddress = firstElementV.address();
+     if (!arrayAddress)
+         return SymbolGroupNodePtrVector();
+     const std::vector<std::string> innerTypes = v.innerTypes();
+     if (innerTypes.size() != 1)
+         return SymbolGroupNodePtrVector();
+     const std::string &innerType = innerTypes.front();
+     const unsigned innerTypeSize = SymbolGroupValue::sizeOf(innerType.c_str());
+     if (!innerTypeSize)
+         return SymbolGroupNodePtrVector();
+     // QList<> is:
+     // 1) An array of 'T[]' for POD/pointer types and small, movable or primitive Qt types.
+     // 2) An array of 'T *[]' for anything else (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic)
+     // isStatic depends on QTypeInfo specializations and hardcoded flags for types.
+     if (SymbolGroupValue::isPointerType(innerType)) // Quick check: Any pointer is T[]
+         return arrayChildList(v.node()->symbolGroup(),
+                               arrayAddress + begin * innerTypeSize,
+                               innerType, innerTypeSize, count);
+     // Check condition for large||static.
+     bool isLargeOrStatic = innerTypeSize > SymbolGroupValue::pointerSize();
+     if (!isLargeOrStatic) {
+         const KnownType kt = knownType(innerType, false); // inner type, no 'class ' prefix.
+         if (kt != KT_Unknown && !(knownType(innerType, false) & (KT_Qt_PrimitiveType|KT_Qt_MovableType)))
+             isLargeOrStatic = true;
+     }
+     if (isLargeOrStatic)
+         return arrayChildList(v.node()->symbolGroup(),
+                               arrayAddress + begin * SymbolGroupValue::pointerSize(),
+                               SymbolGroupValue::addPointerType(innerType),
+                               SymbolGroupValue::pointerSize(), count);
+     return arrayChildList(v.node()->symbolGroup(),
+                           arrayAddress + begin * innerTypeSize,
+                           innerType, innerTypeSize, count);
 }
 
 SymbolGroupNodePtrVector containerChildren(SymbolGroupNode *node, int type,
@@ -123,13 +335,24 @@ SymbolGroupNodePtrVector containerChildren(SymbolGroupNode *node, int type,
         return qVectorChildList(node, size, ctx);
     case KT_StdVector:
         return stdVectorChildList(node, size, ctx);
+    case KT_QLinkedList:
+        return qLinkedListChildList(node, size, ctx);
     case KT_QList:
-        // Differentiate between array and list
+        return qListChildList(SymbolGroupValue(node, ctx), size);
+    case KT_QQueue:
+        if (const SymbolGroupValue qList = SymbolGroupValue(node, ctx)[unsigned(0)])
+            return qListChildList(qList, size);
+        break;
+    case KT_QStack:
+        if (const SymbolGroupValue qVector = SymbolGroupValue(node, ctx)[unsigned(0)])
+            return qVectorChildList(qVector.node(), size, ctx);
         break;
     case KT_QStringList:
         if (const SymbolGroupValue qList = SymbolGroupValue(node, ctx)[unsigned(0)])
-            return qListOfArraryTypeChildren(node->symbolGroup(), qList, size);
+            return qListChildList(qList, size);
         break;
+    case KT_StdList:
+        return stdListChildList(node, size , ctx);
     }
     return SymbolGroupNodePtrVector();
 }
index a488a2d..486500f 100644 (file)
 
 struct SymbolGroupValueContext;
 class SymbolGroupNode;
+class SymbolGroupValue;
 
 #include "common.h"
+#include "knowntype.h"
 
 #include <vector>
 
+// Determine size of containers
+int containerSize(KnownType kt, const SymbolGroupValue &v);
+int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx);
+
 /* Create a list of children of containers. */
 std::vector<SymbolGroupNode *> containerChildren(SymbolGroupNode *node,
                                                  int type,
diff --git a/src/libs/qtcreatorcdbext/knowntype.h b/src/libs/qtcreatorcdbext/knowntype.h
new file mode 100644 (file)
index 0000000..f70dea0
--- /dev/null
@@ -0,0 +1,156 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef KNOWNTYPE_H
+#define KNOWNTYPE_H
+
+// Helpers for detecting types
+enum KnownType
+{
+    KT_Unknown =0,
+    KT_Qt_Type = 0x10000,
+    KT_Qt_PrimitiveType = 0x20000,
+    KT_Qt_MovableType = 0x40000,
+    KT_STL_Type = 0x80000,
+    KT_ContainerType = 0x100000,
+    // Qt Basic
+    KT_QChar = KT_Qt_Type + KT_Qt_MovableType + 1,
+    KT_QByteArray = KT_Qt_Type + KT_Qt_MovableType + 2,
+    KT_QString = KT_Qt_Type + KT_Qt_MovableType + 3,
+    KT_QColor = KT_Qt_Type + 4,
+    KT_QFlags = KT_Qt_Type + 5,
+    KT_QDate = KT_Qt_Type + KT_Qt_MovableType + 6,
+    KT_QTime = KT_Qt_Type + KT_Qt_MovableType + 7,
+    KT_QPoint = KT_Qt_Type + KT_Qt_MovableType + 8,
+    KT_QPointF = KT_Qt_Type +KT_Qt_MovableType + 9,
+    KT_QSize = KT_Qt_Type + KT_Qt_MovableType + 11,
+    KT_QSizeF = KT_Qt_Type + KT_Qt_MovableType + 12,
+    KT_QLine = KT_Qt_Type + KT_Qt_MovableType + 13,
+    KT_QLineF = KT_Qt_Type + KT_Qt_MovableType + 14,
+    KT_QRect = KT_Qt_Type + KT_Qt_MovableType + 15,
+    KT_QRectF = KT_Qt_Type + KT_Qt_MovableType + 16,
+    KT_QVariant = KT_Qt_Type + KT_Qt_MovableType + 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,
+    // Various QT movable types
+    KT_QPen = KT_Qt_Type + KT_Qt_MovableType + 30,
+    KT_QUrl = KT_Qt_Type + KT_Qt_MovableType + 31,
+    KT_QIcon = KT_Qt_Type + KT_Qt_MovableType + 32,
+    KT_QBrush = KT_Qt_Type + KT_Qt_MovableType + 33,
+    KT_QImage = KT_Qt_Type + KT_Qt_MovableType + 35,
+    KT_QLocale = KT_Qt_Type + KT_Qt_MovableType + 36,
+    KT_QMatrix = KT_Qt_Type + KT_Qt_MovableType + 37,
+    KT_QRegExp = KT_Qt_Type + KT_Qt_MovableType + 38,
+    KT_QMargins = KT_Qt_Type + KT_Qt_MovableType + 39,
+    KT_QXmltem = KT_Qt_Type + KT_Qt_MovableType + 40,
+    KT_QXmlName = KT_Qt_Type + KT_Qt_MovableType + 41,
+    KT_QBitArray = KT_Qt_Type + KT_Qt_MovableType + 42,
+    KT_QDateTime = KT_Qt_Type + KT_Qt_MovableType + 43,
+    KT_QFileInfo = KT_Qt_Type + KT_Qt_MovableType + 44,
+    KT_QMetaEnum = KT_Qt_Type + KT_Qt_MovableType + 45,
+    KT_QVector2D = KT_Qt_Type + KT_Qt_MovableType + 46,
+    KT_QVector3D = KT_Qt_Type + KT_Qt_MovableType + 47,
+    KT_QVector4D = KT_Qt_Type + KT_Qt_MovableType + 48,
+    KT_QMatrix4x4 = KT_Qt_Type + KT_Qt_MovableType + 49,
+    KT_QTextBlock = KT_Qt_Type + KT_Qt_MovableType + 50,
+    KT_QTransform = KT_Qt_Type + KT_Qt_MovableType + 51,
+    KT_QBasicTimer = KT_Qt_Type + KT_Qt_MovableType + 52,
+    KT_QMetaMethod = KT_Qt_Type + KT_Qt_MovableType + 53,
+    KT_QModelIndex = KT_Qt_Type + KT_Qt_MovableType + 54,
+    KT_QQuaternion = KT_Qt_Type + KT_Qt_MovableType + 55,
+    KT_QScriptItem = KT_Qt_Type + KT_Qt_MovableType + 56,
+    KT_QKeySequence = KT_Qt_Type + KT_Qt_MovableType + 57,
+    KT_QTextFragment = KT_Qt_Type + KT_Qt_MovableType + 58,
+    KT_QTreeViewItem = KT_Qt_Type + KT_Qt_MovableType + 59,
+    KT_QMetaClassInfo = KT_Qt_Type + KT_Qt_MovableType + 60,
+    KT_QNetworkCookie = KT_Qt_Type + KT_Qt_MovableType + 61,
+    KT_QHashDummyValue = KT_Qt_Type + KT_Qt_MovableType + 62,
+    KT_QSourceLocation = KT_Qt_Type + KT_Qt_MovableType + 63,
+    KT_QNetworkProxyQuery = KT_Qt_Type + KT_Qt_MovableType + 64,
+    KT_QXmlNodeModelIndex = KT_Qt_Type + KT_Qt_MovableType + 65,
+    KT_QItemSelectionRange = KT_Qt_Type + KT_Qt_MovableType + 66,
+    KT_QPaintBufferCommand = KT_Qt_Type + KT_Qt_MovableType + 67,
+    KT_QTextHtmlParserNode = KT_Qt_Type + KT_Qt_MovableType + 68,
+    KT_QXmlStreamAttribute = KT_Qt_Type + KT_Qt_MovableType + 69,
+    KT_QTextBlock_iterator = KT_Qt_Type + KT_Qt_MovableType + 70,
+    KT_QTextFrame_iterator = KT_Qt_Type + KT_Qt_MovableType + 71,
+    KT_QPersistentModelIndex = KT_Qt_Type + KT_Qt_MovableType + 72,
+    KT_QObjectPrivate_Sender = KT_Qt_Type + KT_Qt_MovableType + 73,
+    KT_QPatternist_AtomicValue = KT_Qt_Type + KT_Qt_MovableType + 74,
+    KT_QPatternist_Cardinality = KT_Qt_Type + KT_Qt_MovableType + 75,
+    KT_QObjectPrivate_Connection = KT_Qt_Type + KT_Qt_MovableType + 76,
+    KT_QPatternist_ItemCacheCell = KT_Qt_Type + KT_Qt_MovableType + 77,
+    KT_QPatternist_ItemType_Ptr = KT_Qt_Type + KT_Qt_MovableType + 78,
+    KT_QPatternist_NamePool_Ptr = KT_Qt_Type + KT_Qt_MovableType + 79,
+    KT_QXmlStreamEntityDeclaration = KT_Qt_Type + KT_Qt_MovableType + 80,
+    KT_QPatternist_Expression_Ptr = KT_Qt_Type + KT_Qt_MovableType + 81,
+    KT_QXmlStreamNotationDeclaration = KT_Qt_Type + KT_Qt_MovableType + 82,
+    KT_QPatternist_SequenceType_Ptr = KT_Qt_Type + KT_Qt_MovableType + 83,
+    KT_QXmlStreamNamespaceDeclaration = KT_Qt_Type + KT_Qt_MovableType + 84,
+    KT_QPatternist_Item_Iterator_Ptr = KT_Qt_Type + KT_Qt_MovableType + 85,
+    KT_QPatternist_ItemSequenceCacheCell = KT_Qt_Type + KT_Qt_MovableType + 86,
+    KT_QNetworkHeadersPrivate_RawHeaderPair = KT_Qt_Type + KT_Qt_MovableType + 87,
+    KT_QPatternist_AccelTree_BasicNodeData = KT_Qt_Type + KT_Qt_MovableType + 88,
+    // Qt primitive types
+    KT_QFixed = KT_Qt_Type + KT_Qt_PrimitiveType + 90,
+    KT_QTextItem = KT_Qt_Type + KT_Qt_PrimitiveType + 91,
+    KT_QFixedSize = KT_Qt_Type + KT_Qt_PrimitiveType + 92,
+    KT_QFixedPoint = KT_Qt_Type + KT_Qt_PrimitiveType + 93,
+    KT_QScriptLine = KT_Qt_Type + KT_Qt_PrimitiveType + 94,
+    KT_QScriptAnalysis = KT_Qt_Type + KT_Qt_PrimitiveType + 95,
+    KT_QTextUndoCommand = KT_Qt_Type + KT_Qt_PrimitiveType + 96,
+    KT_QGlyphJustification = KT_Qt_Type + KT_Qt_PrimitiveType + 97,
+    KT_QPainterPath_Element = KT_Qt_Type + KT_Qt_PrimitiveType + 98,
+    // Qt Containers
+    KT_QStringList = KT_Qt_Type + KT_ContainerType + 1,
+    KT_QList = KT_Qt_Type + KT_ContainerType + 2,
+    KT_QLinkedList = KT_Qt_Type + KT_ContainerType + 3,
+    KT_QVector = KT_Qt_Type + KT_ContainerType + 4,
+    KT_QStack = KT_Qt_Type + KT_ContainerType + 5,
+    KT_QQueue = KT_Qt_Type + KT_ContainerType + 6,
+    KT_QSet = KT_Qt_Type + KT_ContainerType + 7,
+    KT_QHash = KT_Qt_Type + KT_ContainerType + 8,
+    KT_QMap = KT_Qt_Type + KT_ContainerType + 9,
+    KT_QMultiMap = KT_Qt_Type + KT_ContainerType + 10,
+    // STL
+    KT_StdString = KT_STL_Type + 1,
+    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_StdStack =  KT_STL_Type + KT_ContainerType + 3,
+    KT_StdDeque =  KT_STL_Type + KT_ContainerType + 4,
+    KT_StdSet =  KT_STL_Type + KT_ContainerType + 5,
+    KT_StdMap =  KT_STL_Type + KT_ContainerType + 6,
+    KT_StdMultiMap =  KT_STL_Type + KT_ContainerType + 7,
+};
+
+#endif // KNOWNTYPE_H
index 62fcbb0..a2cf902 100644 (file)
@@ -67,4 +67,5 @@ HEADERS += extensioncontext.h \
     outputcallback.h \
     base64.h \
     symbolgroupvalue.h \
-    containers.h
+    containers.h \
+    knowntype.h
index f041f8d..30db251 100644 (file)
@@ -73,6 +73,8 @@ std::wstring toWString(const Streamable s)
 }
 
 bool endsWith(const std::string &haystack, const char *needle);
+inline bool endsWith(const std::string &haystack, char needle)
+    { return !haystack.empty() && haystack.at(haystack.size() - 1) == needle; }
 
 // Read an integer from a string as '10' or '0xA'
 template <class Integer>
index f08b02a..427b08f 100644 (file)
@@ -756,6 +756,8 @@ std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx
 {
     if (m_flags & Uninitialized)
         return L"<not in scope>";
+    if (m_flags & SimpleDumperOk)
+        return m_dumperValue;
     if ((m_flags & SimpleDumperMask) == 0) {
         m_flags |= dumpSimpleType(this , ctx, &m_dumperValue,
                                   &m_dumperType, &m_dumperContainerSize);
index ca3544f..311ff22 100644 (file)
@@ -30,6 +30,7 @@
 #include "symbolgroupvalue.h"
 #include "symbolgroup.h"
 #include "stringutils.h"
+#include "containers.h"
 
 #include <iomanip>
 
@@ -215,9 +216,32 @@ std::string SymbolGroupValue::error() const
     return m_errorMessage;
 }
 
+bool SymbolGroupValue::isPointerType(const std::string &t)
+{
+    return endsWith(t, " *");
+}
+
+unsigned SymbolGroupValue::pointerSize()
+{
+    static unsigned ps = 0;
+    if (!ps)
+        ps = SymbolGroupValue::sizeOf("char *");
+    return ps;
+}
+
 std::string SymbolGroupValue::stripPointerType(const std::string &t)
 {
-    return endsWith(t, " *") ? t.substr(0, t.size() - 2) : t;
+    return isPointerType(t) ? t.substr(0, t.size() - 2) : t;
+}
+
+std::string SymbolGroupValue::addPointerType(const std::string &t)
+{
+    // 'char' -> 'char *' -> 'char **'
+    std::string rc = t;
+    if (!endsWith(rc, '*'))
+        rc.push_back(' ');
+    rc.push_back('*');
+    return rc;
 }
 
 std::string SymbolGroupValue::stripArrayType(const std::string &t)
@@ -344,63 +368,61 @@ static inline void formatMilliSeconds(std::wostream &str, int milliSecs)
         << '.' << std::setw(3) << milliSecs;
 }
 
+static const char stdStringTypeC[] = "std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
+static const char stdWStringTypeC[] = "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
 
-static const char stdStringTypeC[] = "class std::basic_string<char,std::char_traits<char>,std::allocator<char> >";
-static const char stdWStringTypeC[] = "class std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >";
-
-// Dump a QString.
-
-KnownType knownType(const std::string &type)
+// Determine type starting from a position (with/without 'class '/'struct ' prefix).
+static KnownType knownTypeHelper(const std::string &type, std::string::size_type pos)
 {
-    // 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 ?
-    const std::wstring::size_type templatePos = type.find('<');
-    static const std::wstring::size_type stlClassPos = 11;
-    if (!type.compare(0, stlClassPos, "class std::")) {
+    const std::wstring::size_type templatePos = type.find('<', pos);
+    static const std::wstring::size_type stlClassLen = 5;
+    if (!type.compare(pos, stlClassLen, "std::")) {
         // STL containers
+        const std::wstring::size_type hPos = pos + stlClassLen;
         if (templatePos != std::string::npos) {
-            switch (templatePos - stlClassPos) {
+            switch (templatePos - stlClassLen - pos) {
             case 3:
-                if (!type.compare(stlClassPos, 3, "set"))
+                if (!type.compare(hPos, 3, "set"))
                     return KT_StdSet;
-                if (!type.compare(stlClassPos, 3, "map"))
+                if (!type.compare(hPos, 3, "map"))
                     return KT_StdMap;
                 break;
             case 4:
-                if (!type.compare(stlClassPos, 4, "list"))
+                if (!type.compare(hPos, 4, "list"))
                     return KT_StdList;
                 break;
+            case 5:
+                if (!type.compare(hPos, 5, "stack"))
+                    return KT_StdStack;
+                if (!type.compare(hPos, 5, "deque"))
+                    return KT_StdDeque;
+                break;
             case 6:
-                if (!type.compare(stlClassPos, 6, "vector"))
+                if (!type.compare(hPos, 6, "vector"))
                     return KT_StdVector;
                 break;
             case 8:
-                if (!type.compare(stlClassPos, 8, "multimap"))
+                if (!type.compare(hPos, 8, "multimap"))
                     return KT_StdMultiMap;
                 break;
             }
         }
         // STL strings
-        if (!type.compare(0, compareLen, stdStringTypeC))
+        if (!type.compare(pos, compareLen - pos, stdStringTypeC))
             return KT_StdString;
-        if (!type.compare(0, compareLen, stdWStringTypeC))
+        if (!type.compare(pos, compareLen - pos, stdWStringTypeC))
             return KT_StdWString;
         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 lastNameSpacePos = type.rfind(':', templatePos);
     const std::wstring::size_type qPos =
-            lastNameSpacePos == std::string::npos ? type.find('Q') : lastNameSpacePos + 1;
+            lastNameSpacePos == std::string::npos ? type.find('Q', pos) : lastNameSpacePos + 1;
     if (qPos == std::string::npos || qPos >= type.size() || type.at(qPos) != 'Q')
         return KT_Unknown;
     // Qt types (templates)
@@ -421,6 +443,10 @@ KnownType knownType(const std::string &type)
         case 6:
             if (!type.compare(qPos, 6, "QFlags"))
                 return KT_QFlags;
+            if (!type.compare(qPos, 6, "QStack"))
+                return KT_QStack;
+            if (!type.compare(qPos, 6, "QQueue"))
+                return KT_QQueue;
             break;
         case 7:
             if (!type.compare(qPos, 7, "QVector"))
@@ -430,10 +456,21 @@ KnownType knownType(const std::string &type)
             if (!type.compare(qPos, 9, "QMultiMap"))
                 return KT_QMultiMap;
             break;
+        case 11:
+            if (!type.compare(qPos, 11, "QLinkedList"))
+                return KT_QLinkedList;
+            break;
         }
     }
     // Remaining non-template types
     switch (compareLen - qPos) {
+
+    case 4:
+        if (!type.compare(qPos, 4, "QPen"))
+            return KT_QPen;
+        if (!type.compare(qPos, 4, "QUrl"))
+            return KT_QUrl;
+        break;
     case 5:
         if (!type.compare(qPos, 5, "QChar"))
             return KT_QChar;
@@ -447,6 +484,8 @@ KnownType knownType(const std::string &type)
             return KT_QLine;
         if (!type.compare(qPos, 5, "QRect"))
             return KT_QRect;
+        if (!type.compare(qPos, 5, "QIcon"))
+            return KT_QIcon;
         break;
     case 6:
         if (!type.compare(qPos, 6, "QColor"))
@@ -459,6 +498,12 @@ KnownType knownType(const std::string &type)
             return KT_QLineF;
         if (!type.compare(qPos, 6, "QRectF"))
             return KT_QRectF;
+        if (!type.compare(qPos, 6, "QBrush"))
+            return KT_QBrush;
+        if (!type.compare(qPos, 6, "QImage"))
+            return KT_QImage;
+        if (!type.compare(qPos, 6, "QFixed"))
+            return KT_QFixed;
         break;
     case 7:
         if (!type.compare(qPos, 7, "QString"))
@@ -469,25 +514,207 @@ KnownType knownType(const std::string &type)
             return KT_QObject;
         if (!type.compare(qPos, 7, "QWidget"))
             return KT_QWidget;
+        if (!type.compare(qPos, 7, "QLocale"))
+            return KT_QLocale;
+        if (!type.compare(qPos, 7, "QMatrix"))
+            return KT_QMatrix;
+        if (!type.compare(qPos, 7, "QRegExp"))
+            return KT_QRegExp;
         break;
     case 8:
         if (!type.compare(qPos, 8, "QVariant"))
             return KT_QVariant;
+        if (!type.compare(qPos, 8, "QMargins"))
+            return KT_QMargins;
+        if (!type.compare(qPos, 8, "QXmlItem"))
+            return KT_QXmltem;
+        if (!type.compare(qPos, 8, "QXmlName"))
+            return KT_QXmlName;
+        break;
+    case 9:
+        if (!type.compare(qPos, 9, "QBitArray"))
+            return KT_QBitArray;
+        if (!type.compare(qPos, 9, "QDateTime"))
+            return KT_QDateTime;
+        if (!type.compare(qPos, 9, "QFileInfo"))
+            return KT_QFileInfo;
+        if (!type.compare(qPos, 9, "QMetaEnum"))
+            return KT_QMetaEnum;
+        if (!type.compare(qPos, 9, "QTextItem"))
+            return KT_QTextItem;
+        if (!type.compare(qPos, 9, "QVector2D"))
+            return KT_QVector2D;
+        if (!type.compare(qPos, 9, "QVector3D"))
+            return KT_QVector3D;
+        if (!type.compare(qPos, 9, "QVector4D"))
+            return KT_QVector4D;
         break;
     case 10:
         if (!type.compare(qPos, 10, "QAtomicInt"))
             return KT_QAtomicInt;
         if (!type.compare(qPos, 10, "QByteArray"))
             return KT_QByteArray;
+        if (!type.compare(qPos, 10, "QMatrix4x4"))
+            return KT_QMatrix4x4;
+        if (!type.compare(qPos, 10, "QTextBlock"))
+            return KT_QTextBlock;
+        if (!type.compare(qPos, 10, "QTransform"))
+            return KT_QTransform;
+        if (!type.compare(qPos, 10, "QFixedSize"))
+            return KT_QFixedSize;
         break;
     case 11:
         if (!type.compare(qPos, 11, "QStringList"))
             return KT_QStringList;
+        if (!type.compare(qPos, 11, "QBasicTimer"))
+            return KT_QBasicTimer;
+        if (!type.compare(qPos, 11, "QMetaMethod"))
+            return KT_QMetaMethod;
+        if (!type.compare(qPos, 11, "QModelIndex"))
+            return KT_QModelIndex;
+        if (!type.compare(qPos, 11, "QQuaternion"))
+            return KT_QQuaternion;
+        if (!type.compare(qPos, 11, "QScriptItem"))
+            return KT_QScriptItem;
+        if (!type.compare(qPos, 11, "QFixedPoint"))
+            return KT_QFixedPoint;
+        if (!type.compare(qPos, 11, "QScriptLine"))
+            return KT_QScriptLine;
+        break;
+    case 12:
+        if (!type.compare(qPos, 12, "QKeySequence"))
+            return KT_QKeySequence;
+        break;
+    case 13:
+        if (!type.compare(qPos, 13, "QTextFragment"))
+            return KT_QTextFragment;
+        if (!type.compare(qPos, 13, "QTreeViewItem"))
+            return KT_QTreeViewItem;
+        break;
+    case 14:
+        if (!type.compare(qPos, 14, "QMetaClassInfo"))
+            return KT_QMetaClassInfo;
+        if (!type.compare(qPos, 14, "QNetworkCookie"))
+            return KT_QNetworkCookie;
         break;
     case 15:
         if (!type.compare(qPos, 15, "QBasicAtomicInt"))
             return KT_QBasicAtomicInt;
+        if (!type.compare(qPos, 15, "QHashDummyValue"))
+            return KT_QHashDummyValue;
+        if (!type.compare(qPos, 15, "QSourceLocation"))
+            return KT_QSourceLocation;
+        if (!type.compare(qPos, 15, "QScriptAnalysis"))
+            return KT_QScriptAnalysis;
+        break;
+    case 16:
+        if (!type.compare(qPos, 16, "QTextUndoCommand"))
+            return KT_QTextUndoCommand;
+        break;
+    case 18:
+        if (!type.compare(qPos, 18, "QNetworkProxyQuery"))
+            return KT_QNetworkProxyQuery;
+        if (!type.compare(qPos, 18, "QXmlNodeModelIndex"))
+            return KT_QXmlNodeModelIndex;
+        break;
+    case 19:
+        if (!type.compare(qPos, 19, "QItemSelectionRange"))
+            return KT_QItemSelectionRange;
+        if (!type.compare(qPos, 19, "QPaintBufferCommand"))
+            return KT_QPaintBufferCommand;
+        if (!type.compare(qPos, 19, "QTextHtmlParserNode"))
+            return KT_QTextHtmlParserNode;
+        if (!type.compare(qPos, 19, "QXmlStreamAttribute"))
+            return KT_QXmlStreamAttribute;
+        if (!type.compare(qPos, 19, "QGlyphJustification"))
+            return KT_QGlyphJustification;
+        break;
+    case 20:
+        if (!type.compare(qPos, 20, "QTextBlock::iterator"))
+            return KT_QTextBlock_iterator;
+        if (!type.compare(qPos, 20, "QTextFrame::iterator"))
+            return KT_QTextFrame_iterator;
+        break;
+    case 21:
+        if (!type.compare(qPos, 21, "QPersistentModelIndex"))
+            return KT_QPersistentModelIndex;
+        if (!type.compare(qPos, 21, "QPainterPath::Element"))
+            return KT_QPainterPath_Element;
+        break;
+    case 22:
+        if (!type.compare(qPos, 22, "QObjectPrivate::Sender"))
+            return KT_QObjectPrivate_Sender;
+        break;
+    case 24:
+        if (!type.compare(qPos, 24, "QPatternist::AtomicValue"))
+            return KT_QPatternist_AtomicValue;
+        if (!type.compare(qPos, 24, "QPatternist::Cardinality"))
+            return KT_QPatternist_Cardinality;
+        break;
+    case 26:
+        if (!type.compare(qPos, 26, "QObjectPrivate::Connection"))
+            return KT_QObjectPrivate_Connection;
+        if (!type.compare(qPos, 26, "QPatternist::ItemCacheCell"))
+            return KT_QPatternist_ItemCacheCell;
+        if (!type.compare(qPos, 26, "QPatternist::ItemType::Ptr"))
+            return KT_QPatternist_ItemType_Ptr;
+        if (!type.compare(qPos, 26, "QPatternist::NamePool::Ptr"))
+            return KT_QPatternist_NamePool_Ptr;
+        break;
+    case 27:
+        if (!type.compare(qPos, 27, "QXmlStreamEntityDeclaration"))
+            return KT_QXmlStreamEntityDeclaration;
+        break;
+    case 28:
+        if (!type.compare(qPos, 28, "QPatternist::Expression::Ptr"))
+            return KT_QPatternist_Expression_Ptr;
+        break;
+    case 29:
+        if (!type.compare(qPos, 29, "QXmlStreamNotationDeclaration"))
+            return KT_QXmlStreamNotationDeclaration;
+    case 30:
+        if (!type.compare(qPos, 30, "QPatternist::SequenceType::Ptr"))
+            return KT_QPatternist_SequenceType_Ptr;
+        if (!type.compare(qPos, 30, "QXmlStreamNamespaceDeclaration"))
+            return KT_QXmlStreamNamespaceDeclaration;
+        break;
+    case 32:
+        break;
+        if (!type.compare(qPos, 32, "QPatternist::Item::Iterator::Ptr"))
+            return KT_QPatternist_Item_Iterator_Ptr;
+    case 34:
         break;
+        if (!type.compare(qPos, 34, "QPatternist::ItemSequenceCacheCell"))
+            return KT_QPatternist_ItemSequenceCacheCell;
+    case 37:
+        break;
+        if (!type.compare(qPos, 37, "QNetworkHeadersPrivate::RawHeaderPair"))
+            return KT_QNetworkHeadersPrivate_RawHeaderPair;
+        if (!type.compare(qPos, 37, "QPatternist::AccelTree::BasicNodeData"))
+            return KT_QPatternist_AccelTree_BasicNodeData;
+        break;
+    }
+    return KT_Unknown;
+}
+
+KnownType knownType(const std::string &type, bool hasClassPrefix)
+{
+    if (type.empty())
+        return KT_Unknown;
+    if (hasClassPrefix) {
+        switch (type.at(0)) { // Check 'class X' or 'struct X'
+        case 'c':
+            if (!type.compare(0, 6, "class "))
+                return knownTypeHelper(type, 6);
+            break;
+        case 's':
+            if (!type.compare(0, 7, "struct "))
+                return knownTypeHelper(type, 7);
+            break;
+        }
+    } else {
+        // No prefix, full check
+        return knownTypeHelper(type, 0);
     }
     return KT_Unknown;
 }
@@ -847,100 +1074,6 @@ 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;
index 365c245..6cdc32e 100644 (file)
@@ -31,6 +31,7 @@
 #define SYMBOLGROUPVALUE_H
 
 #include "common.h"
+#include "knowntype.h"
 
 #include <string>
 #include <vector>
@@ -72,6 +73,8 @@ public:
     std::wstring value() const;
     unsigned size() const;
 
+    SymbolGroupNode *node() const { return m_node; }
+
     int intValue(int defaultValue = -1) const;
     double floatValue(double defaultValue = -999) const;
     ULONG64 pointerValue(ULONG64 defaultValue = 0) const;
@@ -83,9 +86,14 @@ public:
 
     std::string error() const;
 
+    // Some helpers for manipulating types.
     static inline unsigned sizeOf(const char *type) { return GetTypeSize(type); }
     static std::string stripPointerType(const std::string &);
+    static std::string addPointerType(const std::string &);
     static std::string stripArrayType(const std::string &);
+    static bool isPointerType(const std::string &);
+    static unsigned pointerSize();
+
     // get the inner types: "QMap<int, double>" -> "int", "double"
     static std::vector<std::string> innerTypesOf(const std::string &t);
 
@@ -98,53 +106,12 @@ private:
     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,
-    // Qt Basic
-    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_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,
-    // 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);
+/* Helpers for detecting types reported from IDebugSymbolGroup
+ * 1) Class prefix==true is applicable to outer types obtained from
+ *    from IDebugSymbolGroup: 'class foo' or 'struct foo'.
+ * 2) Class prefix==false is for inner types of templates, etc, doing
+ *    a more expensive check:  'foo' */
+KnownType knownType(const std::string &type, bool hasClassPrefix = true);
 
 // Dump builtin simple types using SymbolGroupValue expressions,
 // returning SymbolGroupNode dumper flags.
@@ -153,8 +120,4 @@ unsigned dumpSimpleType(SymbolGroupNode  *n, const SymbolGroupValueContext &ctx,
                         int *knownType = 0,
                         int *containerSizeIn = 0);
 
-// 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