249 lines
7.8 KiB
C++
249 lines
7.8 KiB
C++
#pragma once
|
|
|
|
#include "journal.hpp"
|
|
#include <format>
|
|
#include <ios>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace journal {
|
|
|
|
namespace detail {
|
|
|
|
struct source_location {
|
|
_NODISCARD static constexpr source_location
|
|
current(const uint_least32_t _Line_ = __builtin_LINE(),
|
|
const uint_least32_t _Column_ = __builtin_COLUMN(),
|
|
const char *const _File_ = __builtin_FILE(),
|
|
const char *const _Function_ = __builtin_FUNCTION()) noexcept {
|
|
source_location _Result;
|
|
_Result._Line = _Line_;
|
|
_Result._Column = _Column_;
|
|
_Result._File = _File_;
|
|
_Result._Function = _Function_;
|
|
return _Result;
|
|
}
|
|
|
|
_NODISCARD_CTOR constexpr source_location() noexcept = default;
|
|
|
|
_NODISCARD constexpr uint_least32_t line() const noexcept { return _Line; }
|
|
_NODISCARD constexpr uint_least32_t column() const noexcept {
|
|
return _Column;
|
|
}
|
|
_NODISCARD constexpr const char *file_name() const noexcept { return _File; }
|
|
_NODISCARD constexpr const char *function_name() const noexcept {
|
|
return _Function;
|
|
}
|
|
|
|
private:
|
|
uint_least32_t _Line{};
|
|
uint_least32_t _Column{};
|
|
const char *_File = "";
|
|
const char *_Function = "";
|
|
};
|
|
|
|
enum LogVerbosity {
|
|
Trace,
|
|
Debug,
|
|
Info,
|
|
Warn,
|
|
Error,
|
|
};
|
|
|
|
struct Verbosity {
|
|
journal::detail::LogVerbosity inner;
|
|
|
|
Verbosity(journal::detail::LogVerbosity &&value) : inner(value) {}
|
|
Verbosity(const journal::detail::LogVerbosity &value) : inner(value) {}
|
|
|
|
auto operator<=>(const Verbosity &rhs) const -> std::strong_ordering {
|
|
return static_cast<std::underlying_type_t<decltype(inner)>>(inner) <=>
|
|
static_cast<std::underlying_type_t<decltype(rhs.inner)>>(rhs.inner);
|
|
}
|
|
};
|
|
|
|
constexpr auto to_string(const LogVerbosity& verbosity) -> std::string;
|
|
|
|
namespace formatter {
|
|
|
|
struct Formatter {
|
|
virtual auto operator()(const Verbosity &verbosity,
|
|
const source_location &source) -> std::string = 0;
|
|
virtual ~Formatter() {}
|
|
};
|
|
|
|
} // namespace formatter
|
|
|
|
template <typename... Args>
|
|
inline constexpr auto log(const LogVerbosity &verbosity,
|
|
const detail::source_location &source,
|
|
std::string_view fmt, Args... args) -> void {
|
|
const auto msg = std::vformat(fmt, std::make_format_args(args...));
|
|
log_internal(verbosity, source, msg);
|
|
}
|
|
|
|
auto log_internal(const LogVerbosity &verbosity,
|
|
const detail::source_location source, const std::string &msg)
|
|
-> void;
|
|
|
|
} // namespace detail
|
|
|
|
using detail::LogVerbosity;
|
|
|
|
auto init_std_out(const LogVerbosity &min = LogVerbosity::Info) -> void;
|
|
auto init_std_out_err(const LogVerbosity &min = LogVerbosity::Info) -> void;
|
|
auto init() -> void;
|
|
auto init_no_threads() -> void;
|
|
auto set_formatter(std::unique_ptr<detail::formatter::Formatter> &&formatter)
|
|
-> void;
|
|
auto add_std_out() -> void;
|
|
auto add_std_err() -> void;
|
|
auto add_file(std::string_view file_path,
|
|
std::ios_base::openmode = std::ios_base::ate,
|
|
const LogVerbosity &min = LogVerbosity::Trace,
|
|
const LogVerbosity &max = LogVerbosity::Error) -> void;
|
|
auto add_sink(std::shared_ptr<std::ostream> stream,
|
|
const LogVerbosity &min = LogVerbosity::Trace,
|
|
const LogVerbosity &max = LogVerbosity::Error) -> void;
|
|
|
|
template <typename T> inline constexpr auto ptr(T *p) -> const void * {
|
|
return reinterpret_cast<void *>(p);
|
|
}
|
|
|
|
/// JOURNAL_NONE: undefines all logs
|
|
/// JOURNAL_ALL: defines all logs, on by default
|
|
/// JOURNAL_NOT_ALL: does not define any logs by default even it JOURNAL_ALL is
|
|
/// defined, off by default
|
|
#if defined(JOURNAL_ALL) && !defined(JOURNAL_NONE) && !defined(JOURNAL_NOT_ALL)
|
|
#define JOURNAL_TRACE
|
|
#define JOURNAL_DEBUG
|
|
#define JOURNAL_INFO
|
|
#define JOURNAL_WARN
|
|
#define JOURNAL_ERROR
|
|
#endif
|
|
|
|
#if defined(JOURNAL_NONE)
|
|
#undef JOURNAL_TRACE
|
|
#undef JOURNAL_DEBUG
|
|
#undef JOURNAL_INFO
|
|
#undef JOURNAL_WARN
|
|
#undef JOURNAL_ERROR
|
|
#endif
|
|
|
|
#ifdef JOURNAL_TRACE
|
|
template <typename... Ts> struct trace {
|
|
trace(std::string_view fmt, Ts &&...args,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) {
|
|
detail::log(detail::LogVerbosity::Trace, source, fmt,
|
|
std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
template <typename... Ts> trace(std::string_view, Ts &&...) -> trace<Ts...>;
|
|
#else
|
|
template <typename... Args>
|
|
inline constexpr auto trace(std::string_view fmt, Args... args) -> void {}
|
|
#endif
|
|
|
|
#ifdef JOURNAL_DEBUG
|
|
template <typename... Ts> struct debug {
|
|
debug(std::string_view fmt, Ts &&...args,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) {
|
|
detail::log(detail::LogVerbosity::Debug, source, fmt,
|
|
std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
template <typename... Ts> debug(std::string_view, Ts &&...) -> debug<Ts...>;
|
|
#else
|
|
template <typename... Args>
|
|
inline constexpr auto debug(std::string_view fmt, Args... args) -> void {}
|
|
#endif
|
|
|
|
#ifdef JOURNAL_INFO
|
|
template <typename... Ts> struct info {
|
|
info(std::string_view fmt, Ts &&...args,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) {
|
|
detail::log(detail::LogVerbosity::Info, source, fmt,
|
|
std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
template <typename... Ts>
|
|
info(std::string_view, Ts &&...) -> info<Ts...>;
|
|
#else
|
|
template <typename... Args>
|
|
inline constexpr auto info(std::string_view fmt, Args... args) -> void {}
|
|
#endif
|
|
|
|
#ifdef JOURNAL_WARN
|
|
template <typename... Ts> struct warn {
|
|
warn(std::string_view fmt, Ts &&...args,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) {
|
|
detail::log(detail::LogVerbosity::Warn, source, fmt,
|
|
std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
template <typename... Ts> warn(std::string_view, Ts &&...) -> warn<Ts...>;
|
|
#else
|
|
template <typename... Args>
|
|
inline constexpr auto warn(std::string_view fmt, Args... args) -> void {}
|
|
#endif
|
|
|
|
#ifdef JOURNAL_ERROR
|
|
template <typename... Ts> struct error {
|
|
error(std::string_view fmt, Ts &&...args,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) {
|
|
detail::log(detail::LogVerbosity::Error, source, fmt,
|
|
std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
template <typename... Ts> error(std::string_view, Ts &&...) -> error<Ts...>;
|
|
#else
|
|
template <typename... Args>
|
|
inline constexpr auto error(std::string_view fmt, Args... args) -> void {}
|
|
#endif
|
|
|
|
} // namespace journal
|
|
|
|
/// JOURNAL_GLOG_COMPAT: enables LOG_F macro format which GLOG and Loguru use
|
|
/// for compatibility, on by default
|
|
#if defined(JOURNAL_GLOG_COMPAT)
|
|
namespace journal {
|
|
constexpr auto JournalGLogVerbosity_ERROR = detail::LogVerbosity::Error;
|
|
constexpr auto JournalGLogVerbosity_WARNING = detail::LogVerbosity::Warn;
|
|
constexpr auto JournalGLogVerbosity_WARN = detail::LogVerbosity::Warn;
|
|
constexpr auto JournalGLogVerbosity_INFO = detail::LogVerbosity::Info;
|
|
constexpr auto JournalGLogVerbosity_DEBUG = detail::LogVerbosity::Debug;
|
|
constexpr auto JournalGLogVerbosity_TRACE = detail::LogVerbosity::Trace;
|
|
|
|
struct GLogCompatHelper {
|
|
const detail::source_location source;
|
|
const detail::LogVerbosity verbosity;
|
|
|
|
consteval GLogCompatHelper(const detail::LogVerbosity &verbosity,
|
|
const detail::source_location &source =
|
|
detail::source_location::current()) noexcept
|
|
: source(source), verbosity(verbosity) {}
|
|
|
|
template <typename... Ts>
|
|
auto log(std::string_view fmt, Ts &&...args) const -> void {
|
|
detail::log(verbosity, source, fmt, std::forward<Ts>(args)...);
|
|
}
|
|
};
|
|
|
|
} // namespace journal
|
|
|
|
#define LOG_F(V, ...) \
|
|
journal::GLogCompatHelper(journal::JournalGLogVerbosity_##V, \
|
|
journal::detail::source_location::current()) \
|
|
.log(__VA_ARGS__);
|
|
#endif |