#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 {
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)
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();
}
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,
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();
}
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,
--- /dev/null
+/**************************************************************************
+**
+** 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
outputcallback.h \
base64.h \
symbolgroupvalue.h \
- containers.h
+ containers.h \
+ knowntype.h
}
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>
{
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);
#include "symbolgroupvalue.h"
#include "symbolgroup.h"
#include "stringutils.h"
+#include "containers.h"
#include <iomanip>
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)
<< '.' << 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)
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"))
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;
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"))
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"))
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;
}
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;
#define SYMBOLGROUPVALUE_H
#include "common.h"
+#include "knowntype.h"
#include <string>
#include <vector>
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;
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);
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.
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