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 Q_DECL_UNUSED_MEMBER void *d = nullptr; // reserved for future use
42 const char *name = nullptr;
43
44 struct AtomicBools {
45 QBasicAtomicInteger<bool> enabledDebug;
46 QBasicAtomicInteger<bool> enabledWarning;
47 QBasicAtomicInteger<bool> enabledCritical;
48 QBasicAtomicInteger<bool> enabledInfo;
49 };
50 union {
51 AtomicBools bools;
52 QBasicAtomicInt enabled;
53 };
54 Q_DECL_UNUSED_MEMBER bool placeholder[4]; // reserved for future use
55};
56
57namespace { // allow different TUs to have different QT_NO_xxx_OUTPUT
58template <QtMsgType Which> struct QLoggingCategoryMacroHolder
59{
60 static const bool IsOutputEnabled;
61 const QLoggingCategory *category = nullptr;
62 bool control = false;
63 explicit QLoggingCategoryMacroHolder(const QLoggingCategory &cat)
64 {
65 if (IsOutputEnabled)
66 init(cat);
67 }
68 void init(const QLoggingCategory &cat) noexcept
69 {
70 category = &cat;
71 // same as:
72 // control = cat.isEnabled(Which);
73 // but without an out-of-line call
74 if constexpr (Which == QtDebugMsg) {
75 control = cat.isDebugEnabled();
76 } else if constexpr (Which == QtInfoMsg) {
77 control = cat.isInfoEnabled();
78 } else if constexpr (Which == QtWarningMsg) {
79 control = cat.isWarningEnabled();
80 } else if constexpr (Which == QtCriticalMsg) {
81 control = cat.isCriticalEnabled();
82 } else if constexpr (Which == QtFatalMsg) {
83 control = true;
84 } else {
85 static_assert(QtPrivate::value_dependent_false<Which>(), "Unknown Qt message type");
86 }
87 }
88 const char *name() const { return category->categoryName(); }
89 explicit operator bool() const { return Q_UNLIKELY(control); }
90};
91
92template <QtMsgType Which> const bool QLoggingCategoryMacroHolder<Which>::IsOutputEnabled = true;
93#if defined(QT_NO_DEBUG_OUTPUT)
94template <> const bool QLoggingCategoryMacroHolder<QtDebugMsg>::IsOutputEnabled = false;
95#endif
96#if defined(QT_NO_INFO_OUTPUT)
97template <> const bool QLoggingCategoryMacroHolder<QtInfoMsg>::IsOutputEnabled = false;
98#endif
99#if defined(QT_NO_WARNING_OUTPUT)
100template <> const bool QLoggingCategoryMacroHolder<QtWarningMsg>::IsOutputEnabled = false;
101#endif
102} // unnamed namespace
103
104#define Q_DECLARE_LOGGING_CATEGORY(name) \
105 const QLoggingCategory &name();
106
107#define Q_DECLARE_EXPORTED_LOGGING_CATEGORY(name, export_macro) \
108 export_macro Q_DECLARE_LOGGING_CATEGORY(name)
109
110#define Q_LOGGING_CATEGORY(name, ...) \
111 const QLoggingCategory &name() \
112 { \
113 static const QLoggingCategory category(__VA_ARGS__); \
114 return category; \
115 }
116
117#define QT_MESSAGE_LOGGER_COMMON(category, level) \
118 for (QLoggingCategoryMacroHolder<level> qt_category((category)()); qt_category; qt_category.control = false) \
119 QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, qt_category.name())
120
121#define qCDebug(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtDebugMsg).debug(__VA_ARGS__)
122#define qCInfo(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtInfoMsg).info(__VA_ARGS__)
123#define qCWarning(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtWarningMsg).warning(__VA_ARGS__)
124#define qCCritical(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtCriticalMsg).critical(__VA_ARGS__)
125#define qCFatal(category, ...) QT_MESSAGE_LOGGER_COMMON(category, QtFatalMsg).fatal(__VA_ARGS__)
126
127QT_END_NAMESPACE
128
129#endif // QLOGGINGCATEGORY_H
130

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