diff options
| author | hachem <im@hachem.wtf> | 2026-08-20 02:27:02 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-20 02:40:07 +0200 |
| commit | 5b361d81dbd2af0d0e99b9eb1adebea76ff05db0 (patch) | |
| tree | 34db1df17e8c7248aeeb92156d635d31c2484e3f /src/core/log.h | |
| parent | e3abaaf59777258ba06705135a0cafcb5918ad12 (diff) | |
[chore]: MASSIVE refactor + more vulkan bs
Diffstat (limited to 'src/core/log.h')
| -rw-r--r-- | src/core/log.h | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/core/log.h b/src/core/log.h new file mode 100644 index 0000000..db6b4b4 --- /dev/null +++ b/src/core/log.h @@ -0,0 +1,156 @@ +#pragma once + +#include "core/memory.h" + +#include <string> +#include <vector> +#include <sstream> +#include <iostream> +#include <fstream> +#include <chrono> +#include <iomanip> +#include <mutex> +#include <string_view> + +namespace Donut +{ + enum class LogLevel + { + trace = 0, + Info = 2, + Warn = 3, + Err = 4, + Fatal = 5 + }; + + class Logger + { + public: + Logger(); + ~Logger(); + + static auto init() -> void; + static auto shutdown() -> void; + + static auto get_logger() -> Ref<Logger>; + + template<typename... Args> + static auto trace(const std::string_view& format, const Args&... args) -> void + { + auto logger = get_logger(); + if (logger) logger->log_message(LogLevel::trace, format, args...); + } + + template<typename... Args> + static auto info(const std::string_view& format, const Args&... args) -> void + { + auto logger = get_logger(); + if (logger) logger->log_message(LogLevel::Info, format, args...); + } + + template<typename... Args> + static auto warn(const std::string_view& format, const Args&... args) -> void + { + auto logger = get_logger(); + if (logger) logger->log_message(LogLevel::Warn, format, args...); + } + + template<typename... Args> + static auto error(const std::string_view& format, const Args&... args) -> void + { + auto logger = get_logger(); + if (logger) logger->log_message(LogLevel::Err, format, args...); + } + + template<typename... Args> + static auto fatal(const std::string_view& format, const Args&... args) -> void + { + auto logger = get_logger(); + if (logger) logger->log_message(LogLevel::Fatal, format, args...); + } + + template<typename... Args> + auto log_message(LogLevel level, const std::string_view& format, const Args&... args) -> void + { + if (level < m_log_level) + return; + + std::lock_guard<std::mutex> lock(m_mutex); + std::string message = format_string(format, args...); + std::string full_message = get_time_stamp() + " [" + get_log_level_string(level) + "] " + message; + + if (m_console_output) + { + set_console_color(level); + std::cout << full_message << std::endl; + reset_console_color(); + } + + if (m_file_output && m_log_file.is_open()) + { + m_log_file << full_message << std::endl; + m_log_file.flush(); + } + } + + template<typename... Args> + auto format_string(const std::string_view& format, const Args&... args) -> std::string + { + std::string result = format.data(); + std::vector<std::string> arg_strings = { to_string(args)... }; + + size_t arg_index = 0; + size_t pos = 0; + + while ((pos = result.find("{}", pos)) != std::string::npos && arg_index < arg_strings.size()) + { + result.replace(pos, 2, arg_strings[arg_index]); + pos += arg_strings[arg_index].length(); + arg_index++; + } + + return result; + } + + template<typename T> + auto to_string(const T& value) -> std::string + { + std::stringstream ss; + ss << value; + return ss.str(); + } + + auto set_log_level(LogLevel level) -> void { m_log_level = level; } + auto enable_console_output(bool enable) -> void { m_console_output = enable; } + auto enable_file_output(bool enable) -> void { m_file_output = enable; } + auto set_log_file(const std::string& filename) -> void; + + auto get_time_stamp() -> std::string; + auto get_log_level_string(LogLevel level) -> std::string; + auto set_console_color(LogLevel level) -> void; + auto reset_console_color() -> void; + + private: + LogLevel m_log_level; + bool m_console_output; + bool m_file_output; + std::ofstream m_log_file; + std::mutex m_mutex; + + static Ref<Logger> s_logger; + }; +} + +#if defined(DONUT_DEBUG) + #define DONUT_TRACE(format, ...) ::Donut::Logger::trace(format, ##__VA_ARGS__) + #define DONUT_INFO(format, ...) ::Donut::Logger::info(format, ##__VA_ARGS__) + #define DONUT_WARN(format, ...) ::Donut::Logger::warn(format, ##__VA_ARGS__) + #define DONUT_ERROR(format, ...) ::Donut::Logger::error(format, ##__VA_ARGS__) + #define DONUT_FATAL(format, ...) ::Donut::Logger::fatal(format, ##__VA_ARGS__) +#else + #define DONUT_TRACE(format, ...) {} + #define DONUT_INFO(format, ...) {} + #define DONUT_WARN(format, ...) {} + #define DONUT_ERROR(format, ...) {} + #define DONUT_FATAL(format, ...) {} +#endif |
