#pragma once #include #include 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, }; constexpr auto to_string(const LogVerbosity& verbosity) -> std::string; template inline constexpr auto log(const LogVerbosity &verbosity, std::string_view fmt, Args... args, const detail::source_location source) -> 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_stdout(const LogVerbosity& min = LogVerbosity::Info) -> void; #ifdef JOURNAL_ALL #define JOURNAL_TRACE #define JOURNAL_DEBUG #define JOURNAL_INFO #define JOURNAL_WARN #define JOURNAL_ERROR #endif #ifdef JOURNAL_TRACE template inline constexpr auto trace(std::string_view fmt, Args... args, const detail::source_location source = detail::source_location::current()) -> void { detail::log(detail::LogVerbosity::Trace, fmt, args..., source); } #else template inline constexpr auto trace(std::string_view fmt, Args... args) -> void {} #endif #ifdef JOURNAL_DEBUG template inline constexpr auto debug(std::string_view fmt, Args... args, const detail::source_location source = detail::source_location::current()) -> void { detail::log(detail::LogVerbosity::Debug, fmt, args..., source); } #else template inline constexpr auto debug(std::string_view fmt, Args... args) -> void {} #endif #ifdef JOURNAL_INFO template inline constexpr auto info(std::string_view fmt, Args... args, const detail::source_location source = detail::source_location::current()) -> void { detail::log(detail::LogVerbosity::Info, fmt, args..., source); } #else template inline constexpr auto info(std::string_view fmt, Args... args) -> void {} #endif #ifdef JOURNAL_WARN template inline constexpr auto warn(std::string_view fmt, Args... args, const detail::source_location source = detail::source_location::current()) -> void { detail::log(detail::LogVerbosity::Warn, fmt, args..., source); } #else template inline constexpr auto warn(std::string_view fmt, Args... args) -> void {} #endif #ifdef JOURNAL_ERROR template inline constexpr auto error(std::string_view fmt, Args... args, const detail::source_location source = detail::source_location::current()) -> void { detail::log(detail::LogVerbosity::Error, fmt, args..., source); } #else template inline constexpr auto error(std::string_view fmt, Args... args) -> void {} #endif } // namespace journal