Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdebug.h
Go to the documentation of this file.
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#ifndef QDEBUG_H
6#define QDEBUG_H
7
8#if 0
9#pragma qt_class(QtDebug)
10#endif
11
12#include <QtCore/qcompare.h>
13#include <QtCore/qcontainerfwd.h>
14#include <QtCore/qfloat16.h>
15#include <QtCore/qtextstream.h>
16#include <QtCore/qttypetraits.h>
17#include <QtCore/qtypes.h>
18#include <QtCore/qstring.h>
19#include <QtCore/qcontiguouscache.h>
20#include <QtCore/qsharedpointer.h>
21
22// all these have already been included by various headers above, but don't rely on indirect includes:
23#include <array>
24#include <chrono>
25#include <list>
26#include <map>
27#include <memory>
28#include <optional>
29#include <set>
30#include <string>
31#include <string_view>
32#include <set>
33#include <tuple>
34#include <QtCore/q20type_traits.h>
35#include <unordered_map>
36#include <unordered_set>
37#include <utility>
38#include <unordered_map>
39#include <unordered_set>
40#include <vector>
41
42#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
43# include <QtCore/qlist.h>
44# include <QtCore/qmap.h>
45# include <QtCore/qset.h>
46# include <QtCore/qvarlengtharray.h>
47#endif
48
49QT_BEGIN_NAMESPACE
50
51class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
52{
53 friend class QMessageLogger;
54 friend class QDebugStateSaver;
55 friend class QDebugStateSaverPrivate;
56 struct Stream {
57 enum { VerbosityShift = 29, VerbosityMask = 0x7 };
58
59 explicit Stream(QIODevice *device)
60 : ts(device)
61 {}
62 explicit Stream(QString *string)
63 : ts(string, WriteOnly)
64 {}
65 explicit Stream(QByteArray *ba)
66 : ts(ba, WriteOnly)
67 {}
68 explicit Stream(QtMsgType t)
69 : ts(&buffer, WriteOnly),
70 type(t),
71 message_output(true)
72 {}
73 QTextStream ts;
74 QString buffer;
75 int ref = 1;
76 QtMsgType type = QtDebugMsg;
77 bool space = true;
78 bool noQuotes = false;
79 bool message_output = false;
80 int verbosity = DefaultVerbosity;
81 QMessageLogContext context;
82 } *stream;
83
84 enum Latin1Content { ContainsBinary = 0, ContainsLatin1 };
85
86 QT7_ONLY(Q_CORE_EXPORT) void putUcs4(uint ucs4);
87 QT7_ONLY(Q_CORE_EXPORT) void putString(const QChar *begin, size_t length);
88 QT7_ONLY(Q_CORE_EXPORT) void putByteArray(const char *begin, size_t length, Latin1Content content);
89 QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
90 QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
91 QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
92 QT7_ONLY(Q_CORE_EXPORT) void putQtOrdering(QtOrderingPrivate::QtOrderingTypeFlag flags,
93 Qt::partial_ordering order);
94
95 template <typename...Ts>
96 using if_streamable = std::enable_if_t<
97 std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, Ts>...>
98 , bool>;
99public:
100 explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
101 explicit QDebug(QString *string) : stream(new Stream(string)) {}
102 explicit QDebug(QByteArray *bytes) : stream(new Stream(bytes)) {}
103 explicit QDebug(QtMsgType t) : stream(new Stream(t)) {}
104 QDebug(const QDebug &o) : stream(o.stream) { ++stream->ref; }
105 QDebug(QDebug &&other) noexcept : stream{std::exchange(other.stream, nullptr)} {}
106 inline QDebug &operator=(const QDebug &other);
107 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QDebug)
108 ~QDebug();
109 void swap(QDebug &other) noexcept { qt_ptr_swap(stream, other.stream); }
110
111 QT7_ONLY(Q_CORE_EXPORT) QDebug &resetFormat();
112
113 inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
114 inline QDebug &nospace() { stream->space = false; return *this; }
115 inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
116 inline QDebug &verbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; return *this; }
117 int verbosity() const { return stream->verbosity; }
118 void setVerbosity(int verbosityLevel) { stream->verbosity = verbosityLevel; }
119 enum VerbosityLevel { MinimumVerbosity = 0, DefaultVerbosity = 2, MaximumVerbosity = 7 };
120
121 bool autoInsertSpaces() const { return stream->space; }
122 void setAutoInsertSpaces(bool b) { stream->space = b; }
123
124 [[nodiscard]] bool quoteStrings() const noexcept { return !stream->noQuotes; }
125 void setQuoteStrings(bool b) { stream->noQuotes = !b; }
126
127 inline QDebug &quote() { stream->noQuotes = false; return *this; }
128 inline QDebug &noquote() { stream->noQuotes = true; return *this; }
129 inline QDebug &maybeQuote(char c = '"') { if (!stream->noQuotes) stream->ts << c; return *this; }
130
131 inline QDebug &operator<<(QChar t) { putUcs4(t.unicode()); return maybeSpace(); }
132 inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
133 inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
134 inline QDebug &operator<<(signed short t) { stream->ts << t; return maybeSpace(); }
135 inline QDebug &operator<<(unsigned short t) { stream->ts << t; return maybeSpace(); }
136 inline QDebug &operator<<(char16_t t) { return *this << QChar(t); }
137 inline QDebug &operator<<(char32_t t) { putUcs4(t); return maybeSpace(); }
138 inline QDebug &operator<<(signed int t) { stream->ts << t; return maybeSpace(); }
139 inline QDebug &operator<<(unsigned int t) { stream->ts << t; return maybeSpace(); }
140 inline QDebug &operator<<(signed long t) { stream->ts << t; return maybeSpace(); }
141 inline QDebug &operator<<(unsigned long t) { stream->ts << t; return maybeSpace(); }
142 inline QDebug &operator<<(qint64 t) { stream->ts << t; return maybeSpace(); }
143 inline QDebug &operator<<(quint64 t) { stream->ts << t; return maybeSpace(); }
144 inline QDebug &operator<<(qfloat16 t) { stream->ts << t; return maybeSpace(); }
145 inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
146 inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
147 inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
148 inline QDebug &operator<<(const char16_t *t) { stream->ts << QStringView(t); return maybeSpace(); }
149 inline QDebug &operator<<(const QString & t) { putString(t.constData(), size_t(t.size())); return maybeSpace(); }
150 inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
151 inline QDebug &operator<<(QUtf8StringView s) { putByteArray(reinterpret_cast<const char*>(s.data()), s.size(), ContainsBinary); return maybeSpace(); }
152 inline QDebug &operator<<(QLatin1StringView t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
153 inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
154 inline QDebug &operator<<(QByteArrayView t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
155 inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
156 inline QDebug &operator<<(std::nullptr_t) { stream->ts << "(nullptr)"; return maybeSpace(); }
157 inline QDebug &operator<<(std::nullopt_t) { stream->ts << "nullopt"; return maybeSpace(); }
158 inline QDebug &operator<<(QTextStreamFunction f) {
159 stream->ts << f;
160 return *this;
161 }
162
163 inline QDebug &operator<<(QTextStreamManipulator m)
164 { stream->ts << m; return *this; }
165
166#ifdef Q_QDOC
167 template <typename Char, typename...Args>
168 QDebug &operator<<(const std::basic_string<Char, Args...> &s);
169
170 template <typename Char, typename...Args>
171 QDebug &operator<<(std::basic_string_view<Char, Args...> s);
172#else
173 template <typename...Args>
174 QDebug &operator<<(const std::basic_string<char, Args...> &s)
175 { return *this << QUtf8StringView(s); }
176
177 template <typename...Args>
178 QDebug &operator<<(std::basic_string_view<char, Args...> s)
179 { return *this << QUtf8StringView(s); }
180
181#ifdef __cpp_char8_t
182 template <typename...Args>
183 QDebug &operator<<(const std::basic_string<char8_t, Args...> &s)
184 { return *this << QUtf8StringView(s); }
185
186 template <typename...Args>
187 QDebug &operator<<(std::basic_string_view<char8_t, Args...> s)
188 { return *this << QUtf8StringView(s); }
189#endif // __cpp_char8_t
190
191 template <typename...Args>
192 QDebug &operator<<(const std::basic_string<char16_t, Args...> &s)
193 { return *this << QStringView(s); }
194
195 template <typename...Args>
196 QDebug &operator<<(std::basic_string_view<char16_t, Args...> s)
197 { return *this << QStringView(s); }
198
199 template <typename...Args>
200 QDebug &operator<<(const std::basic_string<wchar_t, Args...> &s)
201 {
202 if constexpr (sizeof(wchar_t) == 2)
203 return *this << QStringView(s);
204 else
205 return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
206 }
207
208 template <typename...Args>
209 QDebug &operator<<(std::basic_string_view<wchar_t, Args...> s)
210 {
211 if constexpr (sizeof(wchar_t) == 2)
212 return *this << QStringView(s);
213 else
214 return *this << QString::fromWCharArray(s.data(), s.size()); // ### optimize
215 }
216
217 template <typename...Args>
218 QDebug &operator<<(const std::basic_string<char32_t, Args...> &s)
219 { return *this << QString::fromUcs4(s.data(), s.size()); }
220
221 template <typename...Args>
222 QDebug &operator<<(std::basic_string_view<char32_t, Args...> s)
223 { return *this << QString::fromUcs4(s.data(), s.size()); }
224#endif // !Q_QDOC
225
226 template <typename Rep, typename Period>
227 QDebug &operator<<(std::chrono::duration<Rep, Period> duration)
228 {
229 stream->ts << duration.count();
230 putTimeUnit(Period::num, Period::den);
231 return maybeSpace();
232 }
233
234#ifdef QT_SUPPORTS_INT128
235private:
236 // Constrained templates so they only match q(u)int128 without conversions.
237 // Also keeps these operators out of the ABI.
238 template <typename T>
239 using if_qint128 = std::enable_if_t<std::is_same_v<T, qint128>, bool>;
240 template <typename T>
241 using if_quint128 = std::enable_if_t<std::is_same_v<T, quint128>, bool>;
242public:
243 template <typename T, if_qint128<T> = true>
244 QDebug &operator<<(T i128) { putInt128(&i128); return maybeSpace(); }
245 template <typename T, if_quint128<T> = true>
246 QDebug &operator<<(T u128) { putUInt128(&u128); return maybeSpace(); }
247#endif // QT_SUPPORTS_INT128
248
249private:
250 template <typename T>
251 static void streamTypeErased(QDebug &d, const void *obj)
252 {
253 d << *static_cast<const T*>(obj);
254 }
255 using StreamTypeErased = void(*)(QDebug&, const void*);
256 QT7_ONLY(Q_CORE_EXPORT) static QString toStringImpl(StreamTypeErased s, const void *obj);
257 QT7_ONLY(Q_CORE_EXPORT) static QByteArray toBytesImpl(StreamTypeErased s, const void *obj);
258 QT7_ONLY(Q_CORE_EXPORT) QDebug &putTupleLikeImplImpl(const char *ns, const char *what, size_t n,
259 StreamTypeErased *ops, const void **data);
260
261 template <typename TupleLike, size_t...Is>
262 QDebug &putTupleLikeImpl(const char *ns, const char *what, const TupleLike &t,
263 std::index_sequence<Is...>)
264 {
265 if constexpr (sizeof...(Is)) {
266 StreamTypeErased ops[] = {
267 &streamTypeErased<q20::remove_cvref_t<std::tuple_element_t<Is, TupleLike>>>...
268 };
269 const void *data[] = {
270 std::addressof(std::get<Is>(t))...
271 };
272 return putTupleLikeImplImpl(ns, what, sizeof...(Is), ops, data);
273 } else {
274 return putTupleLikeImplImpl(ns, what, 0, nullptr, nullptr);
275 }
276 }
277
278 template <typename TupleLike>
279 QDebug &putTupleLike(const char *ns, const char *what, const TupleLike &t)
280 {
281 using Indexes = std::make_index_sequence<std::tuple_size_v<TupleLike>>;
282 return putTupleLikeImpl(ns, what, t, Indexes{});
283 }
284public:
285 template <typename T>
286 static QString toString(const T &object)
287 {
288 return toStringImpl(&streamTypeErased<T>, std::addressof(object));
289 }
290
291 template <typename T>
292 static QByteArray toBytes(const T &object)
293 {
294 return toBytesImpl(&streamTypeErased<T>, std::addressof(object));
295 }
296
297 template <typename...Ts, if_streamable<Ts...> = true>
298 QDebug &operator<<(const std::tuple<Ts...> &t)
299 {
300 return putTupleLike("std", "tuple", t);
301 }
302
303 template <typename T, if_streamable<T> = true>
304 QDebug &operator<<(const std::optional<T> &o)
305 {
306 if (!o)
307 return *this << std::nullopt;
308 StreamTypeErased s = &streamTypeErased<std::remove_cv_t<T>>;
309 const void *d = std::addressof(*o);
310 return putTupleLikeImplImpl("std", "optional", 1, &s, &d);
311 }
312
313private:
314 template <typename T>
315 using if_ordering_type = std::enable_if_t<QtOrderingPrivate::is_ordering_type_v<T>, bool>;
316
317 template <typename T, if_ordering_type<T> = true>
318 friend QDebug operator<<(QDebug debug, T t)
319 {
320 debug.putQtOrdering(QtOrderingPrivate::orderingFlagsFor(t), Qt::partial_ordering(t));
321 return debug;
322 }
323};
324
326
328class QDebugStateSaver
329{
330public:
331 Q_NODISCARD_CTOR Q_CORE_EXPORT
332 QDebugStateSaver(QDebug &dbg);
333 Q_CORE_EXPORT
334 ~QDebugStateSaver();
335private:
336 Q_DISABLE_COPY(QDebugStateSaver)
337 std::unique_ptr<QDebugStateSaverPrivate> d;
338};
339
340class QNoDebug
341{
342public:
343 inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
344 inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
345 inline QNoDebug &space() { return *this; }
346 inline QNoDebug &nospace() { return *this; }
347 inline QNoDebug &maybeSpace() { return *this; }
348 inline QNoDebug &quote() { return *this; }
349 inline QNoDebug &noquote() { return *this; }
350 inline QNoDebug &maybeQuote(const char = '"') { return *this; }
351 inline QNoDebug &verbosity(int) { return *this; }
352
353 template<typename T>
354 inline QNoDebug &operator<<(const T &) { return *this; }
355};
356inline QNoDebug QMessageLogger::noDebug(...) const noexcept
357{ return {}; }
358
359inline QDebug &QDebug::operator=(const QDebug &other)
360{
361 QDebug{other}.swap(*this);
362 return *this;
363}
364
365namespace QtPrivate {
366
367template <typename SequentialContainer>
368inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
369{
370 const QDebugStateSaver saver(debug);
371 debug.nospace() << which << '(';
372 typename SequentialContainer::const_iterator it = c.begin(), end = c.end();
373 if (it != end) {
374 debug << *it;
375 ++it;
376 }
377 while (it != end) {
378 debug << ", " << *it;
379 ++it;
380 }
381 debug << ')';
382 return debug;
383}
384
385template <typename AssociativeContainer>
386inline QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
387{
388 const QDebugStateSaver saver(debug);
389 debug.nospace() << which << "(";
390 for (typename AssociativeContainer::const_iterator it = c.constBegin();
391 it != c.constEnd(); ++it) {
392 debug << '(' << it.key() << ", " << it.value() << ')';
393 }
394 debug << ')';
395 return debug;
396}
397
398} // namespace QtPrivate
399
400template<typename ...T>
401using QDebugIfHasDebugStream =
402 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
403
404template<typename Container, typename ...T>
405using QDebugIfHasDebugStreamContainer =
406 std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
407
408#ifndef Q_QDOC
409
410template<typename T>
411inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
412{
413 return QtPrivate::printSequentialContainer(std::move(debug), "QList", vec);
414}
415
416template<typename T, qsizetype P>
417inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QVarLengthArray<T, P> &vec)
418{
419 return QtPrivate::printSequentialContainer(std::move(debug), "QVarLengthArray", vec);
420}
421
422template <typename T, typename Alloc>
423inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
424{
425 return QtPrivate::printSequentialContainer(std::move(debug), "std::vector", vec);
426}
427
428template <typename T, std::size_t N>
429inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::array<T, N> &array)
430{
431 return QtPrivate::printSequentialContainer(std::move(debug), "std::array", array);
432}
433
434template <typename T, typename Alloc>
435inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const std::list<T, Alloc> &vec)
436{
437 return QtPrivate::printSequentialContainer(std::move(debug), "std::list", vec);
438}
439
440template <typename T>
441inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, std::initializer_list<T> list)
442{
443 return QtPrivate::printSequentialContainer(std::move(debug), "std::initializer_list", list);
444}
445
446template <typename Key, typename T, typename Compare, typename Alloc>
447inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
448{
449 return QtPrivate::printSequentialContainer(std::move(debug), "std::map", map); // yes, sequential: *it is std::pair
450}
451
452template <typename Key, typename T, typename Compare, typename Alloc>
453inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
454{
455 return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair
456}
457
458template <typename Key, typename Compare, typename Alloc>
459inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::multiset<Key, Compare, Alloc> &multiset)
460{
461 return QtPrivate::printSequentialContainer(std::move(debug), "std::multiset", multiset);
462}
463
464template <typename Key, typename Compare, typename Alloc>
465inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::set<Key, Compare, Alloc> &set)
466{
467 return QtPrivate::printSequentialContainer(std::move(debug), "std::set", set);
468}
469
470template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
471inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::unordered_map<Key, T, Hash, KeyEqual, Alloc> &unordered_map)
472{
473 return QtPrivate::printSequentialContainer(std::move(debug), "std::unordered_map", unordered_map); // yes, sequential: *it is std::pair
474}
475
476template <typename Key, typename Hash, typename KeyEqual, typename Alloc>
477inline QDebugIfHasDebugStream<Key> operator<<(QDebug debug, const std::unordered_set<Key, Hash, KeyEqual, Alloc> &unordered_set)
478{
479 return QtPrivate::printSequentialContainer(std::move(debug), "std::unordered_set", unordered_set);
480}
481
482template <class Key, class T>
483inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
484{
485 return QtPrivate::printAssociativeContainer(std::move(debug), "QMap", map);
486}
487
488template <class Key, class T>
489inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
490{
491 return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiMap", map);
492}
493
494template <class Key, class T>
495inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
496{
497 return QtPrivate::printAssociativeContainer(std::move(debug), "QHash", hash);
498}
499
500template <class Key, class T>
501inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
502{
503 return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash);
504}
505
506template <class T1, class T2>
507inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T1, T2> &pair)
508{
509 const QDebugStateSaver saver(debug);
510 debug.nospace() << "std::pair(" << pair.first << ", " << pair.second << ')';
511 return debug;
512}
513
514template <typename T>
515inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
516{
517 return QtPrivate::printSequentialContainer(std::move(debug), "QSet", set);
518}
519
520template <class T>
521inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QContiguousCache<T> &cache)
522{
523 const QDebugStateSaver saver(debug);
524 debug.nospace() << "QContiguousCache(";
525 for (qsizetype i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
526 debug << cache[i];
527 if (i != cache.lastIndex())
528 debug << ", ";
529 }
530 debug << ')';
531 return debug;
532}
533
534#else
535template <class T>
536QDebug operator<<(QDebug debug, const QList<T> &list);
537
538template <class T, qsizetype P>
539QDebug operator<<(QDebug debug, const QVarLengthArray<T, P> &array);
540
541template <typename T, typename Alloc>
542QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec);
543
544template <typename T, std::size_t N>
545QDebug operator<<(QDebug debug, const std::array<T, N> &array);
546
547template <typename T, typename Alloc>
548QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec);
549
550template <typename Key, typename T, typename Compare, typename Alloc>
551QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map);
552
553template <typename Key, typename T, typename Compare, typename Alloc>
554QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map);
555
556template <class Key, class T>
557QDebug operator<<(QDebug debug, const QMap<Key, T> &map);
558
559template <class Key, class T>
560QDebug operator<<(QDebug debug, const QMultiMap<Key, T> &map);
561
562template <class Key, class T>
563QDebug operator<<(QDebug debug, const QHash<Key, T> &hash);
564
565template <class Key, class T>
566QDebug operator<<(QDebug debug, const QMultiHash<Key, T> &hash);
567
568template <typename T>
569QDebug operator<<(QDebug debug, const QSet<T> &set);
570
571template <class T1, class T2>
572QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair);
573
574template <typename T>
575QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache);
576
577template <typename Key, typename Compare, typename Alloc>
578QDebug operator<<(QDebug debug, const std::multiset<Key, Compare, Alloc> &multiset);
579
580template <typename Key, typename Compare, typename Alloc>
581QDebug operator<<(QDebug debug, const std::set<Key, Compare, Alloc> &set);
582
583template <typename Key, typename T, typename Hash, typename KeyEqual, typename Alloc>
584QDebug operator<<(QDebug debug, const std::unordered_map<Key, T, Hash, KeyEqual, Alloc> &unordered_map);
585
586template <typename Key, typename Hash, typename KeyEqual, typename Alloc>
587QDebug operator<<(QDebug debug, const std::unordered_set<Key, Hash, KeyEqual, Alloc> &unordered_set);
588
589#endif // Q_QDOC
590
591template <class T>
592inline QDebug operator<<(QDebug debug, const QSharedPointer<T> &ptr)
593{
594 QDebugStateSaver saver(debug);
595 debug.nospace() << "QSharedPointer(" << ptr.data() << ")";
596 return debug;
597}
598
599template <typename T, typename Tag> class QTaggedPointer;
600
601template <typename T, typename Tag>
602inline QDebug operator<<(QDebug debug, const QTaggedPointer<T, Tag> &ptr)
603{
604 QDebugStateSaver saver(debug);
605 debug.nospace() << "QTaggedPointer(" << ptr.pointer() << ", " << ptr.tag() << ")";
606 return debug;
607}
608
609Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, qint64 value, const QMetaObject *meta, const char *name);
610Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name);
611Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value);
612Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value);
613
614template <typename Int>
615void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
616{
617 static_assert(std::is_unsigned_v<Int>,
618 "Cast value to an unsigned type before calling this function");
619 const QDebugStateSaver saver(debug);
620 debug.resetFormat();
621 debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase;
622 bool needSeparator = false;
623 for (size_t i = 0; i < sizeofT * 8; ++i) {
624 if (value & (Int(1) << i)) {
625 if (needSeparator)
626 debug << '|';
627 else
628 needSeparator = true;
629 debug << (Int(1) << i);
630 }
631 }
632 debug << ')';
633}
634
635template <class Flags,
636 std::enable_if_t<QtPrivate::IsQFlags<Flags>::value, bool> = true>
637inline QDebug operator<<(QDebug debug, Flags flags)
638{
639 using T = typename Flags::enum_type;
640 using UInt = typename QIntegerForSizeof<T>::Unsigned;
641#if !defined(QT_NO_QOBJECT)
642 if constexpr (QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<Flags>::Value) {
643 // if QFlags<T> is a Q_FLAG, we always zero-extend; if not, we need to
644 // allow it to sign-extend if it is signed (see QMetaEnum::valueToKeys)
645 using Int = std::conditional_t<QtPrivate::IsQEnumHelper<Flags>::Value, UInt,
646 std::underlying_type_t<T>>;
647 const QMetaObject *obj = qt_getEnumMetaObject(T());
648 const char *name = qt_getEnumName(T());
649 return qt_QMetaEnum_flagDebugOperator(debug, Int(flags.toInt()), obj, name);
650 } else
651#endif
652 {
653 qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), UInt(flags.toInt()));
654 return debug;
655 }
656}
657
658#ifdef Q_QDOC
659template <typename T>
660QDebug operator<<(QDebug debug, const QFlags<T> &flags);
661#endif // Q_QDOC
662
663#if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC)
664// Debugging of plain enums. There are three cases:
665// 1) the enum is part of a Q_DECLARE_FLAGS and there's a Q_FLAG for that
666// -> debugs as that QFlags (even if a Q_ENUM is present)
667// 2) the enum is declared a Q_ENUM but is not part of a Q_DECLARE_FLAGS
668// -> debugs via qt_QMetaEnum_debugOperator()
669// 3) the enum is not associated with a QMetaObject
670// -> no streaming
671// To avoid ambiguity in overload resolution, the template conditions are
672// mutually exclusive.
673
674namespace QtPrivate {
675template <typename T, bool IsEnum = std::is_enum_v<T>, bool = sizeof(T) <= sizeof(quint64)>
676struct EnumHasQFlag { static constexpr bool Value = false; };
677template <typename T> struct EnumHasQFlag<T, true, true> : QtPrivate::IsQEnumHelper<QFlags<T>> {};
678
679template <typename T, bool IsEnum = std::is_enum_v<T>, bool HasQFlag = EnumHasQFlag<T>::Value>
680struct EnumHasQEnum { static constexpr bool Value = false; };
681template <typename T> struct EnumHasQEnum<T, true, false> : QtPrivate::IsQEnumHelper<T> {};
682}
683
684template <typename T>
685std::enable_if_t<QtPrivate::EnumHasQFlag<T>::Value, QDebug> // case 1
686operator<<(QDebug debug, T flag)
687{
688 return debug << QFlags(flag);
689}
690
691template<typename T>
692std::enable_if_t<QtPrivate::EnumHasQEnum<T>::Value, QDebug> // case 2
693operator<<(QDebug dbg, T value)
694{
695 const QMetaObject *obj = qt_getEnumMetaObject(value);
696 const char *name = qt_getEnumName(value);
697 return qt_QMetaEnum_debugOperator(dbg, static_cast<typename std::underlying_type<T>::type>(value), obj, name);
698}
699#endif // !QT_NO_QOBJECT && !Q_QDOC
700
701inline QDebug operator<<(QDebug debug, QKeyCombination combination)
702{
703 QDebugStateSaver saver(debug);
704 debug.nospace() << "QKeyCombination("
705 << combination.keyboardModifiers()
706 << ", "
707 << combination.key()
708 << ")";
709 return debug;
710}
711
712#ifdef Q_OS_DARWIN
713
714// We provide QDebug stream operators for commonly used Core Foundation
715// and Core Graphics types, as well as NSObject. Additional CF/CG types
716// may be added by the user, using Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE.
717
718#define QT_FOR_EACH_CORE_FOUNDATION_TYPE(F)
719 F(CFArray)
720 F(CFURL)
721 F(CFData)
722 F(CFNumber)
723 F(CFDictionary)
724 F(CFLocale)
725 F(CFDate)
726 F(CFBoolean)
727 F(CFTimeZone)
728
729#define QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(F)
730 F(CFError)
731 F(CFBundle)
732
733#define QT_FOR_EACH_CORE_GRAPHICS_TYPE(F)
734 F(CGPath)
735
736#define QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(F)
737 F(CGColorSpace)
738 F(CGImage)
739 F(CGFont)
740 F(CGColor)
741
742#define QT_FORWARD_DECLARE_CF_TYPE(type) Q_FORWARD_DECLARE_CF_TYPE(type);
743#define QT_FORWARD_DECLARE_MUTABLE_CF_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CF_TYPE(type);
744#define QT_FORWARD_DECLARE_CG_TYPE(type) Q_FORWARD_DECLARE_CG_TYPE(type);
745#define QT_FORWARD_DECLARE_MUTABLE_CG_TYPE(type) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(type);
746
747QT_END_NAMESPACE
748Q_FORWARD_DECLARE_CF_TYPE(CFString);
749struct objc_object;
750Q_FORWARD_DECLARE_OBJC_CLASS(NSObject);
751QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_CF_TYPE)
752QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_MUTABLE_CF_TYPE)
753QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_CG_TYPE)
754QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_MUTABLE_CG_TYPE)
755QT_BEGIN_NAMESPACE
756
757#define QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType)
758 Q_CORE_EXPORT QDebug operator<<(QDebug, CFType##Ref);
759
760#define Q_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE(CFType)
761 QDebug operator<<(QDebug debug, CFType##Ref ref)
762 {
763 if (!ref)
764 return debug << QT_STRINGIFY(CFType) "Ref(0x0)";
765 if (CFStringRef description = CFCopyDescription(ref)) {
766 QDebugStateSaver saver(debug);
767 debug.noquote() << description;
768 CFRelease(description);
769 }
770 return debug;
771 }
772
773// Defined in qcore_mac_objc.mm
774#if defined(__OBJC__)
775Q_CORE_EXPORT QDebug operator<<(QDebug, id);
776#endif
777Q_CORE_EXPORT QDebug operator<<(QDebug, objc_object *);
778Q_CORE_EXPORT QDebug operator<<(QDebug, const NSObject *);
779Q_CORE_EXPORT QDebug operator<<(QDebug, CFStringRef);
780
781QT_FOR_EACH_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
782QT_FOR_EACH_MUTABLE_CORE_FOUNDATION_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
783QT_FOR_EACH_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
784QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_FORWARD_DECLARE_QDEBUG_OPERATOR_FOR_CF_TYPE)
785
786#undef QT_FORWARD_DECLARE_CF_TYPE
787#undef QT_FORWARD_DECLARE_MUTABLE_CF_TYPE
788#undef QT_FORWARD_DECLARE_CG_TYPE
789#undef QT_FORWARD_DECLARE_MUTABLE_CG_TYPE
790
791#endif // Q_OS_DARWIN
792
793QT_END_NAMESPACE
794
795#endif // QDEBUG_H
QByteArray & operator*() noexcept
Definition qbytearray.h:803
QByteArray::Base64DecodingStatus decodingStatus
Definition qbytearray.h:788
friend bool operator==(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are equal, otherwise returns false.
Definition qbytearray.h:807
void swap(QByteArray::FromBase64Result &other) noexcept
Definition qbytearray.h:790
operator bool() const noexcept
\variable QByteArray::FromBase64Result::decoded
Definition qbytearray.h:796
const QByteArray & operator*() const noexcept
Returns the decoded byte array.
Definition qbytearray.h:804
friend bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
Returns true if lhs and rhs are different, otherwise returns false.
Definition qbytearray.h:818
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:49
int initFrom(const QMessageLogContext &logContext)
void populateBacktrace(int frameCount)
QInternalMessageLogContext(const QMessageLogContext &logContext, const QLoggingCategory &categoryOverride)
Definition qlogging_p.h:65
std::optional< BacktraceStorage > backtrace
Definition qlogging_p.h:57
static constexpr int DefaultBacktraceDepth
Definition qlogging_p.h:47
Definition qlist.h:80
\inmodule QtCore
Definition qlogging.h:43
constexpr QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) noexcept
Definition qlogging.h:48
const char * category
Definition qlogging.h:55
constexpr QMessageLogContext() noexcept=default
const char * function
Definition qlogging.h:54
const char * file
Definition qlogging.h:53
\inmodule QtCore
Definition qlogging.h:73
QDebug debug(CategoryFunction catFunc) const
QDebug debug(const QLoggingCategory &cat) const
Logs a debug message into category cat using a QDebug stream.
Definition qlogging.cpp:450
void void void void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION void QT_MESSAGE_LOGGER_NORETURN Q_DECL_COLD_FUNCTION void QDebug debug() const
Logs a debug message using a QDebug stream.
Definition qlogging.cpp:436
QDebug info(const QLoggingCategory &cat) const
Logs an informational message into the category cat using a QDebug stream.
Definition qlogging.cpp:539
QDebug info() const
Logs an informational message using a QDebug stream.
Definition qlogging.cpp:525
QNoDebug noDebug(...) const noexcept
QDebug info(CategoryFunction catFunc) const
static Q_CONSTINIT thread_local bool msgHandlerGrabbed
static const char ifCriticalTokenC[]
static const char emptyTokenC[]
static Q_NEVER_INLINE void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg, va_list ap)
Definition qlogging.cpp:333
static void preformattedMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &formattedMessage)
static bool systemHasStderr()
Returns true if writing to stderr is supported.
Definition qlogging.cpp:187
static const char endifTokenC[]
static bool isDefaultCategory(const char *category)
Definition qlogging.cpp:879
static const char messageTokenC[]
static constexpr SystemMessageSink systemMessageSink
static void qt_maybe_message_fatal(QtMsgType, const QMessageLogContext &context, String &&message)
\inmodule QtCore \title Qt Logging Types
#define HANDLE_IF_TOKEN(LEVEL)
Q_DECLARE_TYPEINFO(QMessagePattern::BacktraceParams, Q_RELOCATABLE_TYPE)
static const char timeTokenC[]
static bool is_fatal_count_down(QAtomicInt &n)
Definition qlogging.cpp:150
static const char qthreadptrTokenC[]
static const char fileTokenC[]
static const char ifDebugTokenC[]
static const char ifFatalTokenC[]
static const char categoryTokenC[]
static const char lineTokenC[]
static const char typeTokenC[]
static const char ifCategoryTokenC[]
static int checked_var_value(const char *varname)
Definition qlogging.cpp:136
static const char pidTokenC[]
Q_TRACE_POINT(qtcore, qt_message_print, int type, const char *category, const char *function, const char *file, int line, const QString &message)
static const char threadidTokenC[]
static QString formatLogMessage(QtMsgType type, const QMessageLogContext &context, const QString &str)
static const char backtraceTokenC[]
static const char functionTokenC[]
#define IF_TOKEN(LEVEL)
static const char ifWarningTokenC[]
static const char appnameTokenC[]
static bool isFatal(QtMsgType msgType)
Definition qlogging.cpp:161
static const char ifInfoTokenC[]
static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message)
static bool stderrHasConsoleAttached()
Returns true if writing to stderr will end up in a console/terminal visible to the user.
Definition qlogging.cpp:212
Combined button and popup list for selecting options.
QDebug printAssociativeContainer(QDebug debug, const char *which, const AssociativeContainer &c)
Definition qdebug.h:386
bool shouldLogToStderr()
Returns true if logging stderr should be ensured.
Definition qlogging.cpp:265
QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
Definition qdebug.h:368
QByteArray operator""_ba(const char *str, size_t size) noexcept
Definition qbytearray.h:853
Definition qcompare.h:76
QByteArray operator+(const QByteArray &a1, const char *a2)
Definition qbytearray.h:709
QByteArray qUncompress(const QByteArray &data)
Definition qbytearray.h:778
QByteArray operator+(char a1, const QByteArray &a2)
Definition qbytearray.h:719
QByteArray operator+(QByteArray &&lhs, char rhs)
Definition qbytearray.h:715
QByteArray operator+(const QByteArray &a1, char a2)
Definition qbytearray.h:713
QByteArray operator+(const char *a1, const QByteArray &a2)
Definition qbytearray.h:717
QByteArray operator+(QByteArray &&lhs, const QByteArray &rhs)
Definition qbytearray.h:707
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:836
QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
Definition qbytearray.h:705
QByteArray qCompress(const QByteArray &data, int compressionLevel=-1)
Definition qbytearray.h:776
#define QT5_NULL_STRINGS
Definition qbytearray.h:25
qsizetype erase(QByteArray &ba, const T &t)
Definition qbytearray.h:830
QByteArray operator+(QByteArray &&lhs, const char *rhs)
Definition qbytearray.h:711
#define __has_include(x)
#define __has_cpp_attribute(x)
void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value)
Definition qdebug.h:615
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, quint64 value)
Definition qdebug.cpp:1415
Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, uint value)
Definition qdebug.cpp:1406
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2462
#define QT_MESSAGELOG_FUNC
Definition qlogging.h:161
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(int code, const char *msg,...)
Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(const char *msg,...)
#define QT_MESSAGELOG_FILE
Definition qlogging.h:159
#define QT_MESSAGE_LOGGER_NORETURN
Definition qlogging.h:69
#define QT_MESSAGELOG_LINE
Definition qlogging.h:160
Q_CORE_EXPORT void qSetMessagePattern(const QString &messagePattern)
#define QT_MESSAGELOGCONTEXT
Definition qlogging.h:154
QtMsgType
Definition qlogging.h:29
@ QtCriticalMsg
Definition qlogging.h:33
@ QtFatalMsg
Definition qlogging.h:34
@ QtDebugMsg
Definition qlogging.h:30
Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const QString &message)
void(* QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &)
Definition qlogging.h:196
QMutex QBasicMutex
Definition qmutex.h:346
void setPattern(const QString &pattern)
std::unique_ptr< std::unique_ptr< const char[]>[]> literals
std::chrono::steady_clock::time_point appStartTime
std::unique_ptr< const char *[]> tokens
QList< QString > timeArgs
static QBasicMutex mutex
void setDefaultPattern()
static constexpr bool Value
Definition qdebug.h:680
static constexpr bool Value
Definition qdebug.h:676