1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QLOGGINGCATEGORY_H
5#define QLOGGINGCATEGORY_H
6
7#include <QtCore/qglobal.h>
8#include <QtCore/qdebug.h>
9
10QT_BEGIN_NAMESPACE
11
12class Q_CORE_EXPORT QLoggingCategory
13{
14 Q_DISABLE_COPY(QLoggingCategory)
15public:
16 explicit QLoggingCategory(const char *category, QtMsgType severityLevel = QtDebugMsg);
17 ~QLoggingCategory();
18
19 bool isEnabled(QtMsgType type) const;
20 void setEnabled(QtMsgType type, bool enable);
21
22 bool isDebugEnabled() const { return bools.enabledDebug.loadRelaxed(); }
23 bool isInfoEnabled() const { return bools.enabledInfo.loadRelaxed(); }
24 bool isWarningEnabled() const { return bools.enabledWarning.loadRelaxed(); }
25 bool isCriticalEnabled() const { return bools.enabledCritical.loadRelaxed(); }
26
27 const char *categoryName() const { return name; }
28
29 // allows usage of both factory method and variable in qCX macros
30 QLoggingCategory &operator()() { return *this; }
31 const QLoggingCategory &operator()() const { return *this; }
32
33 static QLoggingCategory *defaultCategory();
34
35 typedef void (*CategoryFilter)(QLoggingCategory*);
36 static CategoryFilter installFilter(CategoryFilter);
37
38 static void setFilterRules(const QString &rules);
39
40private:
41 void init(const char *category, QtMsgType severityLevel);
42
43 Q_DECL_UNUSED_MEMBER void *d; // reserved for future use
44 const char *name;
45
46 struct AtomicBools {
47 QBasicAtomicInteger<bool> enabledDebug;
48 QBasicAtomicInteger<bool> enabledWarning;
49 QBasicAtomicInteger<bool> enabledCritical;
50 QBasicAtomicInteger<bool> enabledInfo;
51 };
52 union {
53 AtomicBools bools;
54 QBasicAtomicInt enabled;
55 };
56 Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use
57};
58
59namespace { // allow different TUs to have different QT_NO_xxx_OUTPUT
60template <QtMsgType Which> struct QLoggingCategoryMacroHolder
61{
62 static const bool IsOutputEnabled;
63 const QLoggingCategory *category = nullptr;
64 bool control = false;
65 explicit QLoggingCategoryMacroHolder(const QLoggingCategory &cat)
66 {
67 if (IsOutputEnabled)
68 init(cat);
69 }
70 void init(const QLoggingCategory &cat) noexcept
71 {
72 category = &cat;
73 // same as:
74 // control = cat.isEnabled(Which);
75 // but without an out-of-line call
76 if constexpr (Which == QtDebugMsg) {
77 control = cat.isDebugEnabled();
78 } else if constexpr (Which == QtInfoMsg) {
79 control = cat.isInfoEnabled();
80 } else if constexpr (Which == QtWarningMsg) {
81 control = cat.isWarningEnabled();
82 } else if constexpr (Which == QtCriticalMsg) {
83 control = cat.isCriticalEnabled();
84 } else if constexpr (Which == QtFatalMsg) {
85 control = true;
86 } else {
87 static_assert(QtPrivate::value_dependent_false<Which>(), "Unknown Qt message type");
88 }
89 }
90 const char *name() const { return category->categoryName(); }
91 explicit operator bool() const { return Q_UNLIKELY(control); }
92};
93
94template <QtMsgType Which> const bool QLoggingCategoryMacroHolder<Which>::IsOutputEnabled = true;
95#if defined(QT_NO_DEBUG_OUTPUT)
96template <> const bool QLoggingCategoryMacroHolder<QtDebugMsg>::IsOutputEnabled = false;
97#endif
98#if defined(QT_NO_INFO_OUTPUT)
99template <> const bool QLoggingCategoryMacroHolder<QtInfoMsg>::IsOutputEnabled = false;
100#endif
101#if defined(QT_NO_WARNING_OUTPUT)
102template <> const bool QLoggingCategoryMacroHolder<QtWarningMsg>::IsOutputEnabled = false;
103#endif
104} // unnamed namespace
105
106#define Q_DECLARE_LOGGING_CATEGORY(name) \
107 const QLoggingCategory &name();
108
109#define Q_DECLARE_EXPORTED_LOGGING_CATEGORY(name, export_macro) \
110 export_macro Q_DECLARE_LOGGING_CATEGORY(name)
111
112#define Q_LOGGING_CATEGORY(name, ...) \
113 const QLoggingCategory &name() \
114 { \
115 static const QLoggingCategory category(__VA_ARGS__); \
116 return category; \
117 }
118
119#define QT_MESSAGE_LOGGER_COMMON(category, level) \
120 for (QLoggingCategoryMacroHolder<level> qt_category(category()); qt_category; qt_category.control = false) \
121 QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, qt_category.name())
122
123#define qCDebug(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtDebugMsg).debug(__VA_ARGS__)
124#define qCInfo(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtInfoMsg).info(__VA_ARGS__)
125#define qCWarning(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtWarningMsg).warning(__VA_ARGS__)
126#define qCCritical(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtCriticalMsg).critical(__VA_ARGS__)
127#define qCFatal(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtFatalMsg).fatal(__VA_ARGS__)
128
129QT_END_NAMESPACE
130
131#endif // QLOGGINGCATEGORY_H
132

source code of qtbase/src/corelib/io/qloggingcategory.h