-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathLogger.h
More file actions
223 lines (184 loc) · 7.26 KB
/
Copy pathLogger.h
File metadata and controls
223 lines (184 loc) · 7.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
* reference:
* https://github.com/Martinii89/OrganizeMyGarageOpenSource/blob/master/OrganizeMyGarageV2/logging.h
*
* TODO:
* - get a handle on enums with states / options
* - clean up the namespace? make it more intuitive to use?
*
*
* I seen't a log.INFO() notation...
* instead of LOGGER(type, msg);
*
* unfortunately this has a lot of unnecessary cost when you don't need certain debug
* levels :\ (although it is kind of nice to have when changing logging levels at runtime)
*/
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <format>
#include <source_location>
#include <string_view>
#include <codecvt>
#include <locale>
#include <string>
// #include "flagpp/flags.hpp"
#include "bakkesmod/wrappers/cvarmanagerwrapper.h"
// import scoped_enum_bitmask;
namespace LOGGER {
#ifdef _WIN32
// ERROR macro is defined in Windows header
// To avoid conflict between these macro and declaration of ERROR / DEBUG in SEVERITY enum
// We save macro and undef it
#pragma push_macro("ERROR")
#pragma push_macro("DEBUG")
#undef ERROR
#undef DEBUG
#endif
namespace details {
struct FormatString {
std::string_view str;
std::source_location loc {};
FormatString(const char * str, const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
FormatString(const std::string & str, const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
FormatString(const std::string && str, const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
[[nodiscard]] std::string GetLocation() const {
return std::format("[{} ({}:{})]", loc.function_name(), loc.file_name(), loc.line());
}
};
struct FormatWString {
std::wstring_view str;
std::source_location loc {};
FormatWString(const wchar_t * str, const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
FormatWString(
const std::wstring & str,
const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
FormatWString(
const std::wstring && str,
const std::source_location & loc = std::source_location::current()) :
str(str), loc(loc) {}
[[nodiscard]] std::wstring GetLocation() const {
auto basic_string = std::format("[{} ({}:{})]", loc.function_name(), loc.file_name(), loc.line());
return std::wstring(basic_string.begin(), basic_string.end());
}
};
} // namespace details
enum class LOGLEVEL { INFO, DEBUG, WARNING, ERROR, OFF };
enum class LOGOPTIONS {
NONE = 0,
PERSIST = 1 << 0, // write out to a file
CONSOLE = 1 << 1, // write out to the bakkesmod console
SOURCELOC = 1 << 2, // include the source location
};
} // namespace LOGGER
constexpr inline bool operator&(const LOGGER::LOGOPTIONS & lhs, const LOGGER::LOGOPTIONS & rhs) {
return false;
}
namespace LOGGER {
// NOLINTBEGIN
static LOGOPTIONS g_options = LOGOPTIONS::NONE; // default level of options...
static LOGLEVEL g_loglevel = LOGLEVEL::OFF; // default log level
// NOLINTEND
static std::shared_ptr<CVarManagerWrapper> g_cvarmanager;
__forceinline void set_cvarmanager(std::shared_ptr<CVarManagerWrapper> cmw) {
g_cvarmanager = cmw;
}
constexpr inline void set_loglevel(const LOGGER::LOGLEVEL & nl) {
g_loglevel = nl;
}
using details::FormatString;
using details::FormatWString;
//static ::std::queue<::std::pair<::std::wstring, int>> rolling_log;
//static ::std::map<::std::wstring, int> roll_log_db;
//// static int roll_log_sz;
//
//constexpr inline void roll_log(std::string & str) {
// ::std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
// ::std::wstring wide = converter.from_bytes(str);
// roll_log(wide);
//}
//
//constexpr inline void roll_log(std::wstring & str) {
// //
// if (rolling_log.empty()) {
// rolling_log.emplace(std::pair {str, 1});
// } else {
// if (roll_log_db[str] != 0) {
// // pre-existing string.
// }
// }
//}
template <typename... Args>
constexpr inline void LOG(const FormatString & format_str, Args &&... args) {
auto str = std::format(
"{}{}{}",
g_options & LOGOPTIONS::SOURCELOC ? format_str.GetLocation() : "",
g_options & LOGOPTIONS::SOURCELOC ? " " : "",
sizeof...(args) ? std::vformat(format_str.str, std::make_format_args(args...)).c_str() : format_str.str);
// roll_log(std::move(str));
g_cvarmanager->log(std::move(str));
}
template <typename... Args>
constexpr inline void LOG(const FormatWString & wformat_str, Args &&... args) {
auto str = std::format(
L"{}{}{}",
g_options & LOGOPTIONS::SOURCELOC ? wformat_str.GetLocation() : L"",
g_options & LOGOPTIONS::SOURCELOC ? L" " : L"",
sizeof...(args) ? std::vformat(wformat_str.str, std::make_wformat_args(args...)) : wformat_str.str);
// roll_log(std::move(str));
g_cvarmanager->log(std::move(str));
}
// USING LOGLEVEL
template <typename... Args>
constexpr inline void LOG(const LOGLEVEL & log_level, const FormatString & format_str, Args &&... args) {
if (log_level < g_loglevel) { return; }
LOG(format_str, args...);
}
template <typename... Args>
constexpr inline void LOG(const LOGLEVEL & log_level, const FormatWString & wformat_str, Args &&... args) {
if (log_level < g_loglevel) { return; }
LOG(wformat_str, args...);
}
template <typename... Args>
constexpr inline void log_info(const FormatString & format_str, Args &&... args) {
LOG(LOGLEVEL::INFO, format_str, args...);
}
template <typename... Args>
constexpr inline void log_info(const FormatWString & wformat_str, Args &&... args) {
LOG(LOGLEVEL::INFO, wformat_str, args...);
}
template <typename... Args>
constexpr inline void log_debug(const FormatString & format_str, Args &&... args) {
LOG(LOGLEVEL::DEBUG, format_str, args...);
}
template <typename... Args>
constexpr inline void log_debug(const FormatWString & wformat_str, Args &&... args) {
LOG(LOGLEVEL::DEBUG, wformat_str, args...);
}
template <typename... Args>
constexpr inline void log_warning(const FormatString & format_str, Args &&... args) {
LOG(LOGLEVEL::WARNING, format_str, args...);
}
template <typename... Args>
constexpr inline void log_warning(const FormatWString & wformat_str, Args &&... args) {
LOG(LOGLEVEL::WARNING, wformat_str, args...);
}
template <typename... Args>
constexpr inline void log_error(const FormatString & format_str, Args &&... args) {
LOG(LOGLEVEL::ERROR, format_str, args...);
}
template <typename... Args>
constexpr inline void log_error(const FormatWString & wformat_str, Args &&... args) {
LOG(LOGLEVEL::ERROR, wformat_str, args...);
}
}; // namespace LOGGER
#ifdef _WIN32
// We restore the ERROR Windows macro
#pragma pop_macro("ERROR")
#pragma pop_macro("DEBUG")
#endif
#endif