207 lines
12 KiB
C++
207 lines
12 KiB
C++
// =============================================
|
|
// Aster: logger.h
|
|
// Copyright (c) 2020-2024 Anish Bhobe
|
|
// =============================================
|
|
|
|
#pragma once
|
|
|
|
#include "constants.h"
|
|
#include <debugbreak.h>
|
|
#include <fmt/core.h>
|
|
|
|
struct Logger
|
|
{
|
|
enum class LogType : u32
|
|
{
|
|
eError,
|
|
eWarning,
|
|
eInfo,
|
|
eDebug,
|
|
eVerbose,
|
|
};
|
|
|
|
u32 m_MinimumLoggingLevel{Cast<u32>(LogType::eDebug)};
|
|
|
|
void
|
|
SetMinimumLoggingLevel(LogType logType)
|
|
{
|
|
m_MinimumLoggingLevel = Cast<u32>(logType);
|
|
}
|
|
|
|
template <LogType TLogLevel>
|
|
constexpr static const char *
|
|
ToCstr()
|
|
{
|
|
if constexpr (TLogLevel == LogType::eError)
|
|
return "[ERROR]:";
|
|
if constexpr (TLogLevel == LogType::eWarning)
|
|
return "[WARN]: ";
|
|
if constexpr (TLogLevel == LogType::eInfo)
|
|
return "[INFO]: ";
|
|
if constexpr (TLogLevel == LogType::eDebug)
|
|
return "[DEBUG]:";
|
|
if constexpr (TLogLevel == LogType::eVerbose)
|
|
return "[VERB]: ";
|
|
}
|
|
|
|
template <LogType TLogLevel>
|
|
constexpr static const char *
|
|
ToColorCstr()
|
|
{
|
|
if constexpr (TLogLevel == LogType::eError)
|
|
return ansi_color::Red;
|
|
if constexpr (TLogLevel == LogType::eWarning)
|
|
return ansi_color::Yellow;
|
|
if constexpr (TLogLevel == LogType::eInfo)
|
|
return ansi_color::Green;
|
|
if constexpr (TLogLevel == LogType::eDebug)
|
|
return ansi_color::White;
|
|
if constexpr (TLogLevel == LogType::eVerbose)
|
|
return ansi_color::Blue;
|
|
}
|
|
|
|
template <LogType TLogLevel>
|
|
void
|
|
Log(const std::string_view &message, const char *loc, u32 line) const
|
|
{
|
|
if (Cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
|
|
{
|
|
fmt::println("{}{} {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), message.data(),
|
|
ansi_color::Black, loc, line, ansi_color::Reset);
|
|
}
|
|
#if !defined(NDEBUG)
|
|
if constexpr (TLogLevel == LogType::eError)
|
|
{
|
|
debug_break();
|
|
}
|
|
#endif // !defined(NDEBUG)
|
|
}
|
|
|
|
template <LogType TLogLevel>
|
|
void
|
|
LogCond(const char *exprStr, const std::string_view &message, const char *loc, u32 line) const
|
|
{
|
|
if (Cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
|
|
{
|
|
fmt::println("{}{} ({}) {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), exprStr,
|
|
message.data(), ansi_color::Black, loc, line, ansi_color::Reset);
|
|
}
|
|
#if !defined(NDEBUG)
|
|
if constexpr (TLogLevel == LogType::eError)
|
|
{
|
|
debug_break();
|
|
}
|
|
#endif // !defined(NDEBUG)
|
|
}
|
|
};
|
|
|
|
extern Logger g_Logger;
|
|
|
|
#define MIN_LOG_LEVEL(LOG_LVL) g_Logger.SetMinimumLoggingLevel(LOG_LVL)
|
|
#define ERROR(...) g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define WARN(...) g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define INFO(...) g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#define ERROR_IF(expr, ...) \
|
|
if (Cast<bool>(expr)) [[unlikely]] \
|
|
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define WARN_IF(expr, ...) \
|
|
if (Cast<bool>(expr)) [[unlikely]] \
|
|
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define INFO_IF(expr, ...) \
|
|
if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#define ELSE_IF_ERROR(expr, ...) \
|
|
; \
|
|
else if (Cast<bool>(expr)) \
|
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_IF_WARN(expr, ...) \
|
|
; \
|
|
else if (Cast<bool>(expr)) \
|
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_IF_INFO(expr, ...) \
|
|
; \
|
|
else if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#define ELSE_ERROR(...) \
|
|
; \
|
|
else [[unlikely]] g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_WARN(...) \
|
|
; \
|
|
else [[unlikely]] g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_INFO(...) \
|
|
; \
|
|
else g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#if !defined(DEBUG_LOG_DISABLED) && !defined(NDEBUG)
|
|
|
|
#define DEBUG(...) g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define DEBUG_IF(expr, ...) \
|
|
if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_IF_DEBUG(expr, ...) \
|
|
; \
|
|
else if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_DEBUG(...) \
|
|
; \
|
|
else g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#else // !defined(DEBUG_LOG_DISABLED)
|
|
|
|
#define DEBUG(msg) \
|
|
{ \
|
|
}
|
|
#define DEBUG_IF(expr, msg) \
|
|
if (expr) \
|
|
(void)msg
|
|
#define ELSE_IF_DEBUG(expr, msg) \
|
|
; \
|
|
if (expr) \
|
|
(void)msg
|
|
#define ELSE_DEBUG(msg) \
|
|
; \
|
|
{ \
|
|
}
|
|
|
|
#endif // !defined(DEBUG_LOG_DISABLED)
|
|
|
|
#if !defined(VERBOSE_LOG_DISABLED) && !defined(NDEBUG)
|
|
|
|
#define VERBOSE(...) g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define VERBOSE_IF(expr, ...) \
|
|
if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_IF_VERBOSE(expr, ...) \
|
|
; \
|
|
else if (Cast<bool>(expr)) \
|
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
#define ELSE_VERBOSE(...) \
|
|
; \
|
|
else g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
|
|
|
#else // !defined(DEBUG_LOG_DISABLED)
|
|
|
|
#define VERBOSE(msg) \
|
|
{ \
|
|
}
|
|
#define VERBOSE_IF(expr, msg) \
|
|
if (expr) \
|
|
(void)msg
|
|
#define ELSE_IF_VERBOSE(expr, msg) \
|
|
; \
|
|
if (expr) \
|
|
(void)msg
|
|
#define ELSE_VERBOSE(msg) \
|
|
; \
|
|
{ \
|
|
}
|
|
|
|
#endif // !defined(VERBOSE_LOG_DISABLED)
|
|
|
|
#define DO(code) , code
|
|
#define ABORT(code) exit(Cast<i32>(code))
|
|
#define THEN_ABORT(code) , ABORT(code)
|