diff --git a/example/example.cpp b/example/example.cpp index 217faa4e..4b416cd7 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -14,5 +14,5 @@ spdlog::logger *get_logger(); int main(int, char *[]) { auto *l = get_logger(); - l->info("HE LO ", "GA"); + l->info(L"HEllo {}", L"HGFS"); } \ No newline at end of file diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index d923b30f..9dd94ebe 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -79,6 +79,11 @@ bool is_color_terminal() SPDLOG_NOEXCEPT; // Detrmine if the terminal attached // Source: https://github.com/agauniyal/rang/ bool in_terminal(FILE *file) SPDLOG_NOEXCEPT; + +#if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) && defined(_WIN32) +void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target); +#endif + } // namespace os } // namespace details } // namespace spdlog diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 210f9af2..c27ddcfe 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -20,6 +20,10 @@ #include "spdlog/common.h" #include "spdlog/details/log_msg.h" +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +#include "spdlog/details/os.h" +#endif + #include #include #include @@ -52,254 +56,241 @@ public: template void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args) { - if (!should_log(lvl)) - { - return; - } + if (!should_log(lvl)) + { + return; + } - try - { - fmt::memory_buffer buf; - fmt::format_to(buf, fmt, args...); - details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } + try + { + fmt::memory_buffer buf; + fmt::format_to(buf, fmt, args...); + details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); + sink_it_(log_msg); + } + catch (const std::exception &ex) + { + err_handler_(ex.what()); + } + catch (...) + { + err_handler_("Unknown exception in logger"); + } } template void log(level::level_enum lvl, const char *fmt, const Args &... args) { - log(source_loc{}, lvl, fmt, args...); + log(source_loc{}, lvl, fmt, args...); } + void log(source_loc loc, level::level_enum lvl, const char *msg); void log(level::level_enum lvl, const char *msg); template void trace(const char *fmt, const Args &... args) { - log(level::trace, fmt, args...); + log(level::trace, fmt, args...); } template void debug(const char *fmt, const Args &... args) { - log(level::debug, fmt, args...); + log(level::debug, fmt, args...); } template void info(const char *fmt, const Args &... args) { - log(level::info, fmt, args...); + log(level::info, fmt, args...); } template void warn(const char *fmt, const Args &... args) { - log(level::warn, fmt, args...); + log(level::warn, fmt, args...); } template void error(const char *fmt, const Args &... args) { - log(level::err, fmt, args...); + log(level::err, fmt, args...); } template void critical(const char *fmt, const Args &... args) { - log(level::critical, fmt, args...); + log(level::critical, fmt, args...); } -#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT -#ifndef _WIN32 -#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows -#else - inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) - { - int wbuf_size = static_cast(wbuf.size()); - if (wbuf_size == 0) - { - return; - } - - auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL); - - if (result_size > 0) - { - target.resize(result_size); - ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL); - } - else - { - throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); - } - } - - template - void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) - { - if (!should_log(lvl)) - { - return; - } - - try - { - // format to wmemory_buffer and convert to utf8 - using details::fmt_helper::to_string_view; - fmt::wmemory_buffer wbuf; - fmt::format_to(wbuf, fmt, args...); - fmt::memory_buffer buf; - wbuf_to_utf8buf(wbuf, buf); - details::log_msg log_msg(source, &name_, lvl, to_string_view(buf)); - sink_it_(log_msg); - } - SPDLOG_CATCH_AND_HANDLE - } - - template - void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) - { - log(source_loc{}, lvl, fmt, args...); - } - - template - void trace(const wchar_t *fmt, const Args &... args) - { - log(level::trace, fmt, args...); - } - - template - void debug(const wchar_t *fmt, const Args &... args) - { - log(level::debug, fmt, args...); - } - - template - void info(const wchar_t *fmt, const Args &... args) - { - log(level::info, fmt, args...); - } - - template - void warn(const wchar_t *fmt, const Args &... args) - { - log(level::warn, fmt, args...); - } - - template - void error(const wchar_t *fmt, const Args &... args) - { - log(level::err, fmt, args...); - } - - template - void critical(const wchar_t *fmt, const Args &... args) - { - log(level::critical, fmt, args...); - } -#endif // _WIN32 -#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT template void log(level::level_enum lvl, const T &msg) { - log(source_loc{}, lvl, msg); + log(source_loc{}, lvl, msg); } // T can be statically converted to string_view template::value, T>::type * = nullptr> void log(source_loc loc, level::level_enum lvl, const T &msg) { - if (!should_log(lvl)) - { - return; - } - try - { - details::log_msg log_msg(loc, &name_, lvl, msg); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } + if (!should_log(lvl)) + { + return; + } + try + { + details::log_msg log_msg(loc, &name_, lvl, msg); + sink_it_(log_msg); + } + catch (const std::exception &ex) + { + err_handler_(ex.what()); + } + catch (...) + { + err_handler_("Unknown exception in logger"); + } } // T cannot be statically converted to string_view template::value, T>::type * = nullptr> void log(source_loc loc, level::level_enum lvl, const T &msg) { - if (!should_log(lvl)) - { - return; - } - try - { - using details::fmt_helper::to_string_view; - fmt::memory_buffer buf; - fmt::format_to(buf, "{}", msg); - details::log_msg log_msg(loc, &name_, lvl, to_string_view(buf)); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } + if (!should_log(lvl)) + { + return; + } + try + { + using details::fmt_helper::to_string_view; + fmt::memory_buffer buf; + fmt::format_to(buf, "{}", msg); + details::log_msg log_msg(loc, &name_, lvl, to_string_view(buf)); + sink_it_(log_msg); + } + catch (const std::exception &ex) + { + err_handler_(ex.what()); + } + catch (...) + { + err_handler_("Unknown exception in logger"); + } } template void trace(const T &msg) { - log(level::trace, msg); + log(level::trace, msg); } template void debug(const T &msg) { - log(level::debug, msg); + log(level::debug, msg); } template void info(const T &msg) { - log(level::info, msg); + log(level::info, msg); } template void warn(const T &msg) { - log(level::warn, msg); + log(level::warn, msg); } template void error(const T &msg) { - log(level::err, msg); + log(level::err, msg); } template void critical(const T &msg) { - log(level::critical, msg); + log(level::critical, msg); } +#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT +#ifndef _WIN32 +#error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows +#else + template + void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) + { + if (!should_log(lvl)) + { + return; + } + + try + { + // format to wmemory_buffer and convert to utf8 + fmt::wmemory_buffer wbuf; + fmt::format_to(wbuf, fmt, args...); + fmt::memory_buffer buf; + details::os::wbuf_to_utf8buf(wbuf, buf); + details::log_msg log_msg(source, &name_, lvl, string_view_t(buf.data(), buf.size())); + sink_it_(log_msg); + } + catch (const std::exception &ex) + { + err_handler_(ex.what()); + } + catch (...) + { + err_handler_("Unknown exception in logger"); + } + } + + template + void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) + { + log(source_loc{}, lvl, fmt, args...); + } + + template + void trace(const wchar_t *fmt, const Args &... args) + { + log(level::trace, fmt, args...); + } + + template + void debug(const wchar_t *fmt, const Args &... args) + { + log(level::debug, fmt, args...); + } + + template + void info(const wchar_t *fmt, const Args &... args) + { + log(level::info, fmt, args...); + } + + template + void warn(const wchar_t *fmt, const Args &... args) + { + log(level::warn, fmt, args...); + } + + template + void error(const wchar_t *fmt, const Args &... args) + { + log(level::err, fmt, args...); + } + + template + void critical(const wchar_t *fmt, const Args &... args) + { + log(level::critical, fmt, args...); + } +#endif // _WIN32 +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT + bool should_log(level::level_enum msg_level) const; void set_level(level::level_enum log_level); @@ -350,6 +341,8 @@ public: spdlog::level_t level_{spdlog::logger::default_level()}; spdlog::level_t flush_level_{level::off}; void (*custom_err_handler_)(const std::string &msg) {nullptr}; + + }; } // namespace spdlog diff --git a/src/logger.cpp b/src/logger.cpp index cc28d883..32396524 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -172,4 +172,4 @@ void spdlog::logger::err_handler_(const std::string &msg) std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg); } -} \ No newline at end of file +} diff --git a/src/os.cpp b/src/os.cpp index 6d6cad72..93738cb0 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -397,6 +397,30 @@ SPDLOG_INLINE bool in_terminal(FILE *file) SPDLOG_NOEXCEPT return isatty(fileno(file)) != 0; #endif } + +#if defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) && defined(_WIN32) +SPDLOG_INLINE void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target) +{ + int wbuf_size = static_cast(wbuf.size()); + if (wbuf_size == 0) + { + return; + } + + auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL); + + if (result_size > 0) + { + target.resize(result_size); + ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL); + } + else + { + throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); + } +} +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT) && _WIN32 + } // namespace os } // namespace details } // namespace spdlog