GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 84.2% 507 / 0 / 602
Functions: 87.4% 153 / 0 / 175
Branches: 40.0% 164 / 0 / 410

include/DetourModKit/logger.hpp
Line Branch Exec Source
1 #ifndef DETOURMODKIT_LOGGER_HPP
2 #define DETOURMODKIT_LOGGER_HPP
3
4 #include <string>
5 #include <string_view>
6 #include <mutex>
7 #include <memory>
8 #include <chrono>
9 #include <format>
10 #include <atomic>
11
12 #include "DetourModKit/win_file_stream.hpp"
13
14 namespace DetourModKit
15 {
16 /**
17 * @enum LogLevel
18 * @brief Defines the severity levels for log messages.
19 * @note This is an enum class (C++ Core Guidelines Enum.3) to prevent namespace pollution.
20 */
21 enum class LogLevel
22 {
23 Trace = 0,
24 Debug = 1,
25 Info = 2,
26 Warning = 3,
27 Error = 4
28 };
29
30 /**
31 * @brief Converts a LogLevel enum to its string representation.
32 * @param level The LogLevel enum value.
33 * @return std::string_view String representation of the log level.
34 */
35 5230 constexpr std::string_view log_level_to_string(LogLevel level) noexcept
36 {
37
5/6
✓ Branch 2 → 3 taken 108 times.
✓ Branch 2 → 4 taken 665 times.
✓ Branch 2 → 5 taken 3575 times.
✓ Branch 2 → 6 taken 732 times.
✓ Branch 2 → 7 taken 150 times.
✗ Branch 2 → 8 not taken.
5230 switch (level)
38 {
39 108 case LogLevel::Trace:
40 108 return "TRACE";
41 665 case LogLevel::Debug:
42 665 return "DEBUG";
43 3575 case LogLevel::Info:
44 3575 return "INFO";
45 732 case LogLevel::Warning:
46 732 return "WARNING";
47 150 case LogLevel::Error:
48 150 return "ERROR";
49 default:
50 return "UNKNOWN";
51 }
52 }
53
54 // Logger configuration defaults
55 inline constexpr const char *DEFAULT_LOG_PREFIX = "DetourModKit";
56 inline constexpr const char *DEFAULT_LOG_FILE_NAME = "DetourModKit_Log.txt";
57 inline constexpr const char *DEFAULT_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S";
58
59 // Forward declarations
60 struct AsyncLoggerConfig;
61 class AsyncLogger;
62
63 /**
64 * @class Logger
65 * @brief A singleton class for logging messages to a file.
66 * @details Provides thread-safe logging with configurable levels, timestamps,
67 * and log file location. Uses atomic LogLevel for thread-safe level changes.
68 */
69 class Logger
70 {
71 public:
72 /**
73 * @brief Retrieves the singleton instance of the Logger.
74 * @return Logger& Reference to the single Logger instance.
75 */
76 1774 static Logger &get_instance()
77 {
78
4/8
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 8 taken 1773 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 10 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
1774 static Logger instance;
79 1774 return instance;
80 }
81
82 /**
83 * @brief Configures global static settings for the logger before first instantiation.
84 * @details If the logger instance already exists, this will also reconfigure the instance
85 * by reopening the log file with the new settings.
86 * @param prefix Default log prefix string.
87 * @param file_name Default log file name.
88 * @param timestamp_fmt Default timestamp format string (strftime compatible).
89 */
90 static void configure(std::string_view prefix, std::string_view file_name,
91 3 std::string_view timestamp_fmt = DEFAULT_TIMESTAMP_FORMAT);
92
93 /**
94 * @brief Reconfigures an existing logger instance with new settings.
95 * @details Closes the current log file (if open) and reopens it with the new settings.
96 * Thread-safe. Logs a message about the reconfiguration.
97 * @param prefix New log prefix string.
98 * @param file_name New log file name.
99 * @param timestamp_fmt New timestamp format string (strftime compatible).
100 */
101 void reconfigure(std::string_view prefix, std::string_view file_name, std::string_view timestamp_fmt);
102
103 /**
104 * @brief Enables asynchronous logging mode.
105 * @details When enabled, log messages are queued and written by a dedicated
106 * writer thread, reducing latency on the calling thread.
107 * @param config Optional async logger configuration. Uses defaults if not provided.
108 */
109 void enable_async_mode(const AsyncLoggerConfig &config);
110 void enable_async_mode();
111
112 /**
113 * @brief Disables asynchronous logging mode and returns to synchronous mode.
114 * @details Flushes all pending async messages before switching.
115 */
116 void disable_async_mode();
117
118 /**
119 * @brief Checks if async logging mode is enabled.
120 * @return true if async mode is enabled, false otherwise.
121 */
122 bool is_async_mode_enabled() const;
123
124 /**
125 * @brief Flushes all pending log messages.
126 * @details In async mode, waits for all queued messages to be written.
127 * In sync mode, flushes the file stream.
128 */
129 void flush();
130
131 /**
132 * @brief Explicitly shuts down the Logger, closing files without logging.
133 * @details This method is safe to call during shutdown. It closes the log file
134 * and shuts down async logger without attempting to log, preventing
135 * use-after-free if called after other singletons are destroyed.
136 * After calling shutdown(), the destructor becomes a no-op.
137 */
138 void shutdown();
139
140 /**
141 * @brief Gets the current log level.
142 * @return LogLevel The current minimum log level.
143 */
144 31 LogLevel get_log_level() const
145 {
146 31 return current_log_level_.load(std::memory_order_acquire);
147 }
148
149 /**
150 * @brief Checks whether messages at the given level would be logged.
151 * @details Useful for gating expensive trace-only work (e.g. iterating
152 * a data structure solely to build a log message).
153 * @param level The LogLevel to test.
154 * @return true if a message at this level would pass the current filter.
155 */
156 40 bool is_enabled(LogLevel level) const noexcept
157 {
158 40 return level >= current_log_level_.load(std::memory_order_acquire);
159 }
160
161 /**
162 * @brief Sets the minimum log level for messages to be recorded.
163 * @param level The minimum LogLevel to record.
164 */
165 void set_log_level(LogLevel level);
166
167 /**
168 * @brief Logs a message if its level is at or above the current log level.
169 * @param level The LogLevel of the message.
170 * @param message The message string to log.
171 */
172 void log(LogLevel level, std::string_view message);
173
174 /**
175 * @brief Logs a formatted message with the specified log level.
176 * @details Uses std::format-style placeholders. Arguments are only formatted
177 * if the log level is enabled (lazy evaluation).
178 * @tparam Args Types of the format arguments.
179 * @param level The LogLevel of the message.
180 * @param fmt The format string with {} placeholders.
181 * @param args The arguments to substitute into the format string.
182 */
183 template <typename... Args>
184 4225 void log(LogLevel level, std::format_string<Args...> fmt, Args &&...args)
185 {
186
77/132
void DetourModKit::Logger::log<>(DetourModKit::LogLevel, std::basic_format_string<char>):
✓ Branch 3 → 4 taken 343 times.
✓ Branch 3 → 9 taken 482 times.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type>, std::basic_string_view<char, std::char_traits<char> > const&&):
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 11 taken 3 times.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<unsigned long long const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&&, unsigned long long const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 1 time.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const, unsigned long long const&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<unsigned long long const&>::type, std::type_identity<unsigned long long const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&&, unsigned long long const&, unsigned long long const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 15 taken 2 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 11 taken 138 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long long&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long long&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long&&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 15 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long&&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const*>::type>, char const*&&):
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 11 not taken.
void DetourModKit::Logger::log<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const*>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, char const*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<void*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<void*>::type>, void*&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 1 time.
void DetourModKit::Logger::log<char const (&) [6]>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const (&) [6]>::type>, char const (&) [6]):
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 11 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 11 taken 1 time.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<char const*>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*&&):
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 13 taken 1 time.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string_view<char, std::char_traits<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string_view<char, std::char_traits<char> > const&):
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, float const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<float const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, float const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 1 time.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<int const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 4 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long const&):
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 4 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long&&):
✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 11 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<char const*>::type>, std::basic_string_view<char, std::char_traits<char> > const&, char const*&&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<unsigned long long&>::type>, std::basic_string_view<char, std::char_traits<char> > const&, unsigned long long&):
✓ Branch 3 → 4 taken 11 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> > const&, std::basic_string_view<char, std::char_traits<char> >&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 3 times.
void DetourModKit::Logger::log<int const&, int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int const&>::type, std::type_identity<int&>::type>, int const&, int&):
✓ Branch 3 → 4 taken 800 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long const&>::type>, unsigned long long const&):
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 11 taken 15 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 3 → 4 taken 44 times.
✓ Branch 3 → 11 taken 223 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<char const*>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*&&):
✓ Branch 3 → 4 taken 15 times.
✓ Branch 3 → 13 taken 8 times.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<int>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int&&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<long long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, long long&&):
✓ Branch 3 → 4 taken 5 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<void*&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<void*&>::type>, void*&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 1 time.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type>, std::basic_string_view<char, std::char_traits<char> >&):
✓ Branch 3 → 4 taken 371 times.
✓ Branch 3 → 11 taken 15 times.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > const&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 15 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 17 taken 1 time.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<unsigned long long&>::type>, std::basic_string_view<char, std::char_traits<char> >&, unsigned long long&):
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&&):
✓ Branch 3 → 4 taken 567 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&):
✓ Branch 3 → 4 taken 11 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 3 → 4 taken 11 times.
✓ Branch 3 → 15 taken 3 times.
void DetourModKit::Logger::log<int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int&>::type>, int&):
✓ Branch 3 → 4 taken 252 times.
✓ Branch 3 → 11 taken 3 times.
void DetourModKit::Logger::log<int&, int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int&>::type, std::type_identity<int&>::type>, int&, int&):
✓ Branch 3 → 4 taken 25 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type>, unsigned long long&):
✓ Branch 3 → 4 taken 103 times.
✓ Branch 3 → 11 taken 158 times.
void DetourModKit::Logger::log<unsigned long long&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, unsigned long long&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 13 taken 9 times.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long const&>::type>, unsigned long long&, unsigned long long const&):
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long const&, unsigned int&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long const&>::type, std::type_identity<unsigned int&>::type, std::type_identity<unsigned long long const&>::type>, unsigned long long&, unsigned long long const&, unsigned int&, unsigned long long const&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 17 taken 191 times.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long&>::type>, unsigned long long&, unsigned long long&):
✓ Branch 3 → 4 taken 29 times.
✓ Branch 3 → 13 taken 3 times.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long long>::type>, std::basic_string_view<char, std::char_traits<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long&&):
✓ Branch 3 → 4 taken 40 times.
✗ Branch 3 → 15 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&&, std::basic_string_view<char, std::char_traits<char> >&&):
✓ Branch 3 → 4 taken 59 times.
✓ Branch 3 → 13 taken 16 times.
void DetourModKit::Logger::log<bool>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<bool>::type>, bool&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 3 times.
void DetourModKit::Logger::log<char>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char>::type>, char&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 1 time.
void DetourModKit::Logger::log<double>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<double>::type>, double&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 3 times.
void DetourModKit::Logger::log<float>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<float>::type>, float&&):
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 11 taken 2 times.
void DetourModKit::Logger::log<int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type>, int&&):
✓ Branch 3 → 4 taken 18 times.
✓ Branch 3 → 11 taken 17 times.
void DetourModKit::Logger::log<int, char const (&) [4], float>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<char const (&) [4]>::type, std::type_identity<float>::type>, int&&, char const (&) [4], float&&):
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 15 not taken.
void DetourModKit::Logger::log<int, char const (&) [4], float, bool, char>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<char const (&) [4]>::type, std::type_identity<float>::type, std::type_identity<bool>::type, std::type_identity<char>::type>, int&&, char const (&) [4], float&&, bool&&, char&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 19 taken 1 time.
void DetourModKit::Logger::log<int, double>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<double>::type>, int&&, double&&):
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&):
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 13 taken 1 time.
void DetourModKit::Logger::log<int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&):
✓ Branch 3 → 4 taken 5 times.
✓ Branch 3 → 15 taken 1 time.
void DetourModKit::Logger::log<int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 17 taken 1 time.
void DetourModKit::Logger::log<int, int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&, int&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 19 taken 1 time.
void DetourModKit::Logger::log<int, int, int, int, int, int, int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 29 taken 1 time.
void DetourModKit::Logger::log<long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<long>::type>, long&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 1 time.
void DetourModKit::Logger::log<unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type>, unsigned long long&&):
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 11 taken 3 times.
void DetourModKit::Logger::log<unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type>, unsigned long long&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 3 → 4 taken 117 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<unsigned long long, long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<long long>::type>, unsigned long long&&, long long&&):
✓ Branch 3 → 4 taken 28 times.
✗ Branch 3 → 13 not taken.
void DetourModKit::Logger::log<unsigned long long, unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<unsigned long long>::type>, unsigned long long&&, unsigned long long&&):
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 13 not taken.
4225 if (level >= current_log_level_.load(std::memory_order_acquire))
187 {
188
78/264
void DetourModKit::Logger::log<>(DetourModKit::LogLevel, std::basic_format_string<char>):
✓ Branch 4 → 5 taken 343 times.
✗ Branch 4 → 12 not taken.
✓ Branch 6 → 7 taken 343 times.
✗ Branch 6 → 10 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type>, std::basic_string_view<char, std::char_traits<char> > const&&):
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<unsigned long long const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&&, unsigned long long const&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const, unsigned long long const&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<unsigned long long const&>::type, std::type_identity<unsigned long long const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&&, unsigned long long const&, unsigned long long const&):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 18 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long long&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long long&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long&&):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 18 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, unsigned long&&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const*>::type>, char const*&&):
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const*>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, char const*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<void*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<void*>::type>, void*&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<char const (&) [6]>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char const (&) [6]>::type>, char const (&) [6]):
✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<char const*>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*&&):
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string_view<char, std::char_traits<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string_view<char, std::char_traits<char> > const&):
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, float const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<float const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, float const&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<int const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int const&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long const&):
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long&&):
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type>, std::basic_string_view<char, std::char_traits<char> > const&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<char const*>::type>, std::basic_string_view<char, std::char_traits<char> > const&, char const*&&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<unsigned long long&>::type>, std::basic_string_view<char, std::char_traits<char> > const&, unsigned long long&):
✓ Branch 8 → 9 taken 11 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> > const&, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> > const&, std::basic_string_view<char, std::char_traits<char> >&&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<int const&, int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int const&>::type, std::type_identity<int&>::type>, int const&, int&):
✓ Branch 8 → 9 taken 782 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 799 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long const&>::type>, unsigned long long const&):
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 6 → 7 taken 44 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 44 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<char const*>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char const*&&):
✓ Branch 8 → 9 taken 15 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 15 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<int>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int&&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type, std::type_identity<long long>::type>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, long long&&):
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<void*&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<void*&>::type>, void*&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type>, std::basic_string_view<char, std::char_traits<char> >&):
✓ Branch 6 → 7 taken 371 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 372 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > const>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > const&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 18 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 20 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 18 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<unsigned long long&>::type>, std::basic_string_view<char, std::char_traits<char> >&, unsigned long long&):
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&&):
✓ Branch 8 → 9 taken 567 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 567 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&):
✓ Branch 8 → 9 taken 11 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> >&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&, std::basic_string_view<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 10 → 11 taken 11 times.
✗ Branch 10 → 18 not taken.
✓ Branch 12 → 13 taken 11 times.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int&>::type>, int&):
✓ Branch 6 → 7 taken 252 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 252 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<int&, int&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int&>::type, std::type_identity<int&>::type>, int&, int&):
✓ Branch 8 → 9 taken 25 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 25 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type>, unsigned long long&):
✓ Branch 6 → 7 taken 103 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 103 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<unsigned long long&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type>, unsigned long long&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 16 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long const&>::type>, unsigned long long&, unsigned long long const&):
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long const&, unsigned int&, unsigned long long const&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long const&>::type, std::type_identity<unsigned int&>::type, std::type_identity<unsigned long long const&>::type>, unsigned long long&, unsigned long long const&, unsigned int&, unsigned long long const&):
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 20 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 18 not taken.
void DetourModKit::Logger::log<unsigned long long&, unsigned long long&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long&>::type, std::type_identity<unsigned long long&>::type>, unsigned long long&, unsigned long long&):
✓ Branch 8 → 9 taken 29 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 29 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type, std::type_identity<unsigned long long>::type>, std::basic_string_view<char, std::char_traits<char> >&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long long&&):
✓ Branch 10 → 11 taken 40 times.
✗ Branch 10 → 18 not taken.
✓ Branch 12 → 13 taken 40 times.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> > >(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type, std::type_identity<std::basic_string_view<char, std::char_traits<char> > >::type>, std::basic_string_view<char, std::char_traits<char> >&&, std::basic_string_view<char, std::char_traits<char> >&&):
✓ Branch 8 → 9 taken 59 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 59 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<bool>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<bool>::type>, bool&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<char>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<char>::type>, char&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<double>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<double>::type>, double&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<float>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<float>::type>, float&&):
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type>, int&&):
✓ Branch 6 → 7 taken 18 times.
✗ Branch 6 → 14 not taken.
✓ Branch 8 → 9 taken 18 times.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<int, char const (&) [4], float>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<char const (&) [4]>::type, std::type_identity<float>::type>, int&&, char const (&) [4], float&&):
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 18 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<int, char const (&) [4], float, bool, char>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<char const (&) [4]>::type, std::type_identity<float>::type, std::type_identity<bool>::type, std::type_identity<char>::type>, int&&, char const (&) [4], float&&, bool&&, char&&):
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 22 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 20 not taken.
void DetourModKit::Logger::log<int, double>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<double>::type>, int&&, double&&):
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&):
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&):
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 18 not taken.
✓ Branch 12 → 13 taken 5 times.
✗ Branch 12 → 16 not taken.
void DetourModKit::Logger::log<int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&):
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 20 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 18 not taken.
void DetourModKit::Logger::log<int, int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&, int&&):
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 22 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 20 not taken.
void DetourModKit::Logger::log<int, int, int, int, int, int, int, int, int, int>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type, std::type_identity<int>::type>, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&, int&&):
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 32 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 30 not taken.
void DetourModKit::Logger::log<long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<long>::type>, long&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type>, unsigned long long&&):
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 14 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 12 not taken.
void DetourModKit::Logger::log<unsigned long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type>, unsigned long long&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 8 → 9 taken 117 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 117 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long, long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<long long>::type>, unsigned long long&&, long long&&):
✓ Branch 8 → 9 taken 28 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 28 times.
✗ Branch 10 → 14 not taken.
void DetourModKit::Logger::log<unsigned long long, unsigned long long>(DetourModKit::LogLevel, std::basic_format_string<char, std::type_identity<unsigned long long>::type, std::type_identity<unsigned long long>::type>, unsigned long long&&, unsigned long long&&):
✓ Branch 8 → 9 taken 6 times.
✗ Branch 8 → 16 not taken.
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 14 not taken.
4713 log(level, std::format(fmt, std::forward<Args>(args)...));
189 }
190 4224 }
191
192 /// @name Convenience log methods
193 /// Shorthand for `log(LogLevel::X, fmt, args...)`. See log() for parameter docs.
194 /// @{
195 template <typename... Args>
196 72 void trace(std::format_string<Args...> fmt, Args &&...args)
197 {
198 155 log(LogLevel::Trace, fmt, std::forward<Args>(args)...);
199 72 }
200
201 template <typename... Args>
202 1887 void debug(std::format_string<Args...> fmt, Args &&...args)
203 {
204 2553 log(LogLevel::Debug, fmt, std::forward<Args>(args)...);
205 1888 }
206
207 template <typename... Args>
208 1345 void info(std::format_string<Args...> fmt, Args &&...args)
209 {
210 2359 log(LogLevel::Info, fmt, std::forward<Args>(args)...);
211 1344 }
212
213 template <typename... Args>
214 711 void warning(std::format_string<Args...> fmt, Args &&...args)
215 {
216 1287 log(LogLevel::Warning, fmt, std::forward<Args>(args)...);
217 711 }
218
219 template <typename... Args>
220 102 void error(std::format_string<Args...> fmt, Args &&...args)
221 {
222 132 log(LogLevel::Error, fmt, std::forward<Args>(args)...);
223 102 }
224 /// @}
225
226 /**
227 * @brief Converts a log level string to the LogLevel enum.
228 * @param level_str The string to convert (case-insensitive).
229 * @return The corresponding LogLevel enum. Defaults to LogLevel::Info if unrecognized.
230 */
231 static LogLevel string_to_log_level(std::string_view level_str);
232
233 /**
234 * @struct StaticConfig
235 * @brief Immutable configuration snapshot for thread-safe static configuration.
236 * @details Stored behind an atomic shared_ptr so readers never need a mutex.
237 */
238 struct StaticConfig
239 {
240 std::string log_prefix;
241 std::string log_file_name;
242 std::string timestamp_format;
243
244 234 StaticConfig(std::string prefix, std::string file, std::string ts_fmt)
245 468 : log_prefix(std::move(prefix)),
246 468 log_file_name(std::move(file)),
247 468 timestamp_format(std::move(ts_fmt)) {}
248 };
249
250 private:
251 Logger();
252 ~Logger() noexcept;
253
254 Logger(const Logger &) = delete;
255 Logger &operator=(const Logger &) = delete;
256 Logger(Logger &&) = delete;
257 Logger &operator=(Logger &&) = delete;
258
259 /**
260 * @brief Shared shutdown logic used by both ~Logger() and shutdown().
261 */
262 void shutdown_internal();
263
264 /**
265 * @brief Generates the current timestamp formatted according to timestamp_format_.
266 * @return std::string The formatted timestamp string.
267 */
268 std::string get_timestamp() const;
269
270 /**
271 * @brief Determines the full path for the log file.
272 * @return std::wstring The absolute path as a wide string for Unicode fidelity.
273 */
274 std::wstring generate_log_file_path() const;
275
276 static std::shared_ptr<const StaticConfig> get_static_config();
277 static void set_static_config(std::shared_ptr<const StaticConfig> config);
278
279 // Lock ordering (must be acquired in this order to prevent deadlock):
280 // 1. async_mutex_ — async logger lifecycle
281 // 2. *log_mutex_ptr_ — file stream I/O
282
283 std::string log_prefix_;
284 std::string log_file_name_;
285 std::string timestamp_format_;
286
287 std::shared_ptr<WinFileStream> log_file_stream_ptr_;
288 std::shared_ptr<std::mutex> log_mutex_ptr_;
289 std::atomic<LogLevel> current_log_level_{LogLevel::Info};
290 std::atomic<bool> shutdown_called_{false};
291
292 // Async logging support (forward declared).
293 // async_logger_ is atomic for lock-free reads on the log() hot path.
294 // async_mutex_ serializes lifecycle operations (enable/disable/shutdown).
295 //
296 // On MSVC x64, std::atomic<std::shared_ptr<T>> is lock-free (uses
297 // 128-bit compare-exchange). On MinGW/GCC, this may fall back to a
298 // global mutex, which is still correct but serializes the hot-path
299 // load. This is an accepted trade-off: the lock-free fast path
300 // benefits the primary target (MSVC), and the MinGW fallback is
301 // bounded to one mutex acquisition per log() call, which is
302 // comparable to the mutex already used by synchronous mode.
303 std::atomic<std::shared_ptr<AsyncLogger>> async_logger_{};
304 std::atomic<bool> async_mode_enabled_{false};
305 std::mutex async_mutex_;
306 };
307 } // namespace DetourModKit
308
309 #endif // DETOURMODKIT_LOGGER_HPP
310