Commit 5fcc7068 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger[New CDB]: Work on QList.

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.
parent 20b6f407
......@@ -32,23 +32,190 @@
#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();
}
......@@ -32,11 +32,17 @@
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,
......
/**************************************************************************
**
** 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
......@@ -67,4 +67,5 @@ HEADERS += extensioncontext.h \
outputcallback.h \
base64.h \
symbolgroupvalue.h \
containers.h
containers.h \
knowntype.h
......@@ -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>
......
......@@ -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);
......
......@@ -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'))