| 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.get(), 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.get(), 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 |     \memberswap{debug stream instance} | 
| 520 | */ | 
| 521 |  | 
| 522 | /*! | 
| 523 |     Resets the stream formatting options, bringing it back to its original constructed state. | 
| 524 |  | 
| 525 |     \sa space(), quote() | 
| 526 |     \since 5.4 | 
| 527 | */ | 
| 528 | QDebug &QDebug::resetFormat() | 
| 529 | { | 
| 530 |     stream->ts.reset(); | 
| 531 |     stream->space = true; | 
| 532 |     stream->noQuotes = false; | 
| 533 |     stream->verbosity = DefaultVerbosity; | 
| 534 |     return *this; | 
| 535 | } | 
| 536 |  | 
| 537 | /*! | 
| 538 |     \fn QDebug &QDebug::space() | 
| 539 |  | 
| 540 |     Writes a space character to the debug stream and returns a reference to | 
| 541 |     the stream. | 
| 542 |  | 
| 543 |     The stream remembers that automatic insertion of spaces is | 
| 544 |     enabled for future writes. | 
| 545 |  | 
| 546 |     \sa nospace(), maybeSpace() | 
| 547 | */ | 
| 548 |  | 
| 549 | /*! | 
| 550 |     \fn QDebug &QDebug::nospace() | 
| 551 |  | 
| 552 |     Disables automatic insertion of spaces and returns a reference to the stream. | 
| 553 |  | 
| 554 |     \sa space(), maybeSpace() | 
| 555 | */ | 
| 556 |  | 
| 557 | /*! | 
| 558 |     \fn QDebug &QDebug::maybeSpace() | 
| 559 |  | 
| 560 |     Writes a space character to the debug stream, depending on the current | 
| 561 |     setting for automatic insertion of spaces, and returns a reference to the stream. | 
| 562 |  | 
| 563 |     \sa space(), nospace() | 
| 564 | */ | 
| 565 |  | 
| 566 | /*! | 
| 567 |     \fn bool QDebug::autoInsertSpaces() const | 
| 568 |  | 
| 569 |     Returns \c true if this QDebug instance will automatically insert spaces | 
| 570 |     between writes. | 
| 571 |  | 
| 572 |     \since 5.0 | 
| 573 |  | 
| 574 |     \sa QDebugStateSaver | 
| 575 | */ | 
| 576 |  | 
| 577 | /*! | 
| 578 |     \fn void QDebug::setAutoInsertSpaces(bool b) | 
| 579 |  | 
| 580 |     Enables automatic insertion of spaces between writes if \a b is true; otherwise | 
| 581 |     automatic insertion of spaces is disabled. | 
| 582 |  | 
| 583 |     \since 5.0 | 
| 584 |  | 
| 585 |     \sa QDebugStateSaver | 
| 586 | */ | 
| 587 |  | 
| 588 |  | 
| 589 | /*! | 
| 590 |     \fn bool QDebug::quoteStrings() const | 
| 591 |     \since 6.7 | 
| 592 |  | 
| 593 |     Returns \c true if this QDebug instance will quote strings streamed into | 
| 594 |     it (which is the default). | 
| 595 |  | 
| 596 |     \sa QDebugStateSaver, quote(), noquote(), setQuoteStrings() | 
| 597 | */ | 
| 598 |  | 
| 599 | /*! | 
| 600 |     \fn void QDebug::setQuoteStrings(bool b) | 
| 601 |     \since 6.7 | 
| 602 |  | 
| 603 |     Enables quoting of strings streamed into this QDebug instance if \a b is | 
| 604 |     \c true; otherwise quoting is disabled. | 
| 605 |  | 
| 606 |     The default is to quote strings. | 
| 607 |  | 
| 608 |     \sa QDebugStateSaver, quote(), noquote(), quoteStrings() | 
| 609 | */ | 
| 610 |  | 
| 611 |  | 
| 612 | /*! | 
| 613 |     \fn QDebug &QDebug::quote() | 
| 614 |     \since 5.4 | 
| 615 |  | 
| 616 |     Enables automatic insertion of quotation characters around QChar, QString and QByteArray | 
| 617 |     contents and returns a reference to the stream. | 
| 618 |  | 
| 619 |     Quoting is enabled by default. | 
| 620 |  | 
| 621 |     \sa noquote(), maybeQuote() | 
| 622 | */ | 
| 623 |  | 
| 624 | /*! | 
| 625 |     \fn QDebug &QDebug::noquote() | 
| 626 |     \since 5.4 | 
| 627 |  | 
| 628 |     Disables automatic insertion of quotation characters around QChar, QString and QByteArray | 
| 629 |     contents and returns a reference to the stream. | 
| 630 |  | 
| 631 |     When quoting is disabled, these types are printed without quotation | 
| 632 |     characters and without escaping of non-printable characters. | 
| 633 |  | 
| 634 |     \sa quote(), maybeQuote() | 
| 635 | */ | 
| 636 |  | 
| 637 | /*! | 
| 638 |     \fn QDebug &QDebug::maybeQuote(char c) | 
| 639 |     \since 5.4 | 
| 640 |  | 
| 641 |     Writes a character \a c to the debug stream, depending on the | 
| 642 |     current setting for automatic insertion of quotes, and returns a reference to the stream. | 
| 643 |  | 
| 644 |     The default character is a double quote \c{"}. | 
| 645 |  | 
| 646 |     \sa quote(), noquote() | 
| 647 | */ | 
| 648 |  | 
| 649 | /*! | 
| 650 |     \fn int QDebug::verbosity() const | 
| 651 |     \since 5.6 | 
| 652 |  | 
| 653 |     Returns the verbosity of the debug stream. | 
| 654 |  | 
| 655 |     Streaming operators can check the value to decide whether | 
| 656 |     verbose output is desired and print more information depending on the | 
| 657 |     level. Higher values indicate that more information is desired. | 
| 658 |  | 
| 659 |     The allowed range is from 0 to 7. The default value is 2. | 
| 660 |  | 
| 661 |     \sa setVerbosity(), VerbosityLevel | 
| 662 | */ | 
| 663 |  | 
| 664 | /*! | 
| 665 |     \fn void QDebug::setVerbosity(int verbosityLevel) | 
| 666 |     \since 5.6 | 
| 667 |  | 
| 668 |     Sets the verbosity of the stream to \a verbosityLevel. | 
| 669 |  | 
| 670 |     The allowed range is from 0 to 7. The default value is 2. | 
| 671 |  | 
| 672 |     \sa verbosity(), VerbosityLevel | 
| 673 | */ | 
| 674 |  | 
| 675 | /*! | 
| 676 |     \fn QDebug &QDebug::verbosity(int verbosityLevel) | 
| 677 |     \since 5.13 | 
| 678 |  | 
| 679 |     Sets the verbosity of the stream to \a verbosityLevel and returns a reference to the stream. | 
| 680 |  | 
| 681 |     The allowed range is from 0 to 7. The default value is 2. | 
| 682 |  | 
| 683 |     \sa verbosity(), setVerbosity(), VerbosityLevel | 
| 684 | */ | 
| 685 |  | 
| 686 | /*! | 
| 687 |     \enum QDebug::VerbosityLevel | 
| 688 |     \since 5.13 | 
| 689 |  | 
| 690 |     This enum describes the range of verbosity levels. | 
| 691 |  | 
| 692 |     \value MinimumVerbosity | 
| 693 |     \value DefaultVerbosity | 
| 694 |     \value MaximumVerbosity | 
| 695 |  | 
| 696 |     \sa verbosity(), setVerbosity() | 
| 697 | */ | 
| 698 |  | 
| 699 | /*! | 
| 700 |     \fn QDebug &QDebug::operator<<(QChar t) | 
| 701 |  | 
| 702 |     Writes the character, \a t, to the stream and returns a reference to the | 
| 703 |     stream. Normally, QDebug prints control characters and non-US-ASCII | 
| 704 |     characters as their C escape sequences or their Unicode value (\\u1234). To | 
| 705 |     print non-printable characters without transformation, enable the noquote() | 
| 706 |     functionality, but note that some QDebug backends may not be 8-bit clean | 
| 707 |     and may not be able to represent \c t. | 
| 708 | */ | 
| 709 |  | 
| 710 | /*! | 
| 711 |     \fn QDebug &QDebug::operator<<(bool t) | 
| 712 |  | 
| 713 |     Writes the boolean value, \a t, to the stream and returns a reference to the | 
| 714 |     stream. | 
| 715 | */ | 
| 716 |  | 
| 717 | /*! | 
| 718 |     \fn QDebug &QDebug::operator<<(char t) | 
| 719 |  | 
| 720 |     Writes the character, \a t, to the stream and returns a reference to the | 
| 721 |     stream. | 
| 722 | */ | 
| 723 |  | 
| 724 | /*! | 
| 725 |     \fn QDebug &QDebug::operator<<(signed short t) | 
| 726 |  | 
| 727 |     Writes the signed short integer, \a t, to the stream and returns a reference | 
| 728 |     to the stream. | 
| 729 | */ | 
| 730 |  | 
| 731 | /*! | 
| 732 |     \fn QDebug &QDebug::operator<<(unsigned short t) | 
| 733 |  | 
| 734 |     Writes then unsigned short integer, \a t, to the stream and returns a | 
| 735 |     reference to the stream. | 
| 736 | */ | 
| 737 |  | 
| 738 | /*! | 
| 739 |     \fn QDebug &QDebug::operator<<(signed int t) | 
| 740 |  | 
| 741 |     Writes the signed integer, \a t, to the stream and returns a reference | 
| 742 |     to the stream. | 
| 743 | */ | 
| 744 |  | 
| 745 | /*! | 
| 746 |     \fn QDebug &QDebug::operator<<(unsigned int t) | 
| 747 |  | 
| 748 |     Writes then unsigned integer, \a t, to the stream and returns a reference to | 
| 749 |     the stream. | 
| 750 | */ | 
| 751 |  | 
| 752 | /*! | 
| 753 |     \fn QDebug &QDebug::operator<<(signed long t) | 
| 754 |  | 
| 755 |     Writes the signed long integer, \a t, to the stream and returns a reference | 
| 756 |     to the stream. | 
| 757 | */ | 
| 758 |  | 
| 759 | /*! | 
| 760 |     \fn QDebug &QDebug::operator<<(unsigned long t) | 
| 761 |  | 
| 762 |     Writes then unsigned long integer, \a t, to the stream and returns a reference | 
| 763 |     to the stream. | 
| 764 | */ | 
| 765 |  | 
| 766 | /*! | 
| 767 |     \fn QDebug &QDebug::operator<<(qint64 t) | 
| 768 |  | 
| 769 |     Writes the signed 64-bit integer, \a t, to the stream and returns a reference | 
| 770 |     to the stream. | 
| 771 | */ | 
| 772 |  | 
| 773 | /*! | 
| 774 |     \fn QDebug &QDebug::operator<<(quint64 t) | 
| 775 |  | 
| 776 |     Writes then unsigned 64-bit integer, \a t, to the stream and returns a | 
| 777 |     reference to the stream. | 
| 778 | */ | 
| 779 |  | 
| 780 | /*! | 
| 781 |     \fn QDebug &QDebug::operator<<(float t) | 
| 782 |  | 
| 783 |     Writes the 32-bit floating point number, \a t, to the stream and returns a | 
| 784 |     reference to the stream. | 
| 785 | */ | 
| 786 |  | 
| 787 | /*! | 
| 788 |     \fn QDebug &QDebug::operator<<(double t) | 
| 789 |  | 
| 790 |     Writes the 64-bit floating point number, \a t, to the stream and returns a | 
| 791 |     reference to the stream. | 
| 792 | */ | 
| 793 |  | 
| 794 | /*! | 
| 795 |     \fn QDebug &QDebug::operator<<(const char *t) | 
| 796 |  | 
| 797 |     Writes the '\\0'-terminated UTF-8 string, \a t, to the stream and returns a | 
| 798 |     reference to the stream. The string is never quoted or escaped for the | 
| 799 |     output. Note that QDebug buffers internally as UTF-16 and may need to | 
| 800 |     transform to 8-bit using the locale's codec in order to use some backends, | 
| 801 |     which may cause garbled output (mojibake). Restricting to US-ASCII strings | 
| 802 |     is recommended. | 
| 803 | */ | 
| 804 |  | 
| 805 | /*! | 
| 806 |     \fn QDebug &QDebug::operator<<(const char16_t *t) | 
| 807 |     \since 6.0 | 
| 808 |  | 
| 809 |     Writes the u'\\0'-terminated UTF-16 string, \a t, to the stream and returns | 
| 810 |     a reference to the stream. The string is never quoted or escaped for the | 
| 811 |     output. Note that QDebug buffers internally as UTF-16 and may need to | 
| 812 |     transform to 8-bit using the locale's codec in order to use some backends, | 
| 813 |     which may cause garbled output (mojibake). Restricting to US-ASCII strings | 
| 814 |     is recommended. | 
| 815 | */ | 
| 816 |  | 
| 817 | /*! | 
| 818 |     \fn QDebug &QDebug::operator<<(char16_t t) | 
| 819 |     \since 5.5 | 
| 820 |  | 
| 821 |     Writes the UTF-16 character, \a t, to the stream and returns a reference | 
| 822 |     to the stream. | 
| 823 | */ | 
| 824 |  | 
| 825 | /*! | 
| 826 |     \fn QDebug &QDebug::operator<<(char32_t t) | 
| 827 |     \since 5.5 | 
| 828 |  | 
| 829 |     Writes the UTF-32 character, \a t, to the stream and returns a reference | 
| 830 |     to the stream. | 
| 831 | */ | 
| 832 |  | 
| 833 | /*! | 
| 834 |     \fn QDebug &QDebug::operator<<(const QString &t) | 
| 835 |  | 
| 836 |     Writes the string, \a t, to the stream and returns a reference to the | 
| 837 |     stream. Normally, QDebug prints the string inside quotes and transforms | 
| 838 |     non-printable characters to their Unicode values (\\u1234). | 
| 839 |  | 
| 840 |     To print non-printable characters without transformation, enable the | 
| 841 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 842 |     clean. | 
| 843 |  | 
| 844 |     Output examples: | 
| 845 |     \snippet code/src_corelib_io_qdebug.cpp 0 | 
| 846 | */ | 
| 847 |  | 
| 848 | /*! | 
| 849 |     \since 5.10 | 
| 850 |     \fn QDebug &QDebug::operator<<(QStringView s) | 
| 851 |  | 
| 852 |     Writes the string view, \a s, to the stream and returns a reference to the | 
| 853 |     stream. Normally, QDebug prints the string inside quotes and transforms | 
| 854 |     non-printable characters to their Unicode values (\\u1234). | 
| 855 |  | 
| 856 |     To print non-printable characters without transformation, enable the | 
| 857 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 858 |     clean. | 
| 859 |  | 
| 860 |     See the QString overload for examples. | 
| 861 | */ | 
| 862 |  | 
| 863 | /*! | 
| 864 |     \since 6.0 | 
| 865 |     \fn QDebug &QDebug::operator<<(QUtf8StringView s) | 
| 866 |  | 
| 867 |     Writes the string view, \a s, to the stream and returns a reference to the | 
| 868 |     stream. | 
| 869 |  | 
| 870 |     Normally, QDebug prints the data inside quotes and transforms control or | 
| 871 |     non-US-ASCII characters to their C escape sequences (\\xAB). This way, the | 
| 872 |     output is always 7-bit clean and the string can be copied from the output | 
| 873 |     and pasted back into C++ sources, if necessary. | 
| 874 |  | 
| 875 |     To print non-printable characters without transformation, enable the | 
| 876 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 877 |     clean. | 
| 878 | */ | 
| 879 |  | 
| 880 | /*! | 
| 881 |     \fn QDebug &QDebug::operator<<(QLatin1StringView t) | 
| 882 |  | 
| 883 |     Writes the string, \a t, to the stream and returns a reference to the | 
| 884 |     stream. Normally, QDebug prints the string inside quotes and transforms | 
| 885 |     non-printable characters to their Unicode values (\\u1234). | 
| 886 |  | 
| 887 |     To print non-printable characters without transformation, enable the | 
| 888 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 889 |     clean. | 
| 890 |  | 
| 891 |     See the QString overload for examples. | 
| 892 | */ | 
| 893 |  | 
| 894 | /*! | 
| 895 |     \fn QDebug &QDebug::operator<<(const QByteArray &t) | 
| 896 |  | 
| 897 |     Writes the byte array, \a t, to the stream and returns a reference to the | 
| 898 |     stream. Normally, QDebug prints the array inside quotes and transforms | 
| 899 |     control or non-US-ASCII characters to their C escape sequences (\\xAB). This | 
| 900 |     way, the output is always 7-bit clean and the string can be copied from the | 
| 901 |     output and pasted back into C++ sources, if necessary. | 
| 902 |  | 
| 903 |     To print non-printable characters without transformation, enable the | 
| 904 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 905 |     clean. | 
| 906 |  | 
| 907 |     Output examples: | 
| 908 |     \snippet code/src_corelib_io_qdebug.cpp 1 | 
| 909 |  | 
| 910 |     Note how QDebug needed to close and reopen the string in the way C and C++ | 
| 911 |     languages concatenate string literals so that the letter 'b' is not | 
| 912 |     interpreted as part of the previous hexadecimal escape sequence. | 
| 913 | */ | 
| 914 |  | 
| 915 | /*! | 
| 916 |     \since 6.0 | 
| 917 |     \fn QDebug &QDebug::operator<<(QByteArrayView t) | 
| 918 |  | 
| 919 |     Writes the data of the observed byte array, \a t, to the stream and returns | 
| 920 |     a reference to the stream. | 
| 921 |  | 
| 922 |     Normally, QDebug prints the data inside quotes and transforms control or | 
| 923 |     non-US-ASCII characters to their C escape sequences (\\xAB). This way, the | 
| 924 |     output is always 7-bit clean and the string can be copied from the output | 
| 925 |     and pasted back into C++ sources, if necessary. | 
| 926 |  | 
| 927 |     To print non-printable characters without transformation, enable the | 
| 928 |     noquote() functionality. Note that some QDebug backends might not be 8-bit | 
| 929 |     clean. | 
| 930 |  | 
| 931 |     See the QByteArray overload for examples. | 
| 932 | */ | 
| 933 |  | 
| 934 | /*! | 
| 935 |     \fn QDebug &QDebug::operator<<(const void *t) | 
| 936 |  | 
| 937 |     Writes a pointer, \a t, to the stream and returns a reference to the stream. | 
| 938 | */ | 
| 939 |  | 
| 940 | /*! | 
| 941 |     \fn QDebug &QDebug::operator<<(QTextStreamFunction f) | 
| 942 |     \internal | 
| 943 | */ | 
| 944 |  | 
| 945 | /*! | 
| 946 |     \fn QDebug &QDebug::operator<<(QTextStreamManipulator m) | 
| 947 |     \internal | 
| 948 | */ | 
| 949 |  | 
| 950 | /*! | 
| 951 |     \since 6.5 | 
| 952 |     \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(const std::basic_string<Char, Args...> &s) | 
| 953 |     \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(std::basic_string_view<Char, Args...> s) | 
| 954 |  | 
| 955 |     Writes the string or string-view \a s to the stream and returns a reference | 
| 956 |     to the stream. | 
| 957 |  | 
| 958 |     These operators only participate in overload resolution if \c Char is one of | 
| 959 |     \list | 
| 960 |     \li char | 
| 961 |     \li char8_t (C++20 only) | 
| 962 |     \li char16_t | 
| 963 |     \li char32_t | 
| 964 |     \li wchar_t | 
| 965 |     \endlist | 
| 966 | */ | 
| 967 |  | 
| 968 | /*! | 
| 969 |     \since 6.6 | 
| 970 |     \fn template <typename Rep, typename Period> QDebug &QDebug::operator<<(std::chrono::duration<Rep, Period> duration) | 
| 971 |  | 
| 972 |     Prints the time duration \a duration to the stream and returns a reference | 
| 973 |     to the stream. The printed string is the numeric representation of the | 
| 974 |     period followed by the time unit, similar to what the C++ Standard Library | 
| 975 |     would produce with \c{std::ostream}. | 
| 976 |  | 
| 977 |     The unit is not localized. | 
| 978 | */ | 
| 979 |  | 
| 980 | /*! | 
| 981 |     \fn template <typename T, QDebug::if_qint128<T>> QDebug::operator<<(T i) | 
| 982 |     \fn template <typename T, QDebug::if_quint128<T>> QDebug::operator<<(T i) | 
| 983 |     \since 6.7 | 
| 984 |  | 
| 985 |     Prints the textual representation of the 128-bit integer \a i. | 
| 986 |  | 
| 987 |     \note This operator is only available if Qt supports 128-bit integer types. | 
| 988 |     If 128-bit integer types are available in your build, but the Qt libraries | 
| 989 |     were compiled without, the operator will print a warning instead. | 
| 990 |  | 
| 991 |     \note Because the operator is a function template, no implicit conversions | 
| 992 |     are performed on its argument. It must be exactly qint128/quint128. | 
| 993 |  | 
| 994 |     \sa QT_SUPPORTS_INT128 | 
| 995 | */ | 
| 996 |  | 
| 997 | /*! | 
| 998 |     \fn template <class T> QString QDebug::toString(const T &object) | 
| 999 |     \since 6.0 | 
| 1000 |  | 
| 1001 |     \include qdebug-toString.qdocinc | 
| 1002 | */ | 
| 1003 |  | 
| 1004 | /*! \internal */ | 
| 1005 | QString QDebug::toStringImpl(StreamTypeErased s, const void *obj) | 
| 1006 | { | 
| 1007 |     QString result; | 
| 1008 |     { | 
| 1009 |         QDebug d(&result); | 
| 1010 |         s(d.nospace(), obj); | 
| 1011 |     } | 
| 1012 |     return result; | 
| 1013 | } | 
| 1014 |  | 
| 1015 | /*! | 
| 1016 |     \fn template <class T> QDebug operator<<(QDebug debug, const QList<T> &list) | 
| 1017 |     \relates QDebug | 
| 1018 |  | 
| 1019 |     Writes the contents of \a list to \a debug. \c T needs to | 
| 1020 |     support streaming into QDebug. | 
| 1021 | */ | 
| 1022 |  | 
| 1023 | /*! | 
| 1024 |     \fn template <class T, qsizetype P> QDebug operator<<(QDebug debug, const QVarLengthArray<T,P> &array) | 
| 1025 |     \relates QDebug | 
| 1026 |     \since 6.3 | 
| 1027 |  | 
| 1028 |     Writes the contents of \a array to \a debug. \c T needs to | 
| 1029 |     support streaming into QDebug. | 
| 1030 | */ | 
| 1031 |  | 
| 1032 | /*! | 
| 1033 |     \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec) | 
| 1034 |     \relates QDebug | 
| 1035 |     \since 5.7 | 
| 1036 |  | 
| 1037 |     Writes the contents of list \a vec to \a debug. \c T needs to | 
| 1038 |     support streaming into QDebug. | 
| 1039 | */ | 
| 1040 |  | 
| 1041 | /*! | 
| 1042 |     \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec) | 
| 1043 |     \relates QDebug | 
| 1044 |     \since 5.7 | 
| 1045 |  | 
| 1046 |     Writes the contents of vector \a vec to \a debug. \c T needs to | 
| 1047 |     support streaming into QDebug. | 
| 1048 | */ | 
| 1049 |  | 
| 1050 | /*! | 
| 1051 |     \fn template <typename T> QDebug operator<<(QDebug debug, const QSet<T> &set) | 
| 1052 |     \relates QDebug | 
| 1053 |  | 
| 1054 |     Writes the contents of \a set to \a debug. \c T needs to | 
| 1055 |     support streaming into QDebug. | 
| 1056 | */ | 
| 1057 |  | 
| 1058 | /*! | 
| 1059 |     \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMap<Key, T> &map) | 
| 1060 |     \relates QDebug | 
| 1061 |  | 
| 1062 |     Writes the contents of \a map to \a debug. Both \c Key and | 
| 1063 |     \c T need to support streaming into QDebug. | 
| 1064 | */ | 
| 1065 |  | 
| 1066 | /*! | 
| 1067 |     \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map) | 
| 1068 |     \relates QDebug | 
| 1069 |  | 
| 1070 |     Writes the contents of \a map to \a debug. Both \c Key and | 
| 1071 |     \c T need to support streaming into QDebug. | 
| 1072 | */ | 
| 1073 |  | 
| 1074 | /*! | 
| 1075 |     \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map) | 
| 1076 |     \relates QDebug | 
| 1077 |     \since 5.7 | 
| 1078 |  | 
| 1079 |     Writes the contents of \a map to \a debug. Both \c Key and | 
| 1080 |     \c T need to support streaming into QDebug. | 
| 1081 | */ | 
| 1082 |  | 
| 1083 | /*! | 
| 1084 |     \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map) | 
| 1085 |     \relates QDebug | 
| 1086 |     \since 5.7 | 
| 1087 |  | 
| 1088 |     Writes the contents of \a map to \a debug. Both \c Key and | 
| 1089 |     \c T need to support streaming into QDebug. | 
| 1090 | */ | 
| 1091 |  | 
| 1092 | /*! | 
| 1093 |     \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QHash<Key, T> &hash) | 
| 1094 |     \relates QDebug | 
| 1095 |  | 
| 1096 |     Writes the contents of \a hash to \a debug. Both \c Key and | 
| 1097 |     \c T need to support streaming into QDebug. | 
| 1098 | */ | 
| 1099 |  | 
| 1100 | /*! | 
| 1101 |     \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash) | 
| 1102 |     \relates QDebug | 
| 1103 |  | 
| 1104 |     Writes the contents of \a hash to \a debug. Both \c Key and | 
| 1105 |     \c T need to support streaming into QDebug. | 
| 1106 | */ | 
| 1107 |  | 
| 1108 | /*! | 
| 1109 |     \fn template <class T1, class T2> QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair) | 
| 1110 |     \relates QDebug | 
| 1111 |  | 
| 1112 |     Writes the contents of \a pair to \a debug. Both \c T1 and | 
| 1113 |     \c T2 need to support streaming into QDebug. | 
| 1114 | */ | 
| 1115 |  | 
| 1116 | /*! | 
| 1117 |     \since 6.7 | 
| 1118 |     \fn template <class T> QDebug operator<<(QDebug debug, const std::optional<T> &opt) | 
| 1119 |     \relates QDebug | 
| 1120 |  | 
| 1121 |     Writes the contents of \a opt (or \c nullopt if not set) to \a debug. | 
| 1122 |     \c T needs to support streaming into QDebug. | 
| 1123 | */ | 
| 1124 |  | 
| 1125 | /*! | 
| 1126 |     \fn template <typename T> QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) | 
| 1127 |     \relates QDebug | 
| 1128 |  | 
| 1129 |     Writes the contents of \a cache to \a debug. \c T needs to | 
| 1130 |     support streaming into QDebug. | 
| 1131 | */ | 
| 1132 |  | 
| 1133 | /*! | 
| 1134 |     \fn template<typename T> QDebug operator<<(QDebug debug, const QFlags<T> &flags) | 
| 1135 |     \relates QDebug | 
| 1136 |     \since 4.7 | 
| 1137 |  | 
| 1138 |     Writes \a flags to \a debug. | 
| 1139 | */ | 
| 1140 |  | 
| 1141 | /*! | 
| 1142 |     \fn template<typename T> QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr) | 
| 1143 |     \relates QSharedPointer | 
| 1144 |     \since 5.7 | 
| 1145 |  | 
| 1146 |     Writes the pointer tracked by \a ptr into the debug object \a debug for | 
| 1147 |     debugging purposes. | 
| 1148 |  | 
| 1149 |     \sa {Debugging Techniques} | 
| 1150 | */ | 
| 1151 |  | 
| 1152 | /*! | 
| 1153 |   \fn QDebug &QDebug::operator<<(std::nullptr_t) | 
| 1154 |   \internal | 
| 1155 |  */ | 
| 1156 |  | 
| 1157 | /*! | 
| 1158 |     \since 6.7 | 
| 1159 |     \fn QDebug &QDebug::operator<<(std::nullopt_t) | 
| 1160 |  | 
| 1161 |     Writes nullopt to the stream. | 
| 1162 | */ | 
| 1163 |  | 
| 1164 | /*! | 
| 1165 |     \class QDebugStateSaver | 
| 1166 |     \inmodule QtCore | 
| 1167 |     \brief Convenience class for custom QDebug operators. | 
| 1168 |  | 
| 1169 |     Saves the settings used by QDebug, and restores them upon destruction, | 
| 1170 |     then calls \l {QDebug::maybeSpace()}{maybeSpace()}, to separate arguments with a space if | 
| 1171 |     \l {QDebug::autoInsertSpaces()}{autoInsertSpaces()} was true at the time of constructing the QDebugStateSaver. | 
| 1172 |  | 
| 1173 |     The automatic insertion of spaces between writes is one of the settings | 
| 1174 |     that QDebugStateSaver stores for the duration of the current block. | 
| 1175 |  | 
| 1176 |     The settings of the internal QTextStream are also saved and restored, | 
| 1177 |     so that using << Qt::hex in a QDebug operator doesn't affect other QDebug | 
| 1178 |     operators. | 
| 1179 |  | 
| 1180 |     QDebugStateSaver is typically used in the implementation of an operator<<() for debugging: | 
| 1181 |  | 
| 1182 |     \snippet customtype/customtypeexample.cpp custom type streaming operator | 
| 1183 |  | 
| 1184 |     \since 5.1 | 
| 1185 | */ | 
| 1186 |  | 
| 1187 | class QDebugStateSaverPrivate | 
| 1188 | { | 
| 1189 | public: | 
| 1190 |     QDebugStateSaverPrivate(QDebug::Stream *stream) | 
| 1191 |         : m_stream(stream), | 
| 1192 |           m_spaces(stream->space), | 
| 1193 |           m_noQuotes(stream->noQuotes), | 
| 1194 |           m_verbosity(stream->verbosity), | 
| 1195 |           m_streamParams(stream->ts.d_ptr->params) | 
| 1196 |     { | 
| 1197 |     } | 
| 1198 |     void restoreState() | 
| 1199 |     { | 
| 1200 |         const bool currentSpaces = m_stream->space; | 
| 1201 |         if (currentSpaces && !m_spaces) | 
| 1202 |             if (m_stream->buffer.endsWith(c: u' ')) | 
| 1203 |                 m_stream->buffer.chop(n: 1); | 
| 1204 |  | 
| 1205 |         m_stream->space = m_spaces; | 
| 1206 |         m_stream->noQuotes = m_noQuotes; | 
| 1207 |         m_stream->ts.d_ptr->params = m_streamParams; | 
| 1208 |         m_stream->verbosity = m_verbosity; | 
| 1209 |  | 
| 1210 |         if (!currentSpaces && m_spaces) | 
| 1211 |             m_stream->ts << ' '; | 
| 1212 |     } | 
| 1213 |  | 
| 1214 |     QDebug::Stream *m_stream; | 
| 1215 |  | 
| 1216 |     // QDebug state | 
| 1217 |     const bool m_spaces; | 
| 1218 |     const bool m_noQuotes; | 
| 1219 |     const int m_verbosity; | 
| 1220 |  | 
| 1221 |     // QTextStream state | 
| 1222 |     const QTextStreamPrivate::Params m_streamParams; | 
| 1223 | }; | 
| 1224 |  | 
| 1225 |  | 
| 1226 | /*! | 
| 1227 |     Creates a QDebugStateSaver instance, which saves the settings | 
| 1228 |     currently used by \a dbg. | 
| 1229 |  | 
| 1230 |     \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() | 
| 1231 | */ | 
| 1232 | QDebugStateSaver::QDebugStateSaver(QDebug &dbg) | 
| 1233 |     : d(new QDebugStateSaverPrivate(dbg.stream)) | 
| 1234 | { | 
| 1235 | } | 
| 1236 |  | 
| 1237 | /*! | 
| 1238 |     Destroys a QDebugStateSaver instance, which restores the settings | 
| 1239 |     used when the QDebugStateSaver instance was created. | 
| 1240 |  | 
| 1241 |     \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() | 
| 1242 | */ | 
| 1243 | QDebugStateSaver::~QDebugStateSaver() | 
| 1244 | { | 
| 1245 |     d->restoreState(); | 
| 1246 | } | 
| 1247 |  | 
| 1248 | /*! | 
| 1249 |     \internal | 
| 1250 |  | 
| 1251 |     Specialization of the primary template in qdebug.h to out-of-line | 
| 1252 |     the common case of QFlags<T>::Int being 32-bit. | 
| 1253 |  | 
| 1254 |     Just call the generic version so the two don't get out of sync. | 
| 1255 | */ | 
| 1256 | void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value) | 
| 1257 | { | 
| 1258 |     qt_QMetaEnum_flagDebugOperator<uint>(debug, sizeofT, value); | 
| 1259 | } | 
| 1260 |  | 
| 1261 | #ifndef QT_NO_QOBJECT | 
| 1262 | /*! | 
| 1263 |     \internal | 
| 1264 |  | 
| 1265 |     Formats the given enum \a value for debug output. | 
| 1266 |  | 
| 1267 |     The supported verbosity are: | 
| 1268 |  | 
| 1269 |       0: Just the key, or value with enum name if no key is found: | 
| 1270 |  | 
| 1271 |          MyEnum2 | 
| 1272 |          MyEnum(123) | 
| 1273 |          MyScopedEnum::Enum3 | 
| 1274 |          MyScopedEnum(456) | 
| 1275 |  | 
| 1276 |       1: Same as 0, but treating all enums as scoped: | 
| 1277 |  | 
| 1278 |          MyEnum::MyEnum2 | 
| 1279 |          MyEnum(123) | 
| 1280 |          MyScopedEnum::Enum3 | 
| 1281 |          MyScopedEnum(456) | 
| 1282 |  | 
| 1283 |       2: The QDebug default. Same as 0, and includes class/namespace scope: | 
| 1284 |  | 
| 1285 |          MyNamespace::MyClass::MyEnum2 | 
| 1286 |          MyNamespace::MyClass::MyEnum(123) | 
| 1287 |          MyNamespace::MyClass::MyScopedEnum::Enum3 | 
| 1288 |          MyNamespace::MyClass::MyScopedEnum(456) | 
| 1289 |  | 
| 1290 |       3: Same as 2, but treating all enums as scoped: | 
| 1291 |  | 
| 1292 |          MyNamespace::MyClass::MyEnum::MyEnum2 | 
| 1293 |          MyNamespace::MyClass::MyEnum(123) | 
| 1294 |          MyNamespace::MyClass::MyScopedEnum::Enum3 | 
| 1295 |          MyNamespace::MyClass::MyScopedEnum(456) | 
| 1296 |  */ | 
| 1297 | QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, qint64 value, const QMetaObject *meta, const char *name) | 
| 1298 | { | 
| 1299 |     QDebugStateSaver saver(dbg); | 
| 1300 |     dbg.nospace(); | 
| 1301 |     QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); | 
| 1302 |  | 
| 1303 |     const int verbosity = dbg.verbosity(); | 
| 1304 |     if (verbosity >= QDebug::DefaultVerbosity) { | 
| 1305 |         if (const char *scope = me.scope()) | 
| 1306 |             dbg << scope << u"::" ; | 
| 1307 |     } | 
| 1308 |  | 
| 1309 |     const char *key = me.valueToKey(value: static_cast<int>(value)); | 
| 1310 |     const bool scoped = me.isScoped() || verbosity & 1; | 
| 1311 |     if (scoped || !key) | 
| 1312 |         dbg << me.enumName() << (!key ? u"("  : u"::" ); | 
| 1313 |  | 
| 1314 |     if (key) | 
| 1315 |         dbg << key; | 
| 1316 |     else | 
| 1317 |         dbg << value << ')'; | 
| 1318 |  | 
| 1319 |     return dbg; | 
| 1320 | } | 
| 1321 |  | 
| 1322 | /*! | 
| 1323 |     \fn QDebug qt_QMetaEnum_flagDebugOperator(QDebug &, quint64 value, const QMetaObject *, const char *name) | 
| 1324 |     \internal | 
| 1325 |  | 
| 1326 |     Formats the given flag \a value for debug output. | 
| 1327 |  | 
| 1328 |     The supported verbosity are: | 
| 1329 |  | 
| 1330 |       0: Just the key(s): | 
| 1331 |  | 
| 1332 |          MyFlag1 | 
| 1333 |          MyFlag2|MyFlag3 | 
| 1334 |          MyScopedFlag(MyFlag2) | 
| 1335 |          MyScopedFlag(MyFlag2|MyFlag3) | 
| 1336 |  | 
| 1337 |       1: Same as 0, but treating all flags as scoped: | 
| 1338 |  | 
| 1339 |          MyFlag(MyFlag1) | 
| 1340 |          MyFlag(MyFlag2|MyFlag3) | 
| 1341 |          MyScopedFlag(MyFlag2) | 
| 1342 |          MyScopedFlag(MyFlag2|MyFlag3) | 
| 1343 |  | 
| 1344 |       2: The QDebug default. Same as 1, and includes class/namespace scope: | 
| 1345 |  | 
| 1346 |          QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) | 
| 1347 |          QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3) | 
| 1348 |          QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2) | 
| 1349 |          QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3) | 
| 1350 |  */ | 
| 1351 | QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaObject *meta, const char *name) | 
| 1352 | { | 
| 1353 |     const int verbosity = debug.verbosity(); | 
| 1354 |  | 
| 1355 |     QDebugStateSaver saver(debug); | 
| 1356 |     debug.resetFormat(); | 
| 1357 |     debug.noquote(); | 
| 1358 |     debug.nospace(); | 
| 1359 |  | 
| 1360 |     const QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); | 
| 1361 |  | 
| 1362 |     const bool classScope = verbosity >= QDebug::DefaultVerbosity; | 
| 1363 |     if (classScope) { | 
| 1364 |         debug << u"QFlags<" ; | 
| 1365 |  | 
| 1366 |         if (const char *scope = me.scope()) | 
| 1367 |             debug << scope << u"::" ; | 
| 1368 |     } | 
| 1369 |  | 
| 1370 |     const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity; | 
| 1371 |     if (enumScope) { | 
| 1372 |         debug << me.enumName(); | 
| 1373 |         if (classScope) | 
| 1374 |             debug << '>'; | 
| 1375 |         debug << '('; | 
| 1376 |     } | 
| 1377 |  | 
| 1378 |     debug << me.valueToKeys(value: static_cast<int>(value)); | 
| 1379 |  | 
| 1380 |     if (enumScope) | 
| 1381 |         debug << ')'; | 
| 1382 |  | 
| 1383 |     return debug; | 
| 1384 | } | 
| 1385 | #endif // !QT_NO_QOBJECT | 
| 1386 |  | 
| 1387 | QT_END_NAMESPACE | 
| 1388 |  |