forked from qt-creator/qt-creator
Debugger[New CDB]: Add SymbolGroupValue for simple dumping.
This commit is contained in:
@@ -5,6 +5,7 @@ DebugExtensionNotify
|
|||||||
pid
|
pid
|
||||||
expandlocals
|
expandlocals
|
||||||
locals
|
locals
|
||||||
|
dumplocal
|
||||||
assign
|
assign
|
||||||
threads
|
threads
|
||||||
registers
|
registers
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ SOURCES += qtcreatorcdbextension.cpp \
|
|||||||
stringutils.cpp \
|
stringutils.cpp \
|
||||||
gdbmihelpers.cpp \
|
gdbmihelpers.cpp \
|
||||||
outputcallback.cpp \
|
outputcallback.cpp \
|
||||||
base64.cpp
|
base64.cpp \
|
||||||
|
symbolgroupvalue.cpp
|
||||||
|
|
||||||
HEADERS += extensioncontext.h \
|
HEADERS += extensioncontext.h \
|
||||||
common.h \
|
common.h \
|
||||||
@@ -63,5 +64,5 @@ HEADERS += extensioncontext.h \
|
|||||||
stringutils.h \
|
stringutils.h \
|
||||||
gdbmihelpers.h \
|
gdbmihelpers.h \
|
||||||
outputcallback.h \
|
outputcallback.h \
|
||||||
base64.h
|
base64.h \
|
||||||
|
symbolgroupvalue.h
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "outputcallback.h"
|
#include "outputcallback.h"
|
||||||
#include "eventcallback.h"
|
#include "eventcallback.h"
|
||||||
#include "symbolgroup.h"
|
#include "symbolgroup.h"
|
||||||
|
#include "symbolgroupvalue.h"
|
||||||
#include "stringutils.h"
|
#include "stringutils.h"
|
||||||
#include "gdbmihelpers.h"
|
#include "gdbmihelpers.h"
|
||||||
|
|
||||||
@@ -224,6 +225,59 @@ extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extension command 'dumplocal':
|
||||||
|
// Dump a local variable using dumpers (testing command).
|
||||||
|
|
||||||
|
const char dumpLocalUsageC[] = "Usage: dumplocal <frame> <iname>";
|
||||||
|
|
||||||
|
static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int *token, std::string *errorMessage)
|
||||||
|
{
|
||||||
|
// Parse the command
|
||||||
|
StringList tokens = commandTokens<StringList>(args, token);
|
||||||
|
// Frame and iname
|
||||||
|
unsigned frame;
|
||||||
|
if (tokens.empty() || sscanf(tokens.front().c_str(), "%u", &frame) != 1) {
|
||||||
|
*errorMessage = dumpLocalUsageC;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
tokens.pop_front();
|
||||||
|
if (tokens.empty()) {
|
||||||
|
*errorMessage = dumpLocalUsageC;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
const std::string iname = tokens.front();
|
||||||
|
|
||||||
|
SymbolGroup * const symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, errorMessage);
|
||||||
|
if (!symGroup)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
SymbolGroupNode *n = symGroup->find(iname);
|
||||||
|
if (!n) {
|
||||||
|
*errorMessage = "No such iname " + iname;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
std::wstring value;
|
||||||
|
if (!dumpSimpleType(n, SymbolGroupValueContext(exc.dataSpaces()), &value)) {
|
||||||
|
*errorMessage = "Cannot dump " + iname;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return wStringToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" HRESULT CALLBACK dumplocal(CIDebugClient *client, PCSTR argsIn)
|
||||||
|
{
|
||||||
|
ExtensionCommandContext exc(client);
|
||||||
|
std::string errorMessage;
|
||||||
|
int token = 0;
|
||||||
|
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
|
||||||
|
if (value.empty()) {
|
||||||
|
ExtensionContext::instance().report('N', token, "dumplocal", errorMessage.c_str());
|
||||||
|
} else {
|
||||||
|
ExtensionContext::instance().report('R', token, "dumplocal", value.c_str());
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Extension command 'assign':
|
// Extension command 'assign':
|
||||||
// Assign locals by iname: 'assign locals.x=5'
|
// Assign locals by iname: 'assign locals.x=5'
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,15 @@ void replace(std::wstring &s, wchar_t before, wchar_t after)
|
|||||||
s[i] = after;
|
s[i] = after;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool endsWith(const std::string &haystack, const char *needle)
|
||||||
|
{
|
||||||
|
const size_t needleLen = strlen(needle);
|
||||||
|
const size_t haystackLen = haystack.size();
|
||||||
|
if (needleLen > haystackLen)
|
||||||
|
return false;
|
||||||
|
return haystack.compare(haystackLen - needleLen, needleLen, needle) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void formatGdbmiChar(std::ostream &str, wchar_t c)
|
static inline void formatGdbmiChar(std::ostream &str, wchar_t c)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -164,6 +173,18 @@ std::string wStringToString(const std::wstring &w)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring stringToWString(const std::string &w)
|
||||||
|
{
|
||||||
|
if (w.empty())
|
||||||
|
return std::wstring();
|
||||||
|
const std::wstring::size_type size = w.size();
|
||||||
|
std::wstring rc;
|
||||||
|
rc.reserve(size);
|
||||||
|
for (std::wstring::size_type i = 0; i < size; i++)
|
||||||
|
rc.push_back(w.at(i));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
// Format a map as a GDBMI hash {key="value",..}
|
// Format a map as a GDBMI hash {key="value",..}
|
||||||
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m)
|
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ std::string toString(const Streamable s)
|
|||||||
return str.str();
|
return str.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool endsWith(const std::string &haystack, const char *needle);
|
||||||
|
|
||||||
// Read an integer from a string as '10' or '0xA'
|
// Read an integer from a string as '10' or '0xA'
|
||||||
template <class Integer>
|
template <class Integer>
|
||||||
bool integerFromString(const std::string &s, Integer *v)
|
bool integerFromString(const std::string &s, Integer *v)
|
||||||
@@ -115,6 +117,7 @@ inline std::ostream &operator<<(std::ostream &str, const gdbmiWStringFormat &wsf
|
|||||||
|
|
||||||
std::string wStringToGdbmiString(const std::wstring &w);
|
std::string wStringToGdbmiString(const std::wstring &w);
|
||||||
std::string wStringToString(const std::wstring &w);
|
std::string wStringToString(const std::wstring &w);
|
||||||
|
std::wstring stringToWString(const std::string &w);
|
||||||
|
|
||||||
// Format a map as a GDBMI hash {key="value",..}
|
// Format a map as a GDBMI hash {key="value",..}
|
||||||
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &);
|
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &);
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ static bool isSevenBitClean(const wchar_t *buf, ULONG size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SymbolGroupNode::getType() const
|
std::string SymbolGroupNode::type() const
|
||||||
{
|
{
|
||||||
static char buf[BufSize];
|
static char buf[BufSize];
|
||||||
const HRESULT hr = m_symbolGroup->debugSymbolGroup()->GetSymbolTypeName(m_index, buf, BufSize, NULL);
|
const HRESULT hr = m_symbolGroup->debugSymbolGroup()->GetSymbolTypeName(m_index, buf, BufSize, NULL);
|
||||||
@@ -509,7 +509,7 @@ std::wstring SymbolGroupNode::rawValue() const
|
|||||||
std::wstring SymbolGroupNode::fixedValue() const
|
std::wstring SymbolGroupNode::fixedValue() const
|
||||||
{
|
{
|
||||||
std::wstring value = rawValue();
|
std::wstring value = rawValue();
|
||||||
fixValue(getType(), &value);
|
fixValue(type(), &value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +518,15 @@ SymbolGroupNode *SymbolGroupNode::childAt(unsigned i) const
|
|||||||
return i < m_children.size() ? m_children.at(i) : static_cast<SymbolGroupNode *>(0);
|
return i < m_children.size() ? m_children.at(i) : static_cast<SymbolGroupNode *>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolGroupNode *SymbolGroupNode::childByIName(const char *n) const
|
||||||
|
{
|
||||||
|
const SymbolGroupNodePtrVector::const_iterator childrenEnd = m_children.end();
|
||||||
|
for (SymbolGroupNodePtrVector::const_iterator it = m_children.begin(); it != childrenEnd; ++it)
|
||||||
|
if ( (*it)->iName() == n )
|
||||||
|
return *it;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void indentStream(std::ostream &str, unsigned depth)
|
static inline void indentStream(std::ostream &str, unsigned depth)
|
||||||
{
|
{
|
||||||
for (unsigned d = 0; d < depth; d++)
|
for (unsigned d = 0; d < depth; d++)
|
||||||
@@ -528,7 +537,7 @@ void SymbolGroupNode::dump(std::ostream &str, unsigned child, unsigned depth,
|
|||||||
bool humanReadable) const
|
bool humanReadable) const
|
||||||
{
|
{
|
||||||
const std::string iname = fullIName();
|
const std::string iname = fullIName();
|
||||||
const std::string type = getType();
|
const std::string t = type();
|
||||||
|
|
||||||
if (child) { // Separate list of children
|
if (child) { // Separate list of children
|
||||||
str << ',';
|
str << ',';
|
||||||
@@ -539,7 +548,7 @@ void SymbolGroupNode::dump(std::ostream &str, unsigned child, unsigned depth,
|
|||||||
if (humanReadable)
|
if (humanReadable)
|
||||||
indentStream(str, depth);
|
indentStream(str, depth);
|
||||||
str << "{iname=\"" << iname << "\",exp=\"" << iname << "\",name=\"" << m_name
|
str << "{iname=\"" << iname << "\",exp=\"" << iname << "\",name=\"" << m_name
|
||||||
<< "\",type=\"" << type << '"';
|
<< "\",type=\"" << t << '"';
|
||||||
|
|
||||||
if (const ULONG64 addr = address())
|
if (const ULONG64 addr = address())
|
||||||
str << ",addr=\"" << std::hex << std::showbase << addr << std::noshowbase << std::dec
|
str << ",addr=\"" << std::hex << std::showbase << addr << std::noshowbase << std::dec
|
||||||
@@ -559,7 +568,7 @@ void SymbolGroupNode::dump(std::ostream &str, unsigned child, unsigned depth,
|
|||||||
// ASCII or base64?
|
// ASCII or base64?
|
||||||
if (isSevenBitClean(wbuf, valueSize)) {
|
if (isSevenBitClean(wbuf, valueSize)) {
|
||||||
std::wstring value = wbuf;
|
std::wstring value = wbuf;
|
||||||
fixValue(type, &value);
|
fixValue(t, &value);
|
||||||
str << ",valueencoded=\"0\",value=\"" << gdbmiWStringFormat(value) << '"';
|
str << ",valueencoded=\"0\",value=\"" << gdbmiWStringFormat(value) << '"';
|
||||||
} else {
|
} else {
|
||||||
str << ",valueencoded=\"2\",value=\"";
|
str << ",valueencoded=\"2\",value=\"";
|
||||||
@@ -625,7 +634,7 @@ void SymbolGroupNode::debug(std::ostream &str, unsigned verbosity, unsigned dept
|
|||||||
str << " node-flags=" << m_flags;
|
str << " node-flags=" << m_flags;
|
||||||
if (verbosity) {
|
if (verbosity) {
|
||||||
str << ",name=\"" << m_name << "\", Address=0x" << std::hex << address() << std::dec
|
str << ",name=\"" << m_name << "\", Address=0x" << std::hex << address() << std::dec
|
||||||
<< " Type=\"" << getType() << '"';
|
<< " Type=\"" << type() << '"';
|
||||||
if (!(m_flags & Uninitialized))
|
if (!(m_flags & Uninitialized))
|
||||||
str << "\" Value=\"" << gdbmiWStringFormat(rawValue()) << '"';
|
str << "\" Value=\"" << gdbmiWStringFormat(rawValue()) << '"';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ public:
|
|||||||
|
|
||||||
const SymbolGroupNodePtrVector &children() const { return m_children; }
|
const SymbolGroupNodePtrVector &children() const { return m_children; }
|
||||||
SymbolGroupNode *childAt(unsigned) const;
|
SymbolGroupNode *childAt(unsigned) const;
|
||||||
|
SymbolGroupNode *childByIName(const char *) const;
|
||||||
|
|
||||||
const SymbolGroupNode *parent() const { return m_parent; }
|
const SymbolGroupNode *parent() const { return m_parent; }
|
||||||
|
|
||||||
// I/O: Gdbmi dump for Visitors
|
// I/O: Gdbmi dump for Visitors
|
||||||
@@ -86,6 +88,7 @@ public:
|
|||||||
|
|
||||||
std::wstring rawValue() const;
|
std::wstring rawValue() const;
|
||||||
std::wstring fixedValue() const;
|
std::wstring fixedValue() const;
|
||||||
|
std::string type() const;
|
||||||
ULONG64 address() const;
|
ULONG64 address() const;
|
||||||
|
|
||||||
bool accept(SymbolGroupNodeVisitor &visitor, unsigned child, unsigned depth) const;
|
bool accept(SymbolGroupNodeVisitor &visitor, unsigned child, unsigned depth) const;
|
||||||
@@ -101,7 +104,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
// Return allocated wide string array of value
|
// Return allocated wide string array of value
|
||||||
wchar_t *getValue(ULONG *obtainedSize = 0) const;
|
wchar_t *getValue(ULONG *obtainedSize = 0) const;
|
||||||
std::string getType() const;
|
|
||||||
bool isArrayElement() const;
|
bool isArrayElement() const;
|
||||||
// Notify about expansion of a node, shift indexes
|
// Notify about expansion of a node, shift indexes
|
||||||
bool notifyExpanded(ULONG index, ULONG insertedCount);
|
bool notifyExpanded(ULONG index, ULONG insertedCount);
|
||||||
@@ -174,6 +176,7 @@ public:
|
|||||||
ULONG threadId() const { return m_threadId; }
|
ULONG threadId() const { return m_threadId; }
|
||||||
SymbolGroupNode *root() { return m_root; }
|
SymbolGroupNode *root() { return m_root; }
|
||||||
const SymbolGroupNode *root() const { return m_root; }
|
const SymbolGroupNode *root() const { return m_root; }
|
||||||
|
SymbolGroupNode *find(const std::string &iname) const;
|
||||||
|
|
||||||
// Expand a node list "locals.i1,locals.i2", expanding all nested child nodes
|
// Expand a node list "locals.i1,locals.i2", expanding all nested child nodes
|
||||||
// (think mkdir -p).
|
// (think mkdir -p).
|
||||||
@@ -201,7 +204,6 @@ public:
|
|||||||
std::string *errorMessage);
|
std::string *errorMessage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SymbolGroupNode *find(const std::string &iname) const;
|
|
||||||
inline SymbolGroupNode *findI(const std::string &iname) const;
|
inline SymbolGroupNode *findI(const std::string &iname) const;
|
||||||
static bool getSymbolParameters(CIDebugSymbolGroup *m_symbolGroup,
|
static bool getSymbolParameters(CIDebugSymbolGroup *m_symbolGroup,
|
||||||
SymbolParameterVector *vec,
|
SymbolParameterVector *vec,
|
||||||
|
|||||||
161
src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
Normal file
161
src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "symbolgroupvalue.h"
|
||||||
|
#include "symbolgroup.h"
|
||||||
|
#include "stringutils.h"
|
||||||
|
|
||||||
|
SymbolGroupValueContext::SymbolGroupValueContext(CIDebugDataSpaces *ds)
|
||||||
|
: dataspaces(ds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolGroupValueContext::SymbolGroupValueContext() : dataspaces(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolGroupValue::SymbolGroupValue(SymbolGroupNode *node,
|
||||||
|
const SymbolGroupValueContext &ctx) :
|
||||||
|
m_node(node), m_context(ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolGroupValue::SymbolGroupValue() :
|
||||||
|
m_node(0), m_errorMessage("Invalid")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SymbolGroupValue::isValid() const
|
||||||
|
{
|
||||||
|
return m_node != 0 && m_context.dataspaces != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolGroupValue SymbolGroupValue::operator[](const char *name) const
|
||||||
|
{
|
||||||
|
if (isValid() && m_node->expand(&m_errorMessage))
|
||||||
|
if (SymbolGroupNode *child = m_node->childByIName(name))
|
||||||
|
return SymbolGroupValue(child, m_context);
|
||||||
|
return SymbolGroupValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SymbolGroupValue::type() const
|
||||||
|
{
|
||||||
|
return isValid() ? m_node->type() : std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring SymbolGroupValue::value() const
|
||||||
|
{
|
||||||
|
return isValid() ? m_node->fixedValue() : std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SymbolGroupValue::intValue(int defaultValue) const
|
||||||
|
{
|
||||||
|
if (isValid()) {
|
||||||
|
int rc = 0;
|
||||||
|
if (integerFromString(wStringToString(value()), &rc))
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG64 SymbolGroupValue::pointerValue(ULONG64 defaultValue) const
|
||||||
|
{
|
||||||
|
if (isValid()) {
|
||||||
|
ULONG64 rc = 0;
|
||||||
|
if (integerFromString(wStringToString(value()), &rc))
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return allocated array of data
|
||||||
|
unsigned char *SymbolGroupValue::pointerData(unsigned length) const
|
||||||
|
{
|
||||||
|
if (isValid()) {
|
||||||
|
if (const ULONG64 ptr = pointerValue()) {
|
||||||
|
unsigned char *data = new unsigned char[length];
|
||||||
|
std::fill(data, data + length, 0);
|
||||||
|
const HRESULT hr = m_context.dataspaces->ReadVirtual(ptr, data, length, NULL);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
delete [] data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring SymbolGroupValue::wcharPointerData(unsigned charCount, unsigned maxCharCount) const
|
||||||
|
{
|
||||||
|
const bool truncated = charCount > maxCharCount;
|
||||||
|
if (truncated)
|
||||||
|
charCount = maxCharCount;
|
||||||
|
if (const unsigned char *ucData = pointerData(charCount * sizeof(wchar_t))) {
|
||||||
|
const wchar_t *utf16Data = reinterpret_cast<const wchar_t *>(ucData);
|
||||||
|
// Be smart about terminating 0-character
|
||||||
|
if (charCount && utf16Data[charCount - 1] == 0)
|
||||||
|
charCount--;
|
||||||
|
std::wstring rc = std::wstring(utf16Data, charCount);
|
||||||
|
if (truncated)
|
||||||
|
rc += L"...";
|
||||||
|
delete [] ucData;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SymbolGroupValue::error() const
|
||||||
|
{
|
||||||
|
return m_errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump a QString.
|
||||||
|
static bool dumpQString(const SymbolGroupValue &v, std::wstring *s)
|
||||||
|
{
|
||||||
|
if (endsWith(v.type(), "QString")) {
|
||||||
|
if (SymbolGroupValue d = v["d"]) {
|
||||||
|
if (SymbolGroupValue sizeValue = d["size"]) {
|
||||||
|
const int size = sizeValue.intValue();
|
||||||
|
if (size >= 0) {
|
||||||
|
*s = d["data"].wcharPointerData(size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump builtin simple types using SymbolGroupValue expressions.
|
||||||
|
bool dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s)
|
||||||
|
{
|
||||||
|
const SymbolGroupValue v(n, ctx);
|
||||||
|
return dumpQString(v, s);
|
||||||
|
}
|
||||||
83
src/libs/qtcreatorcdbext/symbolgroupvalue.h
Normal file
83
src/libs/qtcreatorcdbext/symbolgroupvalue.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 SYMBOLGROUPVALUE_H
|
||||||
|
#define SYMBOLGROUPVALUE_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SymbolGroupNode;
|
||||||
|
|
||||||
|
// Structure to pass all IDebug interfaces used for SymbolGroupValue
|
||||||
|
struct SymbolGroupValueContext
|
||||||
|
{
|
||||||
|
SymbolGroupValueContext(CIDebugDataSpaces *ds);
|
||||||
|
SymbolGroupValueContext();
|
||||||
|
|
||||||
|
CIDebugDataSpaces *dataspaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SymbolGroupValue: Flyweight tied to a SymbolGroupNode
|
||||||
|
* providing a convenient operator[] + value getters for notation of dumpers.
|
||||||
|
* Inaccesible members return a SymbolGroupValue in state 'invalid'. */
|
||||||
|
|
||||||
|
class SymbolGroupValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SymbolGroupValue(SymbolGroupNode *node, const SymbolGroupValueContext &c);
|
||||||
|
SymbolGroupValue();
|
||||||
|
|
||||||
|
operator bool() const { return isValid(); }
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
SymbolGroupValue operator[](const char *name) const;
|
||||||
|
|
||||||
|
std::string type() const;
|
||||||
|
std::wstring value() const;
|
||||||
|
int intValue(int defaultValue = -1) const;
|
||||||
|
ULONG64 pointerValue(ULONG64 defaultValue = 0) const;
|
||||||
|
// Return allocated array of data pointed to
|
||||||
|
unsigned char *pointerData(unsigned length) const;
|
||||||
|
// Return data pointed to as wchar_t/std::wstring (UTF16)
|
||||||
|
std::wstring wcharPointerData(unsigned charCount, unsigned maxCharCount = 512) const;
|
||||||
|
|
||||||
|
std::string error() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SymbolGroupNode *m_node;
|
||||||
|
SymbolGroupValueContext m_context;
|
||||||
|
mutable std::string m_errorMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dump builtin simple types using SymbolGroupValue expressions.
|
||||||
|
bool dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx, std::wstring *s);
|
||||||
|
|
||||||
|
#endif // SYMBOLGROUPVALUE_H
|
||||||
Reference in New Issue
Block a user