📄 gdbmacros.cpp
字号:
const char *innertype; // 'inner type' for class templates
const void *data; // pointer to raw data
bool dumpChildren; // do we want to see children?
// handling of nested templates
void setupTemplateParameters();
enum { maxTemplateParameters = 10 };
const char *templateParameters[maxTemplateParameters + 1];
int templateParametersCount;
// internal state
bool success; // are we finished?
int pos;
int extraInt[4];
};
QDumper::QDumper()
{
success = false;
pos = 0;
}
QDumper::~QDumper()
{
flush();
char buf[30];
int len = qsnprintf(buf, sizeof(buf) - 1, "%d^done\n", token);
write(buf, len);
}
void QDumper::write(const void *buf, int len)
{
::fwrite(buf, len, 1, stdout);
::fflush(stdout);
}
void QDumper::flush()
{
if (pos != 0) {
char buf[30];
int len = qsnprintf(buf, sizeof(buf) - 1, "%d#%d,", token, pos);
write(buf, len);
write(qDumpBuffer, pos);
write("\n", 1);
pos = 0;
}
}
void QDumper::setupTemplateParameters()
{
char *s = const_cast<char *>(innertype);
templateParametersCount = 1;
templateParameters[0] = s;
for (int i = 1; i != maxTemplateParameters + 1; ++i)
templateParameters[i] = 0;
while (*s) {
while (*s && *s != '@')
++s;
if (*s) {
*s = '\0';
++s;
templateParameters[templateParametersCount++] = s;
}
}
}
QDumper &QDumper::operator<<(unsigned long long c)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%llu", c);
return *this;
}
QDumper &QDumper::operator<<(unsigned long c)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%lu", c);
return *this;
}
QDumper &QDumper::operator<<(float d)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%f", d);
return *this;
}
QDumper &QDumper::operator<<(double d)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%f", d);
return *this;
}
QDumper &QDumper::operator<<(unsigned int i)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%u", i);
return *this;
}
QDumper &QDumper::operator<<(long c)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%ld", c);
return *this;
}
QDumper &QDumper::operator<<(int i)
{
checkFill();
pos += sprintf(qDumpBuffer + pos, "%d", i);
return *this;
}
QDumper &QDumper::operator<<(const void *p)
{
static char buf[100];
if (p) {
sprintf(buf, "%p", p);
// we get a '0x' prefix only on some implementations.
// if it isn't there, write it out manually.
if (buf[1] != 'x') {
put('0');
put('x');
}
*this << buf;
} else {
*this << "<null>";
}
return *this;
}
void QDumper::checkFill()
{
if (pos >= int(sizeof(qDumpBuffer)) - 100)
flush();
}
void QDumper::put(char c)
{
checkFill();
qDumpBuffer[pos++] = c;
}
void QDumper::addCommaIfNeeded()
{
if (pos == 0)
return;
char c = qDumpBuffer[pos - 1];
if (c == '}' || c == '"' || c == ']')
put(',');
}
void QDumper::putBase64Encoded(const char *buf, int n)
{
const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
"ghijklmn" "opqrstuv" "wxyz0123" "456789+/";
const char padchar = '=';
int padlen = 0;
//int tmpsize = ((n * 4) / 3) + 3;
int i = 0;
while (i < n) {
int chunk = 0;
chunk |= int(uchar(buf[i++])) << 16;
if (i == n) {
padlen = 2;
} else {
chunk |= int(uchar(buf[i++])) << 8;
if (i == n)
padlen = 1;
else
chunk |= int(uchar(buf[i++]));
}
int j = (chunk & 0x00fc0000) >> 18;
int k = (chunk & 0x0003f000) >> 12;
int l = (chunk & 0x00000fc0) >> 6;
int m = (chunk & 0x0000003f);
put(alphabet[j]);
put(alphabet[k]);
put(padlen > 1 ? padchar : alphabet[l]);
put(padlen > 0 ? padchar : alphabet[m]);
}
}
QDumper &QDumper::operator<<(const char *str)
{
if (!str)
return *this << "<null>";
while (*str)
put(*(str++));
return *this;
}
QDumper &QDumper::operator<<(const QByteArray &ba)
{
putBase64Encoded(ba.constData(), ba.size());
return *this;
}
QDumper &QDumper::operator<<(const QString &str)
{
QByteArray ba = str.toUtf8();
putBase64Encoded(ba.constData(), ba.size());
return *this;
}
void QDumper::disarm()
{
flush();
success = true;
}
void QDumper::beginHash()
{
addCommaIfNeeded();
put('{');
}
void QDumper::endHash()
{
put('}');
}
void QDumper::putEllipsis()
{
addCommaIfNeeded();
*this << "{name=\"<incomplete>\",value=\"\",type=\"" << innertype << "\"}";
}
//
// Some helpers to keep the dumper code short
//
// dump property=value pair
#undef P
#define P(dumper,name,value) \
do { \
dumper.addCommaIfNeeded(); \
dumper << (name) << "=\"" << value << "\""; \
} while (0)
// simple string property
#undef S
#define S(dumper, name, value) \
dumper.beginHash(); \
P(dumper, "name", name); \
P(dumper, "value", value); \
P(dumper, "type", NS"QString"); \
P(dumper, "numchild", "0"); \
P(dumper, "valueencoded", "1"); \
dumper.endHash();
// simple integer property
#undef I
#define I(dumper, name, value) \
dumper.beginHash(); \
P(dumper, "name", name); \
P(dumper, "value", value); \
P(dumper, "type", "int"); \
P(dumper, "numchild", "0"); \
dumper.endHash();
// simple boolean property
#undef BL
#define BL(dumper, name, value) \
dumper.beginHash(); \
P(dumper, "name", name); \
P(dumper, "value", (value ? "true" : "false")); \
P(dumper, "type", "bool"); \
P(dumper, "numchild", "0"); \
dumper.endHash();
// a single QChar
#undef QC
#define QC(dumper, name, value) \
dumper.beginHash(); \
P(dumper, "name", name); \
P(dumper, "value", QString(QLatin1String("'%1' (%2, 0x%3)")) \
.arg(value).arg(value.unicode()).arg(value.unicode(), 0, 16)); \
P(dumper, "valueencoded", "1"); \
P(dumper, "type", NS"QChar"); \
P(dumper, "numchild", "0"); \
dumper.endHash();
#undef TT
#define TT(type, value) \
"<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
static void qDumpUnknown(QDumper &d)
{
P(d, "iname", d.iname);
P(d, "addr", d.data);
P(d, "value", "<internal error>");
P(d, "type", d.outertype);
P(d, "numchild", "0");
d.disarm();
}
static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr,
const char *key = "value")
{
type = stripNamespace(type);
switch (type[1]) {
case 'l':
if (isEqual(type, "float"))
P(d, key, *(float*)addr);
return;
case 'n':
if (isEqual(type, "int"))
P(d, key, *(int*)addr);
else if (isEqual(type, "unsigned"))
P(d, key, *(unsigned int*)addr);
else if (isEqual(type, "unsigned int"))
P(d, key, *(unsigned int*)addr);
else if (isEqual(type, "unsigned long"))
P(d, key, *(unsigned long*)addr);
else if (isEqual(type, "unsigned long long"))
P(d, key, *(qulonglong*)addr);
return;
case 'o':
if (isEqual(type, "bool"))
switch (*(bool*)addr) {
case 0: P(d, key, "false"); break;
case 1: P(d, key, "true"); break;
default: P(d, key, *(bool*)addr); break;
}
else if (isEqual(type, "double"))
P(d, key, *(double*)addr);
else if (isEqual(type, "long"))
P(d, key, *(long*)addr);
else if (isEqual(type, "long long"))
P(d, key, *(qulonglong*)addr);
return;
case 'B':
if (isEqual(type, "QByteArray")) {
d << key << "encoded=\"1\",";
P(d, key, *(QByteArray*)addr);
}
return;
case 'L':
if (startsWith(type, "QList<")) {
const QListData *ldata = reinterpret_cast<const QListData*>(addr);
P(d, "value", "<" << ldata->size() << " items>");
P(d, "valuedisabled", "true");
P(d, "numchild", ldata->size());
}
return;
case 'O':
if (isEqual(type, "QObject *")) {
if (addr) {
const QObject *ob = reinterpret_cast<const QObject *>(addr);
P(d, "addr", ob);
P(d, "value", ob->objectName());
P(d, "valueencoded", "1");
P(d, "type", NS"QObject");
P(d, "displayedtype", ob->metaObject()->className());
} else {
P(d, "value", "0x0");
P(d, "type", NS"QObject *");
}
}
return;
case 'S':
if (isEqual(type, "QString")) {
d << key << "encoded=\"1\",";
P(d, key, *(QString*)addr);
}
return;
default:
return;
}
}
static void qDumpInnerValue(QDumper &d, const char *type, const void *addr)
{
P(d, "addr", addr);
P(d, "type", type);
if (!type[0])
return;
qDumpInnerValueHelper(d, type, addr);
}
static void qDumpInnerValueOrPointer(QDumper &d,
const char *type, const char *strippedtype, const void *addr)
{
if (strippedtype) {
if (deref(addr)) {
P(d, "addr", deref(addr));
P(d, "type", strippedtype);
qDumpInnerValueHelper(d, strippedtype, deref(addr));
} else {
P(d, "addr", addr);
P(d, "type", strippedtype);
P(d, "value", "<null>");
P(d, "numchild", "0");
}
} else {
P(d, "addr", addr);
P(d, "type", type);
qDumpInnerValueHelper(d, type, addr);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -