mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
133 lines
5 KiB
C++
133 lines
5 KiB
C++
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <format>
|
|
#include <string>
|
|
|
|
#include "unicode.h"
|
|
|
|
namespace logging {
|
|
enum class Level : int {
|
|
Verbose = 0,
|
|
Debug = 1,
|
|
Info = 2,
|
|
Warning = 3,
|
|
Error = 4,
|
|
Fatal = 5,
|
|
};
|
|
|
|
enum FastFailErrorCode : int {
|
|
Unspecified = 12345,
|
|
MinHookUnload,
|
|
};
|
|
|
|
/**
|
|
* @brief Starts writing log to specified file.
|
|
*/
|
|
void start_file_logging(const std::filesystem::path& logPath, bool redirect_stderrout = false);
|
|
|
|
/**
|
|
* @brief Marks this DLL either as loaded or unloaded, top prevent accessing handles when the DLL is not loaded.
|
|
*/
|
|
void update_dll_load_status(bool loaded);
|
|
|
|
/**
|
|
* @brief Prints log, unformatted.
|
|
* @param level Log level.
|
|
* @param s Log to print, as a C-string.
|
|
*/
|
|
template<typename TElem>
|
|
void print(Level level, const TElem* s) { print(level, unicode::convert<std::string>(s).c_str()); }
|
|
|
|
/**
|
|
* @brief Prints log, unformatted.
|
|
* @param level Log level.
|
|
* @param s Log to print, as a basic_string.
|
|
*/
|
|
template<typename TElem, typename TTraits = std::char_traits<TElem>, typename TAlloc = std::allocator<TElem>>
|
|
void print(Level level, const std::basic_string<TElem, TTraits, TAlloc>& s) { print(level, s.c_str()); }
|
|
|
|
/**
|
|
* @brief Prints log, unformatted.
|
|
* @param level Log level.
|
|
* @param s Log to print, as a basic_string_view.
|
|
*/
|
|
template<typename TElem, typename TTraits = std::char_traits<TElem>>
|
|
void print(Level level, const std::basic_string_view<TElem, TTraits>& s) { print(level, unicode::convert<std::string>(s).c_str()); }
|
|
|
|
template<>
|
|
void print<char>(Level level, const char* s);
|
|
|
|
template<typename>
|
|
struct is_basic_string : std::false_type {};
|
|
|
|
template<typename TElem, typename TTraits, typename TAlloc>
|
|
struct is_basic_string<std::basic_string<TElem, TTraits, TAlloc>> : std::true_type {};
|
|
|
|
template<typename T>
|
|
inline constexpr auto is_basic_string_v = is_basic_string<T>::value;
|
|
|
|
template<typename>
|
|
struct is_basic_string_view : std::false_type {};
|
|
|
|
template<typename TElem, typename TTraits, typename TAlloc>
|
|
struct is_basic_string_view<std::basic_string<TElem, TTraits, TAlloc>> : std::true_type {};
|
|
|
|
template<typename T>
|
|
inline constexpr auto is_basic_string_view_v = is_basic_string_view<T>::value;
|
|
|
|
template<typename T>
|
|
auto to_format_arg(T&& x) {
|
|
using Td = std::remove_cvref_t<T>;
|
|
if constexpr (std::is_pointer_v<Td>) {
|
|
using Tdd = std::remove_cvref_t<std::remove_pointer_t<Td>>;
|
|
if constexpr (std::is_same_v<Tdd, wchar_t> || std::is_same_v<Tdd, char8_t> || std::is_same_v<Tdd, char16_t> || std::is_same_v<Tdd, char32_t>)
|
|
return unicode::convert<std::string>(x);
|
|
else
|
|
return std::forward<T>(x);
|
|
|
|
} else {
|
|
if constexpr (is_basic_string_v<Td> || is_basic_string_view_v<Td>) {
|
|
using Tdd = Td::value_type;
|
|
if constexpr (std::is_same_v<Tdd, wchar_t> || std::is_same_v<Tdd, char8_t> || std::is_same_v<Tdd, char16_t> || std::is_same_v<Tdd, char32_t>)
|
|
return unicode::convert<std::string>(x);
|
|
else
|
|
return std::forward<T>(x);
|
|
|
|
} else if constexpr (std::is_same_v<Td, std::filesystem::path>) {
|
|
auto u8s = x.u8string();
|
|
return std::move(*reinterpret_cast<std::string*>(&u8s));
|
|
|
|
} else {
|
|
return std::forward<T>(x);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Prints log, formatted.
|
|
* @param level Log level.
|
|
* @param fmt C-string.
|
|
* @param arg1 First format parameter.
|
|
* @param args Second and further format parameters, if any.
|
|
*/
|
|
template<typename Arg, typename... Args>
|
|
void print(Level level, const char* fmt, Arg&& arg1, Args&&... args) {
|
|
// make_format_args only accepts references now due to https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2905r2.html
|
|
// we can switch std::runtime_format in C++26 :) https://isocpp.org/files/papers/P2918R0.html
|
|
auto transformed_args = std::make_tuple(to_format_arg(arg1), to_format_arg(args)...);
|
|
auto format_args = std::apply(
|
|
[&](auto&... elems) { return std::make_format_args(elems...); },
|
|
transformed_args
|
|
);
|
|
|
|
print(level, std::vformat(fmt, format_args));
|
|
}
|
|
|
|
template<typename...Args> void V(Args&&...args) { print(Level::Verbose, std::forward<Args>(args)...); }
|
|
template<typename...Args> void D(Args&&...args) { print(Level::Debug, std::forward<Args>(args)...); }
|
|
template<typename...Args> void I(Args&&...args) { print(Level::Info, std::forward<Args>(args)...); }
|
|
template<typename...Args> void W(Args&&...args) { print(Level::Warning, std::forward<Args>(args)...); }
|
|
template<typename...Args> void E(Args&&...args) { print(Level::Error, std::forward<Args>(args)...); }
|
|
template<typename...Args> void F(Args&&...args) { print(Level::Fatal, std::forward<Args>(args)...); }
|
|
}
|