diff --git a/CMakeLists.txt b/CMakeLists.txt index 5164609b..b4fe429d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # cmake_minimum_required(VERSION 3.1) -project(spdlog VERSION 0.16.3) +project(spdlog VERSION 0.16.3 LANGUAGES CXX) include(CTest) include(CMakeDependentOption) include(GNUInstallDirs) @@ -73,7 +73,6 @@ configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY) install( TARGETS spdlog EXPORT "${targets_export_name}" - INCLUDES DESTINATION "${include_install_dir}" ) # install headers diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 7859e4d5..cc699729 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,49 +1,49 @@ -# *************************************************************************/ -# * Copyright (c) 2015 Ruslan Baratov. */ -# * */ -# * Permission is hereby granted, free of charge, to any person obtaining */ -# * a copy of this software and associated documentation files (the */ -# * "Software"), to deal in the Software without restriction, including */ -# * without limitation the rights to use, copy, modify, merge, publish, */ -# * distribute, sublicense, and/or sell copies of the Software, and to */ -# * permit persons to whom the Software is furnished to do so, subject to */ -# * the following conditions: */ -# * */ -# * The above copyright notice and this permission notice shall be */ -# * included in all copies or substantial portions of the Software. */ -# * */ -# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -# *************************************************************************/ - -cmake_minimum_required(VERSION 3.0) -project(SpdlogExamples) - -if(TARGET spdlog) - # Part of the main project - add_library(spdlog::spdlog ALIAS spdlog) -else() - # Stand-alone build - find_package(spdlog CONFIG REQUIRED) -endif() - -find_package(Threads) - -add_executable(example example.cpp) -target_link_libraries(example spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) - -add_executable(benchmark bench.cpp) -target_link_libraries(benchmark spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) - -add_executable(multisink multisink.cpp) -target_link_libraries(multisink spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT}) - -enable_testing() -file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") -add_test(NAME RunExample COMMAND example) -add_test(NAME RunBenchmark COMMAND benchmark) +# *************************************************************************/ +# * Copyright (c) 2015 Ruslan Baratov. */ +# * */ +# * Permission is hereby granted, free of charge, to any person obtaining */ +# * a copy of this software and associated documentation files (the */ +# * "Software"), to deal in the Software without restriction, including */ +# * without limitation the rights to use, copy, modify, merge, publish, */ +# * distribute, sublicense, and/or sell copies of the Software, and to */ +# * permit persons to whom the Software is furnished to do so, subject to */ +# * the following conditions: */ +# * */ +# * The above copyright notice and this permission notice shall be */ +# * included in all copies or substantial portions of the Software. */ +# * */ +# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +# *************************************************************************/ + +cmake_minimum_required(VERSION 3.1) +project(SpdlogExamples CXX) + +if(TARGET spdlog) + # Part of the main project + add_library(spdlog::spdlog ALIAS spdlog) +else() + # Stand-alone build + find_package(spdlog CONFIG REQUIRED) +endif() + +find_package(Threads REQUIRED) + +add_executable(example example.cpp) +target_link_libraries(example spdlog::spdlog Threads::Threads) + +add_executable(benchmark bench.cpp) +target_link_libraries(benchmark spdlog::spdlog Threads::Threads) + +add_executable(multisink multisink.cpp) +target_link_libraries(multisink spdlog::spdlog Threads::Threads) + +enable_testing() +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") +add_test(NAME RunExample COMMAND example) +add_test(NAME RunBenchmark COMMAND benchmark) diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index e9fcd5f4..be577a3b 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -31,15 +31,15 @@ namespace details class async_log_helper; } -class async_logger SPDLOG_FINAL :public logger +class async_logger SPDLOG_FINAL : public logger { public: template - async_logger(const std::string& name, + async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); @@ -55,7 +55,7 @@ public: async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, - const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, + const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); @@ -65,8 +65,8 @@ public: void flush() override; // Error handler - virtual void set_error_handler(log_err_handler) override; - virtual log_err_handler error_handler() override; + void set_error_handler(log_err_handler) override; + log_err_handler error_handler() override; protected: void _sink_it(details::log_msg& msg) override; @@ -78,5 +78,4 @@ private: }; } - #include "details/async_logger_impl.h" diff --git a/include/spdlog/common.h b/include/spdlog/common.h index 13a3f39a..cad705f9 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -5,6 +5,10 @@ #pragma once +#define SPDLOG_VERSION "0.16.3" + +#include "tweakme.h" + #include #include #include @@ -74,7 +78,7 @@ using log_err_handler = std::function; //Log level enum namespace level { -typedef enum +enum level_enum { trace = 0, debug = 1, @@ -83,10 +87,10 @@ typedef enum err = 4, critical = 5, off = 6 -} level_enum; +}; #if !defined(SPDLOG_LEVEL_NAMES) -#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "critical", "off" } +#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "critical", "off" } #endif static const char* level_names[] SPDLOG_LEVEL_NAMES; @@ -115,7 +119,6 @@ inline spdlog::level::level_enum to_level_enum(const char* name) using level_hasher = std::hash; } //level - // // Async overflow policy - block by default. // @@ -145,22 +148,24 @@ namespace os std::string errno_str(int err_num); } } -class spdlog_ex: public std::exception +class spdlog_ex : public std::exception { public: - spdlog_ex(const std::string& msg):_msg(msg) + explicit spdlog_ex(std::string msg) : _msg(std::move(msg)) {} + spdlog_ex(const std::string& msg, int last_errno) { _msg = msg + ": " + details::os::errno_str(last_errno); } + const char* what() const SPDLOG_NOEXCEPT override { return _msg.c_str(); } + private: std::string _msg; - }; // @@ -172,5 +177,4 @@ using filename_t = std::wstring; using filename_t = std::string; #endif - } //spdlog diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index bba9bc0e..6faf2f7c 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -43,6 +43,7 @@ class async_log_helper flush, terminate }; + struct async_msg { std::string logger_name; @@ -56,8 +57,14 @@ class async_log_helper async_msg() = default; ~async_msg() = default; + explicit async_msg(async_msg_type m_type) : + level(level::info), + thread_id(0), + msg_type(m_type), + msg_id(0) + {} -async_msg(async_msg&& other) SPDLOG_NOEXCEPT: +async_msg(async_msg&& other) SPDLOG_NOEXCEPT : logger_name(std::move(other.logger_name)), level(std::move(other.level)), time(std::move(other.time)), @@ -67,13 +74,6 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: msg_id(other.msg_id) {} - async_msg(async_msg_type m_type): - level(level::info), - thread_id(0), - msg_type(m_type), - msg_id(0) - {} - async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT { logger_name = std::move(other.logger_name); @@ -91,7 +91,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: async_msg& operator=(const async_msg& other) = delete; // construct from log_msg - async_msg(const details::log_msg& m): + explicit async_msg(const details::log_msg& m): level(m.level), time(m.time), thread_id(m.thread_id), @@ -104,7 +104,6 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: #endif } - // copy into log_msg void fill_log_msg(log_msg &msg) { @@ -118,28 +117,29 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT: }; public: - using item_type = async_msg; using q_type = details::mpmc_bounded_queue; using clock = std::chrono::steady_clock; - async_log_helper(formatter_ptr formatter, - const std::vector& sinks, + std::vector sinks, size_t queue_size, const log_err_handler err_handler, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, - const std::function& worker_warmup_cb = nullptr, + std::function worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), - const std::function& worker_teardown_cb = nullptr); + std::function worker_teardown_cb = nullptr); void log(const details::log_msg& msg); // stop logging and join the back thread ~async_log_helper(); - void set_formatter(formatter_ptr); + async_log_helper(const async_log_helper&) = delete; + async_log_helper& operator=(const async_log_helper&) = delete; + + void set_formatter(formatter_ptr msg_formatter); void flush(bool wait_for_q); @@ -158,7 +158,6 @@ private: bool _terminate_requested; - // overflow policy const async_overflow_policy _overflow_policy; @@ -200,25 +199,26 @@ private: /////////////////////////////////////////////////////////////////////////////// inline spdlog::details::async_log_helper::async_log_helper( formatter_ptr formatter, - const std::vector& sinks, + std::vector sinks, size_t queue_size, log_err_handler err_handler, const async_overflow_policy overflow_policy, - const std::function& worker_warmup_cb, + std::function worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, - const std::function& worker_teardown_cb): - _formatter(formatter), - _sinks(sinks), + std::function worker_teardown_cb): + _formatter(std::move(formatter)), + _sinks(std::move(sinks)), _q(queue_size), - _err_handler(err_handler), + _err_handler(std::move(err_handler)), _flush_requested(false), _terminate_requested(false), _overflow_policy(overflow_policy), - _worker_warmup_cb(worker_warmup_cb), + _worker_warmup_cb(std::move(worker_warmup_cb)), _flush_interval_ms(flush_interval_ms), - _worker_teardown_cb(worker_teardown_cb), - _worker_thread(&async_log_helper::worker_loop, this) -{} + _worker_teardown_cb(std::move(worker_teardown_cb)) +{ + _worker_thread = std::thread(&async_log_helper::worker_loop, this); +} // Send to the worker thread termination message(level=off) // and wait for it to finish gracefully @@ -327,13 +327,10 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_ // Handle empty queue.. // This is the only place where the queue can terminate or flush to avoid losing messages already in the queue - else - { - auto now = details::os::now(); - handle_flush_interval(now, last_flush); - sleep_or_yield(now, last_pop); - return !_terminate_requested; - } + auto now = details::os::now(); + handle_flush_interval(now, last_flush); + sleep_or_yield(now, last_pop); + return !_terminate_requested; } // flush all sinks if _flush_interval_ms has expired @@ -351,10 +348,9 @@ inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock:: inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter) { - _formatter = msg_formatter; + _formatter = std::move(msg_formatter); } - // spin, yield or sleep. use the time passed since last message as a hint inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time) { @@ -391,8 +387,5 @@ inline void spdlog::details::async_log_helper::wait_empty_q() inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler) { - _err_handler = err_handler; + _err_handler = std::move(err_handler); } - - - diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 83732117..72bd4f98 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -21,7 +21,7 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size, - const async_overflow_policy overflow_policy, + const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) : @@ -33,7 +33,7 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks_list, size_t queue_size, - const async_overflow_policy overflow_policy, + const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) : @@ -42,13 +42,13 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, - const async_overflow_policy overflow_policy, + const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) : async_logger(logger_name, { - single_sink + std::move(single_sink) }, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {} diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index dff788ff..d7ccf59b 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -31,9 +31,7 @@ public: const int open_tries = 5; const int open_interval = 10; - explicit file_helper() : - _fd(nullptr) - {} + explicit file_helper() = default; file_helper(const file_helper&) = delete; file_helper& operator=(const file_helper&) = delete; @@ -46,7 +44,6 @@ public: void open(const filename_t& fname, bool truncate = false) { - close(); auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); _filename = fname; @@ -76,7 +73,7 @@ public: void close() { - if (_fd) + if (_fd != nullptr) { std::fclose(_fd); _fd = nullptr; @@ -93,8 +90,10 @@ public: size_t size() const { - if (!_fd) + if (_fd == nullptr) + { throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); + } return os::filesize(_fd); } @@ -137,8 +136,9 @@ public: // finally - return a valid base and extension tuple return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); } + private: - FILE* _fd; + FILE* _fd{ nullptr }; filename_t _filename; }; } diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index a9fe9201..8b441cab 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -8,7 +8,6 @@ #include "../common.h" #include "../details/os.h" - #include #include @@ -21,8 +20,7 @@ struct log_msg log_msg() = default; log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), - level(lvl), - msg_id(0) + level(lvl) { #ifndef SPDLOG_NO_DATETIME time = os::now(); @@ -33,18 +31,18 @@ struct log_msg #endif } - log_msg(const log_msg& other) = delete; + log_msg(const log_msg& other) = delete; log_msg& operator=(log_msg&& other) = delete; log_msg(log_msg&& other) = delete; - const std::string *logger_name; + const std::string *logger_name{ nullptr }; level::level_enum level; log_clock::time_point time; size_t thread_id; fmt::MemoryWriter raw; fmt::MemoryWriter formatted; - size_t msg_id; + size_t msg_id{ 0 }; }; } } diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 88044747..11cbc7e4 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -14,14 +14,14 @@ // create logger with given name, sinks and the default pattern formatter // all other ctors will call this one template -inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end): - _name(logger_name), +inline spdlog::logger::logger(std::string logger_name, const It& begin, const It& end): + _name(std::move(logger_name)), _sinks(begin, end), _formatter(std::make_shared("%+")), _level(level::info), _flush_level(level::off), _last_err_time(0), - _msg_counter(1) // message counter will start from 1. 0-message id will be reserved for controll messages + _msg_counter(1) // message counter will start from 1. 0-message id will be reserved for controll messages { _err_handler = [this](const std::string &msg) { @@ -39,7 +39,7 @@ inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list si inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink): logger(logger_name, { - single_sink + std::move(single_sink) }) {} @@ -49,7 +49,7 @@ inline spdlog::logger::~logger() = default; inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter) { - _set_formatter(msg_formatter); + _set_formatter(std::move(msg_formatter)); } inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time_type pattern_time) @@ -281,7 +281,7 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level) inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler) { - _err_handler = err_handler; + _err_handler = std::move(err_handler); } inline spdlog::log_err_handler spdlog::logger::error_handler() @@ -289,7 +289,6 @@ inline spdlog::log_err_handler spdlog::logger::error_handler() return _err_handler; } - inline void spdlog::logger::flush_on(level::level_enum log_level) { _flush_level.store(log_level); @@ -330,9 +329,10 @@ inline void spdlog::logger::_set_pattern(const std::string& pattern, pattern_tim { _formatter = std::make_shared(pattern, pattern_time); } + inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) { - _formatter = msg_formatter; + _formatter = std::move(msg_formatter); } inline void spdlog::logger::flush() @@ -349,8 +349,8 @@ inline void spdlog::logger::_default_err_handler(const std::string &msg) auto tm_time = details::os::localtime(now); char date_buf[100]; std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time); - details::log_msg err_msg; - err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol); + details::log_msg err_msg; + err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::default_eol); sinks::stderr_sink_mt::instance()->log(err_msg); _last_err_time = now; } diff --git a/include/spdlog/details/mpmc_bounded_q.h b/include/spdlog/details/mpmc_bounded_q.h index 102df855..6187f3b9 100644 --- a/include/spdlog/details/mpmc_bounded_q.h +++ b/include/spdlog/details/mpmc_bounded_q.h @@ -53,13 +53,13 @@ namespace spdlog namespace details { -template +template class mpmc_bounded_queue { public: - using item_type = T; - mpmc_bounded_queue(size_t buffer_size) + + explicit mpmc_bounded_queue(size_t buffer_size) :max_size_(buffer_size), buffer_(new cell_t[buffer_size]), buffer_mask_(buffer_size - 1) @@ -79,6 +79,8 @@ public: delete[] buffer_; } + mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; + void operator=(mpmc_bounded_queue const&) = delete; bool enqueue(T&& data) { @@ -157,7 +159,7 @@ private: size_t const max_size_; static size_t const cacheline_size = 64; - typedef char cacheline_pad_t[cacheline_size]; + using cacheline_pad_t = char[cacheline_size]; cacheline_pad_t pad0_; cell_t* const buffer_; @@ -167,9 +169,6 @@ private: cacheline_pad_t pad2_; std::atomic dequeue_pos_; cacheline_pad_t pad3_; - - mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; - void operator= (mpmc_bounded_queue const&) = delete; }; } // ns details diff --git a/include/spdlog/details/null_mutex.h b/include/spdlog/details/null_mutex.h index 67b0aeee..82b0ed84 100644 --- a/include/spdlog/details/null_mutex.h +++ b/include/spdlog/details/null_mutex.h @@ -27,7 +27,7 @@ struct null_atomic_int int value; null_atomic_int() = default; - null_atomic_int(int val):value(val) + explicit null_atomic_int(int val) : value(val) {} int load(std::memory_order) const diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index b881cae4..4de7b9f8 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -96,7 +96,6 @@ inline std::tm localtime() return localtime(now_t); } - inline std::tm gmtime(const std::time_t &time_tt) { @@ -140,8 +139,7 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2) #endif #endif -SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL; -SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1; +SPDLOG_CONSTEXPR static const char* default_eol = SPDLOG_EOL; @@ -155,10 +153,13 @@ SPDLOG_CONSTEXPR static const char folder_sep = '/'; inline void prevent_child_fd(FILE *f) { + #ifdef _WIN32 +#if !defined(__cplusplus_winrt) auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) throw spdlog_ex("SetHandleInformation failed", errno); +#endif #else auto fd = fileno(f); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) @@ -168,7 +169,7 @@ inline void prevent_child_fd(FILE *f) //fopen_s on non windows for writing -inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode) +inline bool fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode) { #ifdef _WIN32 #ifdef SPDLOG_WCHAR_FILENAMES @@ -248,7 +249,7 @@ inline size_t filesize(FILE *f) int fd = fileno(f); //64 bits(but not in osx or cygwin, where fstat64 is deprecated) #if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__) - struct stat64 st; + struct stat64 st ; if (fstat64(fd, &st) == 0) return static_cast(st.st_size); #else // unix 32 bits or cygwin @@ -316,9 +317,9 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime()) } }; - long int offset_seconds = helper::calculate_gmt_offset(tm); + auto offset_seconds = helper::calculate_gmt_offset(tm); #else - long int offset_seconds = tm.tm_gmtoff; + auto offset_seconds = tm.tm_gmtoff; #endif return static_cast(offset_seconds / 60); @@ -330,12 +331,12 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime()) inline size_t _thread_id() { #ifdef _WIN32 - return static_cast(::GetCurrentThreadId()); + return static_cast(::GetCurrentThreadId()); #elif __linux__ # if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) # define SYS_gettid __NR_gettid # endif - return static_cast(syscall(SYS_gettid)); + return static_cast(syscall(SYS_gettid)); #elif __FreeBSD__ long tid; thr_self(&tid); @@ -352,7 +353,7 @@ inline size_t _thread_id() //Return current thread id as size_t (from thread local storage) inline size_t thread_id() { -#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || (defined(__clang__) && !__has_feature(cxx_thread_local)) +#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt ) || (defined(__clang__) && !__has_feature(cxx_thread_local)) return _thread_id(); #else // cache thread id in tls static thread_local const size_t tid = _thread_id(); @@ -368,7 +369,7 @@ inline size_t thread_id() inline void sleep_for_millis(int milliseconds) { #if defined(_WIN32) - Sleep(milliseconds); + ::Sleep(milliseconds); #else std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); #endif @@ -401,10 +402,7 @@ inline std::string errno_to_string(char buf[256], int res) { return std::string(buf); } - else - { - return "Unknown error"; - } + return "Unknown error"; } // Return errno string (thread safe) @@ -437,7 +435,7 @@ inline int pid() { #ifdef _WIN32 - return ::_getpid(); + return static_cast(::GetCurrentProcessId()); #else return static_cast(::getpid()); #endif @@ -480,9 +478,9 @@ inline bool in_terminal(FILE* file) { #ifdef _WIN32 - return _isatty(_fileno(file)) ? true : false; + return _isatty(_fileno(file)) != 0; #else - return isatty(fileno(file)) ? true : false; + return isatty(fileno(file)) != 0; #endif } } //os diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h index a73f5dea..b5ee6d02 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.h @@ -27,27 +27,23 @@ namespace details class flag_formatter { public: - virtual ~flag_formatter() - {} + virtual ~flag_formatter() = default; virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0; }; /////////////////////////////////////////////////////////////////////// // name & level pattern appenders /////////////////////////////////////////////////////////////////////// -namespace -{ -class name_formatter:public flag_formatter +class name_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { msg.formatted << *msg.logger_name; } }; -} // log level appender -class level_formatter:public flag_formatter +class level_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -56,7 +52,7 @@ class level_formatter:public flag_formatter }; // short log level appender -class short_level_formatter:public flag_formatter +class short_level_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -80,7 +76,7 @@ static int to12h(const tm& t) //Abbreviated weekday name static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -class a_formatter:public flag_formatter +class a_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -90,7 +86,7 @@ class a_formatter:public flag_formatter //Full weekday name static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; -class A_formatter:public flag_formatter +class A_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -99,8 +95,8 @@ class A_formatter:public flag_formatter }; //Abbreviated month -static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" }; -class b_formatter:public flag_formatter +static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" }; +class b_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -110,7 +106,7 @@ class b_formatter:public flag_formatter //Full month name static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; -class B_formatter:public flag_formatter +class B_formatter : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -118,7 +114,6 @@ class B_formatter:public flag_formatter } }; - //write 2 ints separated by sep with padding of 2 static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep) { @@ -133,9 +128,8 @@ static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v return w; } - //Date and time representation (Thu Aug 23 15:35:46 2014) -class c_formatter SPDLOG_FINAL:public flag_formatter +class c_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -144,9 +138,8 @@ class c_formatter SPDLOG_FINAL:public flag_formatter } }; - // year - 2 digit -class C_formatter SPDLOG_FINAL:public flag_formatter +class C_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -154,10 +147,8 @@ class C_formatter SPDLOG_FINAL:public flag_formatter } }; - - // Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 -class D_formatter SPDLOG_FINAL:public flag_formatter +class D_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -165,9 +156,8 @@ class D_formatter SPDLOG_FINAL:public flag_formatter } }; - // year - 4 digit -class Y_formatter SPDLOG_FINAL:public flag_formatter +class Y_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -176,7 +166,7 @@ class Y_formatter SPDLOG_FINAL:public flag_formatter }; // month 1-12 -class m_formatter SPDLOG_FINAL:public flag_formatter +class m_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -185,7 +175,7 @@ class m_formatter SPDLOG_FINAL:public flag_formatter }; // day of month 1-31 -class d_formatter SPDLOG_FINAL:public flag_formatter +class d_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -193,8 +183,8 @@ class d_formatter SPDLOG_FINAL:public flag_formatter } }; -// hours in 24 format 0-23 -class H_formatter SPDLOG_FINAL:public flag_formatter +// hours in 24 format 0-23 +class H_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -202,8 +192,8 @@ class H_formatter SPDLOG_FINAL:public flag_formatter } }; -// hours in 12 format 1-12 -class I_formatter SPDLOG_FINAL:public flag_formatter +// hours in 12 format 1-12 +class I_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -212,7 +202,7 @@ class I_formatter SPDLOG_FINAL:public flag_formatter }; // minutes 0-59 -class M_formatter SPDLOG_FINAL:public flag_formatter +class M_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -221,7 +211,7 @@ class M_formatter SPDLOG_FINAL:public flag_formatter }; // seconds 0-59 -class S_formatter SPDLOG_FINAL:public flag_formatter +class S_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -230,7 +220,7 @@ class S_formatter SPDLOG_FINAL:public flag_formatter }; // milliseconds -class e_formatter SPDLOG_FINAL:public flag_formatter +class e_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -241,7 +231,7 @@ class e_formatter SPDLOG_FINAL:public flag_formatter }; // microseconds -class f_formatter SPDLOG_FINAL:public flag_formatter +class f_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -252,7 +242,7 @@ class f_formatter SPDLOG_FINAL:public flag_formatter }; // nanoseconds -class F_formatter SPDLOG_FINAL:public flag_formatter +class F_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -262,7 +252,7 @@ class F_formatter SPDLOG_FINAL:public flag_formatter } }; -class E_formatter SPDLOG_FINAL:public flag_formatter +class E_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -273,7 +263,7 @@ class E_formatter SPDLOG_FINAL:public flag_formatter }; // AM/PM -class p_formatter SPDLOG_FINAL:public flag_formatter +class p_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -281,9 +271,8 @@ class p_formatter SPDLOG_FINAL:public flag_formatter } }; - // 12 hour clock 02:55:02 pm -class r_formatter SPDLOG_FINAL:public flag_formatter +class r_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -292,7 +281,7 @@ class r_formatter SPDLOG_FINAL:public flag_formatter }; // 24-hour HH:MM time, equivalent to %H:%M -class R_formatter SPDLOG_FINAL:public flag_formatter +class R_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -301,7 +290,7 @@ class R_formatter SPDLOG_FINAL:public flag_formatter }; // ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S -class T_formatter SPDLOG_FINAL:public flag_formatter +class T_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -310,13 +299,12 @@ class T_formatter SPDLOG_FINAL:public flag_formatter }; // ISO 8601 offset from UTC in timezone (+-HH:MM) -class z_formatter SPDLOG_FINAL:public flag_formatter +class z_formatter SPDLOG_FINAL : public flag_formatter { public: const std::chrono::seconds cache_refresh = std::chrono::seconds(5); - z_formatter():_last_update(std::chrono::seconds(0)), _offset_minutes(0) - {} + z_formatter() = default; z_formatter(const z_formatter&) = delete; z_formatter& operator=(const z_formatter&) = delete; @@ -347,13 +335,12 @@ public: pad_n_join(msg.formatted, h, m, ':'); } private: - log_clock::time_point _last_update; - int _offset_minutes; + log_clock::time_point _last_update{ std::chrono::seconds(0) }; + int _offset_minutes{ 0 }; std::mutex _mutex; int get_cached_offset(const log_msg& msg, const std::tm& tm_time) { - using namespace std::chrono; std::lock_guard l(_mutex); if (msg.time - _last_update >= cache_refresh) { @@ -364,10 +351,8 @@ private: } }; - - // Thread id -class t_formatter SPDLOG_FINAL:public flag_formatter +class t_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -376,7 +361,7 @@ class t_formatter SPDLOG_FINAL:public flag_formatter }; // Current pid -class pid_formatter SPDLOG_FINAL:public flag_formatter +class pid_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -385,7 +370,7 @@ class pid_formatter SPDLOG_FINAL:public flag_formatter }; // message counter formatter -class i_formatter SPDLOG_FINAL :public flag_formatter +class i_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -393,7 +378,7 @@ class i_formatter SPDLOG_FINAL :public flag_formatter } }; -class v_formatter SPDLOG_FINAL:public flag_formatter +class v_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm&) override { @@ -401,7 +386,7 @@ class v_formatter SPDLOG_FINAL:public flag_formatter } }; -class ch_formatter SPDLOG_FINAL:public flag_formatter +class ch_formatter SPDLOG_FINAL : public flag_formatter { public: explicit ch_formatter(char ch): _ch(ch) @@ -416,11 +401,11 @@ private: //aggregate user chars to display as is -class aggregate_formatter SPDLOG_FINAL:public flag_formatter +class aggregate_formatter SPDLOG_FINAL : public flag_formatter { public: - aggregate_formatter() - {} + aggregate_formatter() = default; + void add_ch(char ch) { _str += ch; @@ -435,7 +420,7 @@ private: // Full info formatter // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v -class full_formatter SPDLOG_FINAL:public flag_formatter +class full_formatter SPDLOG_FINAL : public flag_formatter { void format(details::log_msg& msg, const std::tm& tm_time) override { @@ -487,8 +472,9 @@ class full_formatter SPDLOG_FINAL:public flag_formatter /////////////////////////////////////////////////////////////////////////////// // pattern_formatter inline impl /////////////////////////////////////////////////////////////////////////////// -inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time) - : _pattern_time(pattern_time) +inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time, std::string eol) : + _eol(std::move(eol)), + _pattern_time(pattern_time) { compile_pattern(pattern); } @@ -503,7 +489,6 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter { if (user_chars) //append user chars found so far _formatters.push_back(std::move(user_chars)); - if (++it != end) handle_flag(*it); else @@ -528,135 +513,135 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) { // logger name case 'n': - _formatters.push_back(std::unique_ptr(new details::name_formatter())); + _formatters.emplace_back(new details::name_formatter()); break; case 'l': - _formatters.push_back(std::unique_ptr(new details::level_formatter())); + _formatters.emplace_back(new details::level_formatter()); break; case 'L': - _formatters.push_back(std::unique_ptr(new details::short_level_formatter())); + _formatters.emplace_back(new details::short_level_formatter()); break; case('t'): - _formatters.push_back(std::unique_ptr(new details::t_formatter())); + _formatters.emplace_back(new details::t_formatter()); break; case('v'): - _formatters.push_back(std::unique_ptr(new details::v_formatter())); + _formatters.emplace_back(new details::v_formatter()); break; case('a'): - _formatters.push_back(std::unique_ptr(new details::a_formatter())); + _formatters.emplace_back(new details::a_formatter()); break; case('A'): - _formatters.push_back(std::unique_ptr(new details::A_formatter())); + _formatters.emplace_back(new details::A_formatter()); break; case('b'): case('h'): - _formatters.push_back(std::unique_ptr(new details::b_formatter())); + _formatters.emplace_back(new details::b_formatter()); break; case('B'): - _formatters.push_back(std::unique_ptr(new details::B_formatter())); + _formatters.emplace_back(new details::B_formatter()); break; case('c'): - _formatters.push_back(std::unique_ptr(new details::c_formatter())); + _formatters.emplace_back(new details::c_formatter()); break; case('C'): - _formatters.push_back(std::unique_ptr(new details::C_formatter())); + _formatters.emplace_back(new details::C_formatter()); break; case('Y'): - _formatters.push_back(std::unique_ptr(new details::Y_formatter())); + _formatters.emplace_back(new details::Y_formatter()); break; case('D'): case('x'): - _formatters.push_back(std::unique_ptr(new details::D_formatter())); + _formatters.emplace_back(new details::D_formatter()); break; case('m'): - _formatters.push_back(std::unique_ptr(new details::m_formatter())); + _formatters.emplace_back(new details::m_formatter()); break; case('d'): - _formatters.push_back(std::unique_ptr(new details::d_formatter())); + _formatters.emplace_back(new details::d_formatter()); break; case('H'): - _formatters.push_back(std::unique_ptr(new details::H_formatter())); + _formatters.emplace_back(new details::H_formatter()); break; case('I'): - _formatters.push_back(std::unique_ptr(new details::I_formatter())); + _formatters.emplace_back(new details::I_formatter()); break; case('M'): - _formatters.push_back(std::unique_ptr(new details::M_formatter())); + _formatters.emplace_back(new details::M_formatter()); break; case('S'): - _formatters.push_back(std::unique_ptr(new details::S_formatter())); + _formatters.emplace_back(new details::S_formatter()); break; case('e'): - _formatters.push_back(std::unique_ptr(new details::e_formatter())); + _formatters.emplace_back(new details::e_formatter()); break; case('f'): - _formatters.push_back(std::unique_ptr(new details::f_formatter())); + _formatters.emplace_back(new details::f_formatter()); break; case('F'): - _formatters.push_back(std::unique_ptr(new details::F_formatter())); + _formatters.emplace_back(new details::F_formatter()); break; case('E'): - _formatters.push_back(std::unique_ptr(new details::E_formatter())); + _formatters.emplace_back(new details::E_formatter()); break; case('p'): - _formatters.push_back(std::unique_ptr(new details::p_formatter())); + _formatters.emplace_back(new details::p_formatter()); break; case('r'): - _formatters.push_back(std::unique_ptr(new details::r_formatter())); + _formatters.emplace_back(new details::r_formatter()); break; case('R'): - _formatters.push_back(std::unique_ptr(new details::R_formatter())); + _formatters.emplace_back(new details::R_formatter()); break; case('T'): case('X'): - _formatters.push_back(std::unique_ptr(new details::T_formatter())); + _formatters.emplace_back(new details::T_formatter()); break; case('z'): - _formatters.push_back(std::unique_ptr(new details::z_formatter())); + _formatters.emplace_back(new details::z_formatter()); break; case ('+'): - _formatters.push_back(std::unique_ptr(new details::full_formatter())); + _formatters.emplace_back(new details::full_formatter()); break; case ('P'): - _formatters.push_back(std::unique_ptr(new details::pid_formatter())); + _formatters.emplace_back(new details::pid_formatter()); break; case ('i'): - _formatters.push_back(std::unique_ptr(new details::i_formatter())); + _formatters.emplace_back(new details::i_formatter()); break; default: //Unknown flag appears as is - _formatters.push_back(std::unique_ptr(new details::ch_formatter('%'))); - _formatters.push_back(std::unique_ptr(new details::ch_formatter(flag))); + _formatters.emplace_back(new details::ch_formatter('%')); + _formatters.emplace_back(new details::ch_formatter(flag)); break; } } @@ -664,9 +649,10 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) inline std::tm spdlog::pattern_formatter::get_time(details::log_msg& msg) { if (_pattern_time == pattern_time_type::local) + { return details::os::localtime(log_clock::to_time_t(msg.time)); - else - return details::os::gmtime(log_clock::to_time_t(msg.time)); + } + return details::os::gmtime(log_clock::to_time_t(msg.time)); } inline void spdlog::pattern_formatter::format(details::log_msg& msg) @@ -682,5 +668,5 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg) f->format(msg, tm_time); } //write eol - msg.formatted.write(details::os::eol, details::os::eol_size); + msg.formatted.write(_eol.data(), _eol.size()); } diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index b68b9f5a..6bd8bb2d 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -26,9 +26,12 @@ namespace spdlog { namespace details { -template class registry_t +template +class registry_t { public: + registry_t(const registry_t&) = delete; + registry_t& operator=(const registry_t&) = delete; void register_logger(std::shared_ptr logger) { @@ -38,7 +41,6 @@ public: _loggers[logger_name] = logger; } - std::shared_ptr get(const std::string& logger_name) { std::lock_guard lock(_mutex); @@ -111,6 +113,7 @@ public: std::lock_guard lock(_mutex); _loggers.clear(); } + std::shared_ptr create(const std::string& logger_name, sinks_init_list sinks) { return create(logger_name, sinks.begin(), sinks.end()); @@ -194,15 +197,14 @@ public: } private: - registry_t() {} - registry_t(const registry_t&) = delete; - registry_t& operator=(const registry_t&) = delete; + registry_t() = default; void throw_if_exists(const std::string &logger_name) { if (_loggers.find(logger_name) != _loggers.end()) throw spdlog_ex("logger with name '" + logger_name + "' already exists"); } + Mutex _mutex; std::unordered_map > _loggers; formatter_ptr _formatter; @@ -212,14 +214,16 @@ private: bool _async_mode = false; size_t _async_q_size = 0; async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; - std::function _worker_warmup_cb = nullptr; + std::function _worker_warmup_cb; std::chrono::milliseconds _flush_interval_ms; - std::function _worker_teardown_cb = nullptr; + std::function _worker_teardown_cb; }; + #ifdef SPDLOG_NO_REGISTRY_MUTEX -typedef registry_t registry; +using registry = registry_t; #else -typedef registry_t registry; +using registry = registry_t; #endif + } } diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index 25c7b7e9..003aff16 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -16,7 +16,7 @@ #include "../sinks/syslog_sink.h" #endif -#ifdef _WIN32 +#if defined _WIN32 && !defined(__cplusplus_winrt) #include "../sinks/wincolor_sink.h" #else #include "../sinks/ansicolor_sink.h" @@ -34,7 +34,7 @@ inline void spdlog::register_logger(std::shared_ptr logger) { - return details::registry::instance().register_logger(logger); + return details::registry::instance().register_logger(std::move(logger)); } inline std::shared_ptr spdlog::get(const std::string& name) @@ -107,7 +107,8 @@ inline std::shared_ptr spdlog::stderr_logger_st(const std::strin // // stdout/stderr color loggers // -#ifdef _WIN32 +#if defined _WIN32 && !defined(__cplusplus_winrt) + inline std::shared_ptr spdlog::stdout_color_mt(const std::string& logger_name) { auto sink = std::make_shared(); @@ -182,13 +183,11 @@ inline std::shared_ptr spdlog::create(const std::string& logger_ } //Create logger with multiple sinks - inline std::shared_ptr spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) { return details::registry::instance().create(logger_name, sinks); } - template inline std::shared_ptr spdlog::create(const std::string& logger_name, Args... args) { @@ -196,7 +195,6 @@ inline std::shared_ptr spdlog::create(const std::string& logger_ return details::registry::instance().create(logger_name, { sink }); } - template inline std::shared_ptr spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) { @@ -223,7 +221,7 @@ inline std::shared_ptr spdlog::create_async(const std::string& l inline void spdlog::set_formatter(spdlog::formatter_ptr f) { - details::registry::instance().formatter(f); + details::registry::instance().formatter(std::move(f)); } inline void spdlog::set_pattern(const std::string& format_string) @@ -243,10 +241,9 @@ inline void spdlog::flush_on(level::level_enum log_level) inline void spdlog::set_error_handler(log_err_handler handler) { - return details::registry::instance().set_error_handler(handler); + return details::registry::instance().set_error_handler(std::move(handler)); } - inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function& worker_teardown_cb) { details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); @@ -259,7 +256,7 @@ inline void spdlog::set_sync_mode() inline void spdlog::apply_all(std::function)> fun) { - details::registry::instance().apply_all(fun); + details::registry::instance().apply_all(std::move(fun)); } inline void spdlog::drop_all() diff --git a/include/spdlog/fmt/bundled/format.cc b/include/spdlog/fmt/bundled/format.cc index 09d2ea9f..2d236bc6 100644 --- a/include/spdlog/fmt/bundled/format.cc +++ b/include/spdlog/fmt/bundled/format.cc @@ -72,9 +72,11 @@ // Dummy implementations of strerror_r and strerror_s called if corresponding // system functions are not available. +FMT_MAYBE_UNUSED static inline fmt::internal::Null<> strerror_r(int, char *, ...) { return fmt::internal::Null<>(); } +FMT_MAYBE_UNUSED static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { return fmt::internal::Null<>(); } @@ -121,7 +123,7 @@ typedef void (*FormatFunc)(Writer &, int, StringRef); // Buffer should be at least of size 1. int safe_strerror( int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { - FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); + FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer"); class StrError { private: @@ -159,6 +161,11 @@ int safe_strerror( ERANGE : result; } +#ifdef __c2__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + // Fallback to strerror if strerror_r and strerror_s are not available. int fallback(internal::Null<>) { errno = 0; @@ -166,13 +173,15 @@ int safe_strerror( return errno; } +#ifdef __c2__ +# pragma clang diagnostic pop +#endif + public: StrError(int err_code, char *&buf, std::size_t buf_size) : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} int run() { - // Suppress a warning about unused strerror_r. - strerror_r(0, FMT_NULL, ""); return handle(strerror_r(error_code_, buffer_, buffer_size_)); } }; @@ -396,51 +405,6 @@ FMT_FUNC void format_system_error( fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. } -template -void internal::ArgMap::init(const ArgList &args) { - if (!map_.empty()) - return; - typedef internal::NamedArg NamedArg; - const NamedArg *named_arg = FMT_NULL; - bool use_values = - args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; - if (use_values) { - for (unsigned i = 0;/*nothing*/; ++i) { - internal::Arg::Type arg_type = args.type(i); - switch (arg_type) { - case internal::Arg::NONE: - return; - case internal::Arg::NAMED_ARG: - named_arg = static_cast(args.values_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - break; - default: - /*nothing*/; - } - } - return; - } - for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) { - internal::Arg::Type arg_type = args.type(i); - if (arg_type == internal::Arg::NAMED_ARG) { - named_arg = static_cast(args.args_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - } - } - for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { - switch (args.args_[i].type) { - case internal::Arg::NONE: - return; - case internal::Arg::NAMED_ARG: - named_arg = static_cast(args.args_[i].pointer); - map_.push_back(Pair(named_arg->name, *named_arg)); - break; - default: - /*nothing*/; - } - } -} - template void internal::FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); @@ -502,8 +466,6 @@ template struct internal::BasicData; template void internal::FixedBuffer::grow(std::size_t); -template void internal::ArgMap::init(const ArgList &args); - template FMT_API int internal::CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, double value); @@ -516,8 +478,6 @@ template FMT_API int internal::CharTraits::format_float( template void internal::FixedBuffer::grow(std::size_t); -template void internal::ArgMap::init(const ArgList &args); - template FMT_API int internal::CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, double value); diff --git a/include/spdlog/fmt/bundled/format.h b/include/spdlog/fmt/bundled/format.h index 91f43481..971c58e2 100644 --- a/include/spdlog/fmt/bundled/format.h +++ b/include/spdlog/fmt/bundled/format.h @@ -28,6 +28,7 @@ #ifndef FMT_FORMAT_H_ #define FMT_FORMAT_H_ +#define FMT_INCLUDE #include #include #include @@ -39,11 +40,26 @@ #include #include #include // for std::pair +#undef FMT_INCLUDE // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 40000 +#define FMT_VERSION 40100 -#ifdef _SECURE_SCL +#if defined(__has_include) +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif + +#if (FMT_HAS_INCLUDE() && __cplusplus > 201402L) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +# include +# define FMT_HAS_STRING_VIEW 1 +#else +# define FMT_HAS_STRING_VIEW 0 +#endif + +#if defined _SECURE_SCL && _SECURE_SCL # define FMT_SECURE_SCL _SECURE_SCL #else # define FMT_SECURE_SCL 0 @@ -97,7 +113,9 @@ typedef __int64 intmax_t; # define FMT_HAS_GXX_CXX11 1 # endif #else +# define FMT_GCC_VERSION 0 # define FMT_GCC_EXTENSION +# define FMT_HAS_GXX_CXX11 0 #endif #if defined(__INTEL_COMPILER) @@ -135,6 +153,32 @@ typedef __int64 intmax_t; # define FMT_HAS_CPP_ATTRIBUTE(x) 0 #endif +#if FMT_HAS_CPP_ATTRIBUTE(maybe_unused) +# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED +// VC++ 1910 support /std: option and that will set _MSVC_LANG macro +// Clang with Microsoft CodeGen doesn't define _MSVC_LANG macro +#elif defined(_MSVC_LANG) && _MSVC_LANG > 201402 && _MSC_VER >= 1910 +# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED +#endif + +#ifdef FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED +# define FMT_MAYBE_UNUSED [[maybe_unused]] +// g++/clang++ also support [[gnu::unused]]. However, we don't use it. +#elif defined(__GNUC__) +# define FMT_MAYBE_UNUSED __attribute__((unused)) +#else +# define FMT_MAYBE_UNUSED +#endif + +// Use the compiler's attribute noreturn +#if defined(__MINGW32__) || defined(__MINGW64__) +# define FMT_NORETURN __attribute__((noreturn)) +#elif FMT_HAS_CPP_ATTRIBUTE(noreturn) && __cplusplus >= 201103L +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + #ifndef FMT_USE_VARIADIC_TEMPLATES // Variadic templates are available in GCC since version 4.4 // (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++ @@ -156,6 +200,12 @@ typedef __int64 intmax_t; # endif #endif +#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700 +# define FMT_USE_ALLOCATOR_TRAITS 1 +#else +# define FMT_USE_ALLOCATOR_TRAITS 0 +#endif + // Check if exceptions are disabled. #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 @@ -262,11 +312,14 @@ typedef __int64 intmax_t; // makes the fmt::literals implementation easier. However, an explicit check // for variadic templates is added here just in case. // For Intel's compiler both it and the system gcc/msc must support UDLs. -# define FMT_USE_USER_DEFINED_LITERALS \ - FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \ +# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \ (FMT_HAS_FEATURE(cxx_user_literals) || \ (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \ (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500) +# define FMT_USE_USER_DEFINED_LITERALS 1 +# else +# define FMT_USE_USER_DEFINED_LITERALS 0 +# endif #endif #ifndef FMT_USE_EXTERN_TEMPLATES @@ -307,7 +360,10 @@ namespace fmt { namespace internal { -# pragma intrinsic(_BitScanReverse) +// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning +# ifndef __clang__ +# pragma intrinsic(_BitScanReverse) +# endif inline uint32_t clz(uint32_t x) { unsigned long r = 0; @@ -322,7 +378,8 @@ inline uint32_t clz(uint32_t x) } # define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n) -# ifdef _WIN64 +// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning +# if defined(_WIN64) && !defined(__clang__) # pragma intrinsic(_BitScanReverse64) # endif @@ -546,6 +603,27 @@ public: const std::basic_string, Allocator> &s) : data_(s.c_str()), size_(s.size()) {} +#if FMT_HAS_STRING_VIEW + /** + \rst + Constructs a string reference from a ``std::basic_string_view`` object. + \endrst + */ + BasicStringRef( + const std::basic_string_view> &s) + : data_(s.data()), size_(s.size()) {} + + /** + \rst + Converts a string reference to an ``std::string_view`` object. + \endrst + */ + explicit operator std::basic_string_view() const FMT_NOEXCEPT + { + return std::basic_string_view(data_, size_); + } +#endif + /** \rst Converts a string reference to an ``std::string`` object. @@ -669,7 +747,7 @@ public: explicit FormatError(CStringRef message) : std::runtime_error(message.c_str()) {} FormatError(const FormatError &ferr) : std::runtime_error(ferr) {} - FMT_API ~FormatError() FMT_DTOR_NOEXCEPT; + FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE; }; namespace internal @@ -812,7 +890,7 @@ template void Buffer::append(const U *begin, const U *end) { FMT_ASSERT(end >= begin, "negative value"); - std::size_t new_size = size_ + (end - begin); + std::size_t new_size = size_ + static_cast(end - begin); if (new_size > capacity_) grow(new_size); std::uninitialized_copy(begin, end, @@ -843,10 +921,7 @@ protected: public: explicit MemoryBuffer(const Allocator &alloc = Allocator()) : Allocator(alloc), Buffer(data_, SIZE) {} - ~MemoryBuffer() - { - deallocate(); - } + ~MemoryBuffer() FMT_OVERRIDE { deallocate(); } #if FMT_USE_RVALUE_REFERENCES private: @@ -900,7 +975,12 @@ void MemoryBuffer::grow(std::size_t size) std::size_t new_capacity = this->capacity_ + this->capacity_ / 2; if (size > new_capacity) new_capacity = size; +#if FMT_USE_ALLOCATOR_TRAITS + T *new_ptr = + std::allocator_traits::allocate(*this, new_capacity, FMT_NULL); +#else T *new_ptr = this->allocate(new_capacity, FMT_NULL); +#endif // The following code doesn't throw, so the raw pointer above doesn't leak. std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_, make_ptr(new_ptr, new_capacity)); @@ -1050,7 +1130,7 @@ struct IntTraits TypeSelector::digits <= 32>::Type MainType; }; -FMT_API void report_unknown_type(char code, const char *type); +FMT_API FMT_NORETURN void report_unknown_type(char code, const char *type); // Static data is placed in this class template to allow header-only // configuration. @@ -1335,19 +1415,19 @@ T &get(); Yes &convert(fmt::ULongLong); No &convert(...); -template +template struct ConvertToIntImpl { enum { value = ENABLE_CONVERSION }; }; -template +template struct ConvertToIntImpl2 { enum { value = false }; }; -template +template struct ConvertToIntImpl2 { enum @@ -1357,7 +1437,7 @@ struct ConvertToIntImpl2 }; }; -template +template struct ConvertToInt { enum @@ -1376,22 +1456,22 @@ FMT_DISABLE_CONVERSION_TO_INT(float); FMT_DISABLE_CONVERSION_TO_INT(double); FMT_DISABLE_CONVERSION_TO_INT(long double); -template +template struct EnableIf {}; -template +template struct EnableIf { typedef T type; }; -template +template struct Conditional { typedef T type; }; -template +template struct Conditional { typedef F type; @@ -1457,10 +1537,10 @@ inline fmt::StringRef thousands_sep(...) typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED #endif -template -void format_arg(Formatter &, const Char *, const T &) +template +void format_arg(Formatter&, ...) { - FMT_STATIC_ASSERT(FalseType::value, + FMT_STATIC_ASSERT(FalseType::value, "Cannot format argument. To enable the use of ostream " "operator<< include fmt/ostream.h. Otherwise provide " "an overload of format_arg."); @@ -1494,6 +1574,9 @@ private: MakeValue(typename WCharHelper::Unsupported); MakeValue(typename WCharHelper::Unsupported); MakeValue(typename WCharHelper::Unsupported); +#if FMT_HAS_STRING_VIEW + MakeValue(typename WCharHelper::Unsupported); +#endif MakeValue(typename WCharHelper::Unsupported); void set_string(StringRef str) @@ -1570,6 +1653,26 @@ public: FMT_MAKE_VALUE(unsigned char, uint_value, UINT) FMT_MAKE_VALUE(char, int_value, CHAR) +#if __cplusplus >= 201103L + template < + typename T, + typename = typename std::enable_if< + std::is_enum::value && ConvertToInt::value>::type> + MakeValue(T value) + { + int_value = value; + } + + template < + typename T, + typename = typename std::enable_if< + std::is_enum::value && ConvertToInt::value>::type> + static uint64_t type(T) + { + return Arg::INT; + } +#endif + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) MakeValue(typename WCharHelper::Supported value) { @@ -1592,6 +1695,9 @@ public: FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING) FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING) FMT_MAKE_STR_VALUE(const std::string &, STRING) +#if FMT_HAS_STRING_VIEW + FMT_MAKE_STR_VALUE(const std::string_view &, STRING) +#endif FMT_MAKE_STR_VALUE(StringRef, STRING) FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str()) @@ -1604,6 +1710,9 @@ public: FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING) FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING) FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING) +#if FMT_HAS_STRING_VIEW + FMT_MAKE_WSTR_VALUE(const std::wstring_view &, WSTRING) +#endif FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING) FMT_MAKE_VALUE(void *, pointer, POINTER) @@ -1689,7 +1798,7 @@ class RuntimeError : public std::runtime_error protected: RuntimeError() : std::runtime_error("") {} RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {} - FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT; + FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE; }; template @@ -2267,7 +2376,7 @@ private: MapType map_; public: - FMT_API void init(const ArgList &args); + void init(const ArgList &args); const internal::Arg *find(const fmt::BasicStringRef &name) const { @@ -2282,6 +2391,61 @@ public: } }; +template +void ArgMap::init(const ArgList &args) +{ + if (!map_.empty()) + return; + typedef internal::NamedArg NamedArg; + const NamedArg *named_arg = FMT_NULL; + bool use_values = + args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; + if (use_values) + { + for (unsigned i = 0;/*nothing*/; ++i) + { + internal::Arg::Type arg_type = args.type(i); + switch (arg_type) + { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast(args.values_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/ + ; + } + } + return; + } + for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) + { + internal::Arg::Type arg_type = args.type(i); + if (arg_type == internal::Arg::NAMED_ARG) + { + named_arg = static_cast(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + } + } + for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) + { + switch (args.args_[i].type) + { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/ + ; + } + } +} + template class ArgFormatterBase : public ArgVisitor { @@ -2623,7 +2787,8 @@ template template struct ArgArray { - typedef Value Type[N > 0 ? N : 1]; + // '+' is used to silence GCC -Wduplicated-branches warning. + typedef Value Type[N > 0 ? N : +1]; template static Value make(const T &value) @@ -2823,7 +2988,7 @@ public: FMT_DEFAULTED_COPY_CTOR(SystemError) FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef) - FMT_API ~SystemError() FMT_DTOR_NOEXCEPT; + FMT_API ~SystemError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE; int error_code() const { @@ -4057,10 +4222,10 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; #define FMT_GET_ARG_NAME(type, index) arg##index #if FMT_USE_VARIADIC_TEMPLATES -# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ +# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ template \ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - const Args & ... args) { \ + const Args & ... args) Const { \ typedef fmt::internal::ArgArray ArgArray; \ typename ArgArray::Type array{ \ ArgArray::template make >(args)...}; \ @@ -4070,35 +4235,35 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; #else // Defines a wrapper for a function taking __VA_ARGS__ arguments // and n additional arguments of arbitrary types. -# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \ +# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \ template \ inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ - FMT_GEN(n, FMT_MAKE_ARG)) { \ + FMT_GEN(n, FMT_MAKE_ARG)) Const { \ fmt::internal::ArgArray::Type arr; \ FMT_GEN(n, FMT_ASSIGN_##Char); \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \ } -# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \ - inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \ +# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \ + inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \ } \ - FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \ - FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__) + FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \ + FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__) #endif // FMT_USE_VARIADIC_TEMPLATES /** @@ -4129,10 +4294,16 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; \endrst */ #define FMT_VARIADIC(ReturnType, func, ...) \ - FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__) + FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_CONST(ReturnType, func, ...) \ + FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__) #define FMT_VARIADIC_W(ReturnType, func, ...) \ - FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__) + FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__) + +#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \ + FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__) #define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id) @@ -4179,20 +4350,22 @@ unsigned parse_nonnegative_int(const Char *&s) { assert('0' <= *s && *s <= '9'); unsigned value = 0; + // Convert to unsigned to prevent a warning. + unsigned max_int = (std::numeric_limits::max)(); + unsigned big = max_int / 10; do { - unsigned new_value = value * 10 + (*s++ - '0'); - // Check if value wrapped around. - if (new_value < value) + // Check for overflow. + if (value > big) { - value = (std::numeric_limits::max)(); + value = max_int + 1; break; } - value = new_value; + value = value * 10 + (*s - '0'); + ++s; } while ('0' <= *s && *s <= '9'); // Convert to unsigned to prevent a warning. - unsigned max_int = (std::numeric_limits::max)(); if (value > max_int) FMT_THROW(FormatError("number is too big")); return value; @@ -4392,7 +4565,8 @@ const Char *BasicFormatter::format( default: FMT_THROW(FormatError("width is not integer")); } - if (value > (std::numeric_limits::max)()) + unsigned max_int = (std::numeric_limits::max)(); + if (value > max_int) FMT_THROW(FormatError("number is too big")); spec.width_ = static_cast(value); } @@ -4435,7 +4609,8 @@ const Char *BasicFormatter::format( default: FMT_THROW(FormatError("precision is not integer")); } - if (value > (std::numeric_limits::max)()) + unsigned max_int = (std::numeric_limits::max)(); + if (value > max_int) FMT_THROW(FormatError("number is too big")); spec.precision_ = static_cast(value); } diff --git a/include/spdlog/fmt/bundled/ostream.h b/include/spdlog/fmt/bundled/ostream.h index cfb8e035..f1b09dfc 100644 --- a/include/spdlog/fmt/bundled/ostream.h +++ b/include/spdlog/fmt/bundled/ostream.h @@ -58,13 +58,15 @@ Yes &convert(std::ostream &); struct DummyStream : std::ostream { DummyStream(); // Suppress a bogus warning in MSVC. + // Hide all operator<< overloads from std::ostream. - void operator<<(Null<>); + template + typename EnableIf::type operator<<(const T &); }; No &operator<<(std::ostream &, int); -template +template struct ConvertToIntImpl { // Convert to int only if T doesn't have an overloaded operator<<. @@ -87,6 +89,7 @@ void format_arg(BasicFormatter &f, internal::FormatBuf format_buf(buffer); std::basic_ostream output(&format_buf); + output.exceptions(std::ios_base::failbit | std::ios_base::badbit); output << value; BasicStringRef str(&buffer[0], buffer.size()); diff --git a/include/spdlog/fmt/bundled/printf.h b/include/spdlog/fmt/bundled/printf.h index 7861b460..14242143 100644 --- a/include/spdlog/fmt/bundled/printf.h +++ b/include/spdlog/fmt/bundled/printf.h @@ -152,7 +152,7 @@ public: visit_any_int(value); } - void visit_char(char value) + void visit_char(int value) { if (type_ != 's') visit_any_int(value); @@ -170,7 +170,7 @@ public: using internal::Arg; typedef typename internal::Conditional< is_same::value, U, T>::type TargetType; - if (sizeof(TargetType) <= sizeof(int)) + if (const_check(sizeof(TargetType) <= sizeof(int))) { // Extra casts are used to silence warnings. if (is_signed) diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index 8bf0f43f..203dc31a 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -21,19 +21,20 @@ class flag_formatter; class formatter { public: - virtual ~formatter() {} + virtual ~formatter() = default; virtual void format(details::log_msg& msg) = 0; }; class pattern_formatter SPDLOG_FINAL : public formatter { - public: - explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local); + explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); pattern_formatter(const pattern_formatter&) = delete; pattern_formatter& operator=(const pattern_formatter&) = delete; void format(details::log_msg& msg) override; + private: + const std::string _eol; const std::string _pattern; const pattern_time_type _pattern_time; std::vector> _formatters; @@ -44,4 +45,3 @@ private: } #include "details/pattern_formatter_impl.h" - diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 742f667f..5502d273 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -25,16 +25,17 @@ namespace spdlog class logger { public: - logger(const std::string& logger_name, sink_ptr single_sink); - logger(const std::string& name, sinks_init_list); - template - logger(const std::string& name, const It& begin, const It& end); + logger(const std::string& name, sink_ptr single_sink); + logger(const std::string& name, sinks_init_list sinks); + + template + logger(std::string name, const It& begin, const It& end); virtual ~logger(); + logger(const logger&) = delete; logger& operator=(const logger&) = delete; - template void log(level::level_enum lvl, const char* fmt, const Args&... args); template void log(level::level_enum lvl, const char* msg); template void trace(const char* fmt, const Arg1&, const Args&... args); @@ -44,7 +45,6 @@ public: template void error(const char* fmt, const Arg1&, const Args&... args); template void critical(const char* fmt, const Arg1&, const Args&... args); - #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT template void log(level::level_enum lvl, const wchar_t* msg); template void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args); @@ -57,19 +57,19 @@ public: #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT template void log(level::level_enum lvl, const T&); - template void trace(const T&); - template void debug(const T&); - template void info(const T&); - template void warn(const T&); - template void error(const T&); - template void critical(const T&); + template void trace(const T& msg); + template void debug(const T& msg); + template void info(const T& msg); + template void warn(const T& msg); + template void error(const T& msg); + template void critical(const T& msg); - bool should_log(level::level_enum) const; - void set_level(level::level_enum); + bool should_log(level::level_enum msg_level) const; + void set_level(level::level_enum log_level); level::level_enum level() const; const std::string& name() const; - void set_pattern(const std::string&, pattern_time_type = pattern_time_type::local); - void set_formatter(formatter_ptr); + void set_pattern(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local); + void set_formatter(formatter_ptr msg_formatter); // automatically call flush() if message level >= log_level void flush_on(level::level_enum log_level); @@ -79,22 +79,22 @@ public: const std::vector& sinks() const; // error handler - virtual void set_error_handler(log_err_handler); + virtual void set_error_handler(log_err_handler err_handler); virtual log_err_handler error_handler(); protected: - virtual void _sink_it(details::log_msg&); - virtual void _set_pattern(const std::string&, pattern_time_type); - virtual void _set_formatter(formatter_ptr); + virtual void _sink_it(details::log_msg& msg); + virtual void _set_pattern(const std::string& pattern, pattern_time_type pattern_time); + virtual void _set_formatter(formatter_ptr msg_formatter); // default error handler: print the error to stderr with the max rate of 1 message/minute virtual void _default_err_handler(const std::string &msg); // return true if the given message level should trigger a flush - bool _should_flush_on(const details::log_msg&); + bool _should_flush_on(const details::log_msg& msg); // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) - void _incr_msg_counter(details::log_msg &msg); + void _incr_msg_counter(details::log_msg& msg); const std::string _name; std::vector _sinks; diff --git a/include/spdlog/sinks/ansicolor_sink.h b/include/spdlog/sinks/ansicolor_sink.h index bd0e3222..4bd884cc 100644 --- a/include/spdlog/sinks/ansicolor_sink.h +++ b/include/spdlog/sinks/ansicolor_sink.h @@ -23,10 +23,10 @@ namespace sinks * If no color terminal detected, omit the escape codes. */ template -class ansicolor_sink: public base_sink +class ansicolor_sink : public base_sink { public: - ansicolor_sink(FILE* file): target_file_(file) + explicit ansicolor_sink(FILE* file) : target_file_(file) { should_do_colors_ = details::os::in_terminal(file) && details::os::is_color_terminal(); colors_[level::trace] = cyan; @@ -37,7 +37,8 @@ public: colors_[level::critical] = bold + on_red; colors_[level::off] = reset; } - virtual ~ansicolor_sink() + + ~ansicolor_sink() override { _flush(); } @@ -79,7 +80,7 @@ public: const std::string on_white = "\033[47m"; protected: - virtual void _sink_it(const details::log_msg& msg) override + void _sink_it(const details::log_msg& msg) override { // Wrap the originally formatted message in color codes. // If color is not supported in the terminal, log as is instead. @@ -102,6 +103,7 @@ protected: { fflush(target_file_); } + FILE* target_file_; bool should_do_colors_; std::unordered_map colors_; @@ -116,6 +118,9 @@ public: {} }; +using ansicolor_stdout_sink_mt = ansicolor_stdout_sink; +using ansicolor_stdout_sink_st = ansicolor_stdout_sink; + template class ansicolor_stderr_sink: public ansicolor_sink { @@ -124,11 +129,8 @@ public: {} }; -typedef ansicolor_stdout_sink ansicolor_stdout_sink_mt; -typedef ansicolor_stdout_sink ansicolor_stdout_sink_st; - -typedef ansicolor_stderr_sink ansicolor_stderr_sink_mt; -typedef ansicolor_stderr_sink ansicolor_stderr_sink_st; +using ansicolor_stderr_sink_mt = ansicolor_stderr_sink; +using ansicolor_stderr_sink_st = ansicolor_stderr_sink; } // namespace sinks } // namespace spdlog diff --git a/include/spdlog/sinks/base_sink.h b/include/spdlog/sinks/base_sink.h index 23c85653..1d975892 100644 --- a/include/spdlog/sinks/base_sink.h +++ b/include/spdlog/sinks/base_sink.h @@ -22,11 +22,10 @@ namespace spdlog namespace sinks { template -class base_sink:public sink +class base_sink : public sink { public: - base_sink():_mutex() {} - virtual ~base_sink() = default; + base_sink() = default; base_sink(const base_sink&) = delete; base_sink& operator=(const base_sink&) = delete; @@ -36,6 +35,7 @@ public: std::lock_guard lock(_mutex); _sink_it(msg); } + void flush() SPDLOG_FINAL override { std::lock_guard lock(_mutex); diff --git a/include/spdlog/sinks/dist_sink.h b/include/spdlog/sinks/dist_sink.h index 537efe1d..39f162c5 100644 --- a/include/spdlog/sinks/dist_sink.h +++ b/include/spdlog/sinks/dist_sink.h @@ -22,13 +22,12 @@ namespace spdlog namespace sinks { template -class dist_sink: public base_sink +class dist_sink : public base_sink { public: explicit dist_sink() :_sinks() {} dist_sink(const dist_sink&) = delete; dist_sink& operator=(const dist_sink&) = delete; - virtual ~dist_sink() = default; protected: std::vector> _sinks; @@ -51,8 +50,6 @@ protected: } public: - - void add_sink(std::shared_ptr sink) { std::lock_guard lock(base_sink::_mutex); @@ -66,7 +63,8 @@ public: } }; -typedef dist_sink dist_sink_mt; -typedef dist_sink dist_sink_st; +using dist_sink_mt = dist_sink; +using dist_sink_st = dist_sink; + } } diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h index e7856172..39f7b7bb 100644 --- a/include/spdlog/sinks/file_sinks.h +++ b/include/spdlog/sinks/file_sinks.h @@ -25,8 +25,8 @@ namespace sinks /* * Trivial file sink with single file as target */ -template -class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex > +template +class simple_file_sink SPDLOG_FINAL : public base_sink { public: explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false) @@ -46,32 +46,32 @@ protected: if(_force_flush) _file_helper.flush(); } + void _flush() override { _file_helper.flush(); } + private: details::file_helper _file_helper; bool _force_flush; }; -typedef simple_file_sink simple_file_sink_mt; -typedef simple_file_sink simple_file_sink_st; +using simple_file_sink_mt = simple_file_sink; +using simple_file_sink_st = simple_file_sink; /* * Rotating file sink based on size */ -template -class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex > +template +class rotating_file_sink SPDLOG_FINAL : public base_sink { public: - rotating_file_sink(const filename_t &base_filename, + rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files) : - _base_filename(base_filename), + _base_filename(std::move(base_filename)), _max_size(max_size), - _max_files(max_files), - _current_size(0), - _file_helper() + _max_files(max_files) { _file_helper.open(calc_filename(_base_filename, 0)); _current_size = _file_helper.size(); //expensive. called only once @@ -81,8 +81,8 @@ public: // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". static filename_t calc_filename(const filename_t& filename, std::size_t index) { - std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; - if (index) + typename std::conditional::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + if (index != 0u) { filename_t basename, ext; std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); @@ -112,7 +112,6 @@ protected: _file_helper.flush(); } - private: // Rotate files: // log.txt -> log.1.txt @@ -135,13 +134,14 @@ private: throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno); } } - if (details::file_helper::file_exists(src) && details::os::rename(src, target)) + if (details::file_helper::file_exists(src) && details::os::rename(src, target) != 0) { throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); } } _file_helper.reopen(true); } + filename_t _base_filename; std::size_t _max_size; std::size_t _max_files; @@ -149,8 +149,8 @@ private: details::file_helper _file_helper; }; -typedef rotating_file_sink rotating_file_sink_mt; -typedef rotating_file_sinkrotating_file_sink_st; +using rotating_file_sink_mt = rotating_file_sink; +using rotating_file_sink_st = rotating_file_sink; /* * Default generator of daily log file names. @@ -195,9 +195,10 @@ class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex > public: //create daily file sink which rotates on given time daily_file_sink( - const filename_t& base_filename, + filename_t base_filename, int rotation_hour, - int rotation_minute) : _base_filename(base_filename), + int rotation_minute) : + _base_filename(std::move(base_filename)), _rotation_h(rotation_hour), _rotation_m(rotation_minute) { @@ -235,9 +236,10 @@ private: date.tm_sec = 0; auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date)); if (rotation_time > now) + { return rotation_time; - else - return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24)); + } + return{ rotation_time + std::chrono::hours(24) }; } filename_t _base_filename; @@ -247,7 +249,8 @@ private: details::file_helper _file_helper; }; -typedef daily_file_sink daily_file_sink_mt; -typedef daily_file_sink daily_file_sink_st; +using daily_file_sink_mt = daily_file_sink; +using daily_file_sink_st = daily_file_sink; + } } diff --git a/include/spdlog/sinks/msvc_sink.h b/include/spdlog/sinks/msvc_sink.h index 22b52c8f..d230613e 100644 --- a/include/spdlog/sinks/msvc_sink.h +++ b/include/spdlog/sinks/msvc_sink.h @@ -23,15 +23,13 @@ namespace sinks * MSVC sink (logging using OutputDebugStringA) */ template -class msvc_sink : public base_sink < Mutex > +class msvc_sink : public base_sink { public: explicit msvc_sink() { } - - protected: void _sink_it(const details::log_msg& msg) override { @@ -42,8 +40,8 @@ protected: {} }; -typedef msvc_sink msvc_sink_mt; -typedef msvc_sink msvc_sink_st; +using msvc_sink_mt = msvc_sink; +using msvc_sink_st = msvc_sink; } } diff --git a/include/spdlog/sinks/null_sink.h b/include/spdlog/sinks/null_sink.h index 7605ac68..9a4fd08d 100644 --- a/include/spdlog/sinks/null_sink.h +++ b/include/spdlog/sinks/null_sink.h @@ -16,7 +16,7 @@ namespace sinks { template -class null_sink : public base_sink < Mutex > +class null_sink : public base_sink { protected: void _sink_it(const details::log_msg&) override @@ -26,8 +26,9 @@ protected: {} }; -typedef null_sink null_sink_st; -typedef null_sink null_sink_mt; + +using null_sink_mt = null_sink; +using null_sink_st = null_sink; } } diff --git a/include/spdlog/sinks/ostream_sink.h b/include/spdlog/sinks/ostream_sink.h index 1e5b261c..9648cc05 100644 --- a/include/spdlog/sinks/ostream_sink.h +++ b/include/spdlog/sinks/ostream_sink.h @@ -16,13 +16,12 @@ namespace spdlog namespace sinks { template -class ostream_sink: public base_sink +class ostream_sink : public base_sink { public: explicit ostream_sink(std::ostream& os, bool force_flush=false) :_ostream(os), _force_flush(force_flush) {} ostream_sink(const ostream_sink&) = delete; ostream_sink& operator=(const ostream_sink&) = delete; - virtual ~ostream_sink() = default; protected: void _sink_it(const details::log_msg& msg) override @@ -41,7 +40,8 @@ protected: bool _force_flush; }; -typedef ostream_sink ostream_sink_mt; -typedef ostream_sink ostream_sink_st; +using ostream_sink_mt = ostream_sink; +using ostream_sink_st = ostream_sink; + } } diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index af61b54c..ff7a144e 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -3,7 +3,6 @@ // Distributed under the MIT License (http://opensource.org/licenses/MIT) // - #pragma once #include "../details/log_msg.h" @@ -15,12 +14,8 @@ namespace sinks class sink { public: - sink() - { - _level = level::trace; - } + virtual ~sink() = default; - virtual ~sink() {} virtual void log(const details::log_msg& msg) = 0; virtual void flush() = 0; @@ -29,8 +24,7 @@ public: level::level_enum level() const; private: - level_t _level; - + level_t _level{ level::trace }; }; inline bool sink::should_log(level::level_enum msg_level) const @@ -50,4 +44,3 @@ inline level::level_enum sink::level() const } } - diff --git a/include/spdlog/sinks/stdout_sinks.h b/include/spdlog/sinks/stdout_sinks.h index dfbfccd5..0567a05d 100644 --- a/include/spdlog/sinks/stdout_sinks.h +++ b/include/spdlog/sinks/stdout_sinks.h @@ -21,14 +21,16 @@ template class stdout_sink SPDLOG_FINAL : public base_sink { using MyType = stdout_sink; + public: - stdout_sink() - {} + explicit stdout_sink() = default; + static std::shared_ptr instance() { static std::shared_ptr instance = std::make_shared(); return instance; } + protected: void _sink_it(const details::log_msg& msg) override { @@ -42,22 +44,23 @@ protected: } }; -typedef stdout_sink stdout_sink_st; -typedef stdout_sink stdout_sink_mt; - +using stdout_sink_mt = stdout_sink; +using stdout_sink_st = stdout_sink; template class stderr_sink SPDLOG_FINAL : public base_sink { using MyType = stderr_sink; + public: - stderr_sink() - {} + explicit stderr_sink() = default; + static std::shared_ptr instance() { static std::shared_ptr instance = std::make_shared(); return instance; } + protected: void _sink_it(const details::log_msg& msg) override { @@ -71,7 +74,8 @@ protected: } }; -typedef stderr_sink stderr_sink_mt; -typedef stderr_sink stderr_sink_st; +using stderr_sink_mt = stderr_sink; +using stderr_sink_st = stderr_sink; + } } diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index c4a726a8..d1ffc5c8 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -33,18 +33,19 @@ public: syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER): _ident(ident) { - _priorities[static_cast(level::trace)] = LOG_DEBUG; - _priorities[static_cast(level::debug)] = LOG_DEBUG; - _priorities[static_cast(level::info)] = LOG_INFO; - _priorities[static_cast(level::warn)] = LOG_WARNING; - _priorities[static_cast(level::err)] = LOG_ERR; - _priorities[static_cast(level::critical)] = LOG_CRIT; - _priorities[static_cast(level::off)] = LOG_INFO; + _priorities[static_cast(level::trace)] = LOG_DEBUG; + _priorities[static_cast(level::debug)] = LOG_DEBUG; + _priorities[static_cast(level::info)] = LOG_INFO; + _priorities[static_cast(level::warn)] = LOG_WARNING; + _priorities[static_cast(level::err)] = LOG_ERR; + _priorities[static_cast(level::critical)] = LOG_CRIT; + _priorities[static_cast(level::off)] = LOG_INFO; //set ident to be program name if empty ::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility); } - ~syslog_sink() + + ~syslog_sink() override { ::closelog(); } @@ -72,7 +73,7 @@ private: // int syslog_prio_from_level(const details::log_msg &msg) const { - return _priorities[static_cast(msg.level)]; + return _priorities[static_cast(msg.level)]; } }; } diff --git a/include/spdlog/sinks/wincolor_sink.h b/include/spdlog/sinks/wincolor_sink.h index f9e86c7a..3b4495b0 100644 --- a/include/spdlog/sinks/wincolor_sink.h +++ b/include/spdlog/sinks/wincolor_sink.h @@ -21,8 +21,8 @@ namespace sinks /* * Windows color console sink. Uses WriteConsoleA to write to the console with colors */ -template -class wincolor_sink: public base_sink +template +class wincolor_sink : public base_sink { public: const WORD BOLD = FOREGROUND_INTENSITY; @@ -42,7 +42,7 @@ public: colors_[level::off] = 0; } - virtual ~wincolor_sink() + ~wincolor_sink() override { this->flush(); } @@ -50,8 +50,15 @@ public: wincolor_sink(const wincolor_sink& other) = delete; wincolor_sink& operator=(const wincolor_sink& other) = delete; + // change the color for the given level + void set_color(level::level_enum level, WORD color) + { + std::lock_guard lock(base_sink::_mutex); + colors_[level] = color; + } + protected: - virtual void _sink_it(const details::log_msg& msg) override + void _sink_it(const details::log_msg& msg) override { auto color = colors_[msg.level]; auto orig_attribs = set_console_attribs(color); @@ -59,18 +66,11 @@ protected: SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors } - virtual void _flush() override + void _flush() override { // windows console always flushed? } - // change the color for the given level - void set_color(level::level_enum level, WORD color) - { - std::lock_guard lock(base_sink::_mutex); - colors_[level] = color; - } - private: HANDLE out_handle_; std::unordered_map colors_; @@ -85,37 +85,37 @@ private: back_color &= static_cast(~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY)); // keep the background color unchanged SetConsoleTextAttribute(out_handle_, attribs | back_color); - return orig_buffer_info.wAttributes; //return orig attribs + return orig_buffer_info.wAttributes; //return orig attribs } }; // // windows color console to stdout // -template -class wincolor_stdout_sink: public wincolor_sink +template +class wincolor_stdout_sink : public wincolor_sink { public: wincolor_stdout_sink() : wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE)) {} }; -typedef wincolor_stdout_sink wincolor_stdout_sink_mt; -typedef wincolor_stdout_sink wincolor_stdout_sink_st; +using wincolor_stdout_sink_mt = wincolor_stdout_sink; +using wincolor_stdout_sink_st = wincolor_stdout_sink; // // windows color console to stderr // -template -class wincolor_stderr_sink: public wincolor_sink +template +class wincolor_stderr_sink : public wincolor_sink { public: wincolor_stderr_sink() : wincolor_sink(GetStdHandle(STD_ERROR_HANDLE)) {} }; -typedef wincolor_stderr_sink wincolor_stderr_sink_mt; -typedef wincolor_stderr_sink wincolor_stderr_sink_st; +using wincolor_stderr_sink_mt = wincolor_stderr_sink; +using wincolor_stderr_sink_st = wincolor_stderr_sink; } } diff --git a/include/spdlog/sinks/windebug_sink.h b/include/spdlog/sinks/windebug_sink.h index c22e9522..37d67245 100644 --- a/include/spdlog/sinks/windebug_sink.h +++ b/include/spdlog/sinks/windebug_sink.h @@ -17,11 +17,11 @@ namespace sinks /* * Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink) */ -template +template using windebug_sink = msvc_sink; -typedef msvc_sink_mt windebug_sink_mt; -typedef msvc_sink_st windebug_sink_st; +using windebug_sink_mt = msvc_sink_mt; +using windebug_sink_st = msvc_sink_st; } } diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index ff79ef6e..8965e59f 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -7,9 +7,7 @@ #pragma once -#define SPDLOG_VERSION "0.16.3" -#include "tweakme.h" #include "common.h" #include "logger.h" @@ -48,7 +46,7 @@ void flush_on(level::level_enum log_level); // // Set global error handler // -void set_error_handler(log_err_handler); +void set_error_handler(log_err_handler handler); // // Turn on async mode (off by default) and set the queue size for each async_logger. @@ -58,7 +56,7 @@ void set_error_handler(log_err_handler); // // async_overflow_policy (optional, block_retry by default): // async_overflow_policy::block_retry - if queue is full, block until queue has room for the new log entry. -// async_overflow_policy::discard_log_msg - never block and discard any new messages when queue overflows. +// async_overflow_policy::discard_log_msg - never block and discard any new messages when queue overflows. // // worker_warmup_cb (optional): // callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity) @@ -86,7 +84,7 @@ std::shared_ptr rotating_logger_mt(const std::string& logger_name, const std::shared_ptr rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); // -// Create file logger which creates new file on the given time (default in midnight): +// Create file logger which creates new file on the given time (default in midnight): // std::shared_ptr daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); std::shared_ptr daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); @@ -131,7 +129,7 @@ std::shared_ptr create(const std::string& logger_name, const It& sinks_b // Example: // spdlog::create("mylog", "dailylog_filename"); template -std::shared_ptr create(const std::string& logger_name, Args...); +std::shared_ptr create(const std::string& logger_name, Args... args); // Create and register an async logger with a single sink std::shared_ptr create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function& worker_teardown_cb = nullptr); diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h index ad01a09c..c5509622 100644 --- a/include/spdlog/tweakme.h +++ b/include/spdlog/tweakme.h @@ -54,7 +54,7 @@ /////////////////////////////////////////////////////////////////////////////// // Uncomment if logger name logging is not needed. -// This will prevent spdlog from copying the logger name on each log call. +// This will prevent spdlog from copying the logger name on each log call. // // #define SPDLOG_NO_NAME /////////////////////////////////////////////////////////////////////////////// @@ -156,5 +156,5 @@ /////////////////////////////////////////////////////////////////////////////// // Uncomment to customize level names (e.g. "MT TRACE") // -// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" } +// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" } /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 94bf8e76..119fab55 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,23 +1,23 @@ -project(spdlog-utests) - -enable_testing() -find_package(Threads REQUIRED) - -set(SPDLOG_UTESTS_SOURCES - errors.cpp - file_helper.cpp - file_log.cpp - format.cpp - includes.h - registry.cpp - test_macros.cpp - utils.cpp - utils.h - main.cpp) - -add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES}) -target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads) -target_link_libraries(${PROJECT_NAME} PRIVATE spdlog) - -add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) -file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") +project(spdlog-utests CXX) +enable_testing() +find_package(Threads REQUIRED) + +set(SPDLOG_UTESTS_SOURCES + errors.cpp + file_helper.cpp + file_log.cpp + test_misc.cpp + test_pattern_formatter + includes.h + registry.cpp + test_macros.cpp + utils.cpp + utils.h + main.cpp) + +add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES}) +target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads) +target_link_libraries(${PROJECT_NAME} PRIVATE spdlog) + +add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") diff --git a/tests/Makefile b/tests/Makefile index b1935e75..e8333186 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,10 @@ CXX ?= g++ ifeq ($(STYLE),printf) $(info *** PRINTF STYLE ***) - CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O2 -I../include + CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O3 -I../include else $(info *** FORMAT STYLE ***) - CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O2 -I../include + CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O3 -I../include endif LDPFALGS = -pthread diff --git a/tests/catch.hpp b/tests/catch.hpp index 925c6bff..5585d1e3 100644 --- a/tests/catch.hpp +++ b/tests/catch.hpp @@ -2913,7 +2913,7 @@ namespace Catch { for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) if( !(*it)->matches( testCase ) ) return false; - return true; + return true; } }; diff --git a/tests/file_helper.cpp b/tests/file_helper.cpp index d127c8f0..f57397eb 100644 --- a/tests/file_helper.cpp +++ b/tests/file_helper.cpp @@ -3,7 +3,8 @@ */ #include "includes.h" -using namespace spdlog::details; +using spdlog::details::log_msg; +using spdlog::details::file_helper; static const std::string target_filename = "logs/file_helper_test.txt"; @@ -15,7 +16,6 @@ static void write_with_helper(file_helper &helper, size_t howmany) helper.flush(); } - TEST_CASE("file_helper_filename", "[file_helper::filename()]]") { prepare_logdir(); @@ -25,8 +25,6 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]") REQUIRE(helper.filename() == target_filename); } - - TEST_CASE("file_helper_size", "[file_helper::size()]]") { prepare_logdir(); @@ -40,7 +38,6 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]") REQUIRE(get_filesize(target_filename) == expected_size); } - TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]") { prepare_logdir(); @@ -73,8 +70,6 @@ TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]") REQUIRE(helper.size() == expected_size); } - - static void test_split_ext(const char* fname, const char* expect_base, const char* expect_ext) { spdlog::filename_t filename(fname); @@ -91,7 +86,6 @@ static void test_split_ext(const char* fname, const char* expect_base, const cha REQUIRE(ext == expected_ext); } - TEST_CASE("file_helper_split_by_extenstion", "[file_helper::split_by_extenstion()]]") { test_split_ext("mylog.txt", "mylog", ".txt"); @@ -113,6 +107,3 @@ TEST_CASE("file_helper_split_by_extenstion", "[file_helper::split_by_extenstion( test_split_ext(".", ".", ""); test_split_ext("..txt", ".", ".txt"); } - - - diff --git a/tests/format.cpp b/tests/test_misc.cpp similarity index 92% rename from tests/format.cpp rename to tests/test_misc.cpp index adb8ba8b..9afaa932 100644 --- a/tests/format.cpp +++ b/tests/test_misc.cpp @@ -1,4 +1,3 @@ - #include "includes.h" template @@ -13,14 +12,9 @@ std::string log_info(const T& what, spdlog::level::level_enum logger_level = spd oss_logger.set_pattern("%v"); oss_logger.info(what); - return oss.str().substr(0, oss.str().length() - spdlog::details::os::eol_size); + return oss.str().substr(0, oss.str().length() - strlen(spdlog::details::os::default_eol)); } - - - - - TEST_CASE("basic_logging ", "[basic_logging]") { //const char @@ -39,7 +33,6 @@ TEST_CASE("basic_logging ", "[basic_logging]") //REQUIRE(log_info(some_logged_class("some_val")) == "some_val"); } - TEST_CASE("log_levels", "[log_levels]") { REQUIRE(log_info("Hello", spdlog::level::err) == ""); @@ -54,3 +47,6 @@ TEST_CASE("log_levels", "[log_levels]") + + + diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp new file mode 100644 index 00000000..51b0f35d --- /dev/null +++ b/tests/test_pattern_formatter.cpp @@ -0,0 +1,61 @@ +#include "includes.h" + +// log to str and return it +static std::string log_to_str(const std::string& msg, const std::shared_ptr& formatter = nullptr) +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + spdlog::logger oss_logger("pattern_tester", oss_sink); + oss_logger.set_level(spdlog::level::info); + if (formatter) oss_logger.set_formatter(formatter); + oss_logger.info(msg); + return oss.str(); +} + +TEST_CASE("custom eol", "[pattern_formatter]") +{ + std::string msg = "Hello custom eol test"; + std::string eol = ";)"; + auto formatter = std::make_shared("%v", spdlog::pattern_time_type::local, ";)"); + + REQUIRE(log_to_str(msg, formatter) == msg + eol); +} + +TEST_CASE("empty format", "[pattern_formatter]") +{ + auto formatter = std::make_shared("", spdlog::pattern_time_type::local, ""); + REQUIRE(log_to_str("Some message", formatter) == ""); +} + +TEST_CASE("empty format2", "[pattern_formatter]") +{ + auto formatter = std::make_shared("", spdlog::pattern_time_type::local, "\n"); + REQUIRE(log_to_str("Some message", formatter) == "\n"); +} + +TEST_CASE("level", "[pattern_formatter]") +{ + auto formatter = std::make_shared("[%l] %v", spdlog::pattern_time_type::local, "\n"); + REQUIRE(log_to_str("Some message", formatter) == "[info] Some message\n"); +} + +TEST_CASE("short level", "[pattern_formatter]") +{ + auto formatter = std::make_shared("[%L] %v", spdlog::pattern_time_type::local, "\n"); + REQUIRE(log_to_str("Some message", formatter) == "[I] Some message\n"); +} + +TEST_CASE("name", "[pattern_formatter]") +{ + auto formatter = std::make_shared("[%n] %v", spdlog::pattern_time_type::local, "\n"); + REQUIRE(log_to_str("Some message", formatter) == "[pattern_tester] Some message\n"); +} + +TEST_CASE("date MM/DD/YY ", "[pattern_formatter]") +{ + auto formatter = std::make_shared("%D %v", spdlog::pattern_time_type::local, "\n"); + auto now_tm = spdlog::details::os::localtime(); + std::stringstream oss; + oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2) << (now_tm.tm_year + 1900) % 1000 << " Some message\n"; + REQUIRE(log_to_str("Some message", formatter) == oss.str()); +} diff --git a/tests/tests.vcxproj b/tests/tests.vcxproj index ef9d78f9..286c6979 100644 --- a/tests/tests.vcxproj +++ b/tests/tests.vcxproj @@ -21,6 +21,7 @@ {59A07559-5F38-4DD6-A7FA-DB4153690B42} tests + 10.0.16299.0 @@ -128,10 +129,11 @@ - + + diff --git a/tests/tests.vcxproj.filters b/tests/tests.vcxproj.filters index adc86e7b..d1fdf73d 100644 --- a/tests/tests.vcxproj.filters +++ b/tests/tests.vcxproj.filters @@ -18,9 +18,6 @@ Source Files - - Source Files - Source Files @@ -39,6 +36,12 @@ Source Files + + Source Files + + + Source Files +