| 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 | // Qt-Security score:critical reason:data-parsing |
| 5 | |
| 6 | #include "qdebug.h" |
| 7 | #include "private/qdebug_p.h" |
| 8 | #include "qmetaobject.h" |
| 9 | #include <private/qlogging_p.h> |
| 10 | #include <private/qtextstream_p.h> |
| 11 | #include <private/qtools_p.h> |
| 12 | |
| 13 | #include <array> |
| 14 | #include <q20chrono.h> |
| 15 | #include <cstdio> |
| 16 | |
| 17 | QT_BEGIN_NAMESPACE |
| 18 | |
| 19 | using namespace QtMiscUtils; |
| 20 | |
| 21 | /* |
| 22 | Returns a human readable representation of the first \a maxSize |
| 23 | characters in \a data. The size, \a len, is a 64-bit quantity to |
| 24 | avoid truncation due to implicit conversions in callers. |
| 25 | */ |
| 26 | QByteArray QtDebugUtils::toPrintable(const char *data, qint64 len, qsizetype maxSize) |
| 27 | { |
| 28 | if (!data) |
| 29 | return "(null)" ; |
| 30 | |
| 31 | QByteArray out; |
| 32 | for (qsizetype i = 0; i < qMin(a: len, b: maxSize); ++i) { |
| 33 | char c = data[i]; |
| 34 | if (isAsciiPrintable(ch: c)) { |
| 35 | out += c; |
| 36 | } else { |
| 37 | switch (c) { |
| 38 | case '\n': |
| 39 | out += "\\n" ; |
| 40 | break; |
| 41 | case '\r': |
| 42 | out += "\\r" ; |
| 43 | break; |
| 44 | case '\t': |
| 45 | out += "\\t" ; |
| 46 | break; |
| 47 | default: { |
| 48 | const char buf[] = { |
| 49 | '\\', |
| 50 | 'x', |
| 51 | toHexLower(value: uchar(c) / 16), |
| 52 | toHexLower(value: uchar(c) % 16), |
| 53 | 0 |
| 54 | }; |
| 55 | out += buf; |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | if (maxSize < len) |
| 62 | out += "..." ; |
| 63 | |
| 64 | return out; |
| 65 | } |
| 66 | |
| 67 | // This file is needed to force compilation of QDebug into the kernel library. |
| 68 | |
| 69 | /*! |
| 70 | \class QDebug |
| 71 | \inmodule QtCore |
| 72 | \ingroup shared |
| 73 | |
| 74 | \brief The QDebug class provides an output stream for debugging information. |
| 75 | |
| 76 | QDebug is used whenever the developer needs to write out debugging or tracing |
| 77 | information to a device, file, string or console. |
| 78 | |
| 79 | \section1 Basic Use |
| 80 | |
| 81 | In the common case, it is useful to call the qDebug() function to obtain a |
| 82 | default QDebug object to use for writing debugging information. |
| 83 | |
| 84 | \snippet qdebug/qdebugsnippet.cpp 1 |
| 85 | |
| 86 | This constructs a QDebug object using the constructor that accepts a QtMsgType |
| 87 | value of QtDebugMsg. Similarly, the qInfo(), qWarning(), qCritical() and qFatal() |
| 88 | functions also return QDebug objects for the corresponding message types. |
| 89 | |
| 90 | The class also provides several constructors for other situations, including |
| 91 | a constructor that accepts a QFile or any other QIODevice subclass that is |
| 92 | used to write debugging information to files and other devices. The constructor |
| 93 | that accepts a QString is used to write to a string for display or serialization. |
| 94 | |
| 95 | \section1 Formatting Options |
| 96 | |
| 97 | QDebug formats output so that it's easily readable. It automatically adds spaces |
| 98 | between arguments, and adds quotes around QString, QByteArray, QChar arguments. |
| 99 | |
| 100 | You can tweak these options through the space(), nospace() and quote(), noquote() |
| 101 | methods. Furthermore, \l{QTextStream manipulators} can be piped into a QDebug |
| 102 | stream. |
| 103 | |
| 104 | QDebugStateSaver limits changes to the formatting to the current scope. |
| 105 | resetFormat() resets the options to the default ones. |
| 106 | |
| 107 | \section1 Writing Custom Types to a Stream |
| 108 | |
| 109 | Many standard types can be written to QDebug objects, and Qt provides support for |
| 110 | most Qt value types. To add support for custom types, you need to implement a |
| 111 | streaming operator, as in the following example: |
| 112 | |
| 113 | \snippet qdebug/qdebugsnippet.cpp 0 |
| 114 | |
| 115 | This is described in the \l{Debugging Techniques} and |
| 116 | \l{Creating Custom Qt Types#Making the Type Printable}{Creating Custom Qt Types} |
| 117 | documents. |
| 118 | */ |
| 119 | |
| 120 | /*! |
| 121 | \fn QDebug::QDebug(QIODevice *device) |
| 122 | |
| 123 | Constructs a debug stream that writes to the given \a device. |
| 124 | */ |
| 125 | |
| 126 | /*! |
| 127 | \fn QDebug::QDebug(QString *string) |
| 128 | |
| 129 | Constructs a debug stream that writes to the given \a string. |
| 130 | */ |
| 131 | |
| 132 | /*! |
| 133 | \fn QDebug::QDebug(QtMsgType t) |
| 134 | |
| 135 | Constructs a debug stream that writes to the handler for the message type \a t. |
| 136 | */ |
| 137 | |
| 138 | /*! |
| 139 | \fn QDebug::QDebug(const QDebug &o) |
| 140 | |
| 141 | Constructs a copy of the other debug stream \a o. |
| 142 | */ |
| 143 | |
| 144 | /*! |
| 145 | \fn QDebug &QDebug::operator=(const QDebug &other) |
| 146 | |
| 147 | Assigns the \a other debug stream to this stream and returns a reference to |
| 148 | this stream. |
| 149 | */ |
| 150 | |
| 151 | /*! |
| 152 | \fn QDebug::~QDebug() |
| 153 | |
| 154 | Flushes any pending data to be written and destroys the debug stream. |
| 155 | */ |
| 156 | QDebug::~QDebug() |
| 157 | { |
| 158 | if (stream && !--stream->ref) { |
| 159 | if (stream->space && stream->buffer.endsWith(c: u' ')) |
| 160 | stream->buffer.chop(n: 1); |
| 161 | if (stream->message_output) { |
| 162 | QInternalMessageLogContext ctxt(stream->context); |
| 163 | qt_message_output(stream->type, |
| 164 | context: ctxt, |
| 165 | message: stream->buffer); |
| 166 | } |
| 167 | delete stream; |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | /*! |
| 172 | \internal |
| 173 | */ |
| 174 | void QDebug::putUcs4(uint ucs4) |
| 175 | { |
| 176 | maybeQuote(c: '\''); |
| 177 | if (ucs4 < 0x20) { |
| 178 | stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset; |
| 179 | } else if (ucs4 < 0x80) { |
| 180 | stream->ts << char(ucs4); |
| 181 | } else { |
| 182 | if (ucs4 < 0x10000) |
| 183 | stream->ts << "\\u" << qSetFieldWidth(width: 4); |
| 184 | else |
| 185 | stream->ts << "\\U" << qSetFieldWidth(width: 8); |
| 186 | stream->ts << Qt::hex << qSetPadChar(ch: u'0') << ucs4 << Qt::reset; |
| 187 | } |
| 188 | maybeQuote(c: '\''); |
| 189 | } |
| 190 | |
| 191 | // These two functions return true if the character should be printed by QDebug. |
| 192 | // For QByteArray, this is technically identical to US-ASCII isprint(); |
| 193 | // for QString, we use QChar::isPrint, which requires a full UCS-4 decode. |
| 194 | static inline bool isPrintable(char32_t ucs4) { return QChar::isPrint(ucs4); } |
| 195 | static inline bool isPrintable(char16_t uc) { return QChar::isPrint(ucs4: uc); } |
| 196 | static inline bool isPrintable(uchar c) |
| 197 | { return isAsciiPrintable(ch: c); } |
| 198 | |
| 199 | template <typename Char> |
| 200 | static inline void putEscapedString(QTextStreamPrivate *d, const Char *begin, size_t length, bool isUnicode = true) |
| 201 | { |
| 202 | constexpr char16_t quotes[] = uR"("")" ; |
| 203 | constexpr char16_t quote = quotes[0]; |
| 204 | d->write(ch: quote); |
| 205 | |
| 206 | bool lastWasHexEscape = false; |
| 207 | const Char *end = begin + length; |
| 208 | for (const Char *p = begin; p != end; ++p) { |
| 209 | // check if we need to insert "" to break an hex escape sequence |
| 210 | if (Q_UNLIKELY(lastWasHexEscape)) { |
| 211 | if (fromHex(*p) != -1) { |
| 212 | // yes, insert it |
| 213 | d->write(data: quotes); |
| 214 | } |
| 215 | lastWasHexEscape = false; |
| 216 | } |
| 217 | |
| 218 | if constexpr (sizeof(Char) == sizeof(QChar)) { |
| 219 | // Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them |
| 220 | qsizetype runLength = 0; |
| 221 | while (p + runLength != end && |
| 222 | isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"') |
| 223 | ++runLength; |
| 224 | if (runLength) { |
| 225 | d->write(data: QStringView{p, runLength}); |
| 226 | p += runLength - 1; |
| 227 | continue; |
| 228 | } |
| 229 | } else if (isPrintable(*p) && *p != '\\' && *p != '"') { |
| 230 | d->write(ch: char16_t{uchar(*p)}); |
| 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 >> 28); |
| 280 | buf[3] = '0'; // toHexUpper(ucs4 >> 24); |
| 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: QStringView{buf, buflen}); |
| 302 | } |
| 303 | |
| 304 | d->write(ch: quote); |
| 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(string: QStringView{begin, 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 | switch (content) { |
| 335 | case Latin1Content::ContainsLatin1: |
| 336 | stream->ts.d_ptr->putString(data: QLatin1StringView{begin, qsizetype(length)}); |
| 337 | break; |
| 338 | case Latin1Content::ContainsBinary: |
| 339 | stream->ts.d_ptr->putString(data: QUtf8StringView{begin, qsizetype(length)}); |
| 340 | break; |
| 341 | } |
| 342 | } else { |
| 343 | // we'll reset the QTextStream formatting mechanisms, so save the state |
| 344 | QDebugStateSaver saver(*this); |
| 345 | stream->ts.d_ptr->params.reset(); |
| 346 | putEscapedString(d: stream->ts.d_ptr.get(), begin: reinterpret_cast<const uchar *>(begin), |
| 347 | length, isUnicode: content == ContainsLatin1); |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | static QByteArray timeUnit(qint64 num, qint64 den) |
| 352 | { |
| 353 | using namespace std::chrono; |
| 354 | using namespace q20::chrono; |
| 355 | |
| 356 | if (num == 1 && den > 1) { |
| 357 | // sub-multiple of seconds |
| 358 | char prefix = '\0'; |
| 359 | auto tryprefix = [&](auto d, char c) { |
| 360 | static_assert(decltype(d)::num == 1, "not an SI prefix" ); |
| 361 | if (den == decltype(d)::den) |
| 362 | prefix = c; |
| 363 | }; |
| 364 | |
| 365 | // "u" should be "µ", but debugging output is not always UTF-8-safe |
| 366 | tryprefix(std::milli{}, 'm'); |
| 367 | tryprefix(std::micro{}, 'u'); |
| 368 | tryprefix(std::nano{}, 'n'); |
| 369 | tryprefix(std::pico{}, 'p'); |
| 370 | tryprefix(std::femto{}, 'f'); |
| 371 | tryprefix(std::atto{}, 'a'); |
| 372 | // uncommon ones later |
| 373 | tryprefix(std::centi{}, 'c'); |
| 374 | tryprefix(std::deci{}, 'd'); |
| 375 | if (prefix) { |
| 376 | char unit[3] = { prefix, 's' }; |
| 377 | return QByteArray(unit, sizeof(unit) - 1); |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | const char *unit = nullptr; |
| 382 | if (num > 1 && den == 1) { |
| 383 | // multiple of seconds - but we don't use SI prefixes |
| 384 | auto tryunit = [&](auto d, const char *name) { |
| 385 | static_assert(decltype(d)::period::den == 1, "not a multiple of a second" ); |
| 386 | if (unit || num % decltype(d)::period::num) |
| 387 | return; |
| 388 | unit = name; |
| 389 | num /= decltype(d)::period::num; |
| 390 | }; |
| 391 | tryunit(years{}, "yr" ); |
| 392 | tryunit(weeks{}, "wk" ); |
| 393 | tryunit(days{}, "d" ); |
| 394 | tryunit(hours{}, "h" ); |
| 395 | tryunit(minutes{}, "min" ); |
| 396 | } |
| 397 | if (!unit) |
| 398 | unit = "s" ; |
| 399 | |
| 400 | if (num == 1 && den == 1) |
| 401 | return unit; |
| 402 | if (Q_UNLIKELY(num < 1 || den < 1)) |
| 403 | return QString::asprintf(format: "<invalid time unit %lld/%lld>" , num, den).toLatin1(); |
| 404 | |
| 405 | // uncommon units: will return something like "[2/3]s" |
| 406 | // strlen("[/]min") = 6 |
| 407 | char buf[2 * (std::numeric_limits<qint64>::digits10 + 2) + 10]; |
| 408 | size_t len = 0; |
| 409 | auto appendChar = [&](char c) { |
| 410 | Q_ASSERT(len < sizeof(buf)); |
| 411 | buf[len++] = c; |
| 412 | }; |
| 413 | auto appendNumber = [&](qint64 value) { |
| 414 | if (value >= 10'000 && (value % 1000) == 0) |
| 415 | len += std::snprintf(s: buf + len, maxlen: sizeof(buf) - len, format: "%.6g" , double(value)); // "1e+06" |
| 416 | else |
| 417 | len += std::snprintf(s: buf + len, maxlen: sizeof(buf) - len, format: "%lld" , value); |
| 418 | }; |
| 419 | appendChar('['); |
| 420 | appendNumber(num); |
| 421 | if (den != 1) { |
| 422 | appendChar('/'); |
| 423 | appendNumber(den); |
| 424 | } |
| 425 | appendChar(']'); |
| 426 | memcpy(dest: buf + len, src: unit, n: strlen(s: unit)); |
| 427 | return QByteArray(buf, len + strlen(s: unit)); |
| 428 | } |
| 429 | |
| 430 | /*! |
| 431 | \since 6.6 |
| 432 | \internal |
| 433 | Helper to the std::chrono::duration debug streaming output. |
| 434 | */ |
| 435 | void QDebug::putTimeUnit(qint64 num, qint64 den) |
| 436 | { |
| 437 | stream->ts << timeUnit(num, den); // ### optimize |
| 438 | } |
| 439 | |
| 440 | namespace { |
| 441 | |
| 442 | #ifdef QT_SUPPORTS_INT128 |
| 443 | |
| 444 | constexpr char Q_INT128_MIN_STR[] = "-170141183460469231731687303715884105728" ; |
| 445 | |
| 446 | constexpr int Int128BufferSize = sizeof(Q_INT128_MIN_STR); |
| 447 | using Int128Buffer = std::array<char, Int128BufferSize>; |
| 448 | // numeric_limits<qint128>::digits10 may not exist |
| 449 | |
| 450 | static char *i128ToStringHelper(Int128Buffer &buffer, quint128 n) |
| 451 | { |
| 452 | auto dst = buffer.data() + buffer.size(); |
| 453 | *--dst = '\0'; // NUL-terminate |
| 454 | if (n == 0) { |
| 455 | *--dst = '0'; // and done |
| 456 | } else { |
| 457 | while (n != 0) { |
| 458 | *--dst = "0123456789" [n % 10]; |
| 459 | n /= 10; |
| 460 | } |
| 461 | } |
| 462 | return dst; |
| 463 | } |
| 464 | #endif // QT_SUPPORTS_INT128 |
| 465 | |
| 466 | [[maybe_unused]] |
| 467 | static const char *int128Warning() |
| 468 | { |
| 469 | const char *msg = "Qt was not compiled with int128 support." ; |
| 470 | qWarning(msg: "%s" , msg); |
| 471 | return msg; |
| 472 | } |
| 473 | |
| 474 | } // unnamed namespace |
| 475 | |
| 476 | /*! |
| 477 | \since 6.7 |
| 478 | \internal |
| 479 | Helper to the qint128 debug streaming output. |
| 480 | */ |
| 481 | void QDebug::putInt128([[maybe_unused]] const void *p) |
| 482 | { |
| 483 | #ifdef QT_SUPPORTS_INT128 |
| 484 | Q_ASSERT(p); |
| 485 | qint128 i; |
| 486 | memcpy(dest: &i, src: p, n: sizeof(i)); // alignment paranoia |
| 487 | if (i == Q_INT128_MIN) { |
| 488 | // -i is not representable, hardcode the result: |
| 489 | stream->ts << Q_INT128_MIN_STR; |
| 490 | } else { |
| 491 | Int128Buffer buffer; |
| 492 | auto dst = i128ToStringHelper(buffer, n: i < 0 ? -i : i); |
| 493 | if (i < 0) |
| 494 | *--dst = '-'; |
| 495 | stream->ts << dst; |
| 496 | } |
| 497 | return; |
| 498 | #endif // QT_SUPPORTS_INT128 |
| 499 | stream->ts << int128Warning(); |
| 500 | } |
| 501 | |
| 502 | /*! |
| 503 | \since 6.7 |
| 504 | \internal |
| 505 | Helper to the quint128 debug streaming output. |
| 506 | */ |
| 507 | void QDebug::putUInt128([[maybe_unused]] const void *p) |
| 508 | { |
| 509 | #ifdef QT_SUPPORTS_INT128 |
| 510 | Q_ASSERT(p); |
| 511 | quint128 i; |
| 512 | memcpy(dest: &i, src: p, n: sizeof(i)); // alignment paranoia |
| 513 | Int128Buffer buffer; |
| 514 | stream->ts << i128ToStringHelper(buffer, n: i); |
| 515 | return; |
| 516 | #endif // QT_SUPPORTS_INT128 |
| 517 | stream->ts << int128Warning(); |
| 518 | } |
| 519 | |
| 520 | /*! |
| 521 | \since 6.9 |
| 522 | \internal |
| 523 | Helper to the <Std/Qt>::<>_ordering debug output. |
| 524 | It generates the string in following format: |
| 525 | <Qt/Std>::<weak/partial/strong>_ordering::<less/equal/greater/unordered> |
| 526 | */ |
| 527 | void QDebug::putQtOrdering(QtOrderingPrivate::QtOrderingTypeFlag flags, Qt::partial_ordering order) |
| 528 | { |
| 529 | using QtOrderingPrivate::QtOrderingType; |
| 530 | std::string result; |
| 531 | if ((flags & QtOrderingType::StdOrder) == QtOrderingType::StdOrder) |
| 532 | result += "std" ; |
| 533 | else if ((flags & QtOrderingType::QtOrder) == QtOrderingType::QtOrder) |
| 534 | result += "Qt" ; |
| 535 | |
| 536 | result += "::" ; |
| 537 | const bool isStrong = ((flags & QtOrderingType::Strong) == QtOrderingType::Strong); |
| 538 | if (isStrong) |
| 539 | result += "strong" ; |
| 540 | else if ((flags & QtOrderingType::Weak) == QtOrderingType::Weak) |
| 541 | result += "weak" ; |
| 542 | else if ((flags & QtOrderingType::Partial) == QtOrderingType::Partial) |
| 543 | result += "partial" ; |
| 544 | result += "_ordering::" ; |
| 545 | |
| 546 | if (order == Qt::partial_ordering::equivalent) { |
| 547 | if (isStrong) |
| 548 | result += "equal" ; |
| 549 | else |
| 550 | result += "equivalent" ; |
| 551 | } else if (order == Qt::partial_ordering::greater) { |
| 552 | result += "greater" ; |
| 553 | } else if (order == Qt::partial_ordering::less) { |
| 554 | result += "less" ; |
| 555 | } else { |
| 556 | result += "unordered" ; |
| 557 | } |
| 558 | stream->ts << result.data(); |
| 559 | } |
| 560 | |
| 561 | /*! |
| 562 | \fn QDebug::swap(QDebug &other) |
| 563 | \since 5.0 |
| 564 | \memberswap{debug stream instance} |
| 565 | */ |
| 566 | |
| 567 | /*! |
| 568 | Resets the stream formatting options, bringing it back to its original constructed state. |
| 569 | |
| 570 | \sa space(), quote() |
| 571 | \since 5.4 |
| 572 | */ |
| 573 | QDebug &QDebug::resetFormat() |
| 574 | { |
| 575 | stream->ts.reset(); |
| 576 | stream->space = true; |
| 577 | stream->noQuotes = false; |
| 578 | stream->verbosity = DefaultVerbosity; |
| 579 | return *this; |
| 580 | } |
| 581 | |
| 582 | /*! |
| 583 | \fn QDebug &QDebug::space() |
| 584 | |
| 585 | Writes a space character to the debug stream and returns a reference to |
| 586 | the stream. |
| 587 | |
| 588 | The stream remembers that automatic insertion of spaces is |
| 589 | enabled for future writes. |
| 590 | |
| 591 | \sa nospace(), maybeSpace() |
| 592 | */ |
| 593 | |
| 594 | /*! |
| 595 | \fn QDebug &QDebug::nospace() |
| 596 | |
| 597 | Disables automatic insertion of spaces and returns a reference to the stream. |
| 598 | |
| 599 | \sa space(), maybeSpace() |
| 600 | */ |
| 601 | |
| 602 | /*! |
| 603 | \fn QDebug &QDebug::maybeSpace() |
| 604 | |
| 605 | Writes a space character to the debug stream, depending on the current |
| 606 | setting for automatic insertion of spaces, and returns a reference to the stream. |
| 607 | |
| 608 | \sa space(), nospace() |
| 609 | */ |
| 610 | |
| 611 | /*! |
| 612 | \fn bool QDebug::autoInsertSpaces() const |
| 613 | |
| 614 | Returns \c true if this QDebug instance will automatically insert spaces |
| 615 | between writes. |
| 616 | |
| 617 | \since 5.0 |
| 618 | |
| 619 | \sa QDebugStateSaver |
| 620 | */ |
| 621 | |
| 622 | /*! |
| 623 | \fn void QDebug::setAutoInsertSpaces(bool b) |
| 624 | |
| 625 | Enables automatic insertion of spaces between writes if \a b is true; otherwise |
| 626 | automatic insertion of spaces is disabled. |
| 627 | |
| 628 | \since 5.0 |
| 629 | |
| 630 | \sa QDebugStateSaver |
| 631 | */ |
| 632 | |
| 633 | |
| 634 | /*! |
| 635 | \fn bool QDebug::quoteStrings() const |
| 636 | \since 6.7 |
| 637 | |
| 638 | Returns \c true if this QDebug instance will quote strings streamed into |
| 639 | it (which is the default). |
| 640 | |
| 641 | \sa QDebugStateSaver, quote(), noquote(), setQuoteStrings() |
| 642 | */ |
| 643 | |
| 644 | /*! |
| 645 | \fn void QDebug::setQuoteStrings(bool b) |
| 646 | \since 6.7 |
| 647 | |
| 648 | Enables quoting of strings streamed into this QDebug instance if \a b is |
| 649 | \c true; otherwise quoting is disabled. |
| 650 | |
| 651 | The default is to quote strings. |
| 652 | |
| 653 | \sa QDebugStateSaver, quote(), noquote(), quoteStrings() |
| 654 | */ |
| 655 | |
| 656 | |
| 657 | /*! |
| 658 | \fn QDebug &QDebug::quote() |
| 659 | \since 5.4 |
| 660 | |
| 661 | Enables automatic insertion of quotation characters around QChar, QString and QByteArray |
| 662 | contents and returns a reference to the stream. |
| 663 | |
| 664 | Quoting is enabled by default. |
| 665 | |
| 666 | \sa noquote(), maybeQuote() |
| 667 | */ |
| 668 | |
| 669 | /*! |
| 670 | \fn QDebug &QDebug::noquote() |
| 671 | \since 5.4 |
| 672 | |
| 673 | Disables automatic insertion of quotation characters around QChar, QString and QByteArray |
| 674 | contents and returns a reference to the stream. |
| 675 | |
| 676 | When quoting is disabled, these types are printed without quotation |
| 677 | characters and without escaping of non-printable characters. |
| 678 | |
| 679 | \sa quote(), maybeQuote() |
| 680 | */ |
| 681 | |
| 682 | /*! |
| 683 | \fn QDebug &QDebug::maybeQuote(char c) |
| 684 | \since 5.4 |
| 685 | |
| 686 | Writes a character \a c to the debug stream, depending on the |
| 687 | current setting for automatic insertion of quotes, and returns a reference to the stream. |
| 688 | |
| 689 | The default character is a double quote \c{"}. |
| 690 | |
| 691 | \sa quote(), noquote() |
| 692 | */ |
| 693 | |
| 694 | /*! |
| 695 | \fn int QDebug::verbosity() const |
| 696 | \since 5.6 |
| 697 | |
| 698 | Returns the verbosity of the debug stream. |
| 699 | |
| 700 | Streaming operators can check the value to decide whether |
| 701 | verbose output is desired and print more information depending on the |
| 702 | level. Higher values indicate that more information is desired. |
| 703 | |
| 704 | The allowed range is from 0 to 7. The default value is 2. |
| 705 | |
| 706 | \sa setVerbosity(), VerbosityLevel |
| 707 | */ |
| 708 | |
| 709 | /*! |
| 710 | \fn void QDebug::setVerbosity(int verbosityLevel) |
| 711 | \since 5.6 |
| 712 | |
| 713 | Sets the verbosity of the stream to \a verbosityLevel. |
| 714 | |
| 715 | The allowed range is from 0 to 7. The default value is 2. |
| 716 | |
| 717 | \sa verbosity(), VerbosityLevel |
| 718 | */ |
| 719 | |
| 720 | /*! |
| 721 | \fn QDebug &QDebug::verbosity(int verbosityLevel) |
| 722 | \since 5.13 |
| 723 | |
| 724 | Sets the verbosity of the stream to \a verbosityLevel and returns a reference to the stream. |
| 725 | |
| 726 | The allowed range is from 0 to 7. The default value is 2. |
| 727 | |
| 728 | \sa verbosity(), setVerbosity(), VerbosityLevel |
| 729 | */ |
| 730 | |
| 731 | /*! |
| 732 | \enum QDebug::VerbosityLevel |
| 733 | \since 5.13 |
| 734 | |
| 735 | This enum describes the range of verbosity levels. |
| 736 | |
| 737 | \value MinimumVerbosity |
| 738 | \value DefaultVerbosity |
| 739 | \value MaximumVerbosity |
| 740 | |
| 741 | \sa verbosity(), setVerbosity() |
| 742 | */ |
| 743 | |
| 744 | /*! |
| 745 | \fn QDebug &QDebug::operator<<(QChar t) |
| 746 | |
| 747 | Writes the character, \a t, to the stream and returns a reference to the |
| 748 | stream. Normally, QDebug prints control characters and non-US-ASCII |
| 749 | characters as their C escape sequences or their Unicode value (\\u1234). To |
| 750 | print non-printable characters without transformation, enable the noquote() |
| 751 | functionality, but note that some QDebug backends may not be 8-bit clean |
| 752 | and may not be able to represent \c t. |
| 753 | */ |
| 754 | |
| 755 | /*! |
| 756 | \fn QDebug &QDebug::operator<<(bool t) |
| 757 | |
| 758 | Writes the boolean value, \a t, to the stream and returns a reference to the |
| 759 | stream. |
| 760 | */ |
| 761 | |
| 762 | /*! |
| 763 | \fn QDebug &QDebug::operator<<(char t) |
| 764 | |
| 765 | Writes the character, \a t, to the stream and returns a reference to the |
| 766 | stream. |
| 767 | */ |
| 768 | |
| 769 | /*! |
| 770 | \fn QDebug &QDebug::operator<<(signed short t) |
| 771 | |
| 772 | Writes the signed short integer, \a t, to the stream and returns a reference |
| 773 | to the stream. |
| 774 | */ |
| 775 | |
| 776 | /*! |
| 777 | \fn QDebug &QDebug::operator<<(unsigned short t) |
| 778 | |
| 779 | Writes then unsigned short integer, \a t, to the stream and returns a |
| 780 | reference to the stream. |
| 781 | */ |
| 782 | |
| 783 | /*! |
| 784 | \fn QDebug &QDebug::operator<<(signed int t) |
| 785 | |
| 786 | Writes the signed integer, \a t, to the stream and returns a reference |
| 787 | to the stream. |
| 788 | */ |
| 789 | |
| 790 | /*! |
| 791 | \fn QDebug &QDebug::operator<<(unsigned int t) |
| 792 | |
| 793 | Writes then unsigned integer, \a t, to the stream and returns a reference to |
| 794 | the stream. |
| 795 | */ |
| 796 | |
| 797 | /*! |
| 798 | \fn QDebug &QDebug::operator<<(signed long t) |
| 799 | |
| 800 | Writes the signed long integer, \a t, to the stream and returns a reference |
| 801 | to the stream. |
| 802 | */ |
| 803 | |
| 804 | /*! |
| 805 | \fn QDebug &QDebug::operator<<(unsigned long t) |
| 806 | |
| 807 | Writes then unsigned long integer, \a t, to the stream and returns a reference |
| 808 | to the stream. |
| 809 | */ |
| 810 | |
| 811 | /*! |
| 812 | \fn QDebug &QDebug::operator<<(qint64 t) |
| 813 | |
| 814 | Writes the signed 64-bit integer, \a t, to the stream and returns a reference |
| 815 | to the stream. |
| 816 | */ |
| 817 | |
| 818 | /*! |
| 819 | \fn QDebug &QDebug::operator<<(quint64 t) |
| 820 | |
| 821 | Writes then unsigned 64-bit integer, \a t, to the stream and returns a |
| 822 | reference to the stream. |
| 823 | */ |
| 824 | |
| 825 | /*! |
| 826 | \fn QDebug &QDebug::operator<<(float t) |
| 827 | |
| 828 | Writes the 32-bit floating point number, \a t, to the stream and returns a |
| 829 | reference to the stream. |
| 830 | */ |
| 831 | |
| 832 | /*! |
| 833 | \fn QDebug &QDebug::operator<<(double t) |
| 834 | |
| 835 | Writes the 64-bit floating point number, \a t, to the stream and returns a |
| 836 | reference to the stream. |
| 837 | */ |
| 838 | |
| 839 | /*! |
| 840 | \fn QDebug &QDebug::operator<<(const char *t) |
| 841 | |
| 842 | Writes the '\\0'-terminated UTF-8 string, \a t, to the stream and returns a |
| 843 | reference to the stream. The string is never quoted or escaped for the |
| 844 | output. Note that QDebug buffers internally as UTF-16 and may need to |
| 845 | transform to 8-bit using the locale's codec in order to use some backends, |
| 846 | which may cause garbled output (mojibake). Restricting to US-ASCII strings |
| 847 | is recommended. |
| 848 | */ |
| 849 | |
| 850 | /*! |
| 851 | \fn QDebug &QDebug::operator<<(const char16_t *t) |
| 852 | \since 6.0 |
| 853 | |
| 854 | Writes the u'\\0'-terminated UTF-16 string, \a t, to the stream and returns |
| 855 | a reference to the stream. The string is never quoted or escaped for the |
| 856 | output. Note that QDebug buffers internally as UTF-16 and may need to |
| 857 | transform to 8-bit using the locale's codec in order to use some backends, |
| 858 | which may cause garbled output (mojibake). Restricting to US-ASCII strings |
| 859 | is recommended. |
| 860 | */ |
| 861 | |
| 862 | /*! |
| 863 | \fn QDebug &QDebug::operator<<(char16_t t) |
| 864 | \since 5.5 |
| 865 | |
| 866 | Writes the UTF-16 character, \a t, to the stream and returns a reference |
| 867 | to the stream. |
| 868 | */ |
| 869 | |
| 870 | /*! |
| 871 | \fn QDebug &QDebug::operator<<(char32_t t) |
| 872 | \since 5.5 |
| 873 | |
| 874 | Writes the UTF-32 character, \a t, to the stream and returns a reference |
| 875 | to the stream. |
| 876 | */ |
| 877 | |
| 878 | /*! |
| 879 | \fn QDebug &QDebug::operator<<(const QString &t) |
| 880 | |
| 881 | Writes the string, \a t, to the stream and returns a reference to the |
| 882 | stream. Normally, QDebug prints the string inside quotes and transforms |
| 883 | non-printable characters to their Unicode values (\\u1234). |
| 884 | |
| 885 | To print non-printable characters without transformation, enable the |
| 886 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 887 | clean. |
| 888 | |
| 889 | Output examples: |
| 890 | \snippet code/src_corelib_io_qdebug.cpp 0 |
| 891 | */ |
| 892 | |
| 893 | /*! |
| 894 | \since 5.10 |
| 895 | \fn QDebug &QDebug::operator<<(QStringView s) |
| 896 | |
| 897 | Writes the string view, \a s, to the stream and returns a reference to the |
| 898 | stream. Normally, QDebug prints the string inside quotes and transforms |
| 899 | non-printable characters to their Unicode values (\\u1234). |
| 900 | |
| 901 | To print non-printable characters without transformation, enable the |
| 902 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 903 | clean. |
| 904 | |
| 905 | See the QString overload for examples. |
| 906 | */ |
| 907 | |
| 908 | /*! |
| 909 | \since 6.0 |
| 910 | \fn QDebug &QDebug::operator<<(QUtf8StringView s) |
| 911 | |
| 912 | Writes the string view, \a s, to the stream and returns a reference to the |
| 913 | stream. |
| 914 | |
| 915 | Normally, QDebug prints the data inside quotes and transforms control or |
| 916 | non-US-ASCII characters to their C escape sequences (\\xAB). This way, the |
| 917 | output is always 7-bit clean and the string can be copied from the output |
| 918 | and pasted back into C++ sources, if necessary. |
| 919 | |
| 920 | To print non-printable characters without transformation, enable the |
| 921 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 922 | clean. |
| 923 | */ |
| 924 | |
| 925 | /*! |
| 926 | \fn QDebug &QDebug::operator<<(QLatin1StringView t) |
| 927 | |
| 928 | Writes the string, \a t, to the stream and returns a reference to the |
| 929 | stream. Normally, QDebug prints the string inside quotes and transforms |
| 930 | non-printable characters to their Unicode values (\\u1234). |
| 931 | |
| 932 | To print non-printable characters without transformation, enable the |
| 933 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 934 | clean. |
| 935 | |
| 936 | See the QString overload for examples. |
| 937 | */ |
| 938 | |
| 939 | /*! |
| 940 | \fn QDebug &QDebug::operator<<(const QByteArray &t) |
| 941 | |
| 942 | Writes the byte array, \a t, to the stream and returns a reference to the |
| 943 | stream. Normally, QDebug prints the array inside quotes and transforms |
| 944 | control or non-US-ASCII characters to their C escape sequences (\\xAB). This |
| 945 | way, the output is always 7-bit clean and the string can be copied from the |
| 946 | output and pasted back into C++ sources, if necessary. |
| 947 | |
| 948 | To print non-printable characters without transformation, enable the |
| 949 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 950 | clean. |
| 951 | |
| 952 | Output examples: |
| 953 | \snippet code/src_corelib_io_qdebug.cpp 1 |
| 954 | |
| 955 | Note how QDebug needed to close and reopen the string in the way C and C++ |
| 956 | languages concatenate string literals so that the letter 'b' is not |
| 957 | interpreted as part of the previous hexadecimal escape sequence. |
| 958 | */ |
| 959 | |
| 960 | /*! |
| 961 | \since 6.0 |
| 962 | \fn QDebug &QDebug::operator<<(QByteArrayView t) |
| 963 | |
| 964 | Writes the data of the observed byte array, \a t, to the stream and returns |
| 965 | a reference to the stream. |
| 966 | |
| 967 | Normally, QDebug prints the data inside quotes and transforms control or |
| 968 | non-US-ASCII characters to their C escape sequences (\\xAB). This way, the |
| 969 | output is always 7-bit clean and the string can be copied from the output |
| 970 | and pasted back into C++ sources, if necessary. |
| 971 | |
| 972 | To print non-printable characters without transformation, enable the |
| 973 | noquote() functionality. Note that some QDebug backends might not be 8-bit |
| 974 | clean. |
| 975 | |
| 976 | See the QByteArray overload for examples. |
| 977 | */ |
| 978 | |
| 979 | /*! |
| 980 | \fn QDebug &QDebug::operator<<(const void *t) |
| 981 | |
| 982 | Writes a pointer, \a t, to the stream and returns a reference to the stream. |
| 983 | */ |
| 984 | |
| 985 | /*! |
| 986 | \fn QDebug &QDebug::operator<<(QTextStreamFunction f) |
| 987 | \internal |
| 988 | */ |
| 989 | |
| 990 | /*! |
| 991 | \fn QDebug &QDebug::operator<<(QTextStreamManipulator m) |
| 992 | \internal |
| 993 | */ |
| 994 | |
| 995 | /*! |
| 996 | \fn template <typename T, QDebug::if_ordering_type<T>> QDebug::operator<<(QDebug debug, T t) |
| 997 | \since 6.9 |
| 998 | Prints the Qt or std ordering value \a t to the \a debug object. |
| 999 | |
| 1000 | \constraints \c T is one of <Qt/Std>::<weak/partial/strong>_ordering. |
| 1001 | */ |
| 1002 | |
| 1003 | /*! |
| 1004 | \since 6.5 |
| 1005 | \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(const std::basic_string<Char, Args...> &s) |
| 1006 | \fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(std::basic_string_view<Char, Args...> s) |
| 1007 | |
| 1008 | Writes the string or string-view \a s to the stream and returns a reference |
| 1009 | to the stream. |
| 1010 | |
| 1011 | These operators only participate in overload resolution if \c Char is one of |
| 1012 | \list |
| 1013 | \li char |
| 1014 | \li char8_t (C++20 only) |
| 1015 | \li char16_t |
| 1016 | \li char32_t |
| 1017 | \li wchar_t |
| 1018 | \endlist |
| 1019 | */ |
| 1020 | |
| 1021 | /*! |
| 1022 | \since 6.6 |
| 1023 | \fn template <typename Rep, typename Period> QDebug &QDebug::operator<<(std::chrono::duration<Rep, Period> duration) |
| 1024 | |
| 1025 | Prints the time duration \a duration to the stream and returns a reference |
| 1026 | to the stream. The printed string is the numeric representation of the |
| 1027 | period followed by the time unit, similar to what the C++ Standard Library |
| 1028 | would produce with \c{std::ostream}. |
| 1029 | |
| 1030 | The unit is not localized. |
| 1031 | */ |
| 1032 | |
| 1033 | /*! |
| 1034 | \fn template <typename T, QDebug::if_qint128<T>> QDebug::operator<<(T i) |
| 1035 | \fn template <typename T, QDebug::if_quint128<T>> QDebug::operator<<(T i) |
| 1036 | \since 6.7 |
| 1037 | |
| 1038 | Prints the textual representation of the 128-bit integer \a i. |
| 1039 | |
| 1040 | \note This operator is only available if Qt supports 128-bit integer types. |
| 1041 | If 128-bit integer types are available in your build, but the Qt libraries |
| 1042 | were compiled without, the operator will print a warning instead. |
| 1043 | |
| 1044 | \note Because the operator is a function template, no implicit conversions |
| 1045 | are performed on its argument. It must be exactly qint128/quint128. |
| 1046 | |
| 1047 | \sa QT_SUPPORTS_INT128 |
| 1048 | */ |
| 1049 | |
| 1050 | /*! |
| 1051 | \fn template <class T> QString QDebug::toString(const T &object) |
| 1052 | \since 6.0 |
| 1053 | |
| 1054 | \include qdebug-toString.qdocinc |
| 1055 | |
| 1056 | \sa toBytes() |
| 1057 | */ |
| 1058 | |
| 1059 | /*! \internal */ |
| 1060 | QString QDebug::toStringImpl(StreamTypeErased s, const void *obj) |
| 1061 | { |
| 1062 | QString result; |
| 1063 | { |
| 1064 | QDebug d(&result); |
| 1065 | s(d.nospace(), obj); |
| 1066 | } |
| 1067 | return result; |
| 1068 | } |
| 1069 | |
| 1070 | /*! |
| 1071 | \fn template <class T> QByteArray QDebug::toBytes(const T &object) |
| 1072 | \since 6.9 |
| 1073 | |
| 1074 | This is equivalent to passing \a object to |
| 1075 | \c{QDebug::toString(object).toUtf8()}, but more efficient. |
| 1076 | |
| 1077 | \sa toString() |
| 1078 | */ |
| 1079 | |
| 1080 | /*! \internal */ |
| 1081 | QByteArray QDebug::toBytesImpl(StreamTypeErased s, const void *obj) |
| 1082 | { |
| 1083 | QByteArray result; |
| 1084 | { |
| 1085 | QDebug d(&result); |
| 1086 | s(d.nospace(), obj); |
| 1087 | } |
| 1088 | return result; |
| 1089 | } |
| 1090 | |
| 1091 | /*! |
| 1092 | \internal |
| 1093 | \since 6.9 |
| 1094 | |
| 1095 | Outputs a heterogeneous product type (pair, tuple, or anything that |
| 1096 | implements the Tuple Protocol). The class name is described by "\a ns |
| 1097 | \c{::} \a what", while the addresses of the \a n elements are stored in the |
| 1098 | array \a data. The formatters are stored in the array \a ops. |
| 1099 | |
| 1100 | If \a ns is empty, only \a what is used. |
| 1101 | */ |
| 1102 | QDebug &QDebug::putTupleLikeImplImpl(const char *ns, const char *what, |
| 1103 | size_t n, StreamTypeErased *ops, const void **data) |
| 1104 | { |
| 1105 | const QDebugStateSaver saver(*this); |
| 1106 | nospace(); |
| 1107 | if (ns && *ns) |
| 1108 | *this << ns << "::" ; |
| 1109 | *this << what << '('; |
| 1110 | while (n--) { |
| 1111 | (*ops++)(*this, *data++); |
| 1112 | if (n) |
| 1113 | *this << ", " ; |
| 1114 | } |
| 1115 | return *this << ')'; |
| 1116 | } |
| 1117 | |
| 1118 | /*! |
| 1119 | \fn template <class T> QDebug operator<<(QDebug debug, const QList<T> &list) |
| 1120 | \relates QDebug |
| 1121 | |
| 1122 | Writes the contents of \a list to \a debug. \c T needs to |
| 1123 | support streaming into QDebug. |
| 1124 | */ |
| 1125 | |
| 1126 | /*! |
| 1127 | \fn template <class T, qsizetype P> QDebug operator<<(QDebug debug, const QVarLengthArray<T,P> &array) |
| 1128 | \relates QDebug |
| 1129 | \since 6.3 |
| 1130 | |
| 1131 | Writes the contents of \a array to \a debug. \c T needs to |
| 1132 | support streaming into QDebug. |
| 1133 | */ |
| 1134 | |
| 1135 | /*! |
| 1136 | \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec) |
| 1137 | \relates QDebug |
| 1138 | \since 5.7 |
| 1139 | |
| 1140 | Writes the contents of list \a vec to \a debug. \c T needs to |
| 1141 | support streaming into QDebug. |
| 1142 | */ |
| 1143 | |
| 1144 | /*! |
| 1145 | \fn template <typename T, typename Alloc> QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec) |
| 1146 | \relates QDebug |
| 1147 | \since 5.7 |
| 1148 | |
| 1149 | Writes the contents of vector \a vec to \a debug. \c T needs to |
| 1150 | support streaming into QDebug. |
| 1151 | */ |
| 1152 | |
| 1153 | /*! |
| 1154 | \fn template <typename T, std::size_t N> QDebug operator<<(QDebug debug, const std::array<T, N> &array) |
| 1155 | \relates QDebug |
| 1156 | \since 6.9 |
| 1157 | |
| 1158 | Writes the contents of \a array to \a debug. \c T needs to |
| 1159 | support streaming into QDebug. |
| 1160 | */ |
| 1161 | |
| 1162 | /*! |
| 1163 | \fn template <typename T> QDebug operator<<(QDebug debug, const QSet<T> &set) |
| 1164 | \relates QDebug |
| 1165 | |
| 1166 | Writes the contents of \a set to \a debug. \c T needs to |
| 1167 | support streaming into QDebug. |
| 1168 | */ |
| 1169 | |
| 1170 | /*! |
| 1171 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMap<Key, T> &map) |
| 1172 | \relates QDebug |
| 1173 | |
| 1174 | Writes the contents of \a map to \a debug. Both \c Key and |
| 1175 | \c T need to support streaming into QDebug. |
| 1176 | */ |
| 1177 | |
| 1178 | /*! |
| 1179 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map) |
| 1180 | \relates QDebug |
| 1181 | |
| 1182 | Writes the contents of \a map to \a debug. Both \c Key and |
| 1183 | \c T need to support streaming into QDebug. |
| 1184 | */ |
| 1185 | |
| 1186 | /*! |
| 1187 | \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map) |
| 1188 | \relates QDebug |
| 1189 | \since 5.7 |
| 1190 | |
| 1191 | Writes the contents of \a map to \a debug. Both \c Key and |
| 1192 | \c T need to support streaming into QDebug. |
| 1193 | */ |
| 1194 | |
| 1195 | /*! |
| 1196 | \fn template <typename Key, typename T, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map) |
| 1197 | \relates QDebug |
| 1198 | \since 5.7 |
| 1199 | |
| 1200 | Writes the contents of \a map to \a debug. Both \c Key and |
| 1201 | \c T need to support streaming into QDebug. |
| 1202 | */ |
| 1203 | |
| 1204 | /*! |
| 1205 | \fn template <typename Key, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::multiset<Key, Compare, Alloc> &multiset) |
| 1206 | \relates QDebug |
| 1207 | \since 6.9 |
| 1208 | |
| 1209 | Writes the contents of \a multiset to \a debug. The \c Key type |
| 1210 | needs to support streaming into QDebug. |
| 1211 | */ |
| 1212 | |
| 1213 | /*! |
| 1214 | \fn template <typename Key, typename Compare, typename Alloc> QDebug operator<<(QDebug debug, const std::set<Key, Compare, Alloc> &set) |
| 1215 | \relates QDebug |
| 1216 | \since 6.9 |
| 1217 | |
| 1218 | Writes the contents of \a set to \a debug. The \c Key type |
| 1219 | needs to support streaming into QDebug. |
| 1220 | */ |
| 1221 | |
| 1222 | /*! |
| 1223 | \fn template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc> QDebug operator<<(QDebug debug, const std::unordered_map<Key, T, Hash, KeyEqual, Alloc> &map) |
| 1224 | \relates QDebug |
| 1225 | \since 6.9 |
| 1226 | |
| 1227 | Writes the contents of \a map to \a debug. Both \c Key and |
| 1228 | \c T need to support streaming into QDebug. |
| 1229 | */ |
| 1230 | |
| 1231 | /*! |
| 1232 | \fn template <typename Key, typename Hash, typename KeyEqual, typename Alloc> QDebug operator<<(QDebug debug, const std::unordered_set<Key, Hash, KeyEqual, Alloc> &unordered_set) |
| 1233 | \relates QDebug |
| 1234 | \since 6.9 |
| 1235 | |
| 1236 | Writes the contents of \a unordered_set to \a debug. The \c Key type |
| 1237 | needs to support streaming into QDebug. |
| 1238 | */ |
| 1239 | |
| 1240 | /*! |
| 1241 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QHash<Key, T> &hash) |
| 1242 | \relates QDebug |
| 1243 | |
| 1244 | Writes the contents of \a hash to \a debug. Both \c Key and |
| 1245 | \c T need to support streaming into QDebug. |
| 1246 | */ |
| 1247 | |
| 1248 | /*! |
| 1249 | \fn template <class Key, class T> QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash) |
| 1250 | \relates QDebug |
| 1251 | |
| 1252 | Writes the contents of \a hash to \a debug. Both \c Key and |
| 1253 | \c T need to support streaming into QDebug. |
| 1254 | */ |
| 1255 | |
| 1256 | /*! |
| 1257 | \fn template <class...Ts, QDebug::if_streamable<Ts...>> QDebug &QDebug::operator<<(const std::tuple<Ts...> &tuple) |
| 1258 | \since 6.9 |
| 1259 | |
| 1260 | Writes the contents of \a tuple to the stream. All \c Ts... need to support |
| 1261 | streaming into QDebug. |
| 1262 | */ |
| 1263 | |
| 1264 | /*! |
| 1265 | \fn template <class T1, class T2> QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair) |
| 1266 | \relates QDebug |
| 1267 | |
| 1268 | Writes the contents of \a pair to \a debug. Both \c T1 and |
| 1269 | \c T2 need to support streaming into QDebug. |
| 1270 | */ |
| 1271 | |
| 1272 | /*! |
| 1273 | \since 6.7 |
| 1274 | \fn template <class T, QDebug::if_streamable<T>> QDebug::operator<<(const std::optional<T> &opt) |
| 1275 | |
| 1276 | Writes the contents of \a opt (or \c nullopt if not set) to this stream. |
| 1277 | \c T needs to support streaming into QDebug. |
| 1278 | */ |
| 1279 | |
| 1280 | /*! |
| 1281 | \fn template <typename T> QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) |
| 1282 | \relates QDebug |
| 1283 | |
| 1284 | Writes the contents of \a cache to \a debug. \c T needs to |
| 1285 | support streaming into QDebug. |
| 1286 | */ |
| 1287 | |
| 1288 | /*! |
| 1289 | \fn template<typename T> QDebug operator<<(QDebug debug, const QFlags<T> &flags) |
| 1290 | \relates QDebug |
| 1291 | \since 4.7 |
| 1292 | |
| 1293 | Writes \a flags to \a debug. |
| 1294 | */ |
| 1295 | |
| 1296 | /*! |
| 1297 | \fn template<typename T> QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr) |
| 1298 | \relates QSharedPointer |
| 1299 | \since 5.7 |
| 1300 | |
| 1301 | Writes the pointer tracked by \a ptr into the debug object \a debug for |
| 1302 | debugging purposes. |
| 1303 | |
| 1304 | \sa {Debugging Techniques} |
| 1305 | */ |
| 1306 | |
| 1307 | /*! |
| 1308 | \fn QDebug &QDebug::operator<<(std::nullptr_t) |
| 1309 | \internal |
| 1310 | */ |
| 1311 | |
| 1312 | /*! |
| 1313 | \since 6.7 |
| 1314 | \fn QDebug &QDebug::operator<<(std::nullopt_t) |
| 1315 | |
| 1316 | Writes nullopt to the stream. |
| 1317 | */ |
| 1318 | |
| 1319 | /*! |
| 1320 | \class QDebugStateSaver |
| 1321 | \inmodule QtCore |
| 1322 | \brief Convenience class for custom QDebug operators. |
| 1323 | |
| 1324 | Saves the settings used by QDebug, and restores them upon destruction, |
| 1325 | then calls \l {QDebug::maybeSpace()}{maybeSpace()}, to separate arguments with a space if |
| 1326 | \l {QDebug::autoInsertSpaces()}{autoInsertSpaces()} was true at the time of constructing the QDebugStateSaver. |
| 1327 | |
| 1328 | The automatic insertion of spaces between writes is one of the settings |
| 1329 | that QDebugStateSaver stores for the duration of the current block. |
| 1330 | |
| 1331 | The settings of the internal QTextStream are also saved and restored, |
| 1332 | so that using << Qt::hex in a QDebug operator doesn't affect other QDebug |
| 1333 | operators. |
| 1334 | |
| 1335 | QDebugStateSaver is typically used in the implementation of an operator<<() for debugging: |
| 1336 | |
| 1337 | \snippet customtype/customtypeexample.cpp custom type streaming operator |
| 1338 | |
| 1339 | \since 5.1 |
| 1340 | */ |
| 1341 | |
| 1342 | class QDebugStateSaverPrivate |
| 1343 | { |
| 1344 | public: |
| 1345 | QDebugStateSaverPrivate(QDebug::Stream *stream) |
| 1346 | : m_stream(stream), |
| 1347 | m_spaces(stream->space), |
| 1348 | m_noQuotes(stream->noQuotes), |
| 1349 | m_verbosity(stream->verbosity), |
| 1350 | m_streamParams(stream->ts.d_ptr->params) |
| 1351 | { |
| 1352 | } |
| 1353 | void restoreState() |
| 1354 | { |
| 1355 | const bool currentSpaces = m_stream->space; |
| 1356 | if (currentSpaces && !m_spaces) |
| 1357 | if (m_stream->buffer.endsWith(c: u' ')) |
| 1358 | m_stream->buffer.chop(n: 1); |
| 1359 | |
| 1360 | m_stream->space = m_spaces; |
| 1361 | m_stream->noQuotes = m_noQuotes; |
| 1362 | m_stream->ts.d_ptr->params = m_streamParams; |
| 1363 | m_stream->verbosity = m_verbosity; |
| 1364 | |
| 1365 | if (!currentSpaces && m_spaces) |
| 1366 | m_stream->ts << ' '; |
| 1367 | } |
| 1368 | |
| 1369 | QDebug::Stream *m_stream; |
| 1370 | |
| 1371 | // QDebug state |
| 1372 | const bool m_spaces; |
| 1373 | const bool m_noQuotes; |
| 1374 | const int m_verbosity; |
| 1375 | |
| 1376 | // QTextStream state |
| 1377 | const QTextStreamPrivate::Params m_streamParams; |
| 1378 | }; |
| 1379 | |
| 1380 | |
| 1381 | /*! |
| 1382 | Creates a QDebugStateSaver instance, which saves the settings |
| 1383 | currently used by \a dbg. |
| 1384 | |
| 1385 | \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() |
| 1386 | */ |
| 1387 | QDebugStateSaver::QDebugStateSaver(QDebug &dbg) |
| 1388 | : d(new QDebugStateSaverPrivate(dbg.stream)) |
| 1389 | { |
| 1390 | } |
| 1391 | |
| 1392 | /*! |
| 1393 | Destroys a QDebugStateSaver instance, which restores the settings |
| 1394 | used when the QDebugStateSaver instance was created. |
| 1395 | |
| 1396 | \sa QDebug::setAutoInsertSpaces(), QDebug::autoInsertSpaces() |
| 1397 | */ |
| 1398 | QDebugStateSaver::~QDebugStateSaver() |
| 1399 | { |
| 1400 | d->restoreState(); |
| 1401 | } |
| 1402 | |
| 1403 | /*! |
| 1404 | \internal |
| 1405 | |
| 1406 | Specialization of the primary template in qdebug.h to out-of-line |
| 1407 | the common case of QFlags<T>::Int being 32-bit. |
| 1408 | |
| 1409 | Just call the generic version so the two don't get out of sync. |
| 1410 | */ |
| 1411 | void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value) |
| 1412 | { |
| 1413 | qt_QMetaEnum_flagDebugOperator(debug, sizeofT, value: quint64(value)); |
| 1414 | } |
| 1415 | |
| 1416 | /*! |
| 1417 | \internal |
| 1418 | Ditto, for 64-bit. |
| 1419 | */ |
| 1420 | void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value) |
| 1421 | { |
| 1422 | qt_QMetaEnum_flagDebugOperator<quint64>(debug, sizeofT, value); |
| 1423 | } |
| 1424 | |
| 1425 | |
| 1426 | #ifndef QT_NO_QOBJECT |
| 1427 | /*! |
| 1428 | \internal |
| 1429 | |
| 1430 | Formats the given enum \a value for debug output. |
| 1431 | |
| 1432 | The supported verbosity are: |
| 1433 | |
| 1434 | 0: Just the key, or value with enum name if no key is found: |
| 1435 | |
| 1436 | MyEnum2 |
| 1437 | MyEnum(123) |
| 1438 | MyScopedEnum::Enum3 |
| 1439 | MyScopedEnum(456) |
| 1440 | |
| 1441 | 1: Same as 0, but treating all enums as scoped: |
| 1442 | |
| 1443 | MyEnum::MyEnum2 |
| 1444 | MyEnum(123) |
| 1445 | MyScopedEnum::Enum3 |
| 1446 | MyScopedEnum(456) |
| 1447 | |
| 1448 | 2: The QDebug default. Same as 0, and includes class/namespace scope: |
| 1449 | |
| 1450 | MyNamespace::MyClass::MyEnum2 |
| 1451 | MyNamespace::MyClass::MyEnum(123) |
| 1452 | MyNamespace::MyClass::MyScopedEnum::Enum3 |
| 1453 | MyNamespace::MyClass::MyScopedEnum(456) |
| 1454 | |
| 1455 | 3: Same as 2, but treating all enums as scoped: |
| 1456 | |
| 1457 | MyNamespace::MyClass::MyEnum::MyEnum2 |
| 1458 | MyNamespace::MyClass::MyEnum(123) |
| 1459 | MyNamespace::MyClass::MyScopedEnum::Enum3 |
| 1460 | MyNamespace::MyClass::MyScopedEnum(456) |
| 1461 | */ |
| 1462 | QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, qint64 value, const QMetaObject *meta, const char *name) |
| 1463 | { |
| 1464 | QDebugStateSaver saver(dbg); |
| 1465 | dbg.nospace(); |
| 1466 | QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); |
| 1467 | |
| 1468 | const int verbosity = dbg.verbosity(); |
| 1469 | if (verbosity >= QDebug::DefaultVerbosity) { |
| 1470 | if (const char *scope = me.scope()) |
| 1471 | dbg << scope << u"::" ; |
| 1472 | } |
| 1473 | |
| 1474 | const char *key = me.valueToKey(value: static_cast<int>(value)); |
| 1475 | const bool scoped = me.isScoped() || verbosity & 1; |
| 1476 | if (scoped || !key) |
| 1477 | dbg << me.enumName() << (!key ? u"(" : u"::" ); |
| 1478 | |
| 1479 | if (key) |
| 1480 | dbg << key; |
| 1481 | else |
| 1482 | dbg << value << ')'; |
| 1483 | |
| 1484 | return dbg; |
| 1485 | } |
| 1486 | |
| 1487 | /*! |
| 1488 | \fn QDebug qt_QMetaEnum_flagDebugOperator(QDebug &, quint64 value, const QMetaObject *, const char *name) |
| 1489 | \internal |
| 1490 | |
| 1491 | Formats the given flag \a value for debug output. |
| 1492 | |
| 1493 | The supported verbosity are: |
| 1494 | |
| 1495 | 0: Just the key(s): |
| 1496 | |
| 1497 | MyFlag1 |
| 1498 | MyFlag2|MyFlag3 |
| 1499 | MyScopedFlag(MyFlag2) |
| 1500 | MyScopedFlag(MyFlag2|MyFlag3) |
| 1501 | |
| 1502 | 1: Same as 0, but treating all flags as scoped: |
| 1503 | |
| 1504 | MyFlag(MyFlag1) |
| 1505 | MyFlag(MyFlag2|MyFlag3) |
| 1506 | MyScopedFlag(MyFlag2) |
| 1507 | MyScopedFlag(MyFlag2|MyFlag3) |
| 1508 | |
| 1509 | 2: The QDebug default. Same as 1, and includes class/namespace scope: |
| 1510 | |
| 1511 | QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) |
| 1512 | QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3) |
| 1513 | QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2) |
| 1514 | QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3) |
| 1515 | */ |
| 1516 | QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaObject *meta, const char *name) |
| 1517 | { |
| 1518 | const int verbosity = debug.verbosity(); |
| 1519 | |
| 1520 | QDebugStateSaver saver(debug); |
| 1521 | debug.resetFormat(); |
| 1522 | debug.noquote(); |
| 1523 | debug.nospace(); |
| 1524 | |
| 1525 | const QMetaEnum me = meta->enumerator(index: meta->indexOfEnumerator(name)); |
| 1526 | |
| 1527 | const bool classScope = verbosity >= QDebug::DefaultVerbosity; |
| 1528 | if (classScope) { |
| 1529 | debug << u"QFlags<" ; |
| 1530 | |
| 1531 | if (const char *scope = me.scope()) |
| 1532 | debug << scope << u"::" ; |
| 1533 | } |
| 1534 | |
| 1535 | const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity; |
| 1536 | if (enumScope) { |
| 1537 | debug << me.enumName(); |
| 1538 | if (classScope) |
| 1539 | debug << '>'; |
| 1540 | debug << '('; |
| 1541 | } |
| 1542 | |
| 1543 | debug << me.valueToKeys(value); |
| 1544 | |
| 1545 | if (enumScope) |
| 1546 | debug << ')'; |
| 1547 | |
| 1548 | return debug; |
| 1549 | } |
| 1550 | |
| 1551 | /*! |
| 1552 | \macro QDebug qDebug() |
| 1553 | \relates QDebug |
| 1554 | \threadsafe |
| 1555 | |
| 1556 | Returns a QDebug object that logs a debug message to the central message handler. |
| 1557 | |
| 1558 | Example: |
| 1559 | |
| 1560 | \snippet code/src_corelib_global_qglobal.cpp 25 |
| 1561 | |
| 1562 | Using qDebug() is an alternative to \l{qDebug(const char *, ...)}, |
| 1563 | which follows the printf paradigm. |
| 1564 | |
| 1565 | Note that QDebug and the type specific stream operators do add various |
| 1566 | formatting to make the debug message easier to read. See the |
| 1567 | \l{Formatting Options}{formatting options} documentation for more details. |
| 1568 | |
| 1569 | This function does nothing if \c QT_NO_DEBUG_OUTPUT was defined during |
| 1570 | compilation. |
| 1571 | |
| 1572 | \sa {qDebug(const char *, ...)}, qCDebug() |
| 1573 | */ |
| 1574 | |
| 1575 | /*! |
| 1576 | \macro QDebug qInfo() |
| 1577 | \relates QDebug |
| 1578 | \threadsafe |
| 1579 | |
| 1580 | Returns a QDebug object that logs an informational message to the central message handler. |
| 1581 | |
| 1582 | Example: |
| 1583 | |
| 1584 | \snippet code/src_corelib_global_qglobal.cpp qInfo_stream |
| 1585 | |
| 1586 | Using qInfo() is an alternative to \l{qInfo(const char *, ...)}, |
| 1587 | which follows the printf paradigm. |
| 1588 | |
| 1589 | Note that QDebug and the type specific stream operators do add various |
| 1590 | formatting to make the debug message easier to read. See the |
| 1591 | \l{Formatting Options}{formatting options} documentation for more details. |
| 1592 | |
| 1593 | This function does nothing if \c QT_NO_INFO_OUTPUT was defined during |
| 1594 | compilation. |
| 1595 | |
| 1596 | \sa {qInfo(const char *, ...)}, qCInfo() |
| 1597 | */ |
| 1598 | |
| 1599 | /*! |
| 1600 | \macro QDebug qWarning() |
| 1601 | \relates QDebug |
| 1602 | \threadsafe |
| 1603 | |
| 1604 | Returns a QDebug object that logs a warning message to the central message handler. |
| 1605 | |
| 1606 | Example: |
| 1607 | |
| 1608 | \snippet code/src_corelib_global_qglobal.cpp 27 |
| 1609 | |
| 1610 | Using qWarning() is an alternative to \l{qWarning(const char *, ...)}, |
| 1611 | which follows the printf paradigm. |
| 1612 | |
| 1613 | Note that QDebug and the type specific stream operators do add various |
| 1614 | formatting to make the debug message easier to read. See the |
| 1615 | \l{Formatting Options}{formatting options} documentation for more details. |
| 1616 | |
| 1617 | This function does nothing if \c QT_NO_WARNING_OUTPUT was defined during |
| 1618 | compilation. |
| 1619 | |
| 1620 | For debugging purposes, it is sometimes convenient to let the |
| 1621 | program abort for warning messages. This allows you then |
| 1622 | to inspect the core dump, or attach a debugger - see also \l{qFatal()}. |
| 1623 | To enable this, set the environment variable \c{QT_FATAL_WARNINGS} |
| 1624 | to a number \c n. The program terminates then for the n-th warning. |
| 1625 | That is, if the environment variable is set to 1, it will terminate |
| 1626 | on the first call; if it contains the value 10, it will exit on the 10th |
| 1627 | call. Any non-numeric value in the environment variable is equivalent to 1. |
| 1628 | |
| 1629 | \sa {qWarning(const char *, ...)}, qCWarning() |
| 1630 | */ |
| 1631 | |
| 1632 | /*! |
| 1633 | \macro QDebug qCritical() |
| 1634 | \relates QDebug |
| 1635 | \threadsafe |
| 1636 | |
| 1637 | Returns a QDebug object that logs a critical message to the central message handler. |
| 1638 | |
| 1639 | Example: |
| 1640 | |
| 1641 | \snippet code/src_corelib_global_qglobal.cpp 29 |
| 1642 | |
| 1643 | Using qCritical() is an alternative to \l{qCritical(const char *, ...)}, |
| 1644 | which follows the printf paradigm. |
| 1645 | |
| 1646 | Note that QDebug and the type specific stream operators do add various |
| 1647 | formatting to make the debug message easier to read. See the |
| 1648 | \l{Formatting Options}{formatting options} documentation for more details. |
| 1649 | |
| 1650 | For debugging purposes, it is sometimes convenient to let the |
| 1651 | program abort for critical messages. This allows you then |
| 1652 | to inspect the core dump, or attach a debugger - see also \l{qFatal()}. |
| 1653 | To enable this, set the environment variable \c{QT_FATAL_CRITICALS} |
| 1654 | to a number \c n. The program terminates then for the n-th critical |
| 1655 | message. |
| 1656 | That is, if the environment variable is set to 1, it will terminate |
| 1657 | on the first call; if it contains the value 10, it will exit on the 10th |
| 1658 | call. Any non-numeric value in the environment variable is equivalent to 1. |
| 1659 | |
| 1660 | \sa {qCritical(const char *, ...)}, qCCritical() |
| 1661 | */ |
| 1662 | |
| 1663 | /*! |
| 1664 | \macro QDebug qFatal() |
| 1665 | \relates QDebug |
| 1666 | \threadsafe |
| 1667 | |
| 1668 | Returns a QDebug object that logs a fatal message to the central message handler. |
| 1669 | |
| 1670 | Using qFatal() is an alternative to \l{qFatal(const char *, ...)}, |
| 1671 | which follows the printf paradigm. |
| 1672 | |
| 1673 | Note that QDebug and the type specific stream operators do add various |
| 1674 | formatting to make the debug message easier to read. See the |
| 1675 | \l{Formatting Options}{formatting options} documentation for more details. |
| 1676 | |
| 1677 | If you are using the \b{default message handler}, the returned stream will abort |
| 1678 | to create a core dump. On Windows, for debug builds, |
| 1679 | this function will report a _CRT_ERROR enabling you to connect a debugger |
| 1680 | to the application. |
| 1681 | |
| 1682 | \sa {qFatal(const char *, ...)}, qCFatal() |
| 1683 | */ |
| 1684 | |
| 1685 | #endif // !QT_NO_QOBJECT |
| 1686 | |
| 1687 | QT_END_NAMESPACE |
| 1688 | |