/src/spdlog/include/spdlog/common.h
Line | Count | Source |
1 | | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. |
2 | | // Distributed under the MIT License (http://opensource.org/licenses/MIT) |
3 | | |
4 | | #pragma once |
5 | | |
6 | | #include <spdlog/details/null_mutex.h> |
7 | | #include <spdlog/tweakme.h> |
8 | | |
9 | | #include <atomic> |
10 | | #include <chrono> |
11 | | #include <cstdio> |
12 | | #include <exception> |
13 | | #include <functional> |
14 | | #include <initializer_list> |
15 | | #include <memory> |
16 | | #include <string> |
17 | | #include <type_traits> |
18 | | |
19 | | #ifdef SPDLOG_USE_STD_FORMAT |
20 | | #include <version> |
21 | | #if __cpp_lib_format >= 202207L |
22 | | #include <format> |
23 | | #else |
24 | | #include <string_view> |
25 | | #endif |
26 | | #endif |
27 | | |
28 | | #ifdef SPDLOG_COMPILED_LIB |
29 | | #undef SPDLOG_HEADER_ONLY |
30 | | #if defined(SPDLOG_SHARED_LIB) |
31 | | #if defined(_WIN32) |
32 | | #ifdef spdlog_EXPORTS |
33 | | #define SPDLOG_API __declspec(dllexport) |
34 | | #else // !spdlog_EXPORTS |
35 | | #define SPDLOG_API __declspec(dllimport) |
36 | | #endif |
37 | | #else // !defined(_WIN32) |
38 | | #define SPDLOG_API __attribute__((visibility("default"))) |
39 | | #endif |
40 | | #else // !defined(SPDLOG_SHARED_LIB) |
41 | | #define SPDLOG_API |
42 | | #endif |
43 | | #define SPDLOG_INLINE |
44 | | #else // !defined(SPDLOG_COMPILED_LIB) |
45 | | #define SPDLOG_API |
46 | | #define SPDLOG_HEADER_ONLY |
47 | | #define SPDLOG_INLINE inline |
48 | | #endif // #ifdef SPDLOG_COMPILED_LIB |
49 | | |
50 | | #include <spdlog/fmt/fmt.h> |
51 | | |
52 | | #if !defined(SPDLOG_USE_STD_FORMAT) && \ |
53 | | FMT_VERSION >= 80000 // backward compatibility with fmt versions older than 8 |
54 | | #define SPDLOG_FMT_RUNTIME(format_string) fmt::runtime(format_string) |
55 | 11.5k | #define SPDLOG_FMT_STRING(format_string) FMT_STRING(format_string) |
56 | | #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) |
57 | | #include <spdlog/fmt/xchar.h> |
58 | | #endif |
59 | | #else |
60 | | #define SPDLOG_FMT_RUNTIME(format_string) format_string |
61 | | #define SPDLOG_FMT_STRING(format_string) format_string |
62 | | #endif |
63 | | |
64 | | // visual studio up to 2013 does not support noexcept nor constexpr |
65 | | #if defined(_MSC_VER) && (_MSC_VER < 1900) |
66 | | #define SPDLOG_NOEXCEPT _NOEXCEPT |
67 | | #define SPDLOG_CONSTEXPR |
68 | | #else |
69 | | #define SPDLOG_NOEXCEPT noexcept |
70 | | #define SPDLOG_CONSTEXPR constexpr |
71 | | #endif |
72 | | |
73 | | // If building with std::format, can just use constexpr, otherwise if building with fmt |
74 | | // SPDLOG_CONSTEXPR_FUNC needs to be set the same as FMT_CONSTEXPR to avoid situations where |
75 | | // a constexpr function in spdlog could end up calling a non-constexpr function in fmt |
76 | | // depending on the compiler |
77 | | // If fmt determines it can't use constexpr, we should inline the function instead |
78 | | #ifdef SPDLOG_USE_STD_FORMAT |
79 | | #define SPDLOG_CONSTEXPR_FUNC constexpr |
80 | | #else // Being built with fmt |
81 | | #if FMT_USE_CONSTEXPR |
82 | | #define SPDLOG_CONSTEXPR_FUNC FMT_CONSTEXPR |
83 | | #else |
84 | | #define SPDLOG_CONSTEXPR_FUNC inline |
85 | | #endif |
86 | | #endif |
87 | | |
88 | | #if defined(__GNUC__) || defined(__clang__) |
89 | | #define SPDLOG_DEPRECATED __attribute__((deprecated)) |
90 | | #elif defined(_MSC_VER) |
91 | | #define SPDLOG_DEPRECATED __declspec(deprecated) |
92 | | #else |
93 | | #define SPDLOG_DEPRECATED |
94 | | #endif |
95 | | |
96 | | // disable thread local on msvc 2013 |
97 | | #ifndef SPDLOG_NO_TLS |
98 | | #if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt) |
99 | | #define SPDLOG_NO_TLS 1 |
100 | | #endif |
101 | | #endif |
102 | | |
103 | | #ifndef SPDLOG_FUNCTION |
104 | 21.7k | #define SPDLOG_FUNCTION static_cast<const char *>(__FUNCTION__) |
105 | | #endif |
106 | | |
107 | | #ifdef SPDLOG_NO_EXCEPTIONS |
108 | | #define SPDLOG_TRY |
109 | | #define SPDLOG_THROW(ex) \ |
110 | | do { \ |
111 | | printf("spdlog fatal error: %s\n", ex.what()); \ |
112 | | std::abort(); \ |
113 | | } while (0) |
114 | | #define SPDLOG_CATCH_STD |
115 | | #else |
116 | 17.5M | #define SPDLOG_TRY try |
117 | 0 | #define SPDLOG_THROW(ex) throw(ex) |
118 | | #define SPDLOG_CATCH_STD \ |
119 | | catch (const std::exception &) { \ |
120 | | } |
121 | | #endif |
122 | | |
123 | | namespace spdlog { |
124 | | |
125 | | class formatter; |
126 | | |
127 | | namespace sinks { |
128 | | class sink; |
129 | | } |
130 | | |
131 | | #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) |
132 | | using filename_t = std::wstring; |
133 | | // allow macro expansion to occur in SPDLOG_FILENAME_T |
134 | | #define SPDLOG_FILENAME_T_INNER(s) L##s |
135 | | #define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s) |
136 | | #else |
137 | | using filename_t = std::string; |
138 | 10 | #define SPDLOG_FILENAME_T(s) s |
139 | | #endif |
140 | | |
141 | | using log_clock = std::chrono::system_clock; |
142 | | using sink_ptr = std::shared_ptr<sinks::sink>; |
143 | | using sinks_init_list = std::initializer_list<sink_ptr>; |
144 | | using err_handler = std::function<void(const std::string &err_msg)>; |
145 | | #ifdef SPDLOG_USE_STD_FORMAT |
146 | | namespace fmt_lib = std; |
147 | | |
148 | | using string_view_t = std::string_view; |
149 | | using memory_buf_t = std::string; |
150 | | |
151 | | template <typename... Args> |
152 | | #if __cpp_lib_format >= 202207L |
153 | | using format_string_t = std::format_string<Args...>; |
154 | | #else |
155 | | using format_string_t = std::string_view; |
156 | | #endif |
157 | | |
158 | | template <class T, class Char = char> |
159 | | struct is_convertible_to_basic_format_string |
160 | | : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::value> {}; |
161 | | |
162 | | #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) |
163 | | using wstring_view_t = std::wstring_view; |
164 | | using wmemory_buf_t = std::wstring; |
165 | | |
166 | | template <typename... Args> |
167 | | #if __cpp_lib_format >= 202207L |
168 | | using wformat_string_t = std::wformat_string<Args...>; |
169 | | #else |
170 | | using wformat_string_t = std::wstring_view; |
171 | | #endif |
172 | | #endif |
173 | | #define SPDLOG_BUF_TO_STRING(x) x |
174 | | #else // use fmt lib instead of std::format |
175 | | namespace fmt_lib = fmt; |
176 | | |
177 | | using string_view_t = fmt::basic_string_view<char>; |
178 | | using memory_buf_t = fmt::basic_memory_buffer<char, 250>; |
179 | | |
180 | | template <typename... Args> |
181 | | using format_string_t = fmt::format_string<Args...>; |
182 | | |
183 | | template <class T> |
184 | | using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; |
185 | | |
186 | | template <typename Char> |
187 | | #if FMT_VERSION >= 90101 |
188 | | using fmt_runtime_string = fmt::runtime_format_string<Char>; |
189 | | #else |
190 | | using fmt_runtime_string = fmt::basic_runtime<Char>; |
191 | | #endif |
192 | | |
193 | | // clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the |
194 | | // condition from basic_format_string here, in addition, fmt::basic_runtime<Char> is only |
195 | | // convertible to basic_format_string<Char> but not basic_string_view<Char> |
196 | | template <class T, class Char = char> |
197 | | struct is_convertible_to_basic_format_string |
198 | | : std::integral_constant<bool, |
199 | | std::is_convertible<T, fmt::basic_string_view<Char>>::value || |
200 | | std::is_same<remove_cvref_t<T>, fmt_runtime_string<Char>>::value> { |
201 | | }; |
202 | | |
203 | | #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) |
204 | | using wstring_view_t = fmt::basic_string_view<wchar_t>; |
205 | | using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>; |
206 | | |
207 | | template <typename... Args> |
208 | | using wformat_string_t = fmt::wformat_string<Args...>; |
209 | | #endif |
210 | | #define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x) |
211 | | #endif |
212 | | |
213 | | #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT |
214 | | #ifndef _WIN32 |
215 | | #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows |
216 | | #endif // _WIN32 |
217 | | #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT |
218 | | |
219 | | template <class T> |
220 | | struct is_convertible_to_any_format_string |
221 | | : std::integral_constant<bool, |
222 | | is_convertible_to_basic_format_string<T, char>::value || |
223 | | is_convertible_to_basic_format_string<T, wchar_t>::value> {}; |
224 | | |
225 | | #if defined(SPDLOG_NO_ATOMIC_LEVELS) |
226 | | using level_t = details::null_atomic_int; |
227 | | #else |
228 | | using level_t = std::atomic<int>; |
229 | | #endif |
230 | | |
231 | | #define SPDLOG_LEVEL_TRACE 0 |
232 | | #define SPDLOG_LEVEL_DEBUG 1 |
233 | | #define SPDLOG_LEVEL_INFO 2 |
234 | | #define SPDLOG_LEVEL_WARN 3 |
235 | | #define SPDLOG_LEVEL_ERROR 4 |
236 | | #define SPDLOG_LEVEL_CRITICAL 5 |
237 | | #define SPDLOG_LEVEL_OFF 6 |
238 | | |
239 | | #if !defined(SPDLOG_ACTIVE_LEVEL) |
240 | | #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO |
241 | | #endif |
242 | | |
243 | | // Log level enum |
244 | | namespace level { |
245 | | enum level_enum : int { |
246 | | trace = SPDLOG_LEVEL_TRACE, |
247 | | debug = SPDLOG_LEVEL_DEBUG, |
248 | | info = SPDLOG_LEVEL_INFO, |
249 | | warn = SPDLOG_LEVEL_WARN, |
250 | | err = SPDLOG_LEVEL_ERROR, |
251 | | critical = SPDLOG_LEVEL_CRITICAL, |
252 | | off = SPDLOG_LEVEL_OFF, |
253 | | n_levels |
254 | | }; |
255 | | |
256 | | #define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t("trace", 5) |
257 | | #define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t("debug", 5) |
258 | | #define SPDLOG_LEVEL_NAME_INFO spdlog::string_view_t("info", 4) |
259 | | #define SPDLOG_LEVEL_NAME_WARNING spdlog::string_view_t("warning", 7) |
260 | | #define SPDLOG_LEVEL_NAME_ERROR spdlog::string_view_t("error", 5) |
261 | | #define SPDLOG_LEVEL_NAME_CRITICAL spdlog::string_view_t("critical", 8) |
262 | | #define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t("off", 3) |
263 | | |
264 | | #if !defined(SPDLOG_LEVEL_NAMES) |
265 | | #define SPDLOG_LEVEL_NAMES \ |
266 | | { \ |
267 | | SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \ |
268 | | SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \ |
269 | | SPDLOG_LEVEL_NAME_OFF \ |
270 | | } |
271 | | #endif |
272 | | |
273 | | #if !defined(SPDLOG_SHORT_LEVEL_NAMES) |
274 | | |
275 | | #define SPDLOG_SHORT_LEVEL_NAMES \ |
276 | | { "T", "D", "I", "W", "E", "C", "O" } |
277 | | #endif |
278 | | |
279 | | SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; |
280 | | SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT; |
281 | | SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT; |
282 | | |
283 | | } // namespace level |
284 | | |
285 | | // |
286 | | // Color mode used by sinks with color support. |
287 | | // |
288 | | enum class color_mode { always, automatic, never }; |
289 | | |
290 | | // |
291 | | // Pattern time - specific time getting to use for pattern_formatter. |
292 | | // local time by default |
293 | | // |
294 | | enum class pattern_time_type { |
295 | | local, // log localtime |
296 | | utc // log utc |
297 | | }; |
298 | | |
299 | | // |
300 | | // Log exception |
301 | | // |
302 | | class SPDLOG_API spdlog_ex : public std::exception { |
303 | | public: |
304 | | explicit spdlog_ex(std::string msg); |
305 | | spdlog_ex(const std::string &msg, int last_errno); |
306 | | const char *what() const SPDLOG_NOEXCEPT override; |
307 | | |
308 | | private: |
309 | | std::string msg_; |
310 | | }; |
311 | | |
312 | | [[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno); |
313 | | [[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg); |
314 | | |
315 | | struct source_loc { |
316 | 52.4M | SPDLOG_CONSTEXPR source_loc() = default; |
317 | | SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in) |
318 | 15.4k | : filename{filename_in}, |
319 | 15.4k | line{line_in}, |
320 | 15.4k | funcname{funcname_in} {} |
321 | | |
322 | 17.6M | SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line <= 0; } |
323 | | const char *filename{nullptr}; |
324 | | int line{0}; |
325 | | const char *funcname{nullptr}; |
326 | | }; |
327 | | |
328 | | struct file_event_handlers { |
329 | | file_event_handlers() |
330 | 5 | : before_open(nullptr), |
331 | 5 | after_open(nullptr), |
332 | 5 | before_close(nullptr), |
333 | 5 | after_close(nullptr) {} |
334 | | |
335 | | std::function<void(const filename_t &filename)> before_open; |
336 | | std::function<void(const filename_t &filename, std::FILE *file_stream)> after_open; |
337 | | std::function<void(const filename_t &filename, std::FILE *file_stream)> before_close; |
338 | | std::function<void(const filename_t &filename)> after_close; |
339 | | }; |
340 | | |
341 | | namespace details { |
342 | | |
343 | | // to_string_view |
344 | | |
345 | | SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf) |
346 | 0 | SPDLOG_NOEXCEPT { |
347 | 0 | return spdlog::string_view_t{buf.data(), buf.size()}; |
348 | 0 | } |
349 | | |
350 | | SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str) |
351 | 38.7k | SPDLOG_NOEXCEPT { |
352 | 38.7k | return str; |
353 | 38.7k | } |
354 | | |
355 | | #if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) |
356 | | SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf) |
357 | | SPDLOG_NOEXCEPT { |
358 | | return spdlog::wstring_view_t{buf.data(), buf.size()}; |
359 | | } |
360 | | |
361 | | SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str) |
362 | | SPDLOG_NOEXCEPT { |
363 | | return str; |
364 | | } |
365 | | #endif |
366 | | |
367 | | #if defined(SPDLOG_USE_STD_FORMAT) && __cpp_lib_format >= 202207L |
368 | | template <typename T, typename... Args> |
369 | | SPDLOG_CONSTEXPR_FUNC std::basic_string_view<T> to_string_view( |
370 | | std::basic_format_string<T, Args...> fmt) SPDLOG_NOEXCEPT { |
371 | | return fmt.get(); |
372 | | } |
373 | | #endif |
374 | | |
375 | | // make_unique support for pre c++14 |
376 | | #if __cplusplus >= 201402L // C++14 and beyond |
377 | | using std::enable_if_t; |
378 | | using std::make_unique; |
379 | | #else |
380 | | template <bool B, class T = void> |
381 | | using enable_if_t = typename std::enable_if<B, T>::type; |
382 | | |
383 | | template <typename T, typename... Args> |
384 | | std::unique_ptr<T> make_unique(Args &&...args) { |
385 | | static_assert(!std::is_array<T>::value, "arrays not supported"); |
386 | | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); |
387 | | } |
388 | | #endif |
389 | | |
390 | | // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) |
391 | | template <typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0> |
392 | | constexpr T conditional_static_cast(U value) { |
393 | | return static_cast<T>(value); |
394 | | } |
395 | | |
396 | | template <typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> |
397 | 9.68k | constexpr T conditional_static_cast(U value) { |
398 | 9.68k | return value; |
399 | 9.68k | } |
400 | | |
401 | | } // namespace details |
402 | | } // namespace spdlog |
403 | | |
404 | | #ifdef SPDLOG_HEADER_ONLY |
405 | | #include "common-inl.h" |
406 | | #endif |