NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
logger.h
Go to the documentation of this file.
1#pragma once
2
3#ifndef INCLUDED_LOGGER_H_
4#define INCLUDED_LOGGER_H_
5
6#ifndef INCLUDE_INSIDE_JIT
7#include <string>
8#include <stdexcept>
9#include <stdint.h>
10
11#include <algorithm>
12#include <vector>
13#include <unordered_set>
14#endif
15
16#define LOG_PRINTF_FUNCTION newlang::Logger::log_printf
17
18#ifndef NDEBUG
19#define LOG_MAKE(level, prefix, ...) LOG_PRINTF_FUNCTION(level, prefix, __FILE__, __LINE__, ##__VA_ARGS__)
20#else
21#define LOG_MAKE(level, prefix, ...) LOG_PRINTF_FUNCTION(level, prefix, NULL, 0, ##__VA_ARGS__)
22#endif
23
24#define LOG_THROW(EXCEPT, LEVEL, PREFIX, ...) throw EXCEPT(LOG_MAKE(LEVEL, PREFIX, ##__VA_ARGS__))
25#define LOG_PARSER(format, ...) LOG_THROW(newlang::ParserError, LOG_LEVEL_ERROR, "P:", format, ##__VA_ARGS__)
26#define LOG_RUNTIME(format, ...) LOG_THROW(std::runtime_error, LOG_LEVEL_ABORT, "R:", format, ##__VA_ARGS__)
27
28
29#ifdef BUILD_UNITTEST
30// Определения только для юнит-тестов
31#define LOG_TEST(...) LOG_MAKE(LOG_LEVEL_DEBUG, "T:", ##__VA_ARGS__)
32#define LOG_TEST_DUMP(...) LOG_MAKE(LOG_LEVEL_DUMP, "TD:", ##__VA_ARGS__)
33#define SCOPE(scope) public
34#else
35// Исключаются при обычной сборке
36#define LOG_TEST(...)
37#define LOG_TEST_DUMP(...)
38#define SCOPE(scope) scope
39#endif
40
41
42#ifndef TO_STR
43#define TO_STR2(ARG) #ARG
44#define TO_STR(ARG) TO_STR2(ARG)
45#endif
46
47// Use: #pragma message WARNING("My message")
48#ifdef _MSC_VER
49#define FILE_LINE_LINK __FILE__ "(" TO_STR(__LINE__) ") : "
50#define WARNING(exp) (FILE_LINE_LINK "WARNING: " exp)
51#else//__GNUC__ - may need other defines for different compilers
52#define WARNING(exp) ("WARNING: " exp)
53#endif
54
55#define STATIC_ASSERT(expr) static_assert((expr), #expr)
56
57#define ASSERT_EXCEPTION(text) do { LOG_MAKE(LOG_LEVEL_ABORT, "[ASSERT]:", "%s%s", text, newlang::Logger::GetStackTrace().c_str()); abort(); } while(0)
58
59#if defined(BUILD_DEBUG)
60#define ASSERT(condition) do {\
61 if(!(condition)) { \
62 ASSERT_EXCEPTION(TO_STR(condition)); \
63 }\
64 } while(0)
65#define VERIFY(exp) ASSERT(exp)
66#else
67#define ASSERT(condition)
68#define VERIFY(exp) (void)(exp)
69#endif
70
71
72
73std::string BinToHex(const uint8_t * buffer, const size_t size);
74std::string HexStrToBinStr(std::string & hex_str);
75
76uint8_t HexToByte(const char c);
77size_t HexToBin(const char * str, uint8_t * buffer, const size_t size);
78int HexToBinEq(const char * str, const uint8_t * buffer, const size_t size);
79size_t BinToHexBuffer(const uint8_t * buffer, const size_t size, char * str, const size_t str_size);
80
81
82
83#define LOG_LEVEL_DEFAULT 0
84
85#define LOG_LEVEL_DUMP 7
86#define LOG_LEVEL_DEBUG 6
87#define LOG_LEVEL_INFO 5
88#define LOG_LEVEL_WARNING 4
89#define LOG_LEVEL_ERROR 3
90#define LOG_LEVEL_FAULT 2
91#define LOG_LEVEL_ABORT 1
92
97#ifndef LOG_LEVEL_MAX
98#ifdef NDEBUG
99#define LOG_LEVEL_MAX LOG_LEVEL_INFO
100#else
101#define LOG_LEVEL_MAX LOG_LEVEL_DUMP
102#endif
103#endif
104
109#ifndef LOG_LEVEL_NORMAL
110#ifdef NDEBUG
111#define LOG_LEVEL_NORMAL LOG_LEVEL_ERROR
112#else
113#define LOG_LEVEL_NORMAL LOG_LEVEL_INFO
114#endif
115#endif
116
117#if LOG_LEVEL_MAX == LOG_LEVEL_DUMP
118#define LOG_DUMP(...) LOG_MAKE(LOG_LEVEL_DUMP, "DUMP:", ##__VA_ARGS__)
119#define LOG_DEBUG(...) LOG_MAKE(LOG_LEVEL_DEBUG, "D:", ##__VA_ARGS__)
120#define LOG_INFO(...) LOG_MAKE(LOG_LEVEL_INFO, NULL, ##__VA_ARGS__)
121#define LOG_WARNING(...) LOG_MAKE(LOG_LEVEL_WARNING, "W:", ##__VA_ARGS__)
122#define LOG_ERROR(...) LOG_MAKE(LOG_LEVEL_ERROR, "E:", ##__VA_ARGS__)
123#define LOG_FAULT(...) LOG_MAKE(LOG_LEVEL_FAULT, "F:", ##__VA_ARGS__)
124#define LOG_ABORT(...) LOG_MAKE(LOG_LEVEL_ABORT, "A:", ##__VA_ARGS__)
125
126#elif LOG_LEVEL_MAX == LOG_LEVEL_DEBUG
127#define LOG_DUMP(...)
128#define LOG_DEBUG(...) LOG_MAKE(LOG_LEVEL_DEBUG, "D:", ##__VA_ARGS__)
129#define LOG_INFO(...) LOG_MAKE(LOG_LEVEL_INFO, NULL, ##__VA_ARGS__)
130#define LOG_WARNING(...) LOG_MAKE(LOG_LEVEL_WARNING, "W:", ##__VA_ARGS__)
131#define LOG_ERROR(...) LOG_MAKE(LOG_LEVEL_ERROR, "E:", ##__VA_ARGS__)
132#define LOG_FAULT(...) LOG_MAKE(LOG_LEVEL_FAULT, "F:", ##__VA_ARGS__)
133#define LOG_ABORT(...) LOG_MAKE(LOG_LEVEL_ABORT, "A:", ##__VA_ARGS__)
134
135#elif LOG_LEVEL_MAX == LOG_LEVEL_INFO
136#define LOG_DUMP(...)
137#define LOG_DEBUG(...)
138#define LOG_INFO(...) LOG_MAKE(LOG_LEVEL_INFO, NULL, ##__VA_ARGS__)
139#define LOG_WARNING(...) LOG_MAKE(LOG_LEVEL_WARNING, "W:", ##__VA_ARGS__)
140#define LOG_ERROR(...) LOG_MAKE(LOG_LEVEL_ERROR, "E:", ##__VA_ARGS__)
141#define LOG_FAULT(...) LOG_MAKE(LOG_LEVEL_FAULT, "F:", ##__VA_ARGS__)
142#define LOG_ABORT(...) LOG_MAKE(LOG_LEVEL_ABORT, "A:", ##__VA_ARGS__)
143
144#else
145#error Define LOG_LEVEL_MAX value LOG_INFO or higher
146#endif
147
148#ifndef INCLUDE_INSIDE_JIT
149namespace newlang {
150
151 // Copy-Past form https://github.com/google/googletest
152
153 inline void SplitString(const ::std::string& str, char delimiter,
154 ::std::vector< ::std::string>* dest) {
155 ::std::vector< ::std::string> parsed;
156 ::std::string::size_type pos = 0;
157 while (true) {
158 const ::std::string::size_type colon = str.find(delimiter, pos);
159 if (colon == ::std::string::npos) {
160 parsed.push_back(str.substr(pos));
161 break;
162 } else {
163 parsed.push_back(str.substr(pos, colon - pos));
164 pos = colon + 1;
165 }
166 }
167 dest->swap(parsed);
168 }
169 // Returns true if and only if the wildcard pattern matches the string. Each
170 // pattern consists of regular characters, single-character wildcards (?), and
171 // multi-character wildcards (*).
172 //
173 // This function implements a linear-time string globbing algorithm based on
174 // https://research.swtch.com/glob.
175
176 static bool PatternMatchesString(const std::string& name_str,
177 const char* pattern, const char* pattern_end) {
178 const char* name = name_str.c_str();
179 const char* const name_begin = name;
180 const char* const name_end = name + name_str.size();
181
182 const char* pattern_next = pattern;
183 const char* name_next = name;
184
185 while (pattern < pattern_end || name < name_end) {
186 if (pattern < pattern_end) {
187 switch (*pattern) {
188 default: // Match an ordinary character.
189 if (name < name_end && *name == *pattern) {
190 ++pattern;
191 ++name;
192 continue;
193 }
194 break;
195 case '?': // Match any single character.
196 if (name < name_end) {
197 ++pattern;
198 ++name;
199 continue;
200 }
201 break;
202 case '*':
203 // Match zero or more characters. Start by skipping over the wildcard
204 // and matching zero characters from name. If that fails, restart and
205 // match one more character than the last attempt.
206 pattern_next = pattern;
207 name_next = name + 1;
208 ++pattern;
209 continue;
210 }
211 }
212 // Failed to match a character. Restart if possible.
213 if (name_begin < name_next && name_next <= name_end) {
214 pattern = pattern_next;
215 name = name_next;
216 continue;
217 }
218 return false;
219 }
220 return true;
221 }
222
223 inline bool IsGlobPattern(const std::string& pattern) {
224 return std::any_of(pattern.begin(), pattern.end(),
225 [](const char c) {
226 return c == '?' || c == '*'; });
227 }
228
230 public:
231 StringMatcher() = default;
232
233 // Constructs a filter from a string of patterns separated by `:`.
234
235 explicit StringMatcher(const std::string& filter, const char separator = ':') : filter_(filter) {
236 // By design "" filter matches "" string.
237 std::vector<std::string> all_patterns;
238 SplitString(filter, separator, &all_patterns);
239 const auto exact_match_patterns_begin = std::partition(
240 all_patterns.begin(), all_patterns.end(), &IsGlobPattern);
241
242 glob_patterns_.reserve(exact_match_patterns_begin - all_patterns.begin());
243 std::move(all_patterns.begin(), exact_match_patterns_begin,
244 std::inserter(glob_patterns_, glob_patterns_.begin()));
245 std::move(
246 exact_match_patterns_begin, all_patterns.end(),
247 std::inserter(exact_match_patterns_, exact_match_patterns_.begin()));
248 }
249
250 // Returns true if and only if name matches at least one of the patterns in
251 // the filter.
252
253 bool MatchesName(const std::string& name) const {
254 return exact_match_patterns_.count(name) > 0 ||
255 std::any_of(glob_patterns_.begin(), glob_patterns_.end(),
256 [&name](const std::string & pattern) {
257 return PatternMatchesString(
258 name, pattern.c_str(),
259 pattern.c_str() + pattern.size());
260 });
261 }
262
263 SCOPE(private) :
264 const std::string_view filter_;
265 std::vector<std::string> glob_patterns_;
266 std::unordered_set<std::string> exact_match_patterns_;
267 };
268
269 // bool UnitTestOptions::MatchesFilter(const std::string& name_str,
270 // const char* filter) {
271 // return UnitTestFilter(filter).MatchesName(name_str);
272 // }
273 //
274 // // Returns true if and only if the user-specified filter matches the test
275 // // suite name and the test name.
276 //
277 // bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name,
278 // const std::string& test_name) {
279 // // Split --gtest_filter at '-', if there is one, to separate into
280 // // positive filter and negative filter portions
281 // return PositiveAndNegativeUnitTestFilter(GTEST_FLAG_GET(filter))
282 // .MatchesTest(test_suite_name, test_name);
283 // }
284 //
285
286 class ParserError : public std::runtime_error {
287 public:
288
289 ParserError(const std::string_view msg) : runtime_error(msg.begin()) {
290 }
291 };
292
293 template <typename T>
294 typename std::enable_if < std::is_same<T, std::string>::value, std::string>::type
295 DumpToString(const T &obj) {
296 return obj;
297 }
298
299 template <typename T>
300 typename std::enable_if < !std::is_same<T, std::string>::value, std::string>::type
301 DumpToString(const T &obj) {
302 return obj.first;
303 }
304
305 template<typename T>
306 std::string Dump(const T &iterable) {
307 std::string result;
308 for (auto &elem : iterable) {
309 if (!result.empty()) {
310 result += '\n';
311 }
312 result += DumpToString(elem);
313 }
314 return result;
315 }
316
317 class Logger {
318 public:
319 typedef uint8_t LogLevelType;
320 typedef void FuncCallback(void *param, LogLevelType level, const char * str, bool flush);
321
323 return m_level;
324 }
325
329
331 LogLevelType prev_level = m_level;
332 if (level >= LOG_LEVEL_ABORT && level <= LOG_LEVEL_MAX) {
333 m_level = level;
334 } else {
336 }
337 return prev_level;
338 }
339
340 bool SetPrintCallstack(bool enable) {
341 bool prev = m_print_callstack;
342 m_print_callstack = enable;
343 return prev;
344 }
345
347 return m_print_callstack;
348 }
349 static std::string GetStackTrace();
350
351 static void PrintfCallback(void *, LogLevelType, const char * str, bool flush) {
352 fprintf(stdout, "%s", str);
353 if (flush) {
354 fflush(stdout);
355 }
356 }
357
358 void SetCallback(FuncCallback * func, void * param) {
359 m_func = func;
360 m_func_param = param;
361 }
362
363 void SaveCallback(FuncCallback *&func, void * &param) {
364 func = m_func;
365 param = m_func_param;
366 }
367
368 static std::string log_printf(uint8_t level, char const *prefix, char const *file, int line, char const *format, ...)
369#ifdef __GNUC__
370 __attribute__ ((format(printf, 5, 6)))
371#endif
372 ;
373
374 const char * AddString(LogLevelType level, char const *string, bool flush);
375 static const char * GetLogLevelDesc(LogLevelType level);
376
377 static Logger * Instance() {
378 // Шаблон с определением static Logger m_instance; собирается с warning в MinGW
379 if (m_instance == nullptr) {
380 m_instance = new Logger();
381 }
382 return m_instance;
383 }
384 // private:
385
389 m_func_param = nullptr;
390 m_print_callstack = false;
391 }
392 Logger(const Logger&) = delete;
393 const Logger& operator=(const Logger&) = delete;
394
395 virtual ~Logger() {
396 }
402 };
403}
404
405#endif // INCLUDE_INSIDE_JIT
406#endif // INCLUDED_LOGGER_H_
407
bool m_print_callstack
Definition logger.h:401
void FuncCallback(void *param, LogLevelType level, const char *str, bool flush)
Definition logger.h:320
const Logger & operator=(const Logger &)=delete
static void PrintfCallback(void *, LogLevelType, const char *str, bool flush)
Definition logger.h:351
void SetCallback(FuncCallback *func, void *param)
Definition logger.h:358
static Logger * m_instance
Definition logger.h:397
bool SetPrintCallstack(bool enable)
Definition logger.h:340
FuncCallback * m_func
Definition logger.h:399
virtual ~Logger()
Definition logger.h:395
static std::string log_printf(uint8_t level, char const *prefix, char const *file, int line, char const *format,...)
Definition logger.cpp:33
LogLevelType GetLogLevelNormal()
Definition logger.h:326
uint8_t LogLevelType
Definition logger.h:319
const char * AddString(LogLevelType level, char const *string, bool flush)
LogLevelType GetLogLevel()
Definition logger.h:322
void SaveCallback(FuncCallback *&func, void *&param)
Definition logger.h:363
static std::string GetStackTrace()
Definition jit.cpp:2789
static const char * GetLogLevelDesc(LogLevelType level)
Definition logger.cpp:11
Logger(const Logger &)=delete
LogLevelType SetLogLevel(const LogLevelType level)
Definition logger.h:330
bool GetPrintCallstack()
Definition logger.h:346
LogLevelType m_level
Definition logger.h:398
static Logger * Instance()
Definition logger.h:377
void * m_func_param
Definition logger.h:400
ParserError(const std::string_view msg)
Definition logger.h:289
std::vector< std::string > glob_patterns_
Definition logger.h:265
const std::string_view filter_
Definition logger.h:264
bool MatchesName(const std::string &name) const
Definition logger.h:253
std::unordered_set< std::string > exact_match_patterns_
Definition logger.h:266
StringMatcher(const std::string &filter, const char separator=':')
Definition logger.h:235
int result
Definition lexer.l:367
__attribute__((weak)) std
Definition logger.cpp:264
#define LOG_LEVEL_ABORT
Definition logger.h:91
size_t BinToHexBuffer(const uint8_t *buffer, const size_t size, char *str, const size_t str_size)
Definition logger.cpp:249
std::string BinToHex(const uint8_t *buffer, const size_t size)
Definition logger.cpp:168
size_t HexToBin(const char *str, uint8_t *buffer, const size_t size)
Definition logger.cpp:130
int HexToBinEq(const char *str, const uint8_t *buffer, const size_t size)
Definition logger.cpp:147
#define SCOPE(scope)
Definition logger.h:38
#define LOG_LEVEL_MAX
Definition logger.h:101
std::string HexStrToBinStr(std::string &hex_str)
Definition logger.cpp:179
#define LOG_LEVEL_NORMAL
Definition logger.h:113
uint8_t HexToByte(const char c)
Definition logger.cpp:117
Definition nlc.h:59
void SplitString(const ::std::string &str, char delimiter, ::std::vector< ::std::string > *dest)
Definition logger.h:153
std::enable_if< std::is_same< T, std::string >::value, std::string >::type DumpToString(const T &obj)
Definition logger.h:295
bool IsGlobPattern(const std::string &pattern)
Definition logger.h:223
static bool PatternMatchesString(const std::string &name_str, const char *pattern, const char *pattern_end)
Definition logger.h:176
std::string Dump(const T &iterable)
Definition logger.h:306