diff --git a/src/celengine/dsodb.cpp b/src/celengine/dsodb.cpp index c17eb5e02e..ec5ab64e83 100644 --- a/src/celengine/dsodb.cpp +++ b/src/celengine/dsodb.cpp @@ -230,7 +230,7 @@ bool DSODatabase::load(std::istream& in, const fs::path& resourcePath) const Hash* objParams = objParamsValue.getHash(); if (objParams == nullptr) { - GetLogger()->error("Error parsing deep sky catalog entry {}\n", objName.c_str()); + GetLogger()->error("Error parsing deep sky catalog entry {}\n", objName); return false; } diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index f5f3da30ca..47b408d799 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -2698,7 +2698,7 @@ void CelestiaCore::fatalError(const string& msg, bool visual) if (visual) flash(msg); else - GetLogger()->error(msg.c_str()); + GetLogger()->error(msg); } else { diff --git a/src/celutil/logger.cpp b/src/celutil/logger.cpp index 8dd5a848e5..c1bcab197a 100644 --- a/src/celutil/logger.cpp +++ b/src/celutil/logger.cpp @@ -9,48 +9,74 @@ // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. +#include #include +#include #ifdef _MSC_VER -#include +# include #endif -#include #include "logger.h" +#include + namespace celestia::util { -Logger* Logger::g_logger = nullptr; +namespace +{ +std::unique_ptr globalLogger = nullptr; +} -Logger* GetLogger() +Logger * +GetLogger() { - return Logger::g_logger; + return globalLogger.get(); } -Logger* CreateLogger(Level level) +Logger * +CreateLogger(Level level) { return CreateLogger(level, std::clog, std::cerr); } -Logger* CreateLogger(Level level, Logger::Stream &log, Logger::Stream &err) +Logger * +CreateLogger(Level level, Logger::Stream &log, Logger::Stream &err) { - if (Logger::g_logger == nullptr) - Logger::g_logger = new Logger(level, log, err); - return Logger::g_logger; + if (globalLogger == nullptr) + { + globalLogger = std::make_unique(level, log, err); + std::atexit(DestroyLogger); + } + return globalLogger.get(); } -void DestroyLogger() +void +DestroyLogger() { - delete Logger::g_logger; + globalLogger = nullptr; } Logger::Logger() : - m_log(std::clog), - m_err(std::cerr) + Logger(Level::Info, std::clog, std::cerr) +{ +} + +Logger::Logger(Level level, Stream &log, Stream &err) : + m_log(log), + m_err(err), + m_level(level) +{ +} + +void +Logger::setLevel(Level level) { + m_level = level; } -void Logger::vlog(Level level, fmt::string_view format, fmt::format_args args) const +void +Logger::vlog(Level level, std::string_view format, fmt::format_args args) const { #ifdef _MSC_VER if (level == Level::Debug && IsDebuggerPresent()) diff --git a/src/celutil/logger.h b/src/celutil/logger.h index ea5ba85ccf..e07e11153a 100644 --- a/src/celutil/logger.h +++ b/src/celutil/logger.h @@ -1,6 +1,6 @@ // logger.h // -// Copyright (C) 2021, Celestia Development Team +// Copyright (C) 2021-present, Celestia Development Team // // Logging functions. // @@ -11,20 +11,17 @@ #pragma once +#include +#include #include #include +#include -#include - -#include - -template <> -struct fmt::formatter : formatter +template<> struct fmt::formatter : formatter { - template - auto format(const fs::path &path, FormatContext &ctx) + template auto format(const fs::path &path, FormatContext &ctx) { - return formatter::format(path.string(), ctx); + return formatter::format(path.u8string(), ctx); } }; @@ -42,91 +39,111 @@ enum class Level class Logger { - public: +public: using Stream = std::basic_ostream; + /** Create a default logger with Info verbocity writing to std::clog and std::cerr */ Logger(); - Logger(Level level, Stream &log, Stream &err) : - m_log(log), - m_err(err), - m_level(level) - {} - void setLevel(Level level) - { - m_level = level; - } + /** + * Create a logger with custom verbocity and output streams + * @param level verbosibility level + * @param log stream used to output normal messages + * @param err stream used to output errors, warnings and debug messages + */ + Logger(Level level, Stream &log, Stream &err); - template inline void - debug(const char *format, const Args&... args) const; + /** + * Set verbocity level + * + * @param level verbosibility level + */ + void setLevel(Level level); - template inline void - info(const char *format, const Args&... args) const; + template + inline void debug(std::string_view format, const Args &...args) const; - template inline void - verbose(const char *format, const Args&... args) const; + template + inline void info(std::string_view format, const Args &...args) const; - template inline void - warn(const char *format, const Args&... args) const; + template + inline void verbose(std::string_view format, const Args &...args) const; - template inline void - error(const char *format, const Args&... args) const; + template + inline void warn(std::string_view format, const Args &...args) const; - template void - log(Level, const char *format, const Args&... args) const; + template + inline void error(std::string_view format, const Args &...args) const; - static Logger* g_logger; + template + void log(Level, std::string_view format, const Args &...args) const; - private: - void vlog(Level level, fmt::string_view format, fmt::format_args args) const; +private: + void vlog(Level level, std::string_view format, fmt::format_args args) const; Stream &m_log; Stream &m_err; - Level m_level { Level::Info }; + Level m_level; }; -template void -Logger::log(Level level, const char *format, const Args&... args) const +template void +Logger::log(Level level, std::string_view format, const Args &...args) const { if (level <= m_level) - vlog(level, fmt::string_view(format), fmt::make_format_args(args...)); + vlog(level, format, fmt::make_format_args(args...)); } -template void -Logger::debug(const char *format, const Args&... args) const +template void +Logger::debug(std::string_view format, const Args &...args) const { log(Level::Debug, format, args...); } -template inline void -Logger::info(const char *format, const Args&... args) const +template inline void +Logger::info(std::string_view format, const Args &...args) const { log(Level::Info, format, args...); } -template inline void -Logger::verbose(const char *format, const Args&... args) const +template inline void +Logger::verbose(std::string_view format, const Args &...args) const { log(Level::Verbose, format, args...); } -template inline void -Logger::warn(const char *format, const Args&... args) const +template inline void +Logger::warn(std::string_view format, const Args &...args) const { log(Level::Warning, format, args...); } -template inline void -Logger::error(const char *format, const Args&... args) const +template inline void +Logger::error(std::string_view format, const Args &...args) const { log(Level::Error, format, args...); } -Logger* GetLogger(); -Logger* CreateLogger(Level level = Level::Info); -Logger* CreateLogger(Level level, - Logger::Stream &log, - Logger::Stream &err); +/** Return a pointer to the default global Logger instance */ +Logger *GetLogger(); + +/** + * Initiliaze the default global Logger instance writing to std::clog and std::cerr + * + * @param level verbosibility level + * @return pointer to the default global Logger instance + */ +Logger *CreateLogger(Level level = Level::Info); + +/** + * Initiliaze the default global Logger instance writing to custom streams + * + * @param level verbosibility level + * @param log stream used to output normal messages + * @param err stream used to output errors, warnings and debug messages +*/ +Logger *CreateLogger(Level level, Logger::Stream &log, Logger::Stream &err); + +/** Destroy the default global Logger instance */ void DestroyLogger(); } // end namespace celestia::util