-
Notifications
You must be signed in to change notification settings - Fork 1
/
base.h
172 lines (145 loc) · 3.86 KB
/
base.h
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
#ifndef SOG_BASE_H
#define SOG_BASE_H
#include <assert.h>
#include <boost/variant.hpp>
#include <string_view>
#include <initializer_list>
#include <memory>
#include <stdint.h>
#include <vector>
// #include <variant>
namespace sog {
struct Value {
using Data = boost::variant<
long,
double,
std::string,
std::string_view>;
Data data;
inline Value(double f): data(f) {}
inline Value(std::string &&s): data(s) {}
inline Value(std::string_view s): data(s) {}
template <class T, typename=std::enable_if_t<std::is_integral<T>::value>>
inline Value(T i): data(static_cast<long>(i)) {}
template <class... A>
inline Value(A&... a): data(std::string_view{std::forward<A>(a)...}) {}
// Prevent accidental copies.
Value(const Value &v): data(v.data) {
assert(!boost::get<std::string>(&v.data));
}
Value(Value &&source) = default;
// Explicit reference.
Value ref() const { return *this; }
// Explicit copy.
Value owned() const {
const std::string *s = boost::get<std::string>(&data);
if (s)
return std::string{*s};
return *this;
}
bool operator==(const Value &that) const;
};
struct Source;
struct Message;
using Level = uint16_t;
namespace level {
constexpr Level FATAL = 0;
constexpr Level ERROR = 1;
constexpr Level WARN = 2;
constexpr Level INFO = 3;
constexpr Level DEBUG = 4;
constexpr Level TRACE = 5;
#ifdef NDEBUG
constexpr Level DFATAL = FATAL;
#else
constexpr Level DFATAL = ERROR;
#endif
};
/// Value used to enable all log messages.
constexpr Level ENABLE_ALL = std::numeric_limits<Level>::max();
/** A value reserved for errors.
*
* Note that it isn't necessarily an error to log at this level, however
* filtering will be different as APIs that parse or otherwise return a
* level may choose to use this as a sentinel value to indicate an error.
*/
constexpr Level LEVEL_ERROR = ENABLE_ALL - 1;
struct SinkData {
virtual ~SinkData();
};
struct Prepared final {
// Data to be passed to the sink.
std::unique_ptr<SinkData> sink_data;
/** Should messages from this sink be logged.
*
* If false log() will never be called for this source.
*
* This can be used to cheaply drop messages that will never be logged.
*/
bool log = true;
};
/** A log source.
*
* A source is a collection of metadata about a "type" of log message. This
* is generally created by the LOG() macro. Sources should be immutable once
* created.
*/
struct Source final {
Level level = level::ERROR;
std::string_view file;
std::string_view function;
uint32_t line = 0;
std::string_view msg_template;
/** Number of values for this source.
*/
size_t value_count;
/** The keys for this source.
*
* This points to the first element of an array of length value_count.
*/
const std::string_view *keys;
Source() {}
inline constexpr Source(
Level level,
std::string_view file,
std::string_view function,
uint32_t line,
std::string_view msg_template,
size_t value_count,
const std::string_view *keys
):
level(level),
file(file),
function(function),
line(line),
msg_template(msg_template),
value_count(value_count),
keys(keys) { }
};
/** A logged message.
*/
struct Message final {
/** The source that logged this message.
*/
const Source *source;
/** Values of this message.
*
* This points to the first value of an array of length
* source->value_count. The values map to the respective key in
* source->keys.
*/
const Value *values;
Message() {}
constexpr Message(
const Source *source,
const Value *values):
source(source), values(values) {}
constexpr Message(
const Source *source,
std::initializer_list<Value> vals):
source(source), values(&*vals.begin()) {}
};
Prepared _prepare(const Source *s);
void _submit(SinkData *d, Message m);
}
#endif