Tool Libs
UMIT-TIROL Institute of Automation and Control Engineering library collection
 
Loading...
Searching...
No Matches
logger.h
Go to the documentation of this file.
1
5#pragma once
6
7#include <cstdio>
8#include <cstdarg>
9template<typename T>
10struct DevNull: Sink<T>, Source<T> {
11 bool empty() override { return true; }
12 T pop() override { return T{}; }
13 bool full() override { return false; }
14 void push(T &&) override { }
15};
17template<typename T>
18inline DevNull<T> devnull;
19
21struct Logger : Sink<Buffer<uint8_t>> {
22 enum Lvl {NONE, INFO, WARN};
23 const char *color[3] = {"\u001b[0m","\u001b[32m", "\u001b[31m"};
25
26 virtual Buffer<uint8_t> pre() {
27 return Buffer<uint8_t>(256);
28 }
29 virtual void mklog(Lvl lvl, const char *fmt, va_list args) {
30 Buffer<uint8_t> b = pre();
31 if (lvl != NONE) {
32 b.len += snprintf((char*)b.buf+b.len, b.size-b.len, "%s", color[lvl]);
33 }
34 b.len += vsnprintf((char*)b.buf+b.len, b.size-b.len, fmt, args);
35 if (lvl != NONE) {
36 b.len += snprintf((char*)b.buf+b.len, b.size-b.len, "%s", color[NONE]);
37 }
38 while (out.full());
39 out.trypush(std::move(b));
40 }
41public:
43 void info(const char *fmt, ...) {
44 va_list args;
45 va_start(args, fmt);
46 mklog(INFO, fmt, args);
47 va_end(args);
48 }
50 void warn(const char *fmt, ...) {
51 va_list args;
52 va_start(args, fmt);
53 mklog(WARN, fmt, args);
54 va_end(args);
55 }
57 void print(const char *fmt, ...) {
58 va_list args;
59 va_start(args, fmt);
60 mklog(NONE, fmt, args);
61 va_end(args);
62 }
63 bool full() override {
64 return out.full();
65 }
67 void push(Buffer<uint8_t> &&b) override {
68 Buffer<uint8_t> tmp = pre();
69 for (auto &c : b) { tmp.append(c); }
70 out.push(std::move(tmp));
71 }
73 Logger(Sink<Buffer<uint8_t>> &snk) : out{snk} { }
74 Logger() : out{devnull<Buffer<uint8_t>>} {}
75 void *operator new(size_t, Logger *where) {
76 return where;
77 }
78};
79
81struct BufferedLogger: public Logger {
82 static constexpr int MAXLEN = 256;
83 char buf[MAXLEN];
84 size_t ix = 0;
85
86 void mklog(Lvl lvl, const char *fmt, va_list args) override {
87 size_t need = snprintf(buf, 0, "%s", color[lvl]);
88 if (need >= MAXLEN - ix) {
89 flush();
90 }
91 ix += snprintf(buf+ix, MAXLEN - ix, "%s", color[lvl]);
92
93 need = vsnprintf(buf, 0, fmt, args);
94 if (need >= MAXLEN - ix) {
95 flush();
96 }
97 ix += vsnprintf(buf+ix, MAXLEN - ix, fmt, args);
98
99 need = snprintf(buf, 0, "%s", color[NONE]);
100 if (need >= MAXLEN - ix) {
101 flush();
102 }
103 ix += snprintf(buf+ix, MAXLEN - ix, "%s", color[NONE]);
104 }
105
106public:
107 BufferedLogger(Sink<Buffer<uint8_t>> &snk) : Logger{snk} { }
108 BufferedLogger() : Logger{devnull<Buffer<uint8_t>>} {}
109 void flush() {
110 if (!ix) return;
111 out.push(std::move(Buffer<uint8_t>((const uint8_t *)buf, ix)));
112 ix = 0;
113 }
114 bool full() override {
115 return ix == MAXLEN;
116 }
117};
118
119
DevNull< T > devnull
black-hole sink & source, just drops all data, provides none
Definition logger.h:18
dynamically allocated, but fixed-size buffer template
Definition buffer.h:18
Buffer & append(T b)
simple append single item
Definition buffer.h:44
size_t size
total capacity of buffer
Definition buffer.h:23
size_t len
number of items stored in buffer
Definition buffer.h:21
buffered logging facility
Definition logger.h:81
bool full() override
check if sink is full
Definition logger.h:114
simple printf-style logging infrastructure
Definition logger.h:21
void print(const char *fmt,...)
None log level.
Definition logger.h:57
void info(const char *fmt,...)
Info log level.
Definition logger.h:43
void push(Buffer< uint8_t > &&b) override
push otherwisely prepared Buffer through Logger
Definition logger.h:67
bool full() override
check if sink is full
Definition logger.h:63
Logger(Sink< Buffer< uint8_t > > &snk)
create Logger wrapping a Buffer Sink
Definition logger.h:73
void warn(const char *fmt,...)
Warn log level.
Definition logger.h:50
generic object sink, i.e.
Definition streams.h:15
virtual bool full()=0
check if sink is full
void trypush(T &&t)
use this if you don't care if it's going to be successful. data gets discarded if sink is full.
Definition streams.h:28
virtual void push(const T &t)
copy semantics does not check for space. guard by using 'if (!full) { ... }'
Definition streams.h:20
generic object source, i.e.
Definition streams.h:40
virtual T pop()=0
pull object from source does not check for data. guard by using 'if (!empty) { ......
virtual bool empty()=0
check if source is empty