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
|
#pragma once
#include <cstdio>
#include <map>
#include <string>
#include <thread>
#include <utility>
#include "common.hpp"
#include "settings.hpp"
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
POLYBAR_NS
enum class loglevel {
NONE = 0,
ERROR,
WARNING,
NOTICE,
INFO,
TRACE,
};
class logger {
public:
using make_type = const logger&;
static make_type make(loglevel level = loglevel::NONE);
explicit logger(loglevel level);
const logger& operator=(const logger&) const {
return *this;
}
static loglevel parse_verbosity(const string& name, loglevel fallback = loglevel::NONE);
void verbosity(loglevel level);
#ifdef DEBUG_LOGGER // {{{
template <typename... Args>
void trace(const string& message, Args&&... args) const {
output(loglevel::TRACE, message, std::forward<Args>(args)...);
}
#ifdef DEBUG_LOGGER_VERBOSE
template <typename... Args>
void trace_x(const string& message, Args&&... args) const {
output(loglevel::TRACE, message, std::forward<Args>(args)...);
}
#else
template <typename... Args>
void trace_x(Args&&...) const {}
#endif
#else
template <typename... Args>
void trace(Args&&...) const {}
template <typename... Args>
void trace_x(Args&&...) const {}
#endif // }}}
/**
* Output an info message
*/
template <typename... Args>
void info(const string& message, Args&&... args) const {
output(loglevel::INFO, message, std::forward<Args>(args)...);
}
/**
* Output a notice
*/
template <typename... Args>
void notice(const string& message, Args&&... args) const {
output(loglevel::NOTICE, message, std::forward<Args>(args)...);
}
/**
* Output a warning message
*/
template <typename... Args>
void warn(const string& message, Args&&... args) const {
output(loglevel::WARNING, message, std::forward<Args>(args)...);
}
/**
* Output an error message
*/
template <typename... Args>
void err(const string& message, Args&&... args) const {
output(loglevel::ERROR, message, std::forward<Args>(args)...);
}
protected:
template <typename T>
decltype(auto) convert(T&& arg) const {
return forward<T>(arg);
}
/**
* Convert string
*/
const char* convert(string& arg) const;
const char* convert(const string& arg) const;
/**
* Convert thread id
*/
size_t convert(std::thread::id arg) const;
/**
* Write the log message to the output channel
* if the defined verbosity level allows it
*/
template <typename... Args>
void output(loglevel level, const string& format, Args&&... values) const {
if (level > m_level) {
return;
}
#if defined(__clang__) // {{{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-security"
#endif // }}}
dprintf(m_fd, (m_prefixes.at(level) + format + m_suffixes.at(level) + "\n").c_str(), convert(values)...);
#if defined(__clang__) // {{{
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif // }}}
}
private:
/**
* Logger verbosity level
*/
loglevel m_level{loglevel::TRACE};
/**
* File descriptor used when writing the log messages
*/
int m_fd{STDERR_FILENO};
/**
* Loglevel specific prefixes
*/
std::map<loglevel, string> m_prefixes;
/**
* Loglevel specific suffixes
*/
std::map<loglevel, string> m_suffixes;
};
POLYBAR_NS_END
|