1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_CORE_ILOGGER_H
17 #define API_CORE_ILOGGER_H
18 
19 #include <cstdarg>
20 
21 #include <base/containers/string_view.h>
22 #include <base/containers/unique_ptr.h>
23 #include <base/namespace.h>
24 #include <base/util/uid.h>
25 #include <core/namespace.h>
26 #include <core/plugin/intf_interface.h>
27 
28 // Enabling warnings checks for format string parameters.
29 #if defined(__clang__)
30 #define FORMAT_FUNC(formatPos, argsPos) __attribute__((__format__(__printf__, formatPos, argsPos)))
31 #define FORMAT_ATTRIBUTE
32 #define CHECK_FORMAT_STRING(...) ((void)0)
33 #elif defined(__GNUC__)
34 #define FORMAT_FUNC(formatPos, argsPos) __attribute__((format(printf, formatPos, argsPos)))
35 #define FORMAT_ATTRIBUTE
36 #define CHECK_FORMAT_STRING(...) ((void)0)
37 #elif defined(_MSC_VER)
38 #define FORMAT_FUNC(...)
39 #define FORMAT_ATTRIBUTE _In_z_ _Printf_format_string_
40 // Hack to force format string verifying during compile time. see
41 // https://devblogs.microsoft.com/cppblog/format-specifiers-checking/ Note that the snprintf should never be evaluated
42 // during runtime due to the use of "false &&" (dead-code elimination works on debug too)
43 #define CHECK_FORMAT_STRING(...) (false && _snprintf_s(nullptr, 0, 0, ##__VA_ARGS__))
44 #else
45 #define FORMAT_FUNC
46 #define FORMAT_ATTRIBUTE
47 #define CHECK_FORMAT_STRING(...) ((void)0)
48 #endif
49 
CORE_BEGIN_NAMESPACE()50 CORE_BEGIN_NAMESPACE()
51 /** @ingroup group_log */
52 /** Logger */
53 class ILogger : public IInterface {
54 public:
55     static constexpr auto UID = BASE_NS::Uid { "d9c55b07-441c-4059-909b-88ebc3c07b1e" };
56 
57     /** Logging level */
58     enum class LogLevel {
59         /** Verbose */
60         LOG_VERBOSE = 0,
61         /** Debug */
62         LOG_DEBUG,
63         /** Info */
64         LOG_INFO,
65         /** Warning */
66         LOG_WARNING,
67         /** Error */
68         LOG_ERROR,
69         /** Fatal */
70         LOG_FATAL,
71 
72         // This level should only be used when setting the log level filter with SetLogLevel(),
73         // not as a log level for a message.
74         /** None */
75         LOG_NONE,
76     };
77 
78     /** Output */
79     class IOutput {
80     public:
81         /** Write */
82         virtual void Write(
83             LogLevel logLevel, BASE_NS::string_view filename, int lineNumber, BASE_NS::string_view message) = 0;
84 
85         struct Deleter {
86             constexpr Deleter() noexcept = default;
87             void operator()(IOutput* ptr) const
88             {
89                 ptr->Destroy();
90             }
91         };
92         using Ptr = BASE_NS::unique_ptr<IOutput, Deleter>;
93 
94     protected:
95         IOutput() = default;
96         virtual ~IOutput() = default;
97         virtual void Destroy() = 0;
98     };
99 
100     /** Write to log (Version of logger that takes va_list, please use macros instead) */
101     virtual void VLog(LogLevel logLevel, BASE_NS::string_view filename, int lineNumber, BASE_NS::string_view format,
102         std::va_list args) = 0;
103     /** Write to log once (Version of logger that takes va_list, please use macros instead) */
104     virtual void VLogOnce(BASE_NS::string_view id, LogLevel logLevel, BASE_NS::string_view filename, int lineNumber,
105         BASE_NS::string_view format, std::va_list args) = 0;
106     virtual bool VLogAssert(BASE_NS::string_view filename, int lineNumber, bool expression,
107         BASE_NS::string_view expressionString, BASE_NS::string_view format, std::va_list args) = 0;
108 
109     /** Write to log (Takes var args) */
110     virtual FORMAT_FUNC(5, 6) void Log(
111         LogLevel logLevel, BASE_NS::string_view filename, int lineNumber, FORMAT_ATTRIBUTE const char* format, ...) = 0;
112     /** Write to log (Version which is used with asserts) */
113     virtual FORMAT_FUNC(6, 7) bool LogAssert(BASE_NS::string_view filename, int lineNumber, bool expression,
114         BASE_NS::string_view expressionString, FORMAT_ATTRIBUTE const char* format, ...) = 0;
115 
116     /** Get log level */
117     virtual LogLevel GetLogLevel() const = 0;
118     /** Set log level */
119     virtual void SetLogLevel(LogLevel logLevel) = 0;
120 
121     /** Add output (for custom loggers) */
122     virtual void AddOutput(IOutput::Ptr output) = 0;
123 
124     /** resets all "logOnce" handles. allowing the messages to be logged again */
125     virtual void CheckOnceReset() = 0;
126 
127 protected:
128     ILogger() = default;
129     virtual ~ILogger() = default;
130 
131     ILogger(ILogger const&) = delete;
132     void operator=(ILogger const&) = delete;
133 };
134 
GetName(const ILogger *)135 inline constexpr BASE_NS::string_view GetName(const ILogger*)
136 {
137     return "ILogger";
138 }
139 
140 /** @} */
141 CORE_END_NAMESPACE()
142 #endif // API_CORE_ILOGGER_H
143