File Coverage

src/panda/log.h
Criterion Covered Total %
statement 1 1 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 1 1 100.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6             #include
7             #include
8             #include "string_view.h"
9             #include "string.h"
10              
11             namespace panda { namespace log {
12              
13             #ifdef WIN32
14             # define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
15             #else
16             # define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
17             #endif
18              
19             #define _panda_log_code_point_ panda::log::CodePoint{__FILENAME__, __LINE__, panda_log_module}
20              
21             #define panda_should_log(level) panda::log::should_log(level, _panda_log_code_point_)
22              
23             #define panda_elog_m(module, level, code) do { \
24             if (panda::log::should_log(level, _panda_log_code_point_, module)) { \
25             std::ostream& log = panda::log::details::_get_os(); \
26             code; \
27             panda::log::details::_do_log(log, _panda_log_code_point_, level); \
28             } \
29             } while (0);
30              
31             #define panda_log_m(module, level, msg) panda_elog_m(module, level, { log << msg; })
32              
33             #define panda_elog(level, code) panda_elog_m(*panda_log_module, level, code)
34             #define panda_log(level, msg) panda_log_m (*panda_log_module, level, msg)
35              
36             #define panda_log_verbose_debug(msg) panda_log(panda::log::VerboseDebug, msg)
37             #define panda_log_debug(msg) panda_log(panda::log::Debug, msg)
38             #define panda_log_info(msg) panda_log(panda::log::Info, msg)
39             #define panda_log_notice(msg) panda_log(panda::log::Notice, msg)
40             #define panda_log_warn(msg) panda_log(panda::log::Warning, msg)
41             #define panda_log_error(msg) panda_log(panda::log::Error, msg)
42             #define panda_log_critical(msg) panda_log(panda::log::Critical, msg)
43             #define panda_log_alert(msg) panda_log(panda::log::Alert, msg)
44             #define panda_log_emergency(msg) panda_log(panda::log::Emergency, msg)
45             #define panda_elog_verbose_debug(code) panda_elog(panda::log::VerboseDebug, code)
46             #define panda_elog_debug(code) panda_elog(panda::log::Debug, code)
47             #define panda_elog_info(code) panda_elog(panda::log::Info, code)
48             #define panda_elog_notice(code) panda_elog(panda::log::Notice, code)
49             #define panda_elog_warn(code) panda_elog(panda::log::Warning, code)
50             #define panda_elog_error(code) panda_elog(panda::log::Error, code)
51             #define panda_elog_critical(code) panda_elog(panda::log::Critical, code)
52             #define panda_elog_alert(code) panda_elog(panda::log::Alert, code)
53             #define panda_elog_emergency(code) panda_elog(panda::log::Emergency, code)
54              
55             #define panda_debug_v(var) panda_log(panda::log::Debug, #var << " = " << (var))
56              
57             #define PANDA_ASSERT(var, msg) if(!(auto assert_value = var)) { panda_log_emergency("assert failed: " << #var << " is " << assert_value << msg) }
58              
59             enum Level {
60             VerboseDebug = 0,
61             Debug,
62             Info,
63             Notice,
64             Warning,
65             Error,
66             Critical,
67             Alert,
68             Emergency
69             };
70              
71 36           struct Module {
72             Module* parent;
73             Level level;
74             string name;
75              
76             Module(const string& name, Level level = Level::Debug);
77             Module(const string& name, Module* parent, Level level = Level::Debug);
78              
79             Module(const Module&) = delete;
80             Module(Module&&) = delete;
81             Module & operator =(const Module&) = delete;
82              
83             void set_level(Level level);
84              
85             std::map children;
86             };
87              
88             struct CodePoint {
89             string_view file;
90             uint32_t line;
91             Module* module;
92              
93             std::string to_string () const;
94             };
95             std::ostream& operator<< (std::ostream&, const CodePoint&);
96              
97             struct ILogger {
98             virtual bool should_log (Level, const CodePoint&) { return true; }
99             virtual void log (Level, const CodePoint&, const std::string&) = 0;
100             virtual ~ILogger() {}
101             };
102              
103             namespace details {
104             extern Level min_level;
105             extern std::unique_ptr ilogger;
106              
107             std::ostream& _get_os ();
108             bool _do_log (std::ostream&, const CodePoint&, Level);
109              
110             template
111             struct CallbackLogger : ILogger {
112             Func f;
113             CallbackLogger (const Func& f) : f(f) {}
114             void log (Level level, const CodePoint& cp, const std::string& s) override { f(level, cp, s); }
115             };
116             }
117              
118             void set_level (Level, const string& name = "");
119             void set_logger (ILogger*);
120              
121             template >>::value>>
122             void set_logger (const Func& f) { set_logger(new details::CallbackLogger(f)); }
123              
124             inline bool should_log (Level level, const CodePoint& cp, const Module& module) {
125             return level >= module.level && details::ilogger && details::ilogger->should_log(level, cp);
126             }
127              
128             struct escaped {
129             string_view src;
130             };
131             std::ostream& operator<< (std::ostream&, const escaped&);
132              
133             }
134             }
135             extern panda::log::Module* panda_log_module;
136