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