From 8bbb7206ba01b1c0779dab8382af59b2c287c633 Mon Sep 17 00:00:00 2001 From: bergmann Date: Wed, 24 Jul 2019 21:14:46 +0200 Subject: [PATCH] * implemented helper classes to set the log entry meta data using the stream operator * fixed bug in log format --- include/cpplogging/interface.h | 1 + include/cpplogging/interface/iomanip.h | 60 +++++++++++++++ include/cpplogging/interface/iomanip.inl | 75 +++++++++++++++++++ include/cpplogging/interface/logger.h | 10 +-- include/cpplogging/interface/logger.inl | 42 +++++------ .../cpplogging/manager/consumer/consumer.inl | 2 +- .../manager/consumer/formatting.cpp | 22 +++--- 7 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 include/cpplogging/interface/iomanip.h create mode 100644 include/cpplogging/interface/iomanip.inl diff --git a/include/cpplogging/interface.h b/include/cpplogging/interface.h index fb2e66c..1a42d2f 100644 --- a/include/cpplogging/interface.h +++ b/include/cpplogging/interface.h @@ -1,4 +1,5 @@ #pragma once #include "interface/global.h" +#include "interface/iomanip.h" #include "interface/logger.h" diff --git a/include/cpplogging/interface/iomanip.h b/include/cpplogging/interface/iomanip.h new file mode 100644 index 0000000..da389ea --- /dev/null +++ b/include/cpplogging/interface/iomanip.h @@ -0,0 +1,60 @@ +#pragma once + +#include "logger.h" + +namespace cpplogging +{ + + namespace __impl + { + template + struct stream_setter + { + using predicate_type = T_pred; + + predicate_type predicate; + }; + + template + std::ostream& operator<<(std::ostream &os, const stream_setter& x); + + template + constexpr decltype(auto) make_stream_setter(T_pred&& pred); + + } + + /** + * @brief Set the log level of a log stream. + */ + inline auto level(log_level level); + + /** + * @brief Set the sender of a log stream. + */ + template + inline auto sender(const T_sender * sender); + + /** + * @brief Set the sender type of a log stream. + */ + inline auto sender_type(const std::string& sender_type); + + /** + * @brief Set the file of a log stream. + */ + inline auto file(const char * file); + + /** + * @brief Set the line of a log stream. + */ + inline auto line(int line); + + /** + * @brief Manipulate the log entry. + */ + template + inline auto manipulate(T_pred&& pred); + +} + +#include "iomanip.inl" diff --git a/include/cpplogging/interface/iomanip.inl b/include/cpplogging/interface/iomanip.inl new file mode 100644 index 0000000..f314469 --- /dev/null +++ b/include/cpplogging/interface/iomanip.inl @@ -0,0 +1,75 @@ +#pragma once + +#include "iomanip.h" + +namespace cpplogging +{ + + namespace __impl + { + + /* stream_setter */ + + template + std::ostream& operator<<(std::ostream &os, const stream_setter& x) + { + auto lh = dynamic_cast(&os); + if (lh) + x.predicate(*lh->entry); + return os; + } + + template + constexpr decltype(auto) make_stream_setter(T_pred&& pred) + { return stream_setter { std::forward(pred) }; } + + } + + auto level(log_level level) + { + return __impl::make_stream_setter([=](log_entry& e){ + e.level = level; + }); + } + + template + auto sender(const T_sender * sender) + { + return __impl::make_stream_setter([=](log_entry& e){ + int status; + auto name = abi::__cxa_demangle(typeid(T_sender).name(), 0, 0, &status); + e.sender_type = std::string(name ? name : typeid(T_sender).name()); + e.sender = sender; + }); + } + + auto sender_type(const std::string& sender_type) + { + return __impl::make_stream_setter([=](log_entry& e){ + e.sender_type = sender_type; + }); + } + + auto file(const char * file) + { + return __impl::make_stream_setter([=](log_entry& e){ + e.file = file; + }); + } + + auto line(int line) + { + return __impl::make_stream_setter([=](log_entry& e){ + e.line = line; + }); + } + + template + auto manipulate(T_pred&& pred) + { + return __impl::make_stream_setter([p=std::forward(pred)](log_entry& e){ + p(e); + }); + } + +} diff --git a/include/cpplogging/interface/logger.h b/include/cpplogging/interface/logger.h index 4bb1a72..2f06bf7 100644 --- a/include/cpplogging/interface/logger.h +++ b/include/cpplogging/interface/logger.h @@ -24,9 +24,9 @@ namespace cpplogging struct log_helper : public std::ostringstream { - private: - logger& _logger; - log_entry_ptr_s _entry; + public: + cpplogging::logger& logger; + log_entry_ptr_s entry; private: /** @@ -45,7 +45,7 @@ namespace cpplogging * * @param[in] p_logger Logger this log helper belongs to. */ - inline log_helper(logger& p_logger); + inline log_helper(cpplogging::logger& p_logger); /** * @brief Constructor. @@ -53,7 +53,7 @@ namespace cpplogging * @param[in] p_logger Logger this log helper belongs to. * @param[in] p_entry Log entry to create. */ - inline log_helper(logger& p_logger, const log_entry_ptr_s& p_entry); + inline log_helper(cpplogging::logger& p_logger, const log_entry_ptr_s& p_entry); /** * @brief Destructor. Will finally write the log entry. diff --git a/include/cpplogging/interface/logger.inl b/include/cpplogging/interface/logger.inl index 69a633d..9ee311d 100644 --- a/include/cpplogging/interface/logger.inl +++ b/include/cpplogging/interface/logger.inl @@ -12,35 +12,35 @@ namespace cpplogging /* log_helper */ log_helper - ::log_helper(logger& p_logger) - : _logger (p_logger) - , _entry (new log_entry()) - { _entry->name = p_logger.name(); } + ::log_helper(cpplogging::logger& p_logger) + : logger (p_logger) + , entry (new log_entry()) + { entry->name = p_logger.name(); } log_helper - ::log_helper(logger& p_logger, const log_entry_ptr_s& p_entry) - : _logger (p_logger) - , _entry (p_entry) - { _entry->name = p_logger.name(); } + ::log_helper(cpplogging::logger& p_logger, const log_entry_ptr_s& p_entry) + : logger (p_logger) + , entry (p_entry) + { entry->name = p_logger.name(); } log_helper ::~log_helper() { - _entry->message += str(); - _logger.write_entry(_entry); + entry->message += str(); + logger.write_entry(entry); } log_helper& log_helper ::level(log_level level) { - _entry->level = level; + entry->level = level; return *this; } log_helper& log_helper ::sender(const void * sender) { - _entry->sender = sender; + entry->sender = sender; return *this; } @@ -50,43 +50,43 @@ namespace cpplogging { int status; auto name = abi::__cxa_demangle(typeid(T_sender).name(), 0, 0, &status); - _entry->sender_type = std::string(name ? name : typeid(T_sender).name()); - _entry->sender = sender; + entry->sender_type = std::string(name ? name : typeid(T_sender).name()); + entry->sender = sender; return *this; } log_helper& log_helper ::sender_type(const std::string& sender_type) { - _entry->sender_type = sender_type; + entry->sender_type = sender_type; return *this; } log_helper& log_helper ::file(const char * file) { - _entry->file = file; + entry->file = file; return *this; } log_helper& log_helper ::line(int line) { - _entry->line = line; + entry->line = line; return *this; } log_helper& log_helper ::message(const std::string& msg) { - _entry->message = msg; + entry->message = msg; return *this; } log_helper& log_helper ::add_message(const std::string& msg) { - _entry->message += msg; + entry->message += msg; return *this; } @@ -94,7 +94,7 @@ namespace cpplogging log_helper& log_helper ::format(const std::string& fmt, T_args&&... args) { - _entry->message = format(fmt, 0x8000, std::forward(args)...); + entry->message = format(fmt, 0x8000, std::forward(args)...); return *this; } @@ -102,7 +102,7 @@ namespace cpplogging log_helper& log_helper ::add_format(const std::string& fmt, T_args&&... args) { - _entry->message += format(fmt, 0x8000, std::forward(args)...); + entry->message += format(fmt, 0x8000, std::forward(args)...); return *this; } diff --git a/include/cpplogging/manager/consumer/consumer.inl b/include/cpplogging/manager/consumer/consumer.inl index 75684b9..0abb97e 100644 --- a/include/cpplogging/manager/consumer/consumer.inl +++ b/include/cpplogging/manager/consumer/consumer.inl @@ -13,7 +13,7 @@ namespace cpplogging static const std::string value( "[${runtime:-016.6f}] " "${level:5S} " - "${sender_type}(${sender:016x})@${thread:016x} " + "${sender_type}(0x${sender:016x})@0x${thread:016x} " "${filename:-25}:${line:5d}$n" "${message}"); return value; diff --git a/src/cpplogging/manager/consumer/formatting.cpp b/src/cpplogging/manager/consumer/formatting.cpp index 09ddddc..50d17c6 100644 --- a/src/cpplogging/manager/consumer/formatting.cpp +++ b/src/cpplogging/manager/consumer/formatting.cpp @@ -242,6 +242,9 @@ consumer::format_type consumer::parse_format(const std::string& format) item.zero_fill = true; x = c + 1; break; + /* if we are in state 'is_in_format_zero' we ignore zeros, because they belong to the length */ + case parser_state::is_in_format_zero: + break; /* in an other case switch back to 'is_text' */ default: state = parser_state::is_text; @@ -471,7 +474,6 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os << std::setfill(i.zero_fill ? '0' : ' ') << std::setw(i.width) << std::setprecision(i.precision); - switch (i.token) { /* level */ @@ -562,14 +564,12 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os os << reinterpret_cast(e.sender); break; case value_format::hex_lower: - os << "0x" - << std::hex + os << std::hex << reinterpret_cast(e.sender) << std::dec; break; default: - os << "0x" - << std::hex + os << std::hex << std::uppercase << reinterpret_cast(e.sender) << std::nouppercase @@ -593,14 +593,12 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os os << e.thread; break; case value_format::hex_lower: - os << "0x" - << std::hex + os << std::hex << e.thread << std::dec; break; default: - os << "0x" - << std::hex + os << std::hex << std::uppercase << e.thread << std::nouppercase @@ -639,14 +637,12 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os os << e.line; break; case value_format::hex_lower: - os << "0x" - << std::hex + os << std::hex << e.line << std::dec; break; default: - os << "0x" - << std::hex + os << std::hex << std::uppercase << e.line << std::nouppercase