You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.5 KiB

#pragma once
#include <SDL.h>
#include <fmt/core.h>
#include <fmt/ranges.h>
#include "utils/stdcompat/string_view.hpp"
#include "utils/str_cat.hpp"
#ifdef USE_SDL1
#include "sdl2_to_1_2_backports.h"
#endif
namespace devilution {
// Local definition to fix compilation issue due to header conflict.
[[noreturn]] void app_fatal(string_view);
enum class LogCategory {
Application = SDL_LOG_CATEGORY_APPLICATION,
Error = SDL_LOG_CATEGORY_ERROR,
Assert = SDL_LOG_CATEGORY_ASSERT,
System = SDL_LOG_CATEGORY_SYSTEM,
Audio = SDL_LOG_CATEGORY_AUDIO,
Video = SDL_LOG_CATEGORY_VIDEO,
Render = SDL_LOG_CATEGORY_RENDER,
Input = SDL_LOG_CATEGORY_INPUT,
Test = SDL_LOG_CATEGORY_TEST,
};
constexpr auto defaultCategory = LogCategory::Application;
enum class LogPriority {
Verbose = SDL_LOG_PRIORITY_VERBOSE,
Debug = SDL_LOG_PRIORITY_DEBUG,
Info = SDL_LOG_PRIORITY_INFO,
Warn = SDL_LOG_PRIORITY_WARN,
Error = SDL_LOG_PRIORITY_ERROR,
Critical = SDL_LOG_PRIORITY_CRITICAL,
};
namespace detail {
template <typename... Args>
std::string format(string_view fmt, Args &&...args)
{
FMT_TRY
{
return fmt::format(fmt::runtime(fmt), std::forward<Args>(args)...);
}
FMT_CATCH(const fmt::format_error &e)
{
#if FMT_EXCEPTIONS
// e.what() is undefined if exceptions are disabled, so we wrap the whole block
// with an `FMT_EXCEPTIONS` check.
std::string error = StrCat("Format error, fmt: ", fmt, " error: ", e.what());
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "%s", error.c_str());
app_fatal(error);
#endif
}
}
} // namespace detail
template <typename... Args>
void Log(string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_Log("%s", str.c_str());
}
template <typename... Args>
void LogVerbose(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogVerbose(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogVerbose(string_view fmt, Args &&...args)
{
LogVerbose(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogDebug(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogDebug(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogDebug(string_view fmt, Args &&...args)
{
LogDebug(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogInfo(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogInfo(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogInfo(string_view fmt, Args &&...args)
{
LogInfo(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogWarn(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogWarn(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogWarn(string_view fmt, Args &&...args)
{
LogWarn(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogError(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogError(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogError(string_view fmt, Args &&...args)
{
LogError(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogCritical(LogCategory category, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogCritical(static_cast<int>(category), "%s", str.c_str());
}
template <typename... Args>
void LogCritical(string_view fmt, Args &&...args)
{
LogCritical(defaultCategory, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void LogMessageV(LogCategory category, LogPriority priority, string_view fmt, Args &&...args)
{
auto str = detail::format(fmt, std::forward<Args>(args)...);
SDL_LogMessageV(static_cast<int>(category), static_cast<SDL_LogPriority>(priority), "%s", str.c_str());
}
template <typename... Args>
void LogMessageV(string_view fmt, Args &&...args)
{
LogMessageV(defaultCategory, fmt, std::forward<Args>(args)...);
}
} // namespace devilution