#ifndef CORE_LOGGER_H #define CORE_LOGGER_H #include "utils/ArrayString.h" namespace Core::Logger { enum class Level { ERROR, WARNING, INFO, DEBUG }; extern Level level; // aborts on critical logging failure template void log(Level l, const char* file, int line, const char* start, const char* format, Args&&... args) { if(Core::Logger::level < l) { return; } Core::ArrayString<2048> s; if(s.append(format)) { printf( "\33[1;31m%s:%d contains an invalid format string\33[39;49m\n", file, line); } else if(s.format(Core::forward(args)...)) { printf("\33[1;31m%s:%d formatting failed\33[39;49m\n", file, line); } else if(fputs(start, stdout) < 0 || s.print() || printf("\33[39;49m\n") <= 0) { Core::exitWithHandler(1); } } } #if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 1 #define CORE_LOG_ERROR(format, ...) \ log(Core::Logger::Level::ERROR, __FILE__, __LINE__, "\33[1;31m[ERROR] ", \ format, __VA_ARGS__); #else #define CORE_LOG_ERROR(format, ...) #endif #if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 2 #define CORE_LOG_WARNING(format, ...) \ log(Core::Logger::Level::WARNING, __FILE__, __LINE__, \ "\33[1;33m[WARNING] ", format, __VA_ARGS__); #else #define CORE_LOG_WARNING(format, ...) #endif #if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 3 #define CORE_LOG_INFO(format, ...) \ log(Core::Logger::Level::INFO, __FILE__, __LINE__, "\33[1;37m[INFO] ", \ format, __VA_ARGS__); #else #define CORE_LOG_INFO(format, ...) #endif #if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 4 #define CORE_LOG_DEBUG(format, ...) \ log(Core::Logger::Level::DEBUG, __FILE__, __LINE__, "\33[1;32m[DEBUG] ", \ format, __VA_ARGS__); #else #define CORE_LOG_DEBUG(format, ...) #endif #endif