* fixed bug in log formatmaster
| @@ -1,4 +1,5 @@ | |||
| #pragma once | |||
| #include "interface/global.h" | |||
| #include "interface/iomanip.h" | |||
| #include "interface/logger.h" | |||
| @@ -0,0 +1,60 @@ | |||
| #pragma once | |||
| #include "logger.h" | |||
| namespace cpplogging | |||
| { | |||
| namespace __impl | |||
| { | |||
| template<typename T_pred> | |||
| struct stream_setter | |||
| { | |||
| using predicate_type = T_pred; | |||
| predicate_type predicate; | |||
| }; | |||
| template<typename T_pred> | |||
| std::ostream& operator<<(std::ostream &os, const stream_setter<T_pred>& x); | |||
| template<typename T_pred> | |||
| 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<typename T_sender> | |||
| 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<typename T_pred> | |||
| inline auto manipulate(T_pred&& pred); | |||
| } | |||
| #include "iomanip.inl" | |||
| @@ -0,0 +1,75 @@ | |||
| #pragma once | |||
| #include "iomanip.h" | |||
| namespace cpplogging | |||
| { | |||
| namespace __impl | |||
| { | |||
| /* stream_setter */ | |||
| template<typename T_pred> | |||
| std::ostream& operator<<(std::ostream &os, const stream_setter<T_pred>& x) | |||
| { | |||
| auto lh = dynamic_cast<log_helper*>(&os); | |||
| if (lh) | |||
| x.predicate(*lh->entry); | |||
| return os; | |||
| } | |||
| template<typename T_pred> | |||
| constexpr decltype(auto) make_stream_setter(T_pred&& pred) | |||
| { return stream_setter<T_pred> { std::forward<T_pred>(pred) }; } | |||
| } | |||
| auto level(log_level level) | |||
| { | |||
| return __impl::make_stream_setter([=](log_entry& e){ | |||
| e.level = level; | |||
| }); | |||
| } | |||
| template<typename T_sender> | |||
| 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<typename T_pred> | |||
| auto manipulate(T_pred&& pred) | |||
| { | |||
| return __impl::make_stream_setter([p=std::forward<T_pred>(pred)](log_entry& e){ | |||
| p(e); | |||
| }); | |||
| } | |||
| } | |||
| @@ -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. | |||
| @@ -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<T_args>(args)...); | |||
| entry->message = format(fmt, 0x8000, std::forward<T_args>(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<T_args>(args)...); | |||
| entry->message += format(fmt, 0x8000, std::forward<T_args>(args)...); | |||
| return *this; | |||
| } | |||
| @@ -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; | |||
| @@ -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<uintptr_t>(e.sender); | |||
| break; | |||
| case value_format::hex_lower: | |||
| os << "0x" | |||
| << std::hex | |||
| os << std::hex | |||
| << reinterpret_cast<uintptr_t>(e.sender) | |||
| << std::dec; | |||
| break; | |||
| default: | |||
| os << "0x" | |||
| << std::hex | |||
| os << std::hex | |||
| << std::uppercase | |||
| << reinterpret_cast<uintptr_t>(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 | |||