1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2016 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include "qdebug.h" |
6 | #include "private/qdebug_p.h" |
7 | #include "qmetaobject.h" |
8 | #include <private/qlogging_p.h> |
9 | #include <private/qtextstream_p.h> |
10 | #include <private/qtools_p.h> |
11 | |
12 | #include <array> |
13 | #include <q20chrono.h> |
14 | #include <cstdio> |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | using namespace QtMiscUtils; |
19 | |
20 | /* |
21 | Returns a human readable representation of the first \a maxSize |
22 | characters in \a data. The size, \a len, is a 64-bit quantity to |
23 | avoid truncation due to implicit conversions in callers. |
24 | */ |
25 | QByteArray QtDebugUtils::toPrintable(const char *data, qint64 len, qsizetype maxSize) |
26 | { |
27 | if (!data) |
28 | return "(null)" ; |
29 | |
30 | QByteArray out; |
31 | for (qsizetype i = 0; i < qMin(a: len, b: maxSize); ++i) { |
32 | char c = data[i]; |
33 | if (isAsciiPrintable(ch: c)) { |
34 | out += c; |
35 | } else { |
36 | switch (c) { |
37 | case '\n': |
38 | out += "\\n" ; |
39 | break; |
40 | case '\r': |
41 | out += "\\r" ; |
42 | break; |
43 | case '\t': |
44 | out += "\\t" ; |
45 | break; |
46 | default: { |
47 | const char buf[] = { |
48 | '\\', |
49 | 'x', |
50 | toHexLower(value: uchar(c) / 16), |
51 | toHexLower(value: uchar(c) % 16), |
52 | 0 |
53 | }; |
54 | out += buf; |
55 | } |
56 | } |
57 | } |
58 | } |
59 | |
60 | if (maxSize < len) |
61 | out += "..." ; |
62 | |
63 | return out; |
64 | } |
65 | |
66 | // This file is needed to force compilation of QDebug into the kernel library. |
67 | |
68 | /*! |
69 | \class QDebug |
70 | \inmodule QtCore |
71 | \ingroup shared |
72 | |
73 | \brief The QDebug class provides an output stream for debugging information. |
74 | |
75 | QDebug is used whenever the developer needs to write out debugging or tracing |
76 | information to a device, file, string or console. |
77 | |
78 | \section1 Basic Use |
79 | |
80 | In the common case, it is useful to call the qDebug() function to obtain a |
81 | default QDebug object to use for writing debugging information. |
82 | |
83 | \snippet qdebug/qdebugsnippet.cpp 1 |
84 | |
85 | This constructs a QDebug object using the constructor that accepts a QtMsgType |
86 | value of QtDebugMsg. Similarly, the qWarning(), qCritical() and qFatal() |
87 | functions also return QDebug objects for the corresponding message types. |
88 | |
89 | The class also provides several constructors for other situations, including |
90 | a constructor that accepts a QFile or any other QIODevice subclass that is |
91 | used to write debugging information to files and other devices. The constructor |
92 | that accepts a QString is used to write to a string for display or serialization. |
93 | |
94 | \section1 Formatting Options |
95 | |
96 | QDebug formats output so that it's easily readable. It automatically adds spaces |
97 | between arguments, and adds quotes around QString, QByteArray, QChar arguments. |
98 | |
99 | You can tweak these options through the space(), nospace() and quote(), noquote() |
100 | methods. Furthermore, \l{QTextStream manipulators} can be piped into a QDebug |
101 | stream. |
102 | |
103 | QDebugStateSaver limits changes to the formatting to the current scope. |
104 | resetFormat() resets the options to the default ones. |
105 | |
106 | \section1 Writing Custom Types to a Stream |
107 | |
108 | Many standard types can be written to QDebug objects, and Qt provides support for |
109 | most Qt value types. To add support for custom types, you need to implement a |
110 | streaming operator, as in the following example: |
111 | |
112 | \snippet qdebug/qdebugsnippet.cpp 0 |
113 | |
114 | This is described in the \l{Debugging Techniques} and |
115 | \l{Creating Custom Qt Types#Making the Type Printable}{Creating Custom Qt Types} |
116 | documents. |
117 | */ |
118 | |
119 | /*! |
120 | \fn QDebug::QDebug(QIODevice *device) |
121 | |
122 | Constructs a debug stream that writes to the given \a device. |
123 | */ |
124 | |
125 | /*! |
126 | \fn QDebug::QDebug(QString *string) |
127 | |
128 | Constructs a debug stream that writes to the given \a string. |
129 | */ |
130 | |
131 | /*! |
132 | \fn QDebug::QDebug(QtMsgType t) |
133 | |
134 | Constructs a debug stream that writes to the handler for the message type \a t. |
135 | */ |
136 | |
137 | /*! |
138 | \fn QDebug::QDebug(const QDebug &o) |
139 | |
140 | Constructs a copy of the other debug stream \a o. |
141 | */ |
142 | |
143 | /*! |
144 | \fn QDebug &QDebug::operator=(const QDebug &other) |
145 | |
146 | Assigns the \a other debug stream to this stream and returns a reference to |
147 | this stream. |
148 | */ |
149 | |
150 | /*! |
151 | \fn QDebug::~QDebug() |
152 | |
153 | Flushes any pending data to be written and destroys the debug stream. |
154 | */ |
155 | QDebug::~QDebug() |
156 | { |
157 | if (stream && !--stream->ref) { |
158 | if (stream->space && stream->buffer.endsWith(c: u' ')) |
159 | stream->buffer.chop(n: 1); |
160 | if (stream->message_output) { |
161 | QInternalMessageLogContext ctxt(stream->context); |
162 | qt_message_output(stream->type, |
163 | context: ctxt, |
164 | message: stream->buffer); |
165 | } |
166 | delete stream; |
167 | } |
168 | } |
169 | |
170 | /*! |
171 | \internal |
172 | */ |
173 | void QDebug::putUcs4(uint ucs4) |
174 | { |
175 | maybeQuote(c: '\''); |
176 | if (ucs4 < 0x20) { |
177 | stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset; |
178 | } else if (ucs4 < 0x80) { |
179 | stream->ts << char(ucs4); |
180 | } else { |
181 | if (ucs4 < 0x10000) |
182 | stream->ts << "\\u" << qSetFieldWidth(width: 4); |
183 | else |
184 | stream->ts << "\\U" << qSetFieldWidth(width: 8); |
185 | stream->ts << Qt::hex << qSetPadChar(ch: u'0') << ucs4 << Qt::reset; |
186 | } |
187 | maybeQuote(c: '\''); |
188 | } |
189 | |
190 | // These two functions return true if the character should be printed by QDebug. |
191 | // For QByteArray, this is technically identical to US-ASCII isprint(); |
192 | // for QString, we use QChar::isPrint, which requires a full UCS-4 decode. |
193 | static inline bool isPrintable(char32_t ucs4) { return QChar::isPrint(ucs4); } |
194 | static inline bool isPrintable(char16_t uc) { return QChar::isPrint(ucs4: uc); } |
195 | static inline bool isPrintable(uchar c) |
196 | { return isAsciiPrintable(ch: c); } |
197 | |
198 | template <typename Char> |
199 | static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, size_t length, bool isUnicode = true) |
200 | { |
201 | QChar quote(u'"'); |
202 | d->write(data: "e, len: 1); |
203 | |
204 | bool lastWasHexEscape = false; |
205 | const Char *end = begin + length; |
206 | for (const Char *p = begin; p != end; ++p) { |
207 | // check if we need to insert "" to break an hex escape sequence |
208 | if (Q_UNLIKELY(lastWasHexEscape)) { |
209 | if (fromHex(*p) != -1) { |
210 | // yes, insert it |
211 | QChar quotes[] = { quote, quote }; |
212 | d->write(data: quotes, len: 2); |
213 | } |
214 | lastWasHexEscape = false; |
215 | } |
216 | |
217 | if (sizeof(Char) == sizeof(QChar)) { |
218 | // Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them |
219 | qsizetype runLength = 0; |
220 | while (p + runLength != end && |
221 | isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"') |
222 | ++runLength; |
223 | if (runLength) { |
224 | d->write(data: reinterpret_cast<const QChar *>(p), len: runLength); |
225 | p += runLength - 1; |
226 | continue; |
227 | } |
228 | } else if (isPrintable(*p) && *p != '\\' && *p != '"') { |
229 | QChar c = QLatin1Char(*p); |
230 | d->write(data: &c, len: 1); |
231 | continue; |
232 | } |
233 | |
234 | // print as an escape sequence (maybe, see below for surrogate pairs) |
235 | qsizetype buflen = 2; |
236 | char16_t buf[std::char_traits<char>::length(s: "\\U12345678" )]; |
237 | buf[0] = '\\'; |
238 | |
239 | switch (*p) { |
240 | case '"': |
241 | case '\\': |
242 | buf[1] = *p; |
243 | break; |
244 | case '\b': |
245 | buf[1] = 'b'; |
246 | break; |
247 | case '\f': |
248 | buf[1] = 'f'; |
249 | break; |
250 | case '\n': |
251 | buf[1] = 'n'; |
252 | break; |
253 | case '\r': |
254 | buf[1] = 'r'; |
255 | break; |
256 | case '\t': |
257 | buf[1] = 't'; |
258 | break; |
259 | default: |
260 | if (!isUnicode) { |
261 | // print as hex escape |
262 | buf[1] = 'x'; |
263 | buf[2] = toHexUpper(value: uchar(*p) >> 4); |
264 | buf[3] = toHexUpper(value: uchar(*p)); |
265 | buflen = 4; |
266 | lastWasHexEscape = true; |
267 | break; |
268 | } |
269 | if (QChar::isHighSurrogate(*p)) { |
270 | if ((p + 1) != end && QChar::isLowSurrogate(p[1])) { |
271 | // properly-paired surrogates |
272 | char32_t ucs4 = QChar::surrogateToUcs4(*p, p[1]); |
273 | if (isPrintable(ucs4)) { |
274 | buf[0] = *p; |
275 | buf[1] = p[1]; |
276 | buflen = 2; |
277 | } else { |
278 | buf[1] = 'U'; |
279 | buf[2] = '0'; // toHexUpper(ucs4 >> 32); |
280 | buf[3] = '0'; // toHexUpper(ucs4 >> 28); |
281 | buf[4] = toHexUpper(value: ucs4 >> 20); |
282 | buf[5] = toHexUpper(value: ucs4 >> 16); |
283 | buf[6] = toHexUpper(value: ucs4 >> 12); |
284 | buf[7] = toHexUpper(value: ucs4 >> 8); |
285 | buf[8] = toHexUpper(value: ucs4 >> 4); |
286 | buf[9] = toHexUpper(value: ucs4); |
287 | buflen = 10; |
288 | } |
289 | ++p; |
290 | break; |
291 | } |
292 | // improperly-paired surrogates, fall through |
293 | } |
294 | buf[1] = 'u'; |
295 | buf[2] = toHexUpper(value: char16_t(*p) >> 12); |
296 | buf[3] = toHexUpper(value: char16_t(*p) >> 8); |
297 | buf[4] = toHexUpper(*p >> 4); |
298 | buf[5] = toHexUpper(*p); |
299 | buflen = 6; |
300 | } |
301 | d->write(data: reinterpret_cast<QChar *>(buf), len: buflen); |
302 | } |
303 | |
304 | d->write(data: "e, len: 1); |
305 | } |
306 | |
307 | /*! |
308 | \internal |
309 | Duplicated from QtTest::toPrettyUnicode(). |
310 | */ |
311 | void QDebug::putString(const QChar *begin, size_t length) |
312 | { |
313 | if (stream->noQuotes) { |
314 | // no quotes, write the string directly too (no pretty-printing) |
315 | // this respects the QTextStream state, though |
316 | stream->ts.d_ptr->putString(data: begin, len: qsizetype(length)); |
317 | } else { |
318 | // we'll reset the QTextStream formatting mechanisms, so save the state |
319 | QDebugStateSaver saver(*this); |
320 | stream->ts.d_ptr->params.reset(); |
321 | putEscapedString(d: stream->ts.d_ptr.data(), begin: reinterpret_cast<const char16_t *>(begin), length); |
322 | } |
323 | } |
324 | |
325 | /*! |
326 | \internal |
327 | Duplicated from QtTest::toPrettyCString(). |
328 | */ |
329 | void QDebug::putByteArray(const char *begin, size_t length, Latin1Content content) |
330 | { |
331 | if (stream->noQuotes) { |
332 | // no quotes, write the string directly too (no pretty-printing) |
333 | // this respects the QTextStream state, though |
334 | QString string = content == ContainsLatin1 ? QString::fromLatin1(str: begin, size: qsizetype(length)) |
335 | : QString::fromUtf8(utf8: begin, size: qsizetype(length)); |
336 | stream->ts.d_ptr->putString(string); |
337 | } else { |
338 | // we'll reset the QTextStream formatting mechanisms, so save the state |
339 | QDebugStateSaver saver(*this); |
340 | stream->ts.d_ptr->params.reset(); |
341 | putEscapedString(d: stream->ts.d_ptr.data(), begin: reinterpret_cast<const uchar *>(begin), |
342 | length, isUnicode: content == ContainsLatin1); |
343 | } |
344 | } |
345 | |
346 | static QByteArray timeUnit(qint64 num, qint64 den) |
347 | { |
348 | using namespace std::chrono; |
349 | using namespace q20::chrono; |
350 | |
351 | if (num == 1 && den > 1) { |
352 | // sub-multiple of seconds |
353 | char prefix = '\0'; |
354 | auto tryprefix = [&](auto d, char c) { |
355 | static_assert(decltype(d)::num == 1, "not an SI prefix" ); |
356 | if (den == decltype(d)::den) |
357 | prefix = c; |
358 | }; |
359 | |
360 | // "u" should be "µ", but debugging output is not always UTF-8-safe |
361 | tryprefix(std::milli{}, 'm'); |
362 | tryprefix(std::micro{}, 'u'); |
363 | tryprefix(std::nano{}, 'n'); |
364 | tryprefix(std::pico{}, 'p'); |
365 | tryprefix(std::femto{}, 'f'); |
366 | tryprefix(std::atto{}, 'a'); |
367 | // uncommon ones later |
368 | tryprefix(std::centi{}, 'c'); |
369 | tryprefix(std::deci{}, 'd'); |
370 | if (prefix) { |
371 | char unit[3] = { prefix, 's' }; |
372 | return QByteArray(unit, sizeof(unit) - 1); |
373 | } |
374 | } |
375 | |
376 | const char *unit = nullptr; |
377 | if (num > 1 && den == 1) { |
378 | // multiple of seconds - but we don't use SI prefixes |
379 | auto tryunit = [&](auto d, const char *name) { |
380 | static_assert(decltype(d)::period::den == 1, "not a multiple of a second" ); |
381 | if (unit || num % decltype(d)::period::num) |
382 | return; |
383 | unit = name; |
384 | num /= decltype(d)::period::num; |
385 | }; |
386 | tryunit(years{}, "yr" ); |
387 | tryunit(weeks{}, "wk" ); |
388 | tryunit(days{}, "d" ); |
389 | tryunit(hours{}, "h" ); |
390 | tryunit(minutes{}, "min" ); |
391 | } |
392 | if (!unit) |
393 | unit = "s" ; |
394 | |
395 | if (num == 1 && den == 1) |
396 | return unit; |
397 | if (Q_UNLIKELY(num < 1 || den < 1)) |
398 | return QString::asprintf(format: "<invalid time unit %lld/%lld>" , num, den).toLatin1(); |
399 | |
400 | // uncommon units: will return something like "[2/3]s" |
401 | // strlen("[/]min") = 6 |
402 | char buf[2 * (std::numeric_limits<qint64>::digits10 + 2) + 10]; |
403 | size_t len = 0; |
404 | auto appendChar = [&](char c) { |
405 | Q_ASSERT(len < sizeof(buf)); |
406 | buf[len++] = c; |
407 | }; |
408 | auto appendNumber = [&](qint64 value) { |
409 | if (value >= 10'000 && (value % 1000) == 0) |
410 | len += std::snprintf(s: buf + len, maxlen: sizeof(buf) - len, format: "%.6g" , double(value)); // "1e+06" |
411 | else |
412 | len += std::snprintf(s: buf + len, maxlen: sizeof(buf) - len, format: "%lld" , value); |
413 | }; |
414 | appendChar('['); |
415 | appendNumber(num); |
416 | if (den != 1) { |
417 | appendChar('/'); |
418 | appendNumber(den); |
419 | } |
420 | appendChar(']'); |
421 | memcpy(dest: buf + len, src: unit, n: strlen(s: unit)); |
422 | return QByteArray(buf, len + strlen(s: unit)); |
423 | } |
424 | |
425 | /*! |
426 | \since 6.6 |
427 | \internal |
428 | Helper to the std::chrono::duration debug streaming output. |
429 | */ |
430 | void QDebug::putTimeUnit(qint64 num, qint64 den) |
431 | { |
432 | stream->ts << timeUnit(num, den); // ### optimize |
433 | } |
434 | |
435 | namespace { |
436 | |
437 | #ifdef QT_SUPPORTS_INT128 |
438 | |
439 | constexpr char Q_INT128_MIN_STR[] = "-170141183460469231731687303715884105728" ; |
440 | |
441 | constexpr int Int128BufferSize = sizeof(Q_INT128_MIN_STR); |
442 | using Int128Buffer = std::array<char, Int128BufferSize>; |
443 | // numeric_limits<qint128>::digits10 may not exist |
444 | |
445 | static char *i128ToStringHelper(Int128Buffer &buffer, quint128 n) |
446 | { |
447 | auto dst = buffer.data() + buffer.size(); |
448 | *--dst = '\0'; // NUL-terminate |
449 | if (n == 0) { |
450 | *--dst = '0'; // and done |
451 | } else { |
452 | while (n != 0) { |
453 | *--dst = "0123456789" [n % 10]; |
454 | n /= 10; |
455 | } |
456 | } |
457 | return dst; |
458 | } |
459 | #endif // QT_SUPPORTS_INT128 |
460 | |
461 | [[maybe_unused]] |
462 | static const char *int128Warning() |
463 | { |
464 | const char *msg = "Qt was not compiled with int128 support." ; |
465 | qWarning(msg: "%s" , msg); |
466 | return msg; |
467 | } |
468 | |
469 | } // unnamed namespace |
470 | |
471 | /*! |
472 | \since 6.7 |
473 | \internal |
474 | Helper to the qint128 debug streaming output. |
475 | */ |
476 | void QDebug::putInt128([[maybe_unused]] const void *p) |
477 | { |
478 | #ifdef QT_SUPPORTS_INT128 |
479 | Q_ASSERT(p); |
480 | qint128 i; |
481 | memcpy(dest: &i, src: p, n: sizeof(i)); // alignment paranoia |
482 | if (i == Q_INT128_MIN) { |
483 | // -i is not representable, hardcode the result: |
484 | stream->ts << Q_INT128_MIN_STR; |
485 | } else { |
486 | Int128Buffer buffer; |
487 | auto dst = i128ToStringHelper(buffer, n: i < 0 ? -i : i); |
488 | if (i < 0) |
489 | *--dst = '-'; |
490 | stream->ts << dst; |
491 | } |
492 | return; |
493 | #endif // QT_SUPPORTS_INT128 |
494 | stream->ts << int128Warning(); |
495 | } |
496 | |
497 | /*! |
498 | \since 6.7 |
499 | \internal |
500 | Helper to the quint128 debug streaming output. |
501 | */ |
502 | void QDebug::putUInt128([[maybe_unused]] const void *p) |
503 | { |
504 | #ifdef QT_SUPPORTS_INT128 |
505 | Q_ASSERT(p); |
506 | quint128 i; |
507 | memcpy(dest: &i, src: p, n: sizeof(i)); // alignment paranoia |
508 | Int128Buffer buffer; |
509 | stream->ts << i128ToStringHelper(buffer, n: i); |
510 | return; |
511 | #endif // QT_SUPPORTS_INT128 |
512 | stream->ts << int128Warning(); |
513 | } |
514 | |
515 | |
516 | /*! |
517 | \fn QDebug::swap(QDebug &other) |
518 | \since 5.0 |
519 | |
520 | Swaps this debug stream instance with \a other. This function is |
521 | very fast and never fails. |
522 | */ |
523 | |
524 | /*! |
525 | Resets the stream formatting options, bringing it back to its original constructed state. |
526 | |
527 | \sa space(), quote() |
528 | \since 5.4 |
529 | */ |
530 | QDebug &QDebug::resetFormat() |
531 | { |
532 | stream->ts.reset(); |
533 | stream->space = true; |
534 | stream->noQuotes = false; |
535 | stream->verbosity = DefaultVerbosity; |
536 | return *this; |
537 | } |
538 | |
539 | /*! |
540 | \fn QDebug &QDebug::space() |
541 | |
542 | Writes a space character to the debug stream and returns a reference to |
543 | the stream. |
544 | |
545 | The stream remembers that automatic insertion of spaces is |
546 | enabled for future writes. |
547 | |
548 | \sa nospace(), maybeSpace() |
549 | */ |
550 | |
551 | /*! |
552 | \fn QDebug &QDebug::nospace() |
553 | |
554 | Disables automatic insertion of spaces and returns a reference to the stream. |
555 | |
556 | \sa space(), maybeSpace() |
557 | */ |
558 | |
559 | /*! |
560 | \fn QDebug &QDebug::maybeSpace() |
561 | |
562 | Writes a space character to the debug stream, depending on the current |
563 | setting for automatic insertion of spaces, and returns a reference to the stream. |
564 | |
565 | \sa space(), nospace() |
566 | */ |
567 | |
568 | /*! |
569 | \fn bool QDebug::autoInsertSpaces() const |
570 | |
571 | Returns \c true if this QDebug instance will automatically insert spaces |
572 | between writes. |
573 | |
574 | \since 5.0 |
575 | |
576 | \sa QDebugStateSaver |
577 | */ |
578 | |
579 | /*! |
580 | \fn void QDebug::setAutoInsertSpaces(bool b) |
581 | |
582 | Enables automatic insertion of spaces between writes if \a b is true; otherwise |
583 | automatic insertion of spaces is disabled. |
584 | |
585 | \since 5.0 |
586 | |
587 | \sa QDebugStateSaver |
588 | */ |
589 | |
590 | |
591 | /*! |
592 | \fn bool QDebug::quoteStrings() const |
593 | \since 6.7 |
594 | |
595 | Returns \c true if this QDebug instance will quote strings streamed into |
596 | it (which is the default). |
597 | |
598 | \sa QDebugStateSaver, quote(), noquote(), setQuoteStrings() |
599 | */ |
600 | |
601 | /*! |
602 | \fn void QDebug::setQuoteStrings(bool b) |
603 | \since 6.7 |
604 | |
605 | Enables quoting of strings streamed into this QDebug instance if \a b is |
606 | \c true; otherwise quoting is disabled. |
607 | |
608 | The default is to quote strings. |
609 | |
610 | \sa QDebugStateSaver, quote(), noquote(), quoteStrings() |
611 | */ |
612 | |
613 | |
614 | /*! |
615 | \fn QDebug &QDebug::quote() |
616 | \since 5.4 |
617 | |
618 | Enables automatic insertion of quotation characters around QChar, QString and QByteArray |
619 | contents and returns a reference to the stream. |
620 | |
621 | Quoting is enabled by default. |
622 | |
623 | \sa noquote(), maybeQuote() |
624 | */ |
625 | |
626 | /*! |
627 | \fn QDebug &QDebug::noquote() |
628 | \since 5.4 |
629 | |
630 | Disables automatic insertion of quotation characters around QChar, QString and QByteArray |
631 | contents and returns a reference to the stream. |
632 | |
633 | When quoting is disabled, these types are printed without quotation |
634 | characters and without escaping of non-printable characters. |
635 | |
636 | \sa quote(), maybeQuote() |
637 | */ |
638 | |
639 | /*! |
640 | \fn QDebug &QDebug::maybeQuote(char c) |
641 | \since 5.4 |
642 | |
643 | Writes a character \a c to the debug stream, depending on the |
644 | current setting for automatic insertion of quotes, and returns a reference to the stream. |
645 | |
646 | The default character is a double quote \c{"}. |
647 | |
648 | \sa quote(), noquote() |
649 | */ |
650 | |
651 | /*! |
652 | \fn int QDebug::verbosity() const |
653 | \since 5.6 |
654 | |
655 | Returns the verbosity of the debug stream. |
656 | |
657 | Streaming operators can check the value to decide whether |
658 | verbose output is desired and print more information depending on the |
659 | level. Higher values indicate that more information is desired. |
660 | |
661 | The allowed range is from 0 to 7. The default value is 2. |
662 | |
663 | \sa setVerbosity(), VerbosityLevel |
664 | */ |
665 | |
666 | /*! |
667 | \fn void QDebug::setVerbosity(int verbosityLevel) |
668 | \since 5.6 |
669 | |
670 | Sets the verbosity of the stream to \a verbosityLevel. |
671 | |
672 | The allowed range is from 0 to 7. The default value is 2. |
673 | |
674 | \sa verbosity(), VerbosityLevel |
675 | */ |
676 | |
677 | /*! |
678 | \fn QDebug &QDebug::verbosity(int verbosityLevel) |
679 | \since 5.13 |
680 | |
681 | Sets the verbosity of the stream to \a verbosityLevel and returns a reference to the stream. |
682 | |
683 | The allowed range is from 0 to 7. The default value is 2. |
684 | |
685 | \sa verbosity(), setVerbosity(), VerbosityLevel |
686 | */ |
687 | |
688 | /*! |
689 | \enum QDebug::VerbosityLevel |
690 | \since 5.13 |
691 | |
692 | This enum describes the range of verbosity levels. |
693 | |
694 | \value MinimumVerbosity |
695 | \value DefaultVerbosity |
696 | \value MaximumVerbosity |
697 | |
698 | \sa verbosity(), setVerbosity() |
699 | */ |
700 | |
701 | /*! |
702 | \fn QDebug &QDebug::operator<<(QChar t) |
703 | |
704 | Writes the character, \a t, to the stream and returns a reference to the |
705 | stream. Normally, QDebug prints control characters and non-US-ASCII |
706 | characters as their C escape sequences or their Unicode value (\\u1234). To |
707 | print non-printable characters without transformation, enable the noquote() |
708 | functionality, but note that some QDebug backends may not be 8-bit clean |
709 | and may not be able to represent \c t. |
710 | */ |
711 | |
712 | /*! |
713 | \fn QDebug &QDebug::operator<<(bool t) |
714 | |
715 | Writes the boolean value, \a t, to the stream and returns a reference to the |
716 | stream. |
717 | */ |
718 | |
719 | /*! |
720 | \fn QDebug &QDebug::operator<<(char t) |
721 | |
722 | Writes the character, \a t, to the stream and returns a reference to the |
723 | stream. |
724 | */ |
725 | |
726 | /*! |
727 | \fn QDebug &QDebug::operator<<(signed short t) |
728 | |
729 | Writes the signed short integer, \a t, to the stream and returns a reference |
730 | to the stream. |
731 | */ |
732 | |
733 | /*! |
734 | \fn QDebug &QDebug::operator<<(unsigned short t) |
735 | |
736 | Writes then unsigned short integer, \a t, to the stream and returns a |
737 | reference to the stream. |
738 | */ |
739 | |
740 | /*! |
741 | \fn QDebug &QDebug::operator<<(signed int t) |
742 | |
743 | Writes the signed integer, \a t, to the stream and returns a reference |
744 | to the stream. |
745 | */ |
746 | |
747 | /*! |
748 | \fn QDebug &QDebug::operator<<(unsigned int t) |
749 | |
750 | Writes then unsigned integer, \a t, to the stream and returns a reference to |
751 | the stream. |
752 | */ |
753 | |
754 | /*! |
755 | \fn QDebug &QDebug::operator<<(signed long t) |
756 | |
757 | Writes the signed long integer, \a t, to the stream and returns a reference |
758 | to the stream. |
759 | */ |
760 | |
761 | /*! |
762 | \fn QDebug &QDebug::operator<<(unsigned long t) |
763 | |
764 | Writes then unsigned long integer, \a t, to the stream and returns a reference |
765 | to the stream. |
766 | */ |
767 | |
768 | /*! |
769 | \fn QDebug &QDebug::operator<<(qint64 t) |
770 | |
771 | Writes the signed 64-bit integer, \a t, to the stream and returns a reference |
772 | to the stream. |
773 | */ |
774 | |
775 | /*! |
776 | \fn QDebug &QDebug::operator<<(quint64 t) |
777 | |
778 | Writes then unsigned 64-bit integer, \a t, to the stream and returns a |
779 | reference to the stream. |
780 | */ |
781 | |
782 | /*! |
783 | \fn QDebug &QDebug::operator<<(float t) |
784 | |
785 | Writes the 32-bit floating point number, \a t, to the stream and returns a |
786 | reference to the stream. |
787 | */ |
788 | |
789 | /*! |
790 | \fn QDebug &QDebug::operator<<(double t) |
791 | |
792 | Writes the 64-bit floating point number, \a t, to the stream and returns a |
793 | reference to the stream. |
794 | */ |
795 | |
796 | /*! |
797 | \fn QDebug &QDebug::operator<<(const char *t) |
798 | |
799 | Writes the '\\0'-terminated UTF-8 string, \a t, to the stream and returns a |
800 | reference to the stream. The string is never quoted or escaped for the |
801 | output. Note that QDebug buffers internally as UTF-16 and may need to |
802 | transform to 8-bit using the locale's codec in order to use some backends, |
803 | which may cause garbled output (mojibake). Restricting to US-ASCII strings |
804 | is recommended. |
805 | */ |
806 | |
807 | /*! |
808 | \fn QDebug &QDebug::operator<<(const char16_t *t) |
809 | \since 6.0 |
810 | |
811 | Writes the u'\\0'-terminated UTF-16 string, \a t, to the stream and returns |
812 | a reference to the stream. The string is never quoted or escaped for the |
813 | output. Note that QDebug buffers internally as UTF-16 and may need to |
814 | transform to 8-bit using the locale's codec in order to use some backends, |
815 | which may cause garbled output (mojibake). Restricting to US-ASCII strings |
816 | is recommended. |
817 | */ |
818 | |
819 | /*! |
820 | \fn QDebug &QDebug::operator<<(char16_t t) |
821 | \since 5.5 |
822 | |
823 | Writes the UTF-16 character, \a t, to the stream and returns a reference |
824 | to the stream. |
825 | */ |
826 | |
827 | /*! |
828 | \fn QDebug &QDebug::operator<<(char32_t t) |
829 | \since 5.5 |
830 | |
831 | Writes the UTF-32 character, \a t, to the stream and returns a reference |
832 | to the stream. |
833 | */ |
834 | |
835 | /*! |
836 | \fn QDebug &QDebug::operator<<(const QString &t) |
837 | |
838 | Writes the string, \a t, to the stream and returns a reference to the |
839 | stream. Normally, QDebug prints the string inside quotes and transforms |
840 | non-printable characters to their Unicode values (\\u1234). |
841 | |
842 | To print non-printable characters without transformation, enable the |
843 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
844 | clean. |
845 | |
846 | Output examples: |
847 | \snippet code/src_corelib_io_qdebug.cpp 0 |
848 | */ |
849 | |
850 | /*! |
851 | \since 5.10 |
852 | \fn QDebug &QDebug::operator<<(QStringView s) |
853 | |
854 | Writes the string view, \a s, to the stream and returns a reference to the |
855 | stream. Normally, QDebug prints the string inside quotes and transforms |
856 | non-printable characters to their Unicode values (\\u1234). |
857 | |
858 | To print non-printable characters without transformation, enable the |
859 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
860 | clean. |
861 | |
862 | See the QString overload for examples. |
863 | */ |
864 | |
865 | /*! |
866 | \since 6.0 |
867 | \fn QDebug &QDebug::operator<<(QUtf8StringView s) |
868 | |
869 | Writes the string view, \a s, to the stream and returns a reference to the |
870 | stream. |
871 | |
872 | Normally, QDebug prints the data inside quotes and transforms control or |
873 | non-US-ASCII characters to their C escape sequences (\\xAB). This way, the |
874 | output is always 7-bit clean and the string can be copied from the output |
875 | and pasted back into C++ sources, if necessary. |
876 | |
877 | To print non-printable characters without transformation, enable the |
878 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
879 | clean. |
880 | */ |
881 | |
882 | /*! |
883 | \fn QDebug &QDebug::operator<<(QLatin1StringView t) |
884 | |
885 | Writes the string, \a t, to the stream and returns a reference to the |
886 | stream. Normally, QDebug prints the string inside quotes and transforms |
887 | non-printable characters to their Unicode values (\\u1234). |
888 | |
889 | To print non-printable characters without transformation, enable the |
890 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
891 | clean. |
892 | |
893 | See the QString overload for examples. |
894 | */ |
895 | |
896 | /*! |
897 | \fn QDebug &QDebug::operator<<(const QByteArray &t) |
898 | |
899 | Writes the byte array, \a t, to the stream and returns a reference to the |
900 | stream. Normally, QDebug prints the array inside quotes and transforms |
901 | control or non-US-ASCII characters to their C escape sequences (\\xAB). This |
902 | way, the output is always 7-bit clean and the string can be copied from the |
903 | output and pasted back into C++ sources, if necessary. |
904 | |
905 | To print non-printable characters without transformation, enable the |
906 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
907 | clean. |
908 | |
909 | Output examples: |
910 | \snippet code/src_corelib_io_qdebug.cpp 1 |
911 | |
912 | Note how QDebug needed to close and reopen the string in the way C and C++ |
913 | languages concatenate string literals so that the letter 'b' is not |
914 | interpreted as part of the previous hexadecimal escape sequence. |
915 | */ |
916 | |
917 | /*! |
918 | \since 6.0 |
919 | \fn QDebug &QDebug::operator<<(QByteArrayView t) |
920 | |
921 | Writes the data of the observed byte array, \a t, to the stream and returns |
922 | a reference to the stream. |
923 | |
924 | Normally, QDebug prints the data inside quotes and transforms control or |
925 | non-US-ASCII characters to their C escape sequences (\\xAB). This way, the |
926 | output is always 7-bit clean and the string can be copied from the output |
927 | and pasted back into C++ sources, if necessary. |
928 | |
929 | To print non-printable characters without transformation, enable the |
930 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
931 | clean. |
932 | |
933 | See the QByteArray overload for examples. |
934 | */ |
935 | |
936 | /*! |
937 | \fn QDebug &QDebug::operator<<(const void *t) |
938 | |
939 | Writes a pointer, \a t, to the stream and returns a reference to the stream. |
940 | */ |
941 | |
942 | /*! |
943 | \fn QDebug &QDebug::operator<<(QTextStreamFunction f) |
944 | \internal |
945 | */ |
946 | |
947 | /*! |
948 | \fn QDebug &QDebug::operator<<(QTextStreamManipulator m) |
949 | \internal |
950 | */ |
951 | |
952 | /*! |
953 | \since 6.5 |
954 | \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(const std::basic_string<Char, Args...> &s) |
955 | \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(std::basic_string_view<Char, Args...> s) |
956 | |
957 | Writes the string or string-view \a s to the stream and returns a reference |
958 | to the stream. |
959 | |
960 | These operators only participate in overload resolution if \c Char is one of |
961 | \list |
962 | \li char |
963 | \li char8_t (C++20 only) |
964 | \li char16_t |
965 | \li char32_t |
966 | \li wchar_t |
967 | \endlist |
968 | */ |
969 | |
970 | /*! |
971 | \since 6.6 |
972 | \fn template <typename Rep, typename Period> QDebug &QDebug::operator<<(std::chrono::duration<Rep, Period> duration) |
973 | |
974 | Prints the time duration \a duration to the stream and returns a reference |
975 | to the stream. The printed string is the numeric representation of the |
976 | period followed by the time unit, similar to what the C++ Standard Library |
977 | would produce with \c{std::ostream}. |
978 | |
979 | The unit is not localized. |
980 | */ |
981 | |
982 | /*! |
983 | \fn template <typename T, QDebug::if_qint128<T>> QDebug::operator<<(T i) |
984 | \fn template <typename T, QDebug::if_quint128<T>> QDebug::operator<<(T i) |
985 | \since 6.7 |
986 | |
987 | Prints the textual representation of the 128-bit integer \a i. |
988 | |
989 | \note This operator is only available if Qt supports 128-bit integer types. |
990 | If 128-bit integer types are available in your build, but the Qt libraries |
991 | were compiled without, the operator will print a warning instead. |
992 | |
993 | \note Because the operator is a function template, no implicit conversions |
994 | are performed on its argument. It must be exactly qint128/quint128. |
995 | |
996 | \sa QT_SUPPORTS_INT128 |
997 | */ |
998 | |
999 | /*! |
1000 | \fn template <class T> QString QDebug::toString(const T &object) |
1001 | \since 6.0 |
1002 | |
1003 | \include qdebug-toString.qdocinc |
1004 | */ |
1005 | |
1006 | /*! \internal */ |
1007 | QString QDebug::toStringImpl(StreamTypeErased s, const void *obj) |
1008 | { |
1009 | QString result; |
1010 | { |
1011 | QDebug d(&result); |
1012 | s(d.nospace(), obj); |
1013 | } |
1014 | return result; |
1015 | } |
1016 | |
1017 | /*! |
1018 | \fn template <class T> QDebug operator<<(QDebug debug, const QList<T> &list) |
1019 | \relates QDebug |
1020 | |
1021 | Writes the contents of \a list to \a debug. \c T needs to |
1022 | support streaming into QDebug. |
1023 | */ |
1024 | |
1025 | /*! |
1026 | \fn template <class T, qsizetype P> QDebug operator<<(QDebug debug, const QVarLengthArray<T,P> &array) |
1027 | \relates QDebug |
1028 | \since 6.3 |
1029 | |
1030 | Writes the contents of \a array to \a debug. \c T needs to |
1031 | support streaming into QDebug. |
1032 | */ |
1033 | |
1034 | /*! |
1035 | \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec) |
1036 | \relates QDebug |
1037 | \since 5.7 |
1038 | |
1039 | Writes the contents of list \a vec to \a debug. \c T needs to |
1040 | support streaming into QDebug. |
1041 | */ |
1042 | |
1043 | /*! |
1044 | \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec) |
1045 | \relates QDebug |
1046 | \since 5.7 |
1047 | |
1048 | Writes the contents of vector \a vec to \a debug. \c T needs to |
1049 | support streaming into QDebug. |
1050 | */ |
1051 | |
1052 | /*! |
1053 | \fn template <typename T> QDebug operator<<(QDebug debug, const QSet<T> &set) |
1054 | \relates QDebug |
1055 | |
1056 | Writes the contents of \a set to \a debug. \c T needs to |
1057 | support streaming into QDebug. |
1058 | */ |
1059 | |
1060 | /*! |
1061 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMap<Key, T> &map) |
1062 | \relates QDebug |
1063 | |
1064 | Writes the contents of \a map to \a debug. Both \c Key and |
1065 | \c T need to support streaming into QDebug. |
1066 | */ |
1067 | |
1068 | /*! |
1069 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map) |
1070 | \relates QDebug |
1071 | |
1072 | Writes the contents of \a map to \a debug. Both \c Key and |
1073 | \c T need to support streaming into QDebug. |
1074 | */ |
1075 | |
1076 | /*! |
1077 | \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map) |
1078 | \relates QDebug |
1079 | \since 5.7 |
1080 | |
1081 | Writes the contents of \a map to \a debug. Both \c Key and |
1082 | \c T need to support streaming into QDebug. |
1083 | */ |
1084 | |
1085 | /*! |
1086 | \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map) |
1087 | \relates QDebug |
1088 | \since 5.7 |
1089 | |
1090 | Writes the contents of \a map to \a debug. Both \c Key and |
1091 | \c T need to support streaming into QDebug. |
1092 | */ |
1093 | |
1094 | /*! |
1095 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QHash<Key, T> &hash) |
1096 | \relates QDebug |
1097 | |
1098 | Writes the contents of \a hash to \a debug. Both \c Key and |
1099 | \c T need to support streaming into QDebug. |
1100 | */ |
1101 | |
1102 | /*! |
1103 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash) |
1104 | \relates QDebug |
1105 | |
1106 | Writes the contents of \a hash to \a debug. Both \c Key and |
1107 | \c T need to support streaming into QDebug. |
1108 | */ |
1109 | |
1110 | /*! |
1111 | \fn template <class T1, class T2> QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair) |
1112 | \relates QDebug |
1113 | |
1114 | Writes the contents of \a pair to \a debug. Both \c T1 and |
1115 | \c T2 need to support streaming into QDebug. |
1116 | */ |
1117 | |
1118 | /*! |
1119 | \since 6.7 |
1120 | \fn template <class T> QDebug operator<<(QDebug debug, const std::optional<T> &opt) |
1121 | \relates QDebug |
1122 | |
1123 | Writes the contents of \a opt (or \c nullopt if not set) to \a debug. |
1124 | \c T needs to support streaming into QDebug. |
1125 | */ |
1126 | |
1127 | /*! |
1128 | \fn template <typename T> QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) |
1129 | \relates QDebug |
1130 | |
1131 | Writes the contents of \a cache to \a debug. \c T needs to |
1132 | support streaming into QDebug. |
1133 | */ |
1134 | |
1135 | /*! |
1136 | \fn template<typename T> QDebug operator<<(QDebug debug, const QFlags<T> &flags) |
1137 | \relates QDebug |
1138 | \since 4.7 |
1139 | |
1140 | Writes \a flags to \a debug. |
1141 | */ |
1142 | |
1143 | /*! |
1144 | \fn template<typename T> QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr) |
1145 | \relates QSharedPointer |
1146 | \since 5.7 |
1147 | |
1148 | Writes the pointer tracked by \a ptr into the debug object \a debug for |
1149 | debugging purposes. |
1150 | |
1151 | \sa {Debugging Techniques} |
1152 | */ |
1153 | |
1154 | /*! |
1155 | \fn QDebug &QDebug::operator<<(std::nullptr_t) |
1156 | \internal |
1157 | */ |
1158 | |
1159 | /*! |
1160 | \since 6.7 |
1161 | \fn QDebug &QDebug::operator<<(std::nullopt_t) |
1162 | |
1163 | Writes nullopt to the stream. |
1164 | */ |
1165 | |
1166 | /*! |
1167 | \class QDebugStateSaver |
1168 | \inmodule QtCore |
1169 | \brief Convenience class for custom QDebug operators. |
1170 | |
1171 | Saves the settings used by QDebug, and restores them upon destruction, |
1172 | then calls \l {QDebug::maybeSpace()}{maybeSpace()}, to separate arguments with a space if |
1173 | \l {QDebug::autoInsertSpaces()}{autoInsertSpaces()} was true at the time of constructing the QDebugStateSaver. |
1174 | |
1175 | The automatic insertion of spaces between writes is one of the settings |
1176 | that QDebugStateSaver stores for the duration of the current block. |
1177 | |
1178 | The settings of the internal QTextStream are also saved and restored, |
1179 | so that using << Qt::hex in a QDebug operator doesn't affect other QDebug |
1180 | operators. |
1181 | |
1182 | QDebugStateSaver is typically used in the implementation of an operator<<() for debugging: |
1183 | |
1184 | \snippet customtype/customtypeexample.cpp custom type streaming operator |
1185 | |
1186 | \since 5.1 |
1187 | */ |
1188 | |
1189 | class QDebugStateSaverPrivate |
1190 | { |
1191 | public: |
1192 | QDebugStateSaverPrivate(QDebug::Stream *stream) |
1193 | : m_stream(stream), |
1194 | m_spaces(stream->space), |
1195 | m_noQuotes(stream->noQuotes), |
1196 | m_verbosity(stream->verbosity), |
1197 | m_streamParams(stream->ts.d_ptr->params) |
1198 | { |
1199 | } |
1200 | void restoreState() |
1201 | { |
1202 | const bool currentSpaces = m_stream->space; |
1203 | if (currentSpaces && !m_spaces) |
1204 | if (m_stream->buffer.endsWith(c: u' ')) |
1205 | m_stream->buffer.chop(n: 1); |
1206 | |
1207 | m_stream->space = m_spaces; |
1208 | m_stream->noQuotes = m_noQuotes; |
1209 | m_stream->ts.d_ptr->params = m_streamParams; |
1210 | m_stream->verbosity = m_verbosity; |
1211 | |
1212 | if (!currentSpaces && m_spaces) |
1213 | m_stream->ts << ' '; |
1214 | } |
1215 | |
1216 | QDebug::Stream *m_stream; |
1217 | |
1218 | // QDebug state |
1219 | const bool m_spaces; |
1220 | const bool m_noQuotes; |
1221 | const int m_verbosity; |
1222 | |
1223 | // QTextStream state |
1224 | const QTextStreamPrivate::Params m_streamParams; |
1225 | }; |
1226 | |
1227 | |
1228 | /*! |
1229 | Creates a QDebugStateSaver instance, which saves the settings |
1230 | currently used by \a dbg. |
1231 | |
1232 | \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() |
1233 | */ |
1234 | QDebugStateSaver::QDebugStateSaver(QDebug &dbg) |
1235 | : d(new QDebugStateSaverPrivate(dbg.stream)) |
1236 | { |
1237 | } |
1238 | |
1239 | /*! |
1240 | Destroys a QDebugStateSaver instance, which restores the settings |
1241 | used when the QDebugStateSaver instance was created. |
1242 | |
1243 | \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() |
1244 | */ |
1245 | QDebugStateSaver::~QDebugStateSaver() |
1246 | { |
1247 | d->restoreState(); |
1248 | } |
1249 | |
1250 | /*! |
1251 | \internal |
1252 | |
1253 | Specialization of the primary template in qdebug.h to out-of-line |
1254 | the common case of QFlags<T>::Int being 32-bit. |
1255 | |
1256 | Just call the generic version so the two don't get out of sync. |
1257 | */ |
1258 | void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value) |
1259 | { |
1260 | qt_QMetaEnum_flagDebugOperator<uint>(debug, sizeofT, value); |
1261 | } |
1262 | |
1263 | #ifndef QT_NO_QOBJECT |
1264 | /*! |
1265 | \internal |
1266 | |
1267 | Formats the given enum \a value for debug output. |
1268 | |
1269 | The supported verbosity are: |
1270 | |
1271 | 0: Just the key, or value with enum name if no key is found: |
1272 | |
1273 | MyEnum2 |
1274 | MyEnum(123) |
1275 | MyScopedEnum::Enum3 |
1276 | MyScopedEnum(456) |
1277 | |
1278 | 1: Same as 0, but treating all enums as scoped: |
1279 | |
1280 | MyEnum::MyEnum2 |
1281 | MyEnum(123) |
1282 | MyScopedEnum::Enum3 |
1283 | MyScopedEnum(456) |
1284 | |
1285 | 2: The QDebug default. Same as 0, and includes class/namespace scope: |
1286 | |
1287 | MyNamespace::MyClass::MyEnum2 |
1288 | MyNamespace::MyClass::MyEnum(123) |
1289 | MyNamespace::MyClass::MyScopedEnum::Enum3 |
1290 | MyNamespace::MyClass::MyScopedEnum(456) |
1291 | |
1292 | 3: Same as 2, but treating all enums as scoped: |
1293 | |
1294 | MyNamespace::MyClass::MyEnum::MyEnum2 |
1295 | MyNamespace::MyClass::MyEnum(123) |
1296 | MyNamespace::MyClass::MyScopedEnum::Enum3 |
1297 | MyNamespace::MyClass::MyScopedEnum(456) |
1298 | */ |
1299 | QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, qint64 value, const QMetaObject *meta, const char *name) |
1300 | { |
1301 | QDebugStateSaver saver(dbg); |
1302 | dbg.nospace(); |
1303 | QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); |
1304 | |
1305 | const int verbosity = dbg.verbosity(); |
1306 | if (verbosity >= QDebug::DefaultVerbosity) { |
1307 | if (const char *scope = me.scope()) |
1308 | dbg << scope << u"::" ; |
1309 | } |
1310 | |
1311 | const char *key = me.valueToKey(value: static_cast<int>(value)); |
1312 | const bool scoped = me.isScoped() || verbosity & 1; |
1313 | if (scoped || !key) |
1314 | dbg << me.enumName() << (!key ? u"(" : u"::" ); |
1315 | |
1316 | if (key) |
1317 | dbg << key; |
1318 | else |
1319 | dbg << value << ')'; |
1320 | |
1321 | return dbg; |
1322 | } |
1323 | |
1324 | /*! |
1325 | \fn QDebug qt_QMetaEnum_flagDebugOperator(QDebug &, quint64 value, const QMetaObject *, const char *name) |
1326 | \internal |
1327 | |
1328 | Formats the given flag \a value for debug output. |
1329 | |
1330 | The supported verbosity are: |
1331 | |
1332 | 0: Just the key(s): |
1333 | |
1334 | MyFlag1 |
1335 | MyFlag2|MyFlag3 |
1336 | MyScopedFlag(MyFlag2) |
1337 | MyScopedFlag(MyFlag2|MyFlag3) |
1338 | |
1339 | 1: Same as 0, but treating all flags as scoped: |
1340 | |
1341 | MyFlag(MyFlag1) |
1342 | MyFlag(MyFlag2|MyFlag3) |
1343 | MyScopedFlag(MyFlag2) |
1344 | MyScopedFlag(MyFlag2|MyFlag3) |
1345 | |
1346 | 2: The QDebug default. Same as 1, and includes class/namespace scope: |
1347 | |
1348 | QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) |
1349 | QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3) |
1350 | QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2) |
1351 | QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3) |
1352 | */ |
1353 | QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaObject *meta, const char *name) |
1354 | { |
1355 | const int verbosity = debug.verbosity(); |
1356 | |
1357 | QDebugStateSaver saver(debug); |
1358 | debug.resetFormat(); |
1359 | debug.noquote(); |
1360 | debug.nospace(); |
1361 | |
1362 | const QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); |
1363 | |
1364 | const bool classScope = verbosity >= QDebug::DefaultVerbosity; |
1365 | if (classScope) { |
1366 | debug << u"QFlags<" ; |
1367 | |
1368 | if (const char *scope = me.scope()) |
1369 | debug << scope << u"::" ; |
1370 | } |
1371 | |
1372 | const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity; |
1373 | if (enumScope) { |
1374 | debug << me.enumName(); |
1375 | if (classScope) |
1376 | debug << '>'; |
1377 | debug << '('; |
1378 | } |
1379 | |
1380 | debug << me.valueToKeys(value: static_cast<int>(value)); |
1381 | |
1382 | if (enumScope) |
1383 | debug << ')'; |
1384 | |
1385 | return debug; |
1386 | } |
1387 | #endif // !QT_NO_QOBJECT |
1388 | |
1389 | QT_END_NAMESPACE |
1390 | |