#pragma once #include "util/loglevel.hh" #include #include namespace logging { namespace ansi { static constexpr auto RED = "\033[31m"; static constexpr auto YELLOW = "\033[33m"; static constexpr auto MAGENTA = "\033[35m"; static constexpr auto WHITE = "\033[37m"; static constexpr auto BOLD = "\033[1m"; static constexpr auto RESET = "\033[0m"; } using fmt::print; class Logger { using LogLevel = matar::LogLevel; public: Logger(LogLevel level = LogLevel::Debug, FILE* stream = stderr) : level(0) , stream(stream) { set_level(level); } template void log(const fmt::format_string& fmt, Args&&... args) { fmt::println(stream, fmt, std::forward(args)...); } template void debug(const fmt::format_string& fmt, Args&&... args) { if (level & static_cast(LogLevel::Debug)) { print(stream, "{}{}[DEBUG] ", ansi::MAGENTA, ansi::BOLD); log(fmt, std::forward(args)...); print(stream, ansi::RESET); } } template void info(const fmt::format_string& fmt, Args&&... args) { if (level & static_cast(LogLevel::Info)) { print(stream, "{}[INFO] ", ansi::WHITE); log(fmt, std::forward(args)...); print(stream, ansi::RESET); } } template void warn(const fmt::format_string& fmt, Args&&... args) { if (level & static_cast(LogLevel::Warn)) { print(stream, "{}[WARN] ", ansi::YELLOW); log(fmt, std::forward(args)...); print(stream, ansi::RESET); } } template void error(const fmt::format_string& fmt, Args&&... args) { if (level & static_cast(LogLevel::Error)) { print(stream, "{}{}[ERROR] ", ansi::RED, ansi::BOLD); log(fmt, std::forward(args)...); print(stream, ansi::RESET); } } void set_level(LogLevel level) { this->level = (static_cast(level) << 1) - 1; } void set_stream(FILE* stream) { this->stream = stream; } private: uint8_t level; FILE* stream; }; } extern logging::Logger glogger; #define debug(x) glogger.debug("{} = {}", #x, x);