forked from qt-creator/qt-creator
Make dumpers output size information.
This commit is contained in:
@@ -470,6 +470,10 @@ void QtDumperHelper::TypeData::clear()
|
||||
|
||||
// ----------------- QtDumperHelper
|
||||
QtDumperHelper::QtDumperHelper() :
|
||||
m_stdAllocatorPrefix(QLatin1String("std::allocator")),
|
||||
m_intSize(0),
|
||||
m_pointerSize(0),
|
||||
m_stdAllocatorSize(0),
|
||||
m_qtVersion(0)
|
||||
{
|
||||
}
|
||||
@@ -479,6 +483,10 @@ void QtDumperHelper::clear()
|
||||
m_nameTypeMap.clear();
|
||||
m_qtVersion = 0;
|
||||
m_qtNamespace.clear();
|
||||
m_sizeCache.clear();
|
||||
m_intSize = 0;
|
||||
m_pointerSize = 0;
|
||||
m_stdAllocatorSize = 0;
|
||||
}
|
||||
|
||||
static inline void formatQtVersion(int v, QTextStream &str)
|
||||
@@ -498,6 +506,12 @@ QString QtDumperHelper::toString(bool debug) const
|
||||
for (NameTypeMap::const_iterator it = m_nameTypeMap.constBegin(); it != cend; ++it) {
|
||||
str <<",[" << it.key() << ',' << it.value() << ']';
|
||||
}
|
||||
str << "Sizes: intsize=" << m_intSize << " pointer size=" << m_pointerSize
|
||||
<< " allocatorsize=" << m_stdAllocatorSize;
|
||||
const SizeCache::const_iterator scend = m_sizeCache.constEnd();
|
||||
for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
|
||||
str << ' ' << it.key() << '=' << it.value();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
|
||||
@@ -824,6 +838,7 @@ bool DumperParser::handleValue(const char *k, int size)
|
||||
|
||||
class QueryDumperParser : public DumperParser {
|
||||
public:
|
||||
typedef QPair<QString, int> SizeEntry;
|
||||
explicit QueryDumperParser(const char *s);
|
||||
|
||||
struct Data {
|
||||
@@ -831,20 +846,23 @@ public:
|
||||
QString qtNameSpace;
|
||||
QString qtVersion;
|
||||
QStringList types;
|
||||
QList<SizeEntry> sizes;
|
||||
};
|
||||
|
||||
inline Data data() const { return m_data; }
|
||||
|
||||
protected:
|
||||
virtual bool handleKeyword(const char *k, int size);
|
||||
virtual bool handleListStart();
|
||||
virtual bool handleListStart();
|
||||
virtual bool handleListEnd();
|
||||
virtual bool handleHashEnd();
|
||||
virtual bool handleValue(const char *k, int size);
|
||||
|
||||
private:
|
||||
enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace };
|
||||
enum Mode { None, ExpectingDumpers, ExpectingVersion, ExpectingNameSpace, ExpectingSizes };
|
||||
Mode m_mode;
|
||||
Data m_data;
|
||||
QString m_lastSizeType;
|
||||
};
|
||||
|
||||
QueryDumperParser::QueryDumperParser(const char *s) :
|
||||
@@ -854,7 +872,11 @@ QueryDumperParser::QueryDumperParser(const char *s) :
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleKeyword(const char *k, int size)
|
||||
{
|
||||
{
|
||||
if (m_mode == ExpectingSizes) {
|
||||
m_lastSizeType = QString::fromLatin1(k, size);
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "dumpers", size)) {
|
||||
m_mode = ExpectingDumpers;
|
||||
return true;
|
||||
@@ -867,6 +889,10 @@ bool QueryDumperParser::handleKeyword(const char *k, int size)
|
||||
m_mode = ExpectingNameSpace;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "sizes", size)) {
|
||||
m_mode = ExpectingSizes;
|
||||
return true;
|
||||
}
|
||||
qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData());
|
||||
return false;
|
||||
}
|
||||
@@ -882,15 +908,21 @@ bool QueryDumperParser::handleListEnd()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleHashEnd()
|
||||
{
|
||||
m_mode = None; // Size hash
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleValue(const char *k, int size)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case None:
|
||||
case None:
|
||||
return false;
|
||||
case ExpectingDumpers:
|
||||
case ExpectingDumpers:
|
||||
m_data.types.push_back(QString::fromLatin1(k, size));
|
||||
break;
|
||||
case ExpectingNameSpace:
|
||||
case ExpectingNameSpace:
|
||||
m_data.qtNameSpace = QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingVersion: // ["4","1","5"]
|
||||
@@ -898,6 +930,9 @@ bool QueryDumperParser::handleValue(const char *k, int size)
|
||||
m_data.qtVersion += QLatin1Char('.');
|
||||
m_data.qtVersion += QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingSizes:
|
||||
m_data.sizes.push_back(SizeEntry(m_lastSizeType, QString::fromLatin1(k, size).toInt()));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -905,7 +940,6 @@ bool QueryDumperParser::handleValue(const char *k, int size)
|
||||
// parse a query
|
||||
bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
||||
{
|
||||
|
||||
QueryDumperParser parser(data);
|
||||
if (!parser.run())
|
||||
return false;
|
||||
@@ -913,9 +947,39 @@ bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
||||
m_qtNamespace = parser.data().qtNameSpace;
|
||||
setQtVersion(parser.data().qtVersion);
|
||||
parseQueryTypes(parser.data().types, debugger);
|
||||
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
|
||||
addSize(se.first, se.second);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtDumperHelper::addSize(const QString &name, int size)
|
||||
{
|
||||
// Special interest cases
|
||||
do {
|
||||
if (name == QLatin1String("char*")) {
|
||||
m_pointerSize = size;
|
||||
break;
|
||||
}
|
||||
if (name == QLatin1String("int")) {
|
||||
m_intSize = size;
|
||||
break;
|
||||
}
|
||||
if (name.startsWith(m_stdAllocatorPrefix)) {
|
||||
m_stdAllocatorSize = size;
|
||||
break;
|
||||
}
|
||||
if (name == QLatin1String("std::string")) {
|
||||
m_sizeCache.insert(QLatin1String("std::basic_string<char,std::char_traits<char>,std::allocator<char>>"), size);
|
||||
break;
|
||||
}
|
||||
if (name == QLatin1String("std::wstring")) {
|
||||
m_sizeCache.insert(QLatin1String("std::basic_string<unsigned short,std::char_traits<unsignedshort>,std::allocator<unsignedshort> >"), size);
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
m_sizeCache.insert(name, size);
|
||||
}
|
||||
|
||||
QtDumperHelper::Type QtDumperHelper::type(const QString &typeName) const
|
||||
{
|
||||
const QtDumperHelper::TypeData td = typeData(typeName);
|
||||
@@ -941,9 +1005,26 @@ QtDumperHelper::TypeData QtDumperHelper::typeData(const QString &typeName) const
|
||||
return td;
|
||||
}
|
||||
|
||||
// Format an expression to have the debugger query the
|
||||
// size. Use size cache if possible
|
||||
QString QtDumperHelper::evaluationSizeofTypeExpression(const QString &typeName,
|
||||
Debugger /* debugger */) const
|
||||
{
|
||||
// Look up fixed types
|
||||
if (m_pointerSize && isPointerType(typeName))
|
||||
return QString::number(m_pointerSize);
|
||||
if (m_stdAllocatorSize && typeName.startsWith(m_stdAllocatorPrefix))
|
||||
return QString::number(m_stdAllocatorSize);
|
||||
const SizeCache::const_iterator sit = m_sizeCache.constFind(typeName);
|
||||
if (sit != m_sizeCache.constEnd())
|
||||
return QString::number(sit.value());
|
||||
// Finally have the debugger evaluate
|
||||
return sizeofTypeExpression(typeName);
|
||||
}
|
||||
|
||||
void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
const TypeData &td,
|
||||
Debugger /* debugger */,
|
||||
Debugger debugger,
|
||||
QByteArray *inBuffer,
|
||||
QStringList *extraArgsIn) const
|
||||
{
|
||||
@@ -970,7 +1051,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
// gives already most information the dumpers need
|
||||
const int count = qMin(int(maxExtraArgCount), inners.size());
|
||||
for (int i = 0; i < count; i++)
|
||||
extraArgs.push_back(sizeofTypeExpression(inners.at(i)));
|
||||
extraArgs.push_back(evaluationSizeofTypeExpression(inners.at(i), debugger));
|
||||
}
|
||||
int extraArgCount = extraArgs.size();
|
||||
// Pad with zeros
|
||||
@@ -1019,14 +1100,14 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
}
|
||||
//qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
|
||||
// << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
|
||||
extraArgs[2] = sizeofTypeExpression(nodetype);
|
||||
extraArgs[2] = evaluationSizeofTypeExpression(nodetype, debugger);
|
||||
extraArgs[3] = QLatin1String("(size_t)&(('");
|
||||
extraArgs[3] += nodetype;
|
||||
extraArgs[3] += QLatin1String("'*)0)->value");
|
||||
}
|
||||
break;
|
||||
case QMapNodeType:
|
||||
extraArgs[2] = sizeofTypeExpression(data.type);
|
||||
extraArgs[2] = evaluationSizeofTypeExpression(data.type, debugger);
|
||||
extraArgs[3] = QLatin1String("(size_t)&(('");
|
||||
extraArgs[3] += data.type;
|
||||
extraArgs[3] += QLatin1String("'*)0)->value");
|
||||
@@ -1036,7 +1117,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
if (inners.at(0) == QLatin1String("bool")) {
|
||||
outertype = QLatin1String("std::vector::bool");
|
||||
} else {
|
||||
//extraArgs[extraArgCount++] = sizeofTypeExpression(data.type);
|
||||
//extraArgs[extraArgCount++] = evaluationSizeofTypeExpression(data.type, debugger);
|
||||
//extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value";
|
||||
}
|
||||
break;
|
||||
@@ -1260,5 +1341,14 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
|
||||
return true;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d)
|
||||
{
|
||||
QDebug nsp = in.nospace();
|
||||
nsp << " type=" << d.type << " tpl=" << d.isTemplate;
|
||||
if (d.isTemplate)
|
||||
nsp << d.tmplate << '<' << d.inner << '>';
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user