-
Notifications
You must be signed in to change notification settings - Fork 0
/
log.cpp
116 lines (82 loc) · 2.18 KB
/
log.cpp
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
// -*- compile-command: "CXXFLAGS=-std=c++14 make log" -*-
#include <iostream>
#include <sstream>
#include <vector>
#include <memory>
#include <functional>
namespace log {
enum level {
debug = 0,
info,
warning,
deprecated,
error,
fatal,
size
};
using handler = std::function<void(const std::string& line)>;
std::vector<handler>& handlers(log::level level) {
static std::vector<handler> table[log::level::size];
return table[level];
}
struct emitter {
std::string tag;
friend std::ostream& operator<<(std::ostream& out, const emitter& self) {
return out << "[" << self.tag << "]";
}
friend std::istream& operator>>(std::istream& in, emitter& self) {
const auto pos = in.tellg();
char c;
if((in >> c) && c == '[') {
std::string tag;
if(std::getline(in, tag, ']')) {
self.tag = tag;
return in;
}
}
in.clear();
in.seekg(pos);
in.setstate(std::ios::failbit);
return in;
}
};
struct dispatch: std::stringbuf {
std::stringstream ss;
dispatch(log::level level):
level(level) { }
const log::level level;
virtual int sync() {
// start from leftovers
ss << str();
// split lines
std::string line;
while(std::getline(ss, line, '\n') && !ss.eof()) {
for(const auto& h: handlers(level)) {
h(line);
}
}
// reset stringstream with leftovers, if any
ss = std::stringstream();
ss << line;
// clear buffer
str("");
return 0;
}
};
}
void default_handler(const std::string& line) {
std::stringstream ss(line);
log::emitter em;
if(ss >> em) {
std::cout << "emitter: " << em.tag << " ";
}
std::cout << "message: " << ss.rdbuf() << "\n";
}
int main(int, char** ) {
log::dispatch buf(log::info);
log::handlers(log::info).emplace_back(default_handler);
std::ostream s(&buf);
s << log::emitter{"michel"} << "yo" << std::endl
<< "what" << std::flush << "dobidou" << "\n" << std::flush;
return 0;
}