pattern per sink and pattern caching
This commit is contained in:
		@@ -49,7 +49,7 @@
 | 
			
		||||
#define SPDLOG_DEPRECATED
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "fmt/fmt.h"
 | 
			
		||||
#include "spdlog/fmt/fmt.h"
 | 
			
		||||
 | 
			
		||||
namespace spdlog {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,6 @@ inline void spdlog::async_logger::backend_log_(details::log_msg &incoming_log_ms
 | 
			
		||||
{
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        formatter_->format(incoming_log_msg);
 | 
			
		||||
        for (auto &s : sinks_)
 | 
			
		||||
        {
 | 
			
		||||
            if (s->should_log(incoming_log_msg.level))
 | 
			
		||||
 
 | 
			
		||||
@@ -80,10 +80,10 @@ public:
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void write(const log_msg &msg)
 | 
			
		||||
    void write(const fmt::memory_buffer &buf)
 | 
			
		||||
    {
 | 
			
		||||
        size_t msg_size = msg.formatted.size();
 | 
			
		||||
        auto data = msg.formatted.data();
 | 
			
		||||
        size_t msg_size = buf.size();
 | 
			
		||||
        auto data = buf.data();
 | 
			
		||||
        if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
 | 
			
		||||
        {
 | 
			
		||||
            throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,12 @@ inline void append_str(const std::string &str, fmt::memory_buffer &dest)
 | 
			
		||||
    dest.append(str_ptr, str_ptr + str.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void append_c_str(const char *c_str, fmt::memory_buffer &dest)
 | 
			
		||||
{
 | 
			
		||||
    auto str_size = strlen(c_str);
 | 
			
		||||
    dest.append(c_str, c_str + str_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest)
 | 
			
		||||
{
 | 
			
		||||
    const char *buf_ptr = buf.data();
 | 
			
		||||
@@ -74,7 +80,7 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest)
 | 
			
		||||
    append_int(n, dest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void append_and_pad6(int n, fmt::memory_buffer &dest)
 | 
			
		||||
inline void append_and_pad6(int n, fmt::memory_buffer &dest)
 | 
			
		||||
{
 | 
			
		||||
    if (n > 99999)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -38,11 +38,10 @@ struct log_msg
 | 
			
		||||
    log_clock::time_point time;
 | 
			
		||||
    size_t thread_id;
 | 
			
		||||
    fmt::memory_buffer raw;
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    size_t msg_id{0};
 | 
			
		||||
    // info about wrapping the formatted text with color
 | 
			
		||||
    size_t color_range_start{0};
 | 
			
		||||
    size_t color_range_end{0};
 | 
			
		||||
    mutable size_t color_range_start{0};
 | 
			
		||||
    mutable size_t color_range_end{0};
 | 
			
		||||
};
 | 
			
		||||
} // namespace details
 | 
			
		||||
} // namespace spdlog
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ template<class It>
 | 
			
		||||
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<pattern_formatter>("%+"))
 | 
			
		||||
    , level_(level::info)
 | 
			
		||||
    , flush_level_(level::off)
 | 
			
		||||
    , last_err_time_(0)
 | 
			
		||||
@@ -37,14 +36,19 @@ inline spdlog::logger::logger(const std::string &logger_name, spdlog::sink_ptr s
 | 
			
		||||
 | 
			
		||||
inline spdlog::logger::~logger() = default;
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
 | 
			
		||||
template<class FormatterT, typename... Args>
 | 
			
		||||
inline void spdlog::logger::set_formatter(const Args &... args)
 | 
			
		||||
{
 | 
			
		||||
    formatter_ = std::move(msg_formatter);
 | 
			
		||||
    for (auto &sink : sinks_)
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_ptr<FormatterT> formatter(new FormatterT(args...));
 | 
			
		||||
        sink->set_formatter(std::move(formatter));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_pattern(const std::string &pattern, pattern_time_type pattern_time)
 | 
			
		||||
{
 | 
			
		||||
    formatter_ = std::make_shared<pattern_formatter>(pattern, pattern_time);
 | 
			
		||||
    set_formatter<spdlog::pattern_formatter>(pattern, pattern_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename... Args>
 | 
			
		||||
@@ -288,7 +292,6 @@ inline void spdlog::logger::sink_it_(details::log_msg &msg)
 | 
			
		||||
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
 | 
			
		||||
    incr_msg_counter_(msg);
 | 
			
		||||
#endif
 | 
			
		||||
    formatter_->format(msg);
 | 
			
		||||
    for (auto &sink : sinks_)
 | 
			
		||||
    {
 | 
			
		||||
        if (sink->should_log(msg.level))
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ class flag_formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~flag_formatter() = default;
 | 
			
		||||
    virtual void format(details::log_msg &msg, const std::tm &tm_time) = 0;
 | 
			
		||||
    virtual void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -36,27 +36,27 @@ public:
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
class name_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(*msg.logger_name, msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(*msg.logger_name, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// log level appender
 | 
			
		||||
class level_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(level::to_str(msg.level), msg.formatted);
 | 
			
		||||
        fmt_helper::append_c_str(level::to_str(msg.level), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// short log level appender
 | 
			
		||||
class short_level_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(level::to_short_str(msg.level), msg.formatted);
 | 
			
		||||
        fmt_helper::append_c_str(level::to_short_str(msg.level), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -78,9 +78,9 @@ static int to12h(const tm &t)
 | 
			
		||||
static const std::string days[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
 | 
			
		||||
class a_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(days[tm_time.tm_wday], msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(days[tm_time.tm_wday], dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -88,9 +88,9 @@ class a_formatter : public flag_formatter
 | 
			
		||||
static const std::string full_days[]{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
 | 
			
		||||
class A_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(full_days[tm_time.tm_wday], msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(full_days[tm_time.tm_wday], dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -98,9 +98,9 @@ class A_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
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(months[tm_time.tm_mon], msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(months[tm_time.tm_mon], dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -109,205 +109,203 @@ static const std::string full_months[]{
 | 
			
		||||
    "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
 | 
			
		||||
class B_formatter : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(full_months[tm_time.tm_mon], msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(full_months[tm_time.tm_mon], dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Date and time representation (Thu Aug 23 15:35:46 2014)
 | 
			
		||||
class c_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt::format_to(msg.formatted, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday); //
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(' ');
 | 
			
		||||
        fmt_helper::append_int(tm_time.tm_year + 1900, msg.formatted);
 | 
			
		||||
        fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday); //
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, dest);
 | 
			
		||||
        dest.push_back(' ');
 | 
			
		||||
        fmt_helper::append_int(tm_time.tm_year + 1900, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// year - 2 digit
 | 
			
		||||
class C_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_year % 100, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_year % 100, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
 | 
			
		||||
class D_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mon + 1, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back('/');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mday, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back('/');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_year % 100, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mon + 1, dest);
 | 
			
		||||
        dest.push_back('/');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mday, dest);
 | 
			
		||||
        dest.push_back('/');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_year % 100, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// year - 4 digit
 | 
			
		||||
class Y_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_int(tm_time.tm_year + 1900, msg.formatted);
 | 
			
		||||
        fmt_helper::append_int(tm_time.tm_year + 1900, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// month 1-12
 | 
			
		||||
class m_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mon + 1, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mon + 1, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// day of month 1-31
 | 
			
		||||
class d_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{:02}", tm_time.tm_mday);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mday, msg.formatted);
 | 
			
		||||
        // fmt::format_to(dest, "{:02}", tm_time.tm_mday);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mday, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(to12h(tm_time), msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(to12h(tm_time), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// minutes 0-59
 | 
			
		||||
class M_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// seconds 0-59
 | 
			
		||||
class S_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// milliseconds
 | 
			
		||||
class e_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
			
		||||
        fmt_helper::append_and_pad3(static_cast<int>(millis), msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad3(static_cast<int>(millis), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// microseconds
 | 
			
		||||
class f_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000;
 | 
			
		||||
        fmt_helper::append_and_pad6(static_cast<int>(micros), msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad6(static_cast<int>(micros), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// nanoseconds
 | 
			
		||||
class F_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000;
 | 
			
		||||
        fmt::format_to(msg.formatted, "{:09}", static_cast<int>(ns));
 | 
			
		||||
        fmt::format_to(dest, "{:09}", static_cast<int>(ns));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class E_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{}", seconds);
 | 
			
		||||
        fmt_helper::append_int(seconds, msg.formatted);
 | 
			
		||||
        fmt_helper::append_int(seconds, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// AM/PM
 | 
			
		||||
class p_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt::format_to(msg.formatted, "{}", ampm(tm_time));
 | 
			
		||||
        fmt::format_to(dest, "{}", ampm(tm_time));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 12 hour clock 02:55:02 pm
 | 
			
		||||
class r_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{:02}:{:02}:{:02} {}", to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ampm(tm_time));
 | 
			
		||||
        fmt_helper::append_and_pad2(to12h(tm_time), msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, msg.formatted);
 | 
			
		||||
        fmt::format_to(msg.formatted, " {}", ampm(tm_time));
 | 
			
		||||
        // fmt::format_to(dest, "{:02}:{:02}:{:02} {}", to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ampm(tm_time));
 | 
			
		||||
        fmt_helper::append_and_pad2(to12h(tm_time), dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, dest);
 | 
			
		||||
        fmt::format_to(dest, " {}", ampm(tm_time));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 24-hour HH:MM time, equivalent to %H:%M
 | 
			
		||||
class R_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{:02}:{:02}", tm_time.tm_hour, tm_time.tm_min);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
 | 
			
		||||
class T_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{:02}:{:02}:{:02}", tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, msg.formatted);
 | 
			
		||||
        // fmt::format_to(dest, "{:02}:{:02}:{:02}", tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -321,13 +319,14 @@ public:
 | 
			
		||||
    z_formatter(const z_formatter &) = delete;
 | 
			
		||||
    z_formatter &operator=(const z_formatter &) = delete;
 | 
			
		||||
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
        int total_minutes = get_cached_offset(msg, tm_time);
 | 
			
		||||
#else
 | 
			
		||||
        // No need to chache under gcc,
 | 
			
		||||
        // it is very fast (already stored in tm.tm_gmtoff)
 | 
			
		||||
        (void)(msg);
 | 
			
		||||
        int total_minutes = os::utc_minutes_offset(tm_time);
 | 
			
		||||
#endif
 | 
			
		||||
        bool is_negative = total_minutes < 0;
 | 
			
		||||
@@ -344,21 +343,19 @@ public:
 | 
			
		||||
 | 
			
		||||
        int h = total_minutes / 60;
 | 
			
		||||
        int m = total_minutes % 60;
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{}{:02}:{:02}", sign, h, m);
 | 
			
		||||
        msg.formatted.push_back(sign);
 | 
			
		||||
        fmt_helper::append_and_pad2(h, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(m, msg.formatted);
 | 
			
		||||
        dest.push_back(sign);
 | 
			
		||||
        fmt_helper::append_and_pad2(h, dest);
 | 
			
		||||
        dest.push_back(':');
 | 
			
		||||
        fmt_helper::append_and_pad2(m, dest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    log_clock::time_point last_update_{std::chrono::seconds(0)};
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    int offset_minutes_{0};
 | 
			
		||||
    std::mutex mutex_;
 | 
			
		||||
 | 
			
		||||
    int get_cached_offset(const log_msg &msg, const std::tm &tm_time)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> l(mutex_);
 | 
			
		||||
        if (msg.time - last_update_ >= cache_refresh)
 | 
			
		||||
        {
 | 
			
		||||
            offset_minutes_ = os::utc_minutes_offset(tm_time);
 | 
			
		||||
@@ -366,42 +363,42 @@ private:
 | 
			
		||||
        }
 | 
			
		||||
        return offset_minutes_;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Thread id
 | 
			
		||||
class t_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{}", msg.thread_id);
 | 
			
		||||
        fmt_helper::append_size_t(msg.thread_id, msg.formatted);
 | 
			
		||||
        // fmt::format_to(dest, "{}", msg.thread_id);
 | 
			
		||||
        fmt_helper::append_size_t(msg.thread_id, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Current pid
 | 
			
		||||
class pid_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        // fmt::format_to(msg.formatted, "{}", details::os::pid());
 | 
			
		||||
        fmt_helper::append_int(details::os::pid(), msg.formatted);
 | 
			
		||||
        fmt_helper::append_int(details::os::pid(), dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// message counter formatter
 | 
			
		||||
class i_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt::format_to(msg.formatted, "{:06}", msg.msg_id);
 | 
			
		||||
        fmt::format_to(dest, "{:06}", msg.msg_id);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class v_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_buf(msg.raw, msg.formatted);
 | 
			
		||||
        fmt_helper::append_buf(msg.raw, dest);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -412,9 +409,9 @@ public:
 | 
			
		||||
        : ch_(ch)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted.push_back(ch_);
 | 
			
		||||
        dest.push_back(ch_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
@@ -431,9 +428,9 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
        str_ += ch;
 | 
			
		||||
    }
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        fmt_helper::append_str(str_, msg.formatted);
 | 
			
		||||
        fmt_helper::append_str(str_, dest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
@@ -443,16 +440,16 @@ private:
 | 
			
		||||
// mark the color range. expect it to be in the form of "%^colored text%$"
 | 
			
		||||
class color_start_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.color_range_start = msg.formatted.size();
 | 
			
		||||
        msg.color_range_start = dest.size();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
class color_stop_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.color_range_end = msg.formatted.size();
 | 
			
		||||
        msg.color_range_end = dest.size();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -460,54 +457,80 @@ class color_stop_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
 | 
			
		||||
class full_formatter SPDLOG_FINAL : public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg &msg, const std::tm &tm_time) override
 | 
			
		||||
    void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
			
		||||
    {
 | 
			
		||||
#ifndef SPDLOG_NO_DATETIME
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
 | 
			
		||||
        // each second cache the header
 | 
			
		||||
        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
 | 
			
		||||
        if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            cached_header_ = std::move(fmt::memory_buffer());
 | 
			
		||||
            cached_header_.push_back('[');
 | 
			
		||||
            fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_);
 | 
			
		||||
            cached_header_.push_back('-');
 | 
			
		||||
 | 
			
		||||
            fmt_helper::append_and_pad2(tm_time.tm_mon + 1, cached_header_);
 | 
			
		||||
            cached_header_.push_back('-');
 | 
			
		||||
 | 
			
		||||
            fmt_helper::append_and_pad2(tm_time.tm_mday, cached_header_);
 | 
			
		||||
            cached_header_.push_back(' ');
 | 
			
		||||
 | 
			
		||||
            fmt_helper::append_and_pad2(tm_time.tm_hour, cached_header_);
 | 
			
		||||
            cached_header_.push_back(':');
 | 
			
		||||
 | 
			
		||||
            fmt_helper::append_and_pad2(tm_time.tm_min, cached_header_);
 | 
			
		||||
            cached_header_.push_back(':');
 | 
			
		||||
 | 
			
		||||
            fmt_helper::append_and_pad2(tm_time.tm_sec, cached_header_);
 | 
			
		||||
            cached_header_.push_back('.');
 | 
			
		||||
 | 
			
		||||
            cached_seconds_ts_ = seconds;
 | 
			
		||||
        }
 | 
			
		||||
        fmt_helper::append_buf(cached_header_, dest);
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
			
		||||
 | 
			
		||||
        msg.formatted.push_back('[');
 | 
			
		||||
        fmt_helper::append_int(tm_time.tm_year + 1900, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back('-');
 | 
			
		||||
        if (cached_millis_.size() == 0 || millis != cached_millis_ts_)
 | 
			
		||||
        {
 | 
			
		||||
            cached_millis_ = std::move(fmt::memory_buffer());
 | 
			
		||||
            fmt_helper::append_and_pad3(static_cast<int>(millis), cached_millis_);
 | 
			
		||||
            cached_millis_.push_back(']');
 | 
			
		||||
            cached_millis_.push_back(' ');
 | 
			
		||||
            cached_millis_ts_ = millis;
 | 
			
		||||
        }
 | 
			
		||||
        fmt_helper::append_buf(cached_millis_, dest);
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mon + 1, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back('-');
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_mday, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(' ');
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_hour, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_min, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(':');
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad2(tm_time.tm_sec, msg.formatted);
 | 
			
		||||
        msg.formatted.push_back('.');
 | 
			
		||||
 | 
			
		||||
        fmt_helper::append_and_pad3(static_cast<int>(millis), msg.formatted);
 | 
			
		||||
        msg.formatted.push_back(']');
 | 
			
		||||
        msg.formatted.push_back(' ');
 | 
			
		||||
 | 
			
		||||
        // no datetime needed
 | 
			
		||||
#else
 | 
			
		||||
#else // no datetime needed
 | 
			
		||||
        (void)tm_time;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef SPDLOG_NO_NAME
 | 
			
		||||
        fmt_helper::append_str(*msg.logger_name, msg.formatted);
 | 
			
		||||
        dest.push_back('[');
 | 
			
		||||
        fmt_helper::append_str(*msg.logger_name, dest);
 | 
			
		||||
        dest.push_back(']');
 | 
			
		||||
        dest.push_back(' ');
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        msg.formatted.push_back('[');
 | 
			
		||||
        dest.push_back('[');
 | 
			
		||||
 | 
			
		||||
        // wrap the level name with color
 | 
			
		||||
        msg.color_range_start = msg.formatted.size();
 | 
			
		||||
        fmt_helper::append_str(level::to_str(msg.level), msg.formatted);
 | 
			
		||||
        msg.color_range_end = msg.formatted.size();
 | 
			
		||||
        msg.formatted.push_back(']');
 | 
			
		||||
        msg.formatted.push_back(' ');
 | 
			
		||||
        fmt_helper::append_buf(msg.raw, msg.formatted);
 | 
			
		||||
        msg.color_range_start = dest.size();
 | 
			
		||||
        fmt_helper::append_c_str(level::to_str(msg.level), dest);
 | 
			
		||||
        msg.color_range_end = dest.size();
 | 
			
		||||
        dest.push_back(']');
 | 
			
		||||
        dest.push_back(' ');
 | 
			
		||||
        fmt_helper::append_buf(msg.raw, dest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    long cached_seconds_ts_{0};
 | 
			
		||||
    long cached_millis_ts_{0};
 | 
			
		||||
    fmt::memory_buffer cached_header_;
 | 
			
		||||
    fmt::memory_buffer cached_millis_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace details
 | 
			
		||||
@@ -704,7 +727,7 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::tm spdlog::pattern_formatter::get_time(details::log_msg &msg)
 | 
			
		||||
inline std::tm spdlog::pattern_formatter::get_time(const details::log_msg &msg)
 | 
			
		||||
{
 | 
			
		||||
    if (pattern_time_ == pattern_time_type::local)
 | 
			
		||||
    {
 | 
			
		||||
@@ -713,7 +736,7 @@ inline std::tm spdlog::pattern_formatter::get_time(details::log_msg &msg)
 | 
			
		||||
    return details::os::gmtime(log_clock::to_time_t(msg.time));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::pattern_formatter::format(details::log_msg &msg)
 | 
			
		||||
inline void spdlog::pattern_formatter::format(const details::log_msg &msg, fmt::memory_buffer &dest)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifndef SPDLOG_NO_DATETIME
 | 
			
		||||
@@ -723,8 +746,8 @@ inline void spdlog::pattern_formatter::format(details::log_msg &msg)
 | 
			
		||||
#endif
 | 
			
		||||
    for (auto &f : formatters_)
 | 
			
		||||
    {
 | 
			
		||||
        f->format(msg, tm_time);
 | 
			
		||||
        f->format(msg, tm_time, dest);
 | 
			
		||||
    }
 | 
			
		||||
    // write eol
 | 
			
		||||
    details::fmt_helper::append_str(eol_, msg.formatted);
 | 
			
		||||
    details::fmt_helper::append_str(eol_, dest);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,10 +46,9 @@ public:
 | 
			
		||||
        auto logger_name = new_logger->name();
 | 
			
		||||
        throw_if_exists(logger_name);
 | 
			
		||||
 | 
			
		||||
        if (formatter_)
 | 
			
		||||
        {
 | 
			
		||||
            new_logger->set_formatter(formatter_);
 | 
			
		||||
        }
 | 
			
		||||
        // create default formatter if not exists
 | 
			
		||||
 | 
			
		||||
        new_logger->set_pattern(formatter_pattern_);
 | 
			
		||||
 | 
			
		||||
        if (err_handler_)
 | 
			
		||||
        {
 | 
			
		||||
@@ -82,23 +81,13 @@ public:
 | 
			
		||||
        return tp_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_formatter(formatter_ptr f)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
			
		||||
        formatter_ = f;
 | 
			
		||||
        for (auto &l : loggers_)
 | 
			
		||||
        {
 | 
			
		||||
            l.second->set_formatter(formatter_);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_pattern(const std::string &pattern)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
			
		||||
        formatter_ = std::make_shared<pattern_formatter>(pattern);
 | 
			
		||||
        formatter_pattern_ = pattern;
 | 
			
		||||
        for (auto &l : loggers_)
 | 
			
		||||
        {
 | 
			
		||||
            l.second->set_formatter(formatter_);
 | 
			
		||||
            l.second->set_pattern(pattern);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -184,7 +173,7 @@ private:
 | 
			
		||||
    Mutex mutex_;
 | 
			
		||||
    Mutex tp_mutex_;
 | 
			
		||||
    std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
 | 
			
		||||
    formatter_ptr formatter_;
 | 
			
		||||
    std::string formatter_pattern_ = "%+";
 | 
			
		||||
    level::level_enum level_ = level::info;
 | 
			
		||||
    level::level_enum flush_level_ = level::off;
 | 
			
		||||
    log_err_handler err_handler_;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "fmt/fmt.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
@@ -12,31 +13,32 @@
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace spdlog {
 | 
			
		||||
namespace details {
 | 
			
		||||
class flag_formatter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~formatter() = default;
 | 
			
		||||
    virtual void format(details::log_msg &msg) = 0;
 | 
			
		||||
    virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace details {
 | 
			
		||||
class flag_formatter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class pattern_formatter SPDLOG_FINAL : public formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    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;
 | 
			
		||||
    pattern_formatter(const pattern_formatter &) = default;
 | 
			
		||||
    pattern_formatter &operator=(const pattern_formatter &) = default;
 | 
			
		||||
    void format(const details::log_msg &msg, fmt::memory_buffer &dest) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const std::string eol_;
 | 
			
		||||
    const pattern_time_type pattern_time_;
 | 
			
		||||
    std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
 | 
			
		||||
    std::tm get_time(details::log_msg &msg);
 | 
			
		||||
    std::tm get_time(const details::log_msg &msg);
 | 
			
		||||
    void handle_flag(char flag);
 | 
			
		||||
    void compile_pattern(const std::string &pattern);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,12 @@
 | 
			
		||||
// Thread safe logger (except for set_pattern(..), set_formatter(..) and set_error_handler())
 | 
			
		||||
// Has name, log level, vector of std::shared sink pointers and formatter
 | 
			
		||||
// Upon each log write the logger:
 | 
			
		||||
// 1. Checks if its log level is enough to log the message
 | 
			
		||||
// 2. Format the message using the formatter function
 | 
			
		||||
// 3. Pass the formatted message to its sinks to performa the actual logging
 | 
			
		||||
// 1. Checks if its log level is enough to log the message and if yes:
 | 
			
		||||
// 2. Call the underlying sinks to do the job.
 | 
			
		||||
// 3. Each sink use its own private copy of a formatter to format the message and send to its destination.
 | 
			
		||||
//
 | 
			
		||||
// The use of private formatter per sink provides the opportunity to cache some formatted data,
 | 
			
		||||
// and support customize format per each sink.
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/formatter.h"
 | 
			
		||||
@@ -111,8 +114,15 @@ public:
 | 
			
		||||
    void set_level(level::level_enum log_level);
 | 
			
		||||
    level::level_enum level() const;
 | 
			
		||||
    const std::string &name() const;
 | 
			
		||||
 | 
			
		||||
    // create a pattern formatter all the sinks in this logger.
 | 
			
		||||
    // each sink gets itw own private copy of a formatter object.
 | 
			
		||||
    void set_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local);
 | 
			
		||||
    void set_formatter(formatter_ptr msg_formatter);
 | 
			
		||||
 | 
			
		||||
    // create a FormatterT formatter all the sinks in this logger.
 | 
			
		||||
    // each sink gets itw own private copy of a formatter object.
 | 
			
		||||
    template<class FormatterT, typename... Args>
 | 
			
		||||
    void set_formatter(const Args &... args);
 | 
			
		||||
 | 
			
		||||
    void flush();
 | 
			
		||||
    void flush_on(level::level_enum log_level);
 | 
			
		||||
@@ -137,7 +147,6 @@ protected:
 | 
			
		||||
 | 
			
		||||
    const std::string name_;
 | 
			
		||||
    std::vector<sink_ptr> sinks_;
 | 
			
		||||
    formatter_ptr formatter_;
 | 
			
		||||
    spdlog::level_t level_;
 | 
			
		||||
    spdlog::level_t flush_level_;
 | 
			
		||||
    log_err_handler err_handler_;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,17 @@ public:
 | 
			
		||||
    void log(const details::log_msg &msg) override
 | 
			
		||||
    {
 | 
			
		||||
        const android_LogPriority priority = convert_to_android(msg.level);
 | 
			
		||||
        const char *msg_output = (use_raw_msg_ ? msg.raw.c_str() : msg.formatted.c_str());
 | 
			
		||||
        fmt::memory_buffer formatted;
 | 
			
		||||
        if (use_raw_msg_)
 | 
			
		||||
        {
 | 
			
		||||
            formatted.append(msg.raw.data(), msg.raw.data() + msg.raw.size());
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            formatter_->format(msg, formatted);
 | 
			
		||||
        }
 | 
			
		||||
        formatted.push_back('\0');
 | 
			
		||||
        const char *msg_output = formatted.data();
 | 
			
		||||
 | 
			
		||||
        // See system/core/liblog/logger_write.c for explanation of return value
 | 
			
		||||
        int ret = __android_log_write(priority, tag_.c_str(), msg_output);
 | 
			
		||||
 
 | 
			
		||||
@@ -88,20 +88,23 @@ public:
 | 
			
		||||
        // Wrap the originally formatted message in color codes.
 | 
			
		||||
        // If color is not supported in the terminal, log as is instead.
 | 
			
		||||
        std::lock_guard<mutex_t> lock(mutex_);
 | 
			
		||||
 | 
			
		||||
        fmt::memory_buffer formatted;
 | 
			
		||||
        formatter_->format(msg, formatted);
 | 
			
		||||
        if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
 | 
			
		||||
        {
 | 
			
		||||
            // before color range
 | 
			
		||||
            print_range_(msg, 0, msg.color_range_start);
 | 
			
		||||
            print_range_(formatted, 0, msg.color_range_start);
 | 
			
		||||
            // in color range
 | 
			
		||||
            print_ccode_(colors_[msg.level]);
 | 
			
		||||
            print_range_(msg, msg.color_range_start, msg.color_range_end);
 | 
			
		||||
            print_range_(formatted, msg.color_range_start, msg.color_range_end);
 | 
			
		||||
            print_ccode_(reset);
 | 
			
		||||
            // after color range
 | 
			
		||||
            print_range_(msg, msg.color_range_end, msg.formatted.size());
 | 
			
		||||
            print_range_(formatted, msg.color_range_end, formatted.size());
 | 
			
		||||
        }
 | 
			
		||||
        else // no color
 | 
			
		||||
        {
 | 
			
		||||
            print_range_(msg, 0, msg.formatted.size());
 | 
			
		||||
            print_range_(formatted, 0, formatted.size());
 | 
			
		||||
        }
 | 
			
		||||
        fflush(target_file_);
 | 
			
		||||
    }
 | 
			
		||||
@@ -117,9 +120,9 @@ private:
 | 
			
		||||
    {
 | 
			
		||||
        fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);
 | 
			
		||||
    }
 | 
			
		||||
    void print_range_(const details::log_msg &msg, size_t start, size_t end)
 | 
			
		||||
    void print_range_(const fmt::memory_buffer &formatted, size_t start, size_t end)
 | 
			
		||||
    {
 | 
			
		||||
        fwrite(msg.formatted.data() + start, sizeof(char), end - start, target_file_);
 | 
			
		||||
        fwrite(formatted.data() + start, sizeof(char), end - start, target_file_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FILE *target_file_;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,20 @@ template<class Mutex>
 | 
			
		||||
class base_sink : public sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    base_sink() = default;
 | 
			
		||||
    base_sink()
 | 
			
		||||
        : sink()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    base_sink(const std::string &formatter_pattern)
 | 
			
		||||
        : sink(formatter_pattern)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    base_sink(std::unique_ptr<spdlog::formatter> sink_formatter)
 | 
			
		||||
        : sink(std::move(sink_formatter))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    base_sink(const base_sink &) = delete;
 | 
			
		||||
    base_sink &operator=(const base_sink &) = delete;
 | 
			
		||||
@@ -29,7 +42,9 @@ public:
 | 
			
		||||
    void log(const details::log_msg &msg) SPDLOG_FINAL override
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(mutex_);
 | 
			
		||||
        sink_it_(msg);
 | 
			
		||||
        fmt::memory_buffer formatted;
 | 
			
		||||
        formatter_->format(msg, formatted);
 | 
			
		||||
        sink_it_(msg, formatted);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush() SPDLOG_FINAL override
 | 
			
		||||
@@ -39,7 +54,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void sink_it_(const details::log_msg &msg) = 0;
 | 
			
		||||
    virtual void sink_it_(const details::log_msg &msg, const fmt::memory_buffer &formatted) = 0;
 | 
			
		||||
    virtual void flush_() = 0;
 | 
			
		||||
    Mutex mutex_;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -76,14 +76,14 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &msg) override
 | 
			
		||||
    void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
 | 
			
		||||
    {
 | 
			
		||||
        if (std::chrono::system_clock::now() >= rotation_tp_)
 | 
			
		||||
        {
 | 
			
		||||
            file_helper_.open(FileNameCalc::calc_filename(base_filename_));
 | 
			
		||||
            rotation_tp_ = next_rotation_tp_();
 | 
			
		||||
        }
 | 
			
		||||
        file_helper_.write(msg);
 | 
			
		||||
        file_helper_.write(formatted);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush_() override
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,12 @@ template<class Mutex>
 | 
			
		||||
class null_sink : public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &) override {}
 | 
			
		||||
    void sink_it_(const details::log_msg &, const fmt::memory_buffer &) override {}
 | 
			
		||||
 | 
			
		||||
    void flush_() override {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using null_sink_mt = null_sink<details::null_mutex>;
 | 
			
		||||
using null_sink_mt = null_sink<std::mutex>;
 | 
			
		||||
using null_sink_st = null_sink<details::null_mutex>;
 | 
			
		||||
 | 
			
		||||
} // namespace sinks
 | 
			
		||||
 
 | 
			
		||||
@@ -26,9 +26,9 @@ public:
 | 
			
		||||
    ostream_sink &operator=(const ostream_sink &) = delete;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &msg) override
 | 
			
		||||
    void sink_it_(const details::log_msg &msg, const fmt::memory_buffer &formatted) override
 | 
			
		||||
    {
 | 
			
		||||
        ostream_.write(msg.formatted.data(), msg.formatted.size());
 | 
			
		||||
        ostream_.write(formatted.data(), formatted.size());
 | 
			
		||||
        if (force_flush_)
 | 
			
		||||
            ostream_.flush();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,15 +55,15 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &msg) override
 | 
			
		||||
    void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
 | 
			
		||||
    {
 | 
			
		||||
        current_size_ += msg.formatted.size();
 | 
			
		||||
        current_size_ += formatted.size();
 | 
			
		||||
        if (current_size_ > max_size_)
 | 
			
		||||
        {
 | 
			
		||||
            rotate_();
 | 
			
		||||
            current_size_ = msg.formatted.size();
 | 
			
		||||
            current_size_ = formatted.size();
 | 
			
		||||
        }
 | 
			
		||||
        file_helper_.write(msg);
 | 
			
		||||
        file_helper_.write(formatted);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush_() override
 | 
			
		||||
 
 | 
			
		||||
@@ -33,9 +33,9 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &msg) override
 | 
			
		||||
    void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
 | 
			
		||||
    {
 | 
			
		||||
        file_helper_.write(msg);
 | 
			
		||||
        file_helper_.write(formatted);
 | 
			
		||||
        if (force_flush_)
 | 
			
		||||
        {
 | 
			
		||||
            file_helper_.flush();
 | 
			
		||||
 
 | 
			
		||||
@@ -6,39 +6,62 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
#include "spdlog/formatter.h"
 | 
			
		||||
 | 
			
		||||
namespace spdlog {
 | 
			
		||||
namespace sinks {
 | 
			
		||||
class sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    // default sink ctor with default pattern formatter
 | 
			
		||||
    sink()
 | 
			
		||||
        : formatter_(std::unique_ptr<spdlog::formatter>(new pattern_formatter("%+")))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit sink(const std::string &formatter_pattern)
 | 
			
		||||
        : formatter_(std::unique_ptr<spdlog::formatter>(new pattern_formatter(formatter_pattern)))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // sink with custom formatter
 | 
			
		||||
    explicit sink(std::unique_ptr<spdlog::formatter> sink_formatter)
 | 
			
		||||
        : formatter_(std::move(sink_formatter))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~sink() = default;
 | 
			
		||||
 | 
			
		||||
    virtual void log(const details::log_msg &msg) = 0;
 | 
			
		||||
    virtual void flush() = 0;
 | 
			
		||||
 | 
			
		||||
    bool should_log(level::level_enum msg_level) const;
 | 
			
		||||
    void set_level(level::level_enum log_level);
 | 
			
		||||
    level::level_enum level() const;
 | 
			
		||||
    bool should_log(level::level_enum msg_level) const
 | 
			
		||||
    {
 | 
			
		||||
        return msg_level >= level_.load(std::memory_order_relaxed);
 | 
			
		||||
    }
 | 
			
		||||
    void set_level(level::level_enum log_level)
 | 
			
		||||
    {
 | 
			
		||||
        level_.store(log_level);
 | 
			
		||||
    }
 | 
			
		||||
    level::level_enum level() const
 | 
			
		||||
    {
 | 
			
		||||
        return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void set_formatter(std::unique_ptr<spdlog::formatter> sink_formatter)
 | 
			
		||||
    {
 | 
			
		||||
        formatter_ = std::move(sink_formatter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    spdlog::formatter *formatter()
 | 
			
		||||
    {
 | 
			
		||||
        return formatter_.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    level_t level_{level::trace};
 | 
			
		||||
    std::unique_ptr<spdlog::formatter> formatter_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool sink::should_log(level::level_enum msg_level) const
 | 
			
		||||
{
 | 
			
		||||
    return msg_level >= level_.load(std::memory_order_relaxed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void sink::set_level(level::level_enum log_level)
 | 
			
		||||
{
 | 
			
		||||
    level_.store(log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline level::level_enum sink::level() const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<spdlog::level::level_enum>(level_.load(std::memory_order_relaxed));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace sinks
 | 
			
		||||
} // namespace spdlog
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../fmt/fmt.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/details/traits.h"
 | 
			
		||||
@@ -63,22 +64,23 @@ public:
 | 
			
		||||
    void log(const details::log_msg &msg) SPDLOG_FINAL override
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<mutex_t> lock(mutex_);
 | 
			
		||||
 | 
			
		||||
        fmt::memory_buffer formatted;
 | 
			
		||||
        formatter_->format(msg, formatted);
 | 
			
		||||
        if (msg.color_range_end > msg.color_range_start)
 | 
			
		||||
        {
 | 
			
		||||
            // before color range
 | 
			
		||||
            print_range_(msg, 0, msg.color_range_start);
 | 
			
		||||
            print_range_(formatted, 0, msg.color_range_start);
 | 
			
		||||
 | 
			
		||||
            // in color range
 | 
			
		||||
            auto orig_attribs = set_console_attribs(colors_[msg.level]);
 | 
			
		||||
            print_range_(msg, msg.color_range_start, msg.color_range_end);
 | 
			
		||||
            print_range_(formatted, msg.color_range_start, msg.color_range_end);
 | 
			
		||||
            ::SetConsoleTextAttribute(out_handle_, orig_attribs); // reset to orig colors
 | 
			
		||||
                                                                  // after color range
 | 
			
		||||
            print_range_(msg, msg.color_range_end, msg.formatted.size());
 | 
			
		||||
            print_range_(formatted, msg.color_range_end, formatted.size());
 | 
			
		||||
        }
 | 
			
		||||
        else // print without colors if color range is invalid
 | 
			
		||||
        {
 | 
			
		||||
            print_range_(msg, 0, msg.formatted.size());
 | 
			
		||||
            print_range_(formatted, 0, formatted.size());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -103,10 +105,10 @@ private:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // print a range of formatted message to console
 | 
			
		||||
    void print_range_(const details::log_msg &msg, size_t start, size_t end)
 | 
			
		||||
    void print_range_(const fmt::memory_buffer formatted, size_t start, size_t end)
 | 
			
		||||
    {
 | 
			
		||||
        auto size = static_cast<DWORD>(end - start);
 | 
			
		||||
        ::WriteConsoleA(out_handle_, msg.formatted.data() + start, size, nullptr, nullptr);
 | 
			
		||||
        ::WriteConsoleA(out_handle_, formatted.data() + start, size, nullptr, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HANDLE out_handle_;
 | 
			
		||||
 
 | 
			
		||||
@@ -62,11 +62,6 @@ inline void set_pattern(const std::string &format_string)
 | 
			
		||||
    details::registry::instance().set_pattern(format_string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void set_formatter(formatter_ptr f)
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().set_formatter(std::move(f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Set global logging level
 | 
			
		||||
//
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,9 @@ static const std::string target_filename = "logs/file_helper_test.txt";
 | 
			
		||||
static void write_with_helper(file_helper &helper, size_t howmany)
 | 
			
		||||
{
 | 
			
		||||
    log_msg msg;
 | 
			
		||||
 | 
			
		||||
    fmt::format_to(msg.formatted, "{}", std::string(howmany, '1'));
 | 
			
		||||
    helper.write(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    fmt::format_to(formatted, "{}", std::string(howmany, '1'));
 | 
			
		||||
    helper.write(formatted);
 | 
			
		||||
    helper.flush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,16 @@
 | 
			
		||||
#include "includes.h"
 | 
			
		||||
 | 
			
		||||
// log to str and return it
 | 
			
		||||
static std::string log_to_str(const std::string &msg, const std::shared_ptr<spdlog::formatter> &formatter = nullptr)
 | 
			
		||||
template<typename... Args>
 | 
			
		||||
 | 
			
		||||
static std::string log_to_str(const std::string &msg, const Args &... args)
 | 
			
		||||
{
 | 
			
		||||
    std::ostringstream oss;
 | 
			
		||||
    auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(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.set_formatter<spdlog::pattern_formatter>(args...);
 | 
			
		||||
 | 
			
		||||
    oss_logger.info(msg);
 | 
			
		||||
    return oss.str();
 | 
			
		||||
}
 | 
			
		||||
@@ -19,49 +19,44 @@ TEST_CASE("custom eol", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    std::string msg = "Hello custom eol test";
 | 
			
		||||
    std::string eol = ";)";
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("%v", spdlog::pattern_time_type::local, ";)");
 | 
			
		||||
    // auto formatter = std::make_shared<spdlog::pattern_formatter>("%v", spdlog::pattern_time_type::local, ";)");
 | 
			
		||||
    std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter("%v", spdlog::pattern_time_type::local, ";)"));
 | 
			
		||||
 | 
			
		||||
    REQUIRE(log_to_str(msg, formatter) == msg + eol);
 | 
			
		||||
    REQUIRE(log_to_str(msg, "%v", spdlog::pattern_time_type::local, ";)") == msg + eol);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("empty format", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", formatter) == "");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "") == "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("empty format2", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", formatter) == "\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "", spdlog::pattern_time_type::local, "\n") == "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("level", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("[%l] %v", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", formatter) == "[info] Some message\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "[%l] %v", spdlog::pattern_time_type::local, "\n") == "[info] Some message\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("short level", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("[%L] %v", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", formatter) == "[I] Some message\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "[%L] %v", spdlog::pattern_time_type::local, "\n") == "[I] Some message\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("name", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("[%n] %v", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", formatter) == "[pattern_tester] Some message\n");
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "[%n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("%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());
 | 
			
		||||
    REQUIRE(log_to_str("Some message", "%D %v", spdlog::pattern_time_type::local, "\n") == oss.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("color range test1", "[pattern_formatter]")
 | 
			
		||||
@@ -69,27 +64,30 @@ TEST_CASE("color range test1", "[pattern_formatter]")
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%v%$", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    fmt::format_to(msg.raw, "Hello");
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 0);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 5);
 | 
			
		||||
    REQUIRE(log_to_str("hello", formatter) == "hello\n");
 | 
			
		||||
    REQUIRE(log_to_str("hello", "%^%v%$", spdlog::pattern_time_type::local, "\n") == "hello\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("color range test2", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%$", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 0);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 0);
 | 
			
		||||
    REQUIRE(log_to_str("", formatter) == "\n");
 | 
			
		||||
    REQUIRE(log_to_str("", "%^%$", spdlog::pattern_time_type::local, "\n") == "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("color range test3", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("%^***%$");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 0);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 3);
 | 
			
		||||
}
 | 
			
		||||
@@ -99,17 +97,19 @@ TEST_CASE("color range test4", "[pattern_formatter]")
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("XX%^YYY%$", spdlog::pattern_time_type::local, "\n");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    fmt::format_to(msg.raw, "ignored");
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 2);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 5);
 | 
			
		||||
    REQUIRE(log_to_str("ignored", formatter) == "XXYYY\n");
 | 
			
		||||
    REQUIRE(log_to_str("ignored", "XX%^YYY%$", spdlog::pattern_time_type::local, "\n") == "XXYYY\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("color range test5", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("**%^");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 2);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 0);
 | 
			
		||||
}
 | 
			
		||||
@@ -118,7 +118,8 @@ TEST_CASE("color range test6", "[pattern_formatter]")
 | 
			
		||||
{
 | 
			
		||||
    auto formatter = std::make_shared<spdlog::pattern_formatter>("**%$");
 | 
			
		||||
    spdlog::details::log_msg msg;
 | 
			
		||||
    formatter->format(msg);
 | 
			
		||||
    fmt::memory_buffer formatted;
 | 
			
		||||
    formatter->format(msg, formatted);
 | 
			
		||||
    REQUIRE(msg.color_range_start == 0);
 | 
			
		||||
    REQUIRE(msg.color_range_end == 2);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void sink_it_(const details::log_msg &) override
 | 
			
		||||
    void sink_it_(const details::log_msg &, const fmt::memory_buffer &) override
 | 
			
		||||
    {
 | 
			
		||||
        msg_counter_++;
 | 
			
		||||
        std::this_thread::sleep_for(delay_);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user