* fixed bug in log formatmaster
| @@ -1,4 +1,5 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "interface/global.h" | #include "interface/global.h" | ||||
| #include "interface/iomanip.h" | |||||
| #include "interface/logger.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 | struct log_helper | ||||
| : public std::ostringstream | : public std::ostringstream | ||||
| { | { | ||||
| private: | |||||
| logger& _logger; | |||||
| log_entry_ptr_s _entry; | |||||
| public: | |||||
| cpplogging::logger& logger; | |||||
| log_entry_ptr_s entry; | |||||
| private: | private: | ||||
| /** | /** | ||||
| @@ -45,7 +45,7 @@ namespace cpplogging | |||||
| * | * | ||||
| * @param[in] p_logger Logger this log helper belongs to. | * @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. | * @brief Constructor. | ||||
| @@ -53,7 +53,7 @@ namespace cpplogging | |||||
| * @param[in] p_logger Logger this log helper belongs to. | * @param[in] p_logger Logger this log helper belongs to. | ||||
| * @param[in] p_entry Log entry to create. | * @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. | * @brief Destructor. Will finally write the log entry. | ||||
| @@ -12,35 +12,35 @@ namespace cpplogging | |||||
| /* log_helper */ | /* log_helper */ | ||||
| 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 | ||||
| ::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 | ||||
| ::~log_helper() | ::~log_helper() | ||||
| { | { | ||||
| _entry->message += str(); | |||||
| _logger.write_entry(_entry); | |||||
| entry->message += str(); | |||||
| logger.write_entry(entry); | |||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::level(log_level level) | ::level(log_level level) | ||||
| { | { | ||||
| _entry->level = level; | |||||
| entry->level = level; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::sender(const void * sender) | ::sender(const void * sender) | ||||
| { | { | ||||
| _entry->sender = sender; | |||||
| entry->sender = sender; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| @@ -50,43 +50,43 @@ namespace cpplogging | |||||
| { | { | ||||
| int status; | int status; | ||||
| auto name = abi::__cxa_demangle(typeid(T_sender).name(), 0, 0, &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; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::sender_type(const std::string& sender_type) | ::sender_type(const std::string& sender_type) | ||||
| { | { | ||||
| _entry->sender_type = sender_type; | |||||
| entry->sender_type = sender_type; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::file(const char * file) | ::file(const char * file) | ||||
| { | { | ||||
| _entry->file = file; | |||||
| entry->file = file; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::line(int line) | ::line(int line) | ||||
| { | { | ||||
| _entry->line = line; | |||||
| entry->line = line; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::message(const std::string& msg) | ::message(const std::string& msg) | ||||
| { | { | ||||
| _entry->message = msg; | |||||
| entry->message = msg; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::add_message(const std::string& msg) | ::add_message(const std::string& msg) | ||||
| { | { | ||||
| _entry->message += msg; | |||||
| entry->message += msg; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| @@ -94,7 +94,7 @@ namespace cpplogging | |||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::format(const std::string& fmt, T_args&&... args) | ::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; | return *this; | ||||
| } | } | ||||
| @@ -102,7 +102,7 @@ namespace cpplogging | |||||
| log_helper& log_helper | log_helper& log_helper | ||||
| ::add_format(const std::string& fmt, T_args&&... args) | ::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; | return *this; | ||||
| } | } | ||||
| @@ -13,7 +13,7 @@ namespace cpplogging | |||||
| static const std::string value( | static const std::string value( | ||||
| "[${runtime:-016.6f}] " | "[${runtime:-016.6f}] " | ||||
| "${level:5S} " | "${level:5S} " | ||||
| "${sender_type}(${sender:016x})@${thread:016x} " | |||||
| "${sender_type}(0x${sender:016x})@0x${thread:016x} " | |||||
| "${filename:-25}:${line:5d}$n" | "${filename:-25}:${line:5d}$n" | ||||
| "${message}"); | "${message}"); | ||||
| return value; | return value; | ||||
| @@ -242,6 +242,9 @@ consumer::format_type consumer::parse_format(const std::string& format) | |||||
| item.zero_fill = true; | item.zero_fill = true; | ||||
| x = c + 1; | x = c + 1; | ||||
| break; | 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' */ | /* in an other case switch back to 'is_text' */ | ||||
| default: | default: | ||||
| state = parser_state::is_text; | 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::setfill(i.zero_fill ? '0' : ' ') | ||||
| << std::setw(i.width) | << std::setw(i.width) | ||||
| << std::setprecision(i.precision); | << std::setprecision(i.precision); | ||||
| switch (i.token) | switch (i.token) | ||||
| { | { | ||||
| /* level */ | /* 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); | os << reinterpret_cast<uintptr_t>(e.sender); | ||||
| break; | break; | ||||
| case value_format::hex_lower: | case value_format::hex_lower: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << reinterpret_cast<uintptr_t>(e.sender) | << reinterpret_cast<uintptr_t>(e.sender) | ||||
| << std::dec; | << std::dec; | ||||
| break; | break; | ||||
| default: | default: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << std::uppercase | << std::uppercase | ||||
| << reinterpret_cast<uintptr_t>(e.sender) | << reinterpret_cast<uintptr_t>(e.sender) | ||||
| << std::nouppercase | << std::nouppercase | ||||
| @@ -593,14 +593,12 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os | |||||
| os << e.thread; | os << e.thread; | ||||
| break; | break; | ||||
| case value_format::hex_lower: | case value_format::hex_lower: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << e.thread | << e.thread | ||||
| << std::dec; | << std::dec; | ||||
| break; | break; | ||||
| default: | default: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << std::uppercase | << std::uppercase | ||||
| << e.thread | << e.thread | ||||
| << std::nouppercase | << std::nouppercase | ||||
| @@ -639,14 +637,12 @@ void consumer::write_formatted(const log_entry& e, const format_type& f, std::os | |||||
| os << e.line; | os << e.line; | ||||
| break; | break; | ||||
| case value_format::hex_lower: | case value_format::hex_lower: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << e.line | << e.line | ||||
| << std::dec; | << std::dec; | ||||
| break; | break; | ||||
| default: | default: | ||||
| os << "0x" | |||||
| << std::hex | |||||
| os << std::hex | |||||
| << std::uppercase | << std::uppercase | ||||
| << e.line | << e.line | ||||
| << std::nouppercase | << std::nouppercase | ||||