1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the QtCore module of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include <qdatetime.h>
|
---|
43 | #include <qdebug.h>
|
---|
44 | #include <qdir.h>
|
---|
45 | #include <qfileinfo.h>
|
---|
46 | #include <qhash.h>
|
---|
47 | #include <qmap.h>
|
---|
48 | #include <qmetaobject.h>
|
---|
49 | #include <qobject.h>
|
---|
50 | #include <qstring.h>
|
---|
51 | #include <qvariant.h>
|
---|
52 | #include <qvector.h>
|
---|
53 |
|
---|
54 | #if !defined(Q_OS_WINCE) && !defined(QT_NO_DUMPER)
|
---|
55 |
|
---|
56 | #include <stdlib.h>
|
---|
57 | #include <stdio.h>
|
---|
58 |
|
---|
59 | #ifdef Q_OS_WIN
|
---|
60 | # include <windows.h>
|
---|
61 | #endif
|
---|
62 |
|
---|
63 | QT_BEGIN_NAMESPACE
|
---|
64 |
|
---|
65 | namespace {
|
---|
66 |
|
---|
67 | // This is used to abort evaluation of custom data dumpers in a "coordinated"
|
---|
68 | // way. Abortion will happen anyway when we try to access a non-initialized
|
---|
69 | // non-trivial object, so there is no way to prevent this from occuring at all
|
---|
70 | // conceptionally. Gdb will catch SIGSEGV and return to the calling frame.
|
---|
71 | // This is just fine provided we only _read_ memory in the custom handlers
|
---|
72 | // below.
|
---|
73 |
|
---|
74 | volatile int qProvokeSegFaultHelper;
|
---|
75 |
|
---|
76 | static void qCheckAccess(const void *d)
|
---|
77 | {
|
---|
78 | // provoke segfault when address is not readable
|
---|
79 | qProvokeSegFaultHelper = *(char*)d;
|
---|
80 | }
|
---|
81 |
|
---|
82 | static void qCheckPointer(const void *d)
|
---|
83 | {
|
---|
84 | if (!d)
|
---|
85 | return;
|
---|
86 | qProvokeSegFaultHelper = *(char*)d;
|
---|
87 | }
|
---|
88 |
|
---|
89 | static void qProvokeSegFault()
|
---|
90 | {
|
---|
91 | // provoke segfault unconditionally
|
---|
92 | qCheckAccess(0);
|
---|
93 | }
|
---|
94 |
|
---|
95 | static char qDumpInBuffer[100];
|
---|
96 | static char qDumpBuffer[1000];
|
---|
97 | #ifdef Q_OS_WIN
|
---|
98 | static char qDumpBuffer2[sizeof(qDumpBuffer) + 100];
|
---|
99 | #endif
|
---|
100 |
|
---|
101 | static char toHex(int n)
|
---|
102 | {
|
---|
103 | return n < 10 ? '0' + n : 'a' - 10 + n;
|
---|
104 | }
|
---|
105 |
|
---|
106 |
|
---|
107 | struct QDumper
|
---|
108 | {
|
---|
109 | explicit QDumper();
|
---|
110 | ~QDumper();
|
---|
111 | void flush();
|
---|
112 | QDumper &operator<<(long c);
|
---|
113 | QDumper &operator<<(int i);
|
---|
114 | QDumper &operator<<(unsigned long c);
|
---|
115 | QDumper &operator<<(unsigned int i);
|
---|
116 | QDumper &operator<<(const void *p);
|
---|
117 | void put(char c);
|
---|
118 | void addCommaIfNeeded();
|
---|
119 | void putEncoded(unsigned c);
|
---|
120 | QDumper &operator<<(const char *str);
|
---|
121 | QDumper &operator<<(const QString &str);
|
---|
122 | void disarm();
|
---|
123 |
|
---|
124 | void beginHash(); // start of data hash output
|
---|
125 | void endHash(); // start of data hash output
|
---|
126 |
|
---|
127 | // the dumper arguments
|
---|
128 | int protocolVersion; // dumper protocol version
|
---|
129 | int token; // some token to show on success
|
---|
130 | const char *outertype; // object type
|
---|
131 | const char *iname; // object name used for display
|
---|
132 | const char *exp; // object expression
|
---|
133 | const char *innertype; // 'inner type' for class templates
|
---|
134 | const void *data; // pointer to raw data
|
---|
135 | bool dumpChildren; // do we want to see children?
|
---|
136 |
|
---|
137 | // handling of nested templates
|
---|
138 | void setupTemplateParameters();
|
---|
139 | enum { maxTemplateParameters = 10 };
|
---|
140 | const char *templateParameters[maxTemplateParameters + 1];
|
---|
141 | int templateParametersCount;
|
---|
142 |
|
---|
143 | // internal state
|
---|
144 | bool success; // are we finished?
|
---|
145 | size_t pos;
|
---|
146 | };
|
---|
147 |
|
---|
148 |
|
---|
149 | QDumper::QDumper()
|
---|
150 | {
|
---|
151 | success = false;
|
---|
152 | pos = 0;
|
---|
153 | }
|
---|
154 |
|
---|
155 | QDumper::~QDumper()
|
---|
156 | {
|
---|
157 | flush();
|
---|
158 | put(0); // our end marker
|
---|
159 | #ifdef Q_OS_WIN
|
---|
160 | sprintf(qDumpBuffer2, "@@CDD/%d/done\n", token);
|
---|
161 | OutputDebugStringA(qDumpBuffer2);
|
---|
162 | #else
|
---|
163 | fprintf(stderr, "%d/done\n", token);
|
---|
164 | #endif
|
---|
165 | qDumpInBuffer[0] = 0;
|
---|
166 | }
|
---|
167 |
|
---|
168 | void QDumper::flush()
|
---|
169 | {
|
---|
170 | qDumpBuffer[pos++] = 0;
|
---|
171 | #ifdef Q_OS_WIN
|
---|
172 | sprintf(qDumpBuffer2, "@@CDD#%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
|
---|
173 | OutputDebugStringA(qDumpBuffer2);
|
---|
174 | #else
|
---|
175 | fprintf(stderr, "%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
|
---|
176 | #endif
|
---|
177 | pos = 0;
|
---|
178 | }
|
---|
179 |
|
---|
180 | void QDumper::setupTemplateParameters()
|
---|
181 | {
|
---|
182 | char *s = const_cast<char *>(innertype);
|
---|
183 |
|
---|
184 | templateParametersCount = 1;
|
---|
185 | templateParameters[0] = s;
|
---|
186 | for (int i = 1; i != maxTemplateParameters + 1; ++i)
|
---|
187 | templateParameters[i] = 0;
|
---|
188 |
|
---|
189 | while (*s) {
|
---|
190 | while (*s && *s != '@')
|
---|
191 | ++s;
|
---|
192 | if (*s) {
|
---|
193 | *s = '\0';
|
---|
194 | ++s;
|
---|
195 | templateParameters[templateParametersCount++] = s;
|
---|
196 | }
|
---|
197 | }
|
---|
198 | }
|
---|
199 |
|
---|
200 | QDumper &QDumper::operator<<(unsigned long c)
|
---|
201 | {
|
---|
202 | static char buf[100];
|
---|
203 | sprintf(buf, "%lu", c);
|
---|
204 | return (*this) << buf;
|
---|
205 | }
|
---|
206 |
|
---|
207 | QDumper &QDumper::operator<<(unsigned int i)
|
---|
208 | {
|
---|
209 | static char buf[100];
|
---|
210 | sprintf(buf, "%u", i);
|
---|
211 | return (*this) << buf;
|
---|
212 | }
|
---|
213 |
|
---|
214 | QDumper &QDumper::operator<<(long c)
|
---|
215 | {
|
---|
216 | static char buf[100];
|
---|
217 | sprintf(buf, "%ld", c);
|
---|
218 | return (*this) << buf;
|
---|
219 | }
|
---|
220 |
|
---|
221 | QDumper &QDumper::operator<<(int i)
|
---|
222 | {
|
---|
223 | static char buf[100];
|
---|
224 | sprintf(buf, "%d", i);
|
---|
225 | return (*this) << buf;
|
---|
226 | }
|
---|
227 |
|
---|
228 | QDumper &QDumper::operator<<(const void *p)
|
---|
229 | {
|
---|
230 | static char buf[100];
|
---|
231 | sprintf(buf, "%p", p);
|
---|
232 | // we get a '0x' prefix only on some implementations.
|
---|
233 | // if it isn't there, write it out manually.
|
---|
234 | if (buf[1] != 'x') {
|
---|
235 | put('0');
|
---|
236 | put('x');
|
---|
237 | }
|
---|
238 | return (*this) << buf;
|
---|
239 | }
|
---|
240 |
|
---|
241 | void QDumper::put(char c)
|
---|
242 | {
|
---|
243 | if (pos >= sizeof(qDumpBuffer) - 100)
|
---|
244 | flush();
|
---|
245 | qDumpBuffer[pos++] = c;
|
---|
246 | }
|
---|
247 |
|
---|
248 | void QDumper::addCommaIfNeeded()
|
---|
249 | {
|
---|
250 | if (pos == 0)
|
---|
251 | return;
|
---|
252 | if (qDumpBuffer[pos - 1] == '}' || qDumpBuffer[pos - 1] == '"')
|
---|
253 | put(',');
|
---|
254 | }
|
---|
255 |
|
---|
256 | void QDumper::putEncoded(unsigned c)
|
---|
257 | {
|
---|
258 | if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
|
---|
259 | put(c);
|
---|
260 | } else {
|
---|
261 | put('\\');
|
---|
262 | put('u');
|
---|
263 | put(toHex((c >> 12) & 0xf));
|
---|
264 | put(toHex((c >> 8) & 0xf));
|
---|
265 | put(toHex((c >> 4) & 0xf));
|
---|
266 | put(toHex( c & 0xf));
|
---|
267 | }
|
---|
268 | }
|
---|
269 |
|
---|
270 | QDumper &QDumper::operator<<(const char *str)
|
---|
271 | {
|
---|
272 | while (*str)
|
---|
273 | put(*(str++));
|
---|
274 | return *this;
|
---|
275 | }
|
---|
276 |
|
---|
277 | QDumper &QDumper::operator<<(const QString &str)
|
---|
278 | {
|
---|
279 | int n = str.size();
|
---|
280 | if (n < 0) {
|
---|
281 | qProvokeSegFault();
|
---|
282 | } else {
|
---|
283 | //(*this) << "[" << n << "]";
|
---|
284 | if (n > 1000000)
|
---|
285 | n = 1000000;
|
---|
286 | //put(' ');
|
---|
287 | put('\\');
|
---|
288 | put('"');
|
---|
289 | for (int i = 0; i != n; ++i)
|
---|
290 | putEncoded(str[i].unicode());
|
---|
291 | put('\\');
|
---|
292 | put('"');
|
---|
293 | if (n < str.size())
|
---|
294 | (*this) << "<incomplete string>";
|
---|
295 | }
|
---|
296 | return *this;
|
---|
297 | }
|
---|
298 |
|
---|
299 | void QDumper::disarm()
|
---|
300 | {
|
---|
301 | flush();
|
---|
302 | success = true;
|
---|
303 | }
|
---|
304 |
|
---|
305 | void QDumper::beginHash()
|
---|
306 | {
|
---|
307 | addCommaIfNeeded();
|
---|
308 | put('{');
|
---|
309 | }
|
---|
310 |
|
---|
311 | void QDumper::endHash()
|
---|
312 | {
|
---|
313 | put('}');
|
---|
314 | }
|
---|
315 |
|
---|
316 |
|
---|
317 | //
|
---|
318 | // Some helpers to keep the dumper code short
|
---|
319 | //
|
---|
320 |
|
---|
321 | // dump property=value pair
|
---|
322 | #undef P
|
---|
323 | #define P(dumper,name,value) \
|
---|
324 | do { \
|
---|
325 | dumper.addCommaIfNeeded(); \
|
---|
326 | dumper << (name) << "=\"" << value << "\""; \
|
---|
327 | } while (0)
|
---|
328 |
|
---|
329 | // simple string property
|
---|
330 | #undef S
|
---|
331 | #define S(dumper, name, value) \
|
---|
332 | dumper.beginHash(); \
|
---|
333 | P(dumper, "name", name); \
|
---|
334 | P(dumper, "value", value); \
|
---|
335 | P(dumper, "type", "QString"); \
|
---|
336 | P(dumper, "numchild", "0"); \
|
---|
337 | dumper.endHash();
|
---|
338 |
|
---|
339 | // simple integer property
|
---|
340 | #undef I
|
---|
341 | #define I(dumper, name, value) \
|
---|
342 | dumper.beginHash(); \
|
---|
343 | P(dumper, "name", name); \
|
---|
344 | P(dumper, "value", value); \
|
---|
345 | P(dumper, "type", "int"); \
|
---|
346 | P(dumper, "numchild", "0"); \
|
---|
347 | dumper.endHash();
|
---|
348 |
|
---|
349 | // simple boolean property
|
---|
350 | #undef BL
|
---|
351 | #define BL(dumper, name, value) \
|
---|
352 | dumper.beginHash(); \
|
---|
353 | P(dumper, "name", name); \
|
---|
354 | P(dumper, "value", (value ? "true" : "false")); \
|
---|
355 | P(dumper, "type", "bool"); \
|
---|
356 | P(dumper, "numchild", "0"); \
|
---|
357 | dumper.endHash();
|
---|
358 |
|
---|
359 | #undef TT
|
---|
360 | #define TT(type, value) \
|
---|
361 | "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
|
---|
362 |
|
---|
363 | static void qDumpUnknown(QDumper &d)
|
---|
364 | {
|
---|
365 | P(d, "iname", d.iname);
|
---|
366 | P(d, "addr", d.data);
|
---|
367 | P(d, "value", "<internal error>");
|
---|
368 | P(d, "type", d.outertype);
|
---|
369 | P(d, "numchild", "0");
|
---|
370 | d.disarm();
|
---|
371 | }
|
---|
372 |
|
---|
373 | static void qDumpQPropertyList(QDumper &d)
|
---|
374 | {
|
---|
375 | const QObject *ob = (const QObject *)d.data;
|
---|
376 | const QMetaObject *mo = ob->metaObject();
|
---|
377 | P(d, "iname", d.iname);
|
---|
378 | P(d, "addr", "<synthetic>");
|
---|
379 | P(d, "type", "QObject");
|
---|
380 | P(d, "numchild", mo->propertyCount());
|
---|
381 | if (d.dumpChildren) {
|
---|
382 | d << ",children=[";
|
---|
383 | for (int i = mo->propertyCount(); --i >= 0; ) {
|
---|
384 | const QMetaProperty & prop = mo->property(i);
|
---|
385 | d.beginHash();
|
---|
386 | P(d, "name", prop.name());
|
---|
387 | if (QLatin1String(prop.typeName()) == QLatin1String("QString")) {
|
---|
388 | P(d, "value", prop.read(ob).toString());
|
---|
389 | P(d, "numchild", "0");
|
---|
390 | } else if (QLatin1String(prop.typeName()) == QLatin1String("bool")) {
|
---|
391 | P(d, "value", (prop.read(ob).toBool() ? "true" : "false"));
|
---|
392 | P(d, "numchild", "0");
|
---|
393 | } else if (QLatin1String(prop.typeName()) == QLatin1String("int")) {
|
---|
394 | P(d, "value", prop.read(ob).toInt());
|
---|
395 | P(d, "numchild", "0");
|
---|
396 | } else {
|
---|
397 | P(d, "exp", "((" << mo->className() << "*)" << ob
|
---|
398 | << ")->" << prop.name() << "()");
|
---|
399 | }
|
---|
400 | P(d, "type", prop.typeName());
|
---|
401 | P(d, "numchild", "1");
|
---|
402 | d.endHash();
|
---|
403 | }
|
---|
404 | d << "]";
|
---|
405 | }
|
---|
406 | d.disarm();
|
---|
407 | }
|
---|
408 |
|
---|
409 | static void qDumpQObject(QDumper &d)
|
---|
410 | {
|
---|
411 | const QObject *ob = reinterpret_cast<const QObject *>(d.data);
|
---|
412 | P(d, "iname", d.iname);
|
---|
413 | P(d, "addr", d.data);
|
---|
414 | P(d, "value", (void*)d.data);
|
---|
415 | P(d, "type", "QObject");
|
---|
416 | P(d, "numchild", 4);
|
---|
417 | if (d.dumpChildren) {
|
---|
418 | const QMetaObject *mo = ob->metaObject();
|
---|
419 | const QObjectList &children = ob->children();
|
---|
420 | d << ",children=[";
|
---|
421 | S(d, "objectName", ob->objectName());
|
---|
422 | d.beginHash();
|
---|
423 | P(d, "name", "properties");
|
---|
424 | // FIXME: Note that when simply using '(QObject*)'
|
---|
425 | // in the cast below, Gdb/MI _sometimes misparses
|
---|
426 | // expressions further down in the tree.
|
---|
427 | P(d, "exp", "*(class QObject*)" << d.data);
|
---|
428 | P(d, "type", "QPropertyList");
|
---|
429 | P(d, "value", "<" << mo->propertyCount() << " items>");
|
---|
430 | P(d, "numchild", mo->propertyCount());
|
---|
431 | d.endHash();
|
---|
432 | d.beginHash();
|
---|
433 | P(d, "name", "children");
|
---|
434 | P(d, "exp", "((class QObject*)" << d.data << ")->children()");
|
---|
435 | P(d, "type", "QList<QObject *>");
|
---|
436 | P(d, "value", "<" << children.size() << " items>");
|
---|
437 | P(d, "numchild", children.size());
|
---|
438 | d.endHash();
|
---|
439 | d.beginHash();
|
---|
440 | P(d, "name", "parent");
|
---|
441 | P(d, "exp", "((class QObject*)" << d.data << ")->parent()");
|
---|
442 | P(d, "type", "QObject *");
|
---|
443 | P(d, "numchild", (ob->parent() ? "1" : "0"));
|
---|
444 | d.endHash();
|
---|
445 | d << "]";
|
---|
446 | }
|
---|
447 | d.disarm();
|
---|
448 | }
|
---|
449 |
|
---|
450 | static void qDumpQDir(QDumper &d)
|
---|
451 | {
|
---|
452 | const QDir &dir = *reinterpret_cast<const QDir *>(d.data);
|
---|
453 | P(d, "iname", d.iname);
|
---|
454 | P(d, "addr", d.data);
|
---|
455 | P(d, "value", dir.path());
|
---|
456 | P(d, "type", "QDir");
|
---|
457 | P(d, "numchild", "3");
|
---|
458 | if (d.dumpChildren) {
|
---|
459 | d << ",children=[";
|
---|
460 | S(d, "absolutePath", dir.absolutePath());
|
---|
461 | S(d, "canonicalPath", dir.canonicalPath());
|
---|
462 | d << "]";
|
---|
463 | }
|
---|
464 | d.disarm();
|
---|
465 | }
|
---|
466 |
|
---|
467 | static void qDumpQFileInfo(QDumper &d)
|
---|
468 | {
|
---|
469 | const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);
|
---|
470 | P(d, "iname", d.iname);
|
---|
471 | P(d, "addr", d.data);
|
---|
472 | P(d, "value", info.filePath());
|
---|
473 | P(d, "type", "QDir");
|
---|
474 | P(d, "numchild", "3");
|
---|
475 | if (d.dumpChildren) {
|
---|
476 | d << ",children=[";
|
---|
477 | S(d, "absolutePath", info.absolutePath());
|
---|
478 | S(d, "absoluteFilePath", info.absoluteFilePath());
|
---|
479 | S(d, "canonicalPath", info.canonicalPath());
|
---|
480 | S(d, "canonicalFilePath", info.canonicalFilePath());
|
---|
481 | S(d, "completeBaseName", info.completeBaseName());
|
---|
482 | S(d, "completeSuffix", info.completeSuffix());
|
---|
483 | S(d, "baseName", info.baseName());
|
---|
484 | #ifdef Q_OS_MACX
|
---|
485 | BL(d, "isBundle", info.isBundle());
|
---|
486 | S(d, "bundleName", info.bundleName());
|
---|
487 | #endif
|
---|
488 | S(d, "completeSuffix", info.completeSuffix());
|
---|
489 | S(d, "fileName", info.fileName());
|
---|
490 | S(d, "filePath", info.filePath());
|
---|
491 | S(d, "group", info.group());
|
---|
492 | S(d, "owner", info.owner());
|
---|
493 | S(d, "path", info.path());
|
---|
494 |
|
---|
495 | I(d, "groupid", (long)info.groupId());
|
---|
496 | I(d, "ownerid", (long)info.ownerId());
|
---|
497 | //QFile::Permissions permissions () const
|
---|
498 | I(d, "permissions", info.permissions());
|
---|
499 |
|
---|
500 | //QDir absoluteDir () const
|
---|
501 | //QDir dir () const
|
---|
502 |
|
---|
503 | BL(d, "caching", info.caching());
|
---|
504 | BL(d, "exists", info.exists());
|
---|
505 | BL(d, "isAbsolute", info.isAbsolute());
|
---|
506 | BL(d, "isDir", info.isDir());
|
---|
507 | BL(d, "isExecutable", info.isExecutable());
|
---|
508 | BL(d, "isFile", info.isFile());
|
---|
509 | BL(d, "isHidden", info.isHidden());
|
---|
510 | BL(d, "isReadable", info.isReadable());
|
---|
511 | BL(d, "isRelative", info.isRelative());
|
---|
512 | BL(d, "isRoot", info.isRoot());
|
---|
513 | BL(d, "isSymLink", info.isSymLink());
|
---|
514 | BL(d, "isWritable", info.isWritable());
|
---|
515 |
|
---|
516 | #ifndef QT_NO_DATESTRING
|
---|
517 | d.beginHash();
|
---|
518 | P(d, "name", "created");
|
---|
519 | P(d, "value", info.created().toString());
|
---|
520 | P(d, "exp", "((QFileInfo*)" << d.data << ")->created()");
|
---|
521 | P(d, "type", "QDateTime");
|
---|
522 | P(d, "numchild", "1");
|
---|
523 | d.endHash();
|
---|
524 |
|
---|
525 | d.beginHash();
|
---|
526 | P(d, "name", "lastModified");
|
---|
527 | P(d, "value", info.lastModified().toString());
|
---|
528 | P(d, "exp", "((QFileInfo*)" << d.data << ")->lastModified()");
|
---|
529 | P(d, "type", "QDateTime");
|
---|
530 | P(d, "numchild", "1");
|
---|
531 | d.endHash();
|
---|
532 |
|
---|
533 | d.beginHash();
|
---|
534 | P(d, "name", "lastRead");
|
---|
535 | P(d, "value", info.lastRead().toString());
|
---|
536 | P(d, "exp", "((QFileInfo*)" << d.data << ")->lastRead()");
|
---|
537 | P(d, "type", "QDateTime");
|
---|
538 | P(d, "numchild", "1");
|
---|
539 | d.endHash();
|
---|
540 | #endif
|
---|
541 |
|
---|
542 | d << "]";
|
---|
543 | }
|
---|
544 | d.disarm();
|
---|
545 | }
|
---|
546 |
|
---|
547 | static void qDumpQDateTime(QDumper &d)
|
---|
548 | {
|
---|
549 | #ifdef QT_NO_DATESTRING
|
---|
550 | qDumpUnknown(d);
|
---|
551 | #else
|
---|
552 | const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data);
|
---|
553 | P(d, "iname", d.iname);
|
---|
554 | P(d, "addr", d.data);
|
---|
555 | P(d, "value", date.toString());
|
---|
556 | P(d, "type", "QDateTime");
|
---|
557 | P(d, "numchild", "3");
|
---|
558 | if (d.dumpChildren) {
|
---|
559 | d << ",children=[";
|
---|
560 | BL(d, "isNull", date.isNull());
|
---|
561 | I(d, "toTime_t", (long)date.toTime_t());
|
---|
562 | S(d, "toString", date.toString());
|
---|
563 | S(d, "toString_(ISO)", date.toString(Qt::ISODate));
|
---|
564 | S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate));
|
---|
565 | S(d, "toString_(Locale)", date.toString(Qt::LocaleDate));
|
---|
566 | S(d, "toString", date.toString());
|
---|
567 |
|
---|
568 | d.beginHash();
|
---|
569 | P(d, "name", "toUTC");
|
---|
570 | P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::UTC)");
|
---|
571 | P(d, "type", "QDateTime");
|
---|
572 | P(d, "numchild", "1");
|
---|
573 | d.endHash();
|
---|
574 |
|
---|
575 | d.beginHash();
|
---|
576 | P(d, "name", "toLocalTime");
|
---|
577 | P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::LocalTime)");
|
---|
578 | P(d, "type", "QDateTime");
|
---|
579 | P(d, "numchild", "1");
|
---|
580 | d.endHash();
|
---|
581 |
|
---|
582 | d << "]";
|
---|
583 | }
|
---|
584 | d.disarm();
|
---|
585 | #endif // ifdef QT_NO_DATESTRING
|
---|
586 | }
|
---|
587 |
|
---|
588 | static void qDumpQString(QDumper &d)
|
---|
589 | {
|
---|
590 | const QString &str = *reinterpret_cast<const QString *>(d.data);
|
---|
591 |
|
---|
592 | // Try to provoke segfaults early to prevent the frontend
|
---|
593 | // from asking for unavailable child details
|
---|
594 | if (!str.isEmpty()) {
|
---|
595 | volatile ushort dummy = 0;
|
---|
596 | dummy += str.at(0).unicode();
|
---|
597 | dummy += str.at(str.size() - 1).unicode();
|
---|
598 | }
|
---|
599 |
|
---|
600 | P(d, "iname", d.iname);
|
---|
601 | P(d, "addr", d.data);
|
---|
602 | P(d, "value", str);
|
---|
603 | P(d, "type", "QString");
|
---|
604 | P(d, "numchild", "0");
|
---|
605 | d.disarm();
|
---|
606 | }
|
---|
607 |
|
---|
608 | static void qDumpQStringList(QDumper &d)
|
---|
609 | {
|
---|
610 | const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
|
---|
611 | int n = list.size();
|
---|
612 | if (n < 0)
|
---|
613 | qProvokeSegFault();
|
---|
614 | if (n > 0) {
|
---|
615 | qCheckAccess(&list.front());
|
---|
616 | qCheckAccess(&list.back());
|
---|
617 | }
|
---|
618 |
|
---|
619 | P(d, "iname", d.iname);
|
---|
620 | P(d, "addr", d.data);
|
---|
621 | P(d, "value", "<" << n << " items>");
|
---|
622 | P(d, "valuedisabled", "true");
|
---|
623 | P(d, "numchild", n);
|
---|
624 | if (d.dumpChildren) {
|
---|
625 | if (n > 100)
|
---|
626 | n = 100;
|
---|
627 | d << ",children=[";
|
---|
628 | for (int i = 0; i != n; ++i) {
|
---|
629 | S(d, "[" << i << "]", list[i]);
|
---|
630 | }
|
---|
631 | if (n < list.size()) {
|
---|
632 | d.beginHash();
|
---|
633 | P(d, "value", "<incomplete>");
|
---|
634 | P(d, "type", " ");
|
---|
635 | P(d, "numchild", "0");
|
---|
636 | d.endHash();
|
---|
637 | }
|
---|
638 | d << "]";
|
---|
639 | }
|
---|
640 | d.disarm();
|
---|
641 | }
|
---|
642 |
|
---|
643 | static void qDumpQVariantHelper(const void *data, QString *value,
|
---|
644 | QString *exp, int *numchild)
|
---|
645 | {
|
---|
646 | const QVariant &v = *reinterpret_cast<const QVariant *>(data);
|
---|
647 | switch (v.type()) {
|
---|
648 | case QVariant::Invalid:
|
---|
649 | *value = QLatin1String("<invalid>");
|
---|
650 | *numchild = 0;
|
---|
651 | break;
|
---|
652 | case QVariant::String:
|
---|
653 | *value = QLatin1Char('"') + v.toString() + QLatin1Char('"');
|
---|
654 | *numchild = 0;
|
---|
655 | break;
|
---|
656 | case QVariant::StringList:
|
---|
657 | *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c"))
|
---|
658 | .arg((qulonglong)data);
|
---|
659 | *numchild = v.toStringList().size();
|
---|
660 | break;
|
---|
661 | case QVariant::Int:
|
---|
662 | *value = QString::number(v.toInt());
|
---|
663 | *numchild= 0;
|
---|
664 | break;
|
---|
665 | case QVariant::Double:
|
---|
666 | *value = QString::number(v.toDouble());
|
---|
667 | *numchild = 0;
|
---|
668 | break;
|
---|
669 | default:
|
---|
670 | // FIXME
|
---|
671 | //*exp = QString("qVariantValue<" << v.typeName() << ">"
|
---|
672 | // << "(*(QVariant*)" << data << ")");
|
---|
673 | break;
|
---|
674 | }
|
---|
675 | }
|
---|
676 |
|
---|
677 | static void qDumpQVariant(QDumper &d)
|
---|
678 | {
|
---|
679 | const QVariant &v = *reinterpret_cast<const QVariant *>(d.data);
|
---|
680 | QString value;
|
---|
681 | QString exp;
|
---|
682 | int numchild = 0;
|
---|
683 | qDumpQVariantHelper(d.data, &value, &exp, &numchild);
|
---|
684 | P(d, "iname", d.iname);
|
---|
685 | P(d, "addr", d.data);
|
---|
686 | P(d, "value", "(" << v.typeName() << ") " << qPrintable(value));
|
---|
687 | P(d, "type", "QVariant");
|
---|
688 | P(d, "numchild", 1);
|
---|
689 | if (d.dumpChildren) {
|
---|
690 | d << ",children=[";
|
---|
691 | d.beginHash();
|
---|
692 | P(d, "name", "value");
|
---|
693 | if (!exp.isEmpty())
|
---|
694 | P(d, "exp", qPrintable(exp));
|
---|
695 | if (!value.isEmpty())
|
---|
696 | P(d, "value", qPrintable(value));
|
---|
697 | P(d, "type", v.typeName());
|
---|
698 | P(d, "numchild", numchild);
|
---|
699 | d.endHash();
|
---|
700 | d << "]";
|
---|
701 | }
|
---|
702 | d.disarm();
|
---|
703 | }
|
---|
704 |
|
---|
705 | static void qDumpQList(QDumper &d)
|
---|
706 | {
|
---|
707 | // This uses the knowledge that QList<T> has only a single member
|
---|
708 | // of type union { QListData p; QListData::Data *d; };
|
---|
709 | const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
|
---|
710 | const QListData::Data *pdata = *reinterpret_cast<const QListData::Data* const*>(d.data);
|
---|
711 | int nn = ldata.size();
|
---|
712 | if (nn < 0)
|
---|
713 | qProvokeSegFault();
|
---|
714 | if (nn > 0) {
|
---|
715 | qCheckAccess(ldata.d->array);
|
---|
716 | //qCheckAccess(ldata.d->array[0]);
|
---|
717 | //qCheckAccess(ldata.d->array[nn - 1]);
|
---|
718 | }
|
---|
719 |
|
---|
720 | int n = nn;
|
---|
721 | P(d, "iname", d.iname);
|
---|
722 | P(d, "value", "<" << n << " items>");
|
---|
723 | P(d, "valuedisabled", "true");
|
---|
724 | P(d, "numchild", n);
|
---|
725 | if (d.dumpChildren) {
|
---|
726 | if (n > 100)
|
---|
727 | n = 100;
|
---|
728 | d << ",children=[";
|
---|
729 | for (int i = 0; i != n; ++i) {
|
---|
730 | d.beginHash();
|
---|
731 | P(d, "name", "[" << i << "]");
|
---|
732 | // The exact condition here is:
|
---|
733 | // QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
|
---|
734 | // but this data is not available in the compiled binary.
|
---|
735 | // So as first approximation only do the 'isLarge' check:
|
---|
736 | void *p = &(ldata.d->array[i + pdata->begin]);
|
---|
737 | unsigned long voidpsize = sizeof(void*);
|
---|
738 | P(d, "exp", "(sizeof(" << d.innertype << ")>" << voidpsize <<
|
---|
739 | "?(**(" << d.innertype << "**)(" << p << "))"
|
---|
740 | ":(*(" << d.innertype << "*)(" << p << ")))");
|
---|
741 | P(d, "type", d.innertype);
|
---|
742 | d.endHash();
|
---|
743 | }
|
---|
744 | if (n < nn) {
|
---|
745 | d << ",{";
|
---|
746 | P(d, "value", "<incomplete>");
|
---|
747 | d.endHash();
|
---|
748 | }
|
---|
749 | d << "]";
|
---|
750 | }
|
---|
751 | d.disarm();
|
---|
752 | }
|
---|
753 |
|
---|
754 | static void qDumpQVector(QDumper &d)
|
---|
755 | {
|
---|
756 | // Use 'int' as representative value. No way (and no need)
|
---|
757 | // to deduce proper type here.
|
---|
758 | const QVector<int> &vec = *reinterpret_cast<const QVector<int> *>(d.data);
|
---|
759 | const int nn = vec.size();
|
---|
760 |
|
---|
761 | // Try to provoke segfaults early to prevent the frontend
|
---|
762 | // from asking for unavailable child details
|
---|
763 | if (nn < 0)
|
---|
764 | qProvokeSegFault();
|
---|
765 | if (nn > 0) {
|
---|
766 | qCheckAccess(&vec.front());
|
---|
767 | qCheckAccess(&vec.back());
|
---|
768 | }
|
---|
769 |
|
---|
770 | //int innersize = 0;
|
---|
771 | //scanf(qDumpInBuffer, "%d", &innersize);
|
---|
772 |
|
---|
773 | int n = nn;
|
---|
774 | P(d, "iname", d.iname);
|
---|
775 | P(d, "addr", d.data);
|
---|
776 | P(d, "value", "<" << n << " items>");
|
---|
777 | P(d, "valuedisabled", "true");
|
---|
778 | P(d, "numchild", n);
|
---|
779 | if (d.dumpChildren) {
|
---|
780 | if (n > 100)
|
---|
781 | n = 100;
|
---|
782 | d << ",children=[";
|
---|
783 | for (int i = 0; i != n; ++i) {
|
---|
784 | if (i)
|
---|
785 | d << ",";
|
---|
786 | d.beginHash();
|
---|
787 | P(d, "name", "[" << i << "]");
|
---|
788 | P(d, "exp", "(" << d.exp << ".d->array[" << i << "])");
|
---|
789 | P(d, "type", d.innertype);
|
---|
790 | d.endHash();
|
---|
791 | }
|
---|
792 | if (n < nn) {
|
---|
793 | d << ",{";
|
---|
794 | P(d, "value", "<incomplete>");
|
---|
795 | d.endHash();
|
---|
796 | }
|
---|
797 | d << "]";
|
---|
798 | }
|
---|
799 | d.disarm();
|
---|
800 | }
|
---|
801 |
|
---|
802 | static void qDumpQHashNode(QDumper &d)
|
---|
803 | {
|
---|
804 | struct NodeOS { void *next; uint k; uint v; } nodeOS; // int-key optimization, small value
|
---|
805 | struct NodeOL { void *next; uint k; void *v; } nodeOL; // int-key optimiatzion, large value
|
---|
806 | struct NodeNS { void *next; uint h; uint k; uint v; } nodeNS; // no optimization, small value
|
---|
807 | struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL; // no optimization, large value
|
---|
808 | struct NodeL { void *next; uint h; void *k; void *v; } nodeL; // complex key
|
---|
809 |
|
---|
810 | // offsetof(...,...) not yet in Standard C++
|
---|
811 | const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS );
|
---|
812 | const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS );
|
---|
813 | const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL );
|
---|
814 | const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL );
|
---|
815 | const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS );
|
---|
816 | const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS );
|
---|
817 | const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL );
|
---|
818 | const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL );
|
---|
819 | const ulong nodeLk ( (char *)&nodeL.k - (char *)&nodeL );
|
---|
820 | const ulong nodeLv ( (char *)&nodeL.v - (char *)&nodeL );
|
---|
821 |
|
---|
822 | const QHashData *h = reinterpret_cast<const QHashData *>(d.data);
|
---|
823 | const char *keyType = d.templateParameters[0];
|
---|
824 | const char *valueType = d.templateParameters[1];
|
---|
825 |
|
---|
826 | P(d, "iname", d.iname);
|
---|
827 | P(d, "addr", d.data);
|
---|
828 | P(d, "value", "");
|
---|
829 | P(d, "numchild", 2);
|
---|
830 | if (d.dumpChildren) {
|
---|
831 | // there is a hash specialization in cast the key are integers or shorts
|
---|
832 | bool isOptimizedIntKey = qstrcmp(keyType, "int") == 0
|
---|
833 | #if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
---|
834 | || qstrcmp(keyType, "short") == 0
|
---|
835 | || qstrcmp(keyType, "ushort") == 0
|
---|
836 | #endif
|
---|
837 | || qstrcmp(keyType, "uint") == 0;
|
---|
838 |
|
---|
839 | d << ",children=[";
|
---|
840 | d.beginHash();
|
---|
841 | P(d, "name", "key");
|
---|
842 | P(d, "type", keyType);
|
---|
843 | unsigned long intsize = sizeof(int);
|
---|
844 | if (isOptimizedIntKey) {
|
---|
845 | P(d, "exp", "*(" << keyType << "*)"
|
---|
846 | "(((sizeof(" << valueType << ")>" << intsize << ")?"
|
---|
847 | << nodeOLk << ":" << nodeOSk <<
|
---|
848 | ")+(char*)" << h << ")");
|
---|
849 | } else {
|
---|
850 | P(d, "exp", "*(" << keyType << "*)"
|
---|
851 | "(((sizeof(" << keyType << ")>" << intsize << ")?"
|
---|
852 | << nodeLk << ":"
|
---|
853 | "((sizeof(" << valueType << ")>" << intsize << ")?"
|
---|
854 | << nodeNLk << ":" << nodeNSk << "))+(char*)" << h << ")");
|
---|
855 | }
|
---|
856 | d.endHash();
|
---|
857 | d.beginHash();
|
---|
858 | P(d, "name", "value");
|
---|
859 | P(d, "type", valueType);
|
---|
860 | if (isOptimizedIntKey) {
|
---|
861 | P(d, "exp", "*(" << valueType << "*)"
|
---|
862 | "(((sizeof(" << valueType << ")>" << intsize << ")?"
|
---|
863 | << nodeOLv << ":" << nodeOSv << ")+(char*)" << h << ")");
|
---|
864 | } else {
|
---|
865 | P(d, "exp", "*(" << valueType << "*)"
|
---|
866 | "(((sizeof(" << keyType << ")>" << intsize << ")?" << nodeLv << ":"
|
---|
867 | "((sizeof(" << valueType << ")>" << intsize << ")?"
|
---|
868 | << nodeNLv << ":" << nodeNSv << "))+(char*)" << h << ")");
|
---|
869 | }
|
---|
870 | d.endHash();
|
---|
871 | d << "]";
|
---|
872 | }
|
---|
873 | d.disarm();
|
---|
874 | }
|
---|
875 |
|
---|
876 | static void qDumpQHash(QDumper &d)
|
---|
877 | {
|
---|
878 | QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
|
---|
879 | const char *keyType = d.templateParameters[0];
|
---|
880 | const char *valueType = d.templateParameters[1];
|
---|
881 |
|
---|
882 | qCheckPointer(h->fakeNext);
|
---|
883 | qCheckPointer(h->buckets);
|
---|
884 |
|
---|
885 | int n = h->size;
|
---|
886 |
|
---|
887 | if (n < 0)
|
---|
888 | qProvokeSegFault();
|
---|
889 | if (n > 0) {
|
---|
890 | qCheckPointer(h->fakeNext);
|
---|
891 | qCheckPointer(*h->buckets);
|
---|
892 | }
|
---|
893 |
|
---|
894 | P(d, "iname", d.iname);
|
---|
895 | P(d, "addr", d.data);
|
---|
896 | P(d, "value", "<" << n << " items>");
|
---|
897 | P(d, "numchild", n);
|
---|
898 | if (d.dumpChildren) {
|
---|
899 | if (n > 100)
|
---|
900 | n = 100;
|
---|
901 | d << ",children=[";
|
---|
902 |
|
---|
903 | QHashData::Node *node = h->firstNode();
|
---|
904 | QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h);
|
---|
905 | int i = 0;
|
---|
906 |
|
---|
907 | while (node != end) {
|
---|
908 | d.beginHash();
|
---|
909 | P(d, "name", "[" << i << "]");
|
---|
910 | P(d, "type", "QHashNode<" << keyType << "," << valueType << " >");
|
---|
911 | P(d, "exp", "*(QHashNode<" << keyType << "," << valueType << " >*)" << node);
|
---|
912 | d.endHash();
|
---|
913 |
|
---|
914 | ++i;
|
---|
915 | node = QHashData::nextNode(node);
|
---|
916 | }
|
---|
917 | d << "]";
|
---|
918 | }
|
---|
919 | d.disarm();
|
---|
920 | }
|
---|
921 |
|
---|
922 | static void qDumpQMapNode(QDumper &d)
|
---|
923 | {
|
---|
924 | const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
|
---|
925 | const char *keyType = d.templateParameters[0];
|
---|
926 | const char *valueType = d.templateParameters[1];
|
---|
927 |
|
---|
928 | qCheckAccess(h->backward);
|
---|
929 | qCheckAccess(h->forward[0]);
|
---|
930 |
|
---|
931 | P(d, "iname", d.iname);
|
---|
932 | P(d, "addr", d.data);
|
---|
933 | P(d, "value", "");
|
---|
934 | P(d, "numchild", 2);
|
---|
935 | if (d.dumpChildren) {
|
---|
936 | unsigned long voidpsize = sizeof(void*);
|
---|
937 | d << ",children=[";
|
---|
938 | d.beginHash();
|
---|
939 | P(d, "name", "key");
|
---|
940 | P(d, "type", keyType);
|
---|
941 | P(d, "exp", "*(" << keyType << "*)"
|
---|
942 | << "("
|
---|
943 | << 2 * voidpsize
|
---|
944 | << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
|
---|
945 | << "+(char*)" << h
|
---|
946 | << ")");
|
---|
947 | d.endHash();
|
---|
948 | d.beginHash();
|
---|
949 | P(d, "name", "value");
|
---|
950 | P(d, "type", valueType);
|
---|
951 | P(d, "exp", "*(" << valueType << "*)"
|
---|
952 | << "("
|
---|
953 | << "(size_t)&(('QMap<" << keyType << "," << valueType << ">::Node'*)0)->value"
|
---|
954 | << "+" << 2 * voidpsize
|
---|
955 | << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
|
---|
956 | << "+(char*)" << h
|
---|
957 | << ")");
|
---|
958 | d.endHash();
|
---|
959 | d << "]";
|
---|
960 | }
|
---|
961 |
|
---|
962 | d.disarm();
|
---|
963 | }
|
---|
964 |
|
---|
965 | static void qDumpQMap(QDumper &d)
|
---|
966 | {
|
---|
967 | QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
|
---|
968 | const char *keyType = d.templateParameters[0];
|
---|
969 | const char *valueType = d.templateParameters[1];
|
---|
970 |
|
---|
971 | int n = h->size;
|
---|
972 |
|
---|
973 | if (n < 0)
|
---|
974 | qProvokeSegFault();
|
---|
975 | if (n > 0) {
|
---|
976 | qCheckAccess(h->backward);
|
---|
977 | qCheckAccess(h->forward[0]);
|
---|
978 | qCheckPointer(h->backward->backward);
|
---|
979 | qCheckPointer(h->forward[0]->backward);
|
---|
980 | }
|
---|
981 |
|
---|
982 | P(d, "iname", d.iname);
|
---|
983 | P(d, "addr", d.data);
|
---|
984 | P(d, "value", "<" << n << " items>");
|
---|
985 | P(d, "numchild", n);
|
---|
986 | if (d.dumpChildren) {
|
---|
987 | if (n > 100)
|
---|
988 | n = 100;
|
---|
989 | d << ",children=[";
|
---|
990 |
|
---|
991 | QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]);
|
---|
992 | QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h);
|
---|
993 | int i = 0;
|
---|
994 |
|
---|
995 | while (node != end) {
|
---|
996 | d.beginHash();
|
---|
997 | P(d, "name", "[" << i << "]");
|
---|
998 | P(d, "type", "QMap<" << keyType << "," << valueType << ">::Node");
|
---|
999 | P(d, "exp", "*('QMap<" << keyType << "," << valueType << ">::Node'*)" << node);
|
---|
1000 | d.endHash();
|
---|
1001 |
|
---|
1002 | ++i;
|
---|
1003 | node = node->forward[0];
|
---|
1004 | }
|
---|
1005 | d << "]";
|
---|
1006 | }
|
---|
1007 |
|
---|
1008 | d.disarm();
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | static void qDumpQSet(QDumper &d)
|
---|
1012 | {
|
---|
1013 | // This uses the knowledge that QHash<T> has only a single member
|
---|
1014 | // of union { QHashData *d; QHashNode<Key, T> *e; };
|
---|
1015 | QHashData *hd = *(QHashData**)d.data;
|
---|
1016 | QHashData::Node *node = hd->firstNode();
|
---|
1017 |
|
---|
1018 | int n = hd->size;
|
---|
1019 | if (n < 0)
|
---|
1020 | qProvokeSegFault();
|
---|
1021 | if (n > 0) {
|
---|
1022 | qCheckAccess(node);
|
---|
1023 | qCheckPointer(node->next);
|
---|
1024 | }
|
---|
1025 |
|
---|
1026 | P(d, "iname", d.iname);
|
---|
1027 | P(d, "addr", d.data);
|
---|
1028 | P(d, "value", "<" << n << " items>");
|
---|
1029 | P(d, "valuedisabled", "true");
|
---|
1030 | P(d, "numchild", 2 * n);
|
---|
1031 | if (d.dumpChildren) {
|
---|
1032 | if (n > 100)
|
---|
1033 | n = 100;
|
---|
1034 | d << ",children=[";
|
---|
1035 | int i = 0;
|
---|
1036 | for (int bucket = 0; bucket != hd->numBuckets; ++bucket) {
|
---|
1037 | for (node = hd->buckets[bucket]; node->next; node = node->next) {
|
---|
1038 | d.beginHash();
|
---|
1039 | P(d, "name", "[" << i << "]");
|
---|
1040 | P(d, "type", d.innertype);
|
---|
1041 | P(d, "exp", "(('QHashNode<" << d.innertype
|
---|
1042 | << ",QHashDummyValue>'*)"
|
---|
1043 | << static_cast<const void*>(node) << ")->key"
|
---|
1044 | );
|
---|
1045 | d.endHash();
|
---|
1046 | ++i;
|
---|
1047 | }
|
---|
1048 | }
|
---|
1049 | d << "]";
|
---|
1050 | }
|
---|
1051 | d.disarm();
|
---|
1052 | }
|
---|
1053 |
|
---|
1054 | static void handleProtocolVersion2(QDumper & d)
|
---|
1055 | {
|
---|
1056 | if (!d.outertype[0]) {
|
---|
1057 | qDumpUnknown(d);
|
---|
1058 | return;
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 | d.setupTemplateParameters();
|
---|
1062 | // d.outertype[0] is usally 'Q', so don't use it
|
---|
1063 | switch (d.outertype[1]) {
|
---|
1064 | case 'D':
|
---|
1065 | if (qstrcmp(d.outertype, "QDateTime") == 0)
|
---|
1066 | qDumpQDateTime(d);
|
---|
1067 | else if (qstrcmp(d.outertype, "QDir") == 0)
|
---|
1068 | qDumpQDir(d);
|
---|
1069 | break;
|
---|
1070 | case 'F':
|
---|
1071 | if (qstrcmp(d.outertype, "QFileInfo") == 0)
|
---|
1072 | qDumpQFileInfo(d);
|
---|
1073 | break;
|
---|
1074 | case 'H':
|
---|
1075 | if (qstrcmp(d.outertype, "QHash") == 0)
|
---|
1076 | qDumpQHash(d);
|
---|
1077 | else if (qstrcmp(d.outertype, "QHashNode") == 0)
|
---|
1078 | qDumpQHashNode(d);
|
---|
1079 | break;
|
---|
1080 | case 'L':
|
---|
1081 | if (qstrcmp(d.outertype, "QList") == 0)
|
---|
1082 | qDumpQList(d);
|
---|
1083 | break;
|
---|
1084 | case 'M':
|
---|
1085 | if (qstrcmp(d.outertype, "QMap") == 0)
|
---|
1086 | qDumpQMap(d);
|
---|
1087 | else if (qstrcmp(d.outertype, "QMap::Node") == 0)
|
---|
1088 | qDumpQMapNode(d);
|
---|
1089 | break;
|
---|
1090 | case 'O':
|
---|
1091 | if (qstrcmp(d.outertype, "QObject") == 0)
|
---|
1092 | qDumpQObject(d);
|
---|
1093 | break;
|
---|
1094 | case 'P':
|
---|
1095 | if (qstrcmp(d.outertype, "QPropertyList") == 0)
|
---|
1096 | qDumpQPropertyList(d);
|
---|
1097 | break;
|
---|
1098 | case 'S':
|
---|
1099 | if (qstrcmp(d.outertype, "QSet") == 0)
|
---|
1100 | qDumpQSet(d);
|
---|
1101 | else if (qstrcmp(d.outertype, "QString") == 0)
|
---|
1102 | qDumpQString(d);
|
---|
1103 | else if (qstrcmp(d.outertype, "QStringList") == 0)
|
---|
1104 | qDumpQStringList(d);
|
---|
1105 | break;
|
---|
1106 | case 'V':
|
---|
1107 | if (qstrcmp(d.outertype, "QVariant") == 0)
|
---|
1108 | qDumpQVariant(d);
|
---|
1109 | else if (qstrcmp(d.outertype, "QVector") == 0)
|
---|
1110 | qDumpQVector(d);
|
---|
1111 | break;
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | if (!d.success)
|
---|
1115 | qDumpUnknown(d);
|
---|
1116 | }
|
---|
1117 |
|
---|
1118 | } // anonymous namespace
|
---|
1119 |
|
---|
1120 |
|
---|
1121 | extern "C" Q_CORE_EXPORT void qDumpObjectData(
|
---|
1122 | int protocolVersion,
|
---|
1123 | int token,
|
---|
1124 | const char *outertype,
|
---|
1125 | const char *iname,
|
---|
1126 | const char *exp,
|
---|
1127 | const char *innertype,
|
---|
1128 | const void *data,
|
---|
1129 | bool dumpChildren)
|
---|
1130 | {
|
---|
1131 | if (protocolVersion == 1) {
|
---|
1132 | // used to test whether error output gets through
|
---|
1133 | //fprintf(stderr, "using stderr, qDebug follows: %d\n", token);
|
---|
1134 | //qDebug() << "using qDebug, stderr already used: " << token;
|
---|
1135 | }
|
---|
1136 |
|
---|
1137 | else if (protocolVersion == 2) {
|
---|
1138 | QDumper d;
|
---|
1139 | d.protocolVersion = protocolVersion;
|
---|
1140 | d.token = token;
|
---|
1141 | d.outertype = outertype ? outertype : "";
|
---|
1142 | d.iname = iname ? iname : "";
|
---|
1143 | d.exp = exp ? exp : "";
|
---|
1144 | d.innertype = innertype ? innertype : "";
|
---|
1145 | d.data = data ? data : "";
|
---|
1146 | d.dumpChildren = dumpChildren;
|
---|
1147 | handleProtocolVersion2(d);
|
---|
1148 | }
|
---|
1149 |
|
---|
1150 | else {
|
---|
1151 | qDebug() << "Unsupported protocol version" << protocolVersion;
|
---|
1152 | }
|
---|
1153 | }
|
---|
1154 |
|
---|
1155 | QT_END_NAMESPACE
|
---|
1156 |
|
---|
1157 | #endif // !Q_OS_WINCE && !QT_NO_QDUMPER
|
---|