| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#pragma once |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
#include |
|
4
|
|
|
|
|
|
|
#include |
|
5
|
|
|
|
|
|
|
#include |
|
6
|
|
|
|
|
|
|
#include |
|
7
|
|
|
|
|
|
|
#include |
|
8
|
|
|
|
|
|
|
#include |
|
9
|
|
|
|
|
|
|
#include |
|
10
|
|
|
|
|
|
|
#include |
|
11
|
|
|
|
|
|
|
#include |
|
12
|
|
|
|
|
|
|
#include |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
namespace panda { |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
namespace logger { |
|
17
|
|
|
|
|
|
|
struct CodePoint; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
template |
|
20
|
|
|
|
|
|
|
S& operator <<(S& stream, const CodePoint& cp); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
struct CodePoint { |
|
23
|
|
|
|
|
|
|
std::string_view file; |
|
24
|
|
|
|
|
|
|
uint32_t line; |
|
25
|
|
|
|
|
|
|
|
|
26
|
0
|
|
|
|
|
|
std::string to_string() const { |
|
27
|
0
|
0
|
|
|
|
|
std::ostringstream os; |
|
28
|
0
|
0
|
|
|
|
|
os << *this; |
|
29
|
0
|
0
|
|
|
|
|
os.flush(); |
|
30
|
0
|
0
|
|
|
|
|
return os.str(); |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
}; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
template |
|
35
|
0
|
|
|
|
|
|
S& operator <<(S& stream, const CodePoint& cp) { |
|
36
|
0
|
|
|
|
|
|
size_t total = cp.file.size() + log10(cp.line) + 2; |
|
37
|
0
|
|
|
|
|
|
const char* whitespaces = " "; // 24 spaces |
|
38
|
0
|
0
|
|
|
|
|
if (total < 24) { |
|
39
|
0
|
|
|
|
|
|
whitespaces += total; |
|
40
|
|
|
|
|
|
|
} else { |
|
41
|
0
|
|
|
|
|
|
whitespaces = ""; |
|
42
|
|
|
|
|
|
|
} |
|
43
|
0
|
|
|
|
|
|
stream << cp.file << ":" << cp.line << whitespaces; |
|
44
|
0
|
|
|
|
|
|
return stream; |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
enum Level { |
|
49
|
|
|
|
|
|
|
EMERGENCY, |
|
50
|
|
|
|
|
|
|
CRITICAL, |
|
51
|
|
|
|
|
|
|
WARNING, |
|
52
|
|
|
|
|
|
|
INFO, |
|
53
|
|
|
|
|
|
|
VERBOSE, |
|
54
|
|
|
|
|
|
|
DEBUG |
|
55
|
|
|
|
|
|
|
}; |
|
56
|
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
struct ILogger { |
|
58
|
0
|
|
|
|
|
|
virtual bool should_log(Level, CodePoint) {return true;} |
|
59
|
|
|
|
|
|
|
virtual void log(Level, CodePoint, const std::string&) = 0; |
|
60
|
|
|
|
|
|
|
}; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
class Log |
|
64
|
|
|
|
|
|
|
{ |
|
65
|
|
|
|
|
|
|
public: |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Log(logger::CodePoint cp, logger::Level log_level = logger::DEBUG) |
|
68
|
|
|
|
|
|
|
: level(log_level), |
|
69
|
|
|
|
|
|
|
cp(cp) |
|
70
|
|
|
|
|
|
|
{} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Log(Log&& oth) = default; |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
explicit operator bool() const { |
|
75
|
|
|
|
|
|
|
return should_log(level, cp); |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
template |
|
79
|
|
|
|
|
|
|
std::ostringstream& operator <<(T&& t) |
|
80
|
|
|
|
|
|
|
{ |
|
81
|
|
|
|
|
|
|
os << t; |
|
82
|
|
|
|
|
|
|
return os; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
~Log() |
|
86
|
|
|
|
|
|
|
{ |
|
87
|
|
|
|
|
|
|
if (!logger()) { |
|
88
|
|
|
|
|
|
|
return; |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
os.flush(); |
|
91
|
|
|
|
|
|
|
s = os.str(); |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
logger()->log(level, cp, s); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
static std::unique_ptr& logger(); |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
static bool should_log(logger::Level level, logger::CodePoint cp); |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
static void set_max_level(logger::Level val); |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
private: |
|
103
|
|
|
|
|
|
|
std::string s; |
|
104
|
|
|
|
|
|
|
std::ostringstream os; |
|
105
|
|
|
|
|
|
|
logger::Level level; |
|
106
|
|
|
|
|
|
|
logger::CodePoint cp; |
|
107
|
|
|
|
|
|
|
}; |
|
108
|
|
|
|
|
|
|
#ifdef WIN323 |
|
109
|
|
|
|
|
|
|
# define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) |
|
110
|
|
|
|
|
|
|
#else |
|
111
|
|
|
|
|
|
|
# define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) |
|
112
|
|
|
|
|
|
|
#endif // WIN32 |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#define _panda_code_point_ panda::logger::CodePoint{__FILENAME__, __LINE__} |
|
115
|
|
|
|
|
|
|
#define _panda_log_impl_(LEVEL, MSG) panda::Log::should_log(panda::logger::LEVEL, _panda_code_point_) \ |
|
116
|
|
|
|
|
|
|
&& (panda::Log(_panda_code_point_, panda::logger::LEVEL) << MSG) |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
#define panda_debug_v(VAR) _panda_log_impl_(DEBUG, #VAR << " = " << (VAR)) |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
#define panda_log_debug(MSG) _panda_log_impl_(DEBUG, MSG) |
|
121
|
|
|
|
|
|
|
#define panda_log_verbose(MSG) _panda_log_impl_(VERBOSE, MSG) |
|
122
|
|
|
|
|
|
|
#define panda_log_info(MSG) _panda_log_impl_(INFO, MSG) |
|
123
|
|
|
|
|
|
|
#define panda_log_warn(MSG) _panda_log_impl_(WARNING, MSG) |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
#define panda_log_critical(MSG) _panda_log_impl_(CRITICAL, MSG) |
|
126
|
|
|
|
|
|
|
#define panda_log_emergency(MSG) _panda_log_impl_(EMERGENCY, MSG) |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#define PANDA_ASSERT(VAR, MSG) if(!(auto assert_value = VAR)) {panda_log_emergency("assert failed: " << #VAR << " is " << assert_value << MSG)} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
} |