#pragma once #include #include "uart_handler.hpp" enum class LogLevel { ERROR = 0, INFO, DEBUG, TRACE, }; inline constexpr std::string_view get_loglevel_string(LogLevel level) { switch (level) { case (LogLevel::ERROR): { return "[Error]"; } case (LogLevel::INFO): { return "[Info] "; } case (LogLevel::DEBUG): { return "[Debug]"; } case (LogLevel::TRACE): { return "[Trace]"; } } return "[Unknown]"; } class logging_adapter { public: virtual bool init() { return true; } virtual void log(std::string_view message) const = 0; }; class uart_logger : public logging_adapter { public: bool init() { return uart_interface::init(); } virtual void log(std::string_view message) const override { uart_interface::write(message, 2048); } }; class log { public: template static bool init() { if (logger) { return true; } static LoggerType logger_impl; logger = &logger_impl; return logger_impl.init(); } static void linebreak() { const auto val = std::string_view{"\r\n"}; return logger->log(val); } template static void error(Args&&... args) { if (!log_impl_begin(LogLevel::ERROR)) { return; } log_impl(std::forward(args)...); } template static void debug(Args&&... args) { if (!log_impl_begin(LogLevel::DEBUG)) { return; } log_impl(std::forward(args)...); } template static void info(Args&&... args) { if (!log_impl_begin(LogLevel::INFO)) { return; } log_impl(std::forward(args)...); } static void set_loglevel(LogLevel level) { info("New LogLevel: ", get_loglevel_string(level)); log_level = level; } private: static bool log_impl_begin(LogLevel level) { if (log_level < level) { return false; } logger->log(get_loglevel_string(level)); logger->log(": "); return true; } template static void log_impl(std::string_view message, Args&&... args) { logger->log(message); log_impl(std::forward(args)...); } static void log_impl(std::string_view message) { logger->log(message); constexpr std::string_view carriage_return{"\r\n"}; logger->log(carriage_return); } static logging_adapter* logger; static LogLevel log_level; };