Pattern formatter optimizations
This commit is contained in:
		@@ -26,17 +26,13 @@ inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest)
 | 
				
			|||||||
    dest.append(buf_ptr, buf_ptr + buf.size());
 | 
					    dest.append(buf_ptr, buf_ptr + buf.size());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void append_int(int n, fmt::memory_buffer &dest)
 | 
					template<typename T>
 | 
				
			||||||
 | 
					inline void append_int(T n, fmt::memory_buffer &dest)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fmt::format_int i(n);
 | 
					    fmt::format_int i(n);
 | 
				
			||||||
    dest.append(i.data(), i.data() + i.size());
 | 
					    dest.append(i.data(), i.data() + i.size());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void append_size_t(size_t n, fmt::memory_buffer &dest)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    fmt::format_int i(n);
 | 
					 | 
				
			||||||
    dest.append(i.data(), i.data() + i.size());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void append_and_pad2(int n, fmt::memory_buffer &dest)
 | 
					inline void append_and_pad2(int n, fmt::memory_buffer &dest)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -64,12 +60,17 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (n > 9) // 10-99
 | 
					    if (n > 9) // 10-99
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        dest.push_back('0');
 | 
					        dest.push_back('0');		
 | 
				
			||||||
 | 
							dest.push_back('0' + n / 10);
 | 
				
			||||||
 | 
							dest.push_back('0' + n % 10);		
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (n >= 0)
 | 
					    else if (n >= 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        dest.push_back('0');
 | 
					        dest.push_back('0');
 | 
				
			||||||
        dest.push_back('0');
 | 
					        dest.push_back('0');
 | 
				
			||||||
 | 
							dest.push_back('0' + n);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // negatives (unlikely, but just in case let fmt deal with it)
 | 
					    // negatives (unlikely, but just in case let fmt deal with it)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
@@ -77,7 +78,7 @@ inline void append_and_pad3(int n, fmt::memory_buffer &dest)
 | 
				
			|||||||
        fmt::format_to(dest, "{:03}", n);
 | 
					        fmt::format_to(dest, "{:03}", n);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    append_int(n, dest);
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void append_and_pad6(int n, fmt::memory_buffer &dest)
 | 
					inline void append_and_pad6(int n, fmt::memory_buffer &dest)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -460,13 +460,12 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
 | 
				
			|||||||
    void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
					    void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
#ifndef SPDLOG_NO_DATETIME
 | 
					#ifndef SPDLOG_NO_DATETIME
 | 
				
			||||||
        auto duration = msg.time.time_since_epoch();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // each second cache the header
 | 
					        // each second cache the header
 | 
				
			||||||
 | 
					        auto duration = msg.time.time_since_epoch();
 | 
				
			||||||
        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
 | 
					        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
 | 
				
			||||||
        if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
 | 
					        if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					 | 
				
			||||||
            cached_header_ = std::move(fmt::memory_buffer());
 | 
					            cached_header_ = std::move(fmt::memory_buffer());
 | 
				
			||||||
            cached_header_.push_back('[');
 | 
					            cached_header_.push_back('[');
 | 
				
			||||||
            fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_);
 | 
					            fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_);
 | 
				
			||||||
@@ -491,19 +490,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        fmt_helper::append_buf(cached_header_, dest);
 | 
					        fmt_helper::append_buf(cached_header_, dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
					        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
				
			||||||
 | 
					        fmt_helper::append_and_pad3(static_cast<int>(millis), dest);
 | 
				
			||||||
        if (cached_millis_.size() == 0 || millis != cached_millis_ts_)
 | 
					        dest.push_back(']');
 | 
				
			||||||
        {
 | 
					        dest.push_back(' ');
 | 
				
			||||||
            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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else // no datetime needed
 | 
					#else // no datetime needed
 | 
				
			||||||
        (void)tm_time;
 | 
					        (void)tm_time;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -528,226 +518,237 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    std::chrono::seconds::rep cached_seconds_ts_{0};
 | 
					    std::chrono::seconds::rep cached_seconds_ts_{0};
 | 
				
			||||||
    std::chrono::milliseconds::rep cached_millis_ts_{0};
 | 
					 | 
				
			||||||
    fmt::memory_buffer cached_header_;
 | 
					    fmt::memory_buffer cached_header_;
 | 
				
			||||||
    fmt::memory_buffer cached_millis_;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace details
 | 
					} // namespace details
 | 
				
			||||||
} // namespace spdlog
 | 
					 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
// pattern_formatter inline impl
 | 
					 | 
				
			||||||
///////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
inline spdlog::pattern_formatter::pattern_formatter(const std::string &pattern, pattern_time_type pattern_time, std::string eol)
 | 
					 | 
				
			||||||
    : eol_(std::move(eol))
 | 
					 | 
				
			||||||
    , pattern_time_(pattern_time)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    compile_pattern(pattern);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void spdlog::pattern_formatter::compile_pattern(const std::string &pattern)
 | 
					class pattern_formatter SPDLOG_FINAL : public formatter
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto end = pattern.end();
 | 
					public:
 | 
				
			||||||
    std::unique_ptr<details::aggregate_formatter> user_chars;
 | 
					    explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
 | 
				
			||||||
    for (auto it = pattern.begin(); it != end; ++it)
 | 
					        std::string eol = spdlog::details::os::default_eol)
 | 
				
			||||||
 | 
					        : eol_(std::move(eol))
 | 
				
			||||||
 | 
					        , pattern_time_(pattern_time)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (*it == '%')
 | 
					        compile_pattern(pattern);
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (user_chars) // append user chars found so far
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                formatters_.push_back(std::move(user_chars));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // if(
 | 
					 | 
				
			||||||
            if (++it != end)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                handle_flag(*it);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else // chars not following the % sign should be displayed as is
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (!user_chars)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            user_chars->add_ch(*it);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (user_chars) // append raw chars found so far
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        formatters_.push_back(std::move(user_chars));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
inline void spdlog::pattern_formatter::handle_flag(char flag)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    switch (flag)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    // logger name
 | 
					 | 
				
			||||||
    case 'n':
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::name_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'l':
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::level_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'L':
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::short_level_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('t'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::t_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('v'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::v_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('a'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::a_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('A'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::A_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('b'):
 | 
					 | 
				
			||||||
    case ('h'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::b_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('B'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::B_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case ('c'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::c_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('C'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::C_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('Y'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::Y_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('D'):
 | 
					 | 
				
			||||||
    case ('x'):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::D_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('m'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::m_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('d'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::d_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('H'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::H_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('I'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::I_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('M'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::M_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('S'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::S_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('e'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::e_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('f'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::f_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case ('F'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::F_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('E'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::E_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('p'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::p_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('r'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::r_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('R'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::R_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('T'):
 | 
					 | 
				
			||||||
    case ('X'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::T_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('z'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::z_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('+'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::full_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('P'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::pid_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('i'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::i_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('^'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::color_start_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case ('$'):
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::color_stop_formatter());
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default: // Unknown flag appears as is
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::ch_formatter('%'));
 | 
					 | 
				
			||||||
        formatters_.emplace_back(new details::ch_formatter(flag));
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
inline std::tm spdlog::pattern_formatter::get_time(const details::log_msg &msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (pattern_time_ == pattern_time_type::local)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return details::os::localtime(log_clock::to_time_t(msg.time));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return details::os::gmtime(log_clock::to_time_t(msg.time));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
inline void spdlog::pattern_formatter::format(const details::log_msg &msg, fmt::memory_buffer &dest)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef SPDLOG_NO_DATETIME
 | 
					#ifndef SPDLOG_NO_DATETIME
 | 
				
			||||||
    auto tm_time = get_time(msg);
 | 
					        auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());
 | 
				
			||||||
#else
 | 
					        if (secs != last_log_secs_)
 | 
				
			||||||
    std::tm tm_time;
 | 
					        {
 | 
				
			||||||
 | 
					            cached_tm_ = get_time(msg);
 | 
				
			||||||
 | 
					            last_log_secs_ = secs;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    for (auto &f : formatters_)
 | 
					        for (auto &f : formatters_)
 | 
				
			||||||
    {
 | 
					        {
 | 
				
			||||||
        f->format(msg, tm_time, dest);
 | 
					            f->format(msg, cached_tm_, dest);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // write eol
 | 
				
			||||||
 | 
					        details::fmt_helper::append_str(eol_, dest);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // write eol
 | 
					
 | 
				
			||||||
    details::fmt_helper::append_str(eol_, dest);
 | 
					private:
 | 
				
			||||||
}
 | 
					    const std::string eol_;
 | 
				
			||||||
 | 
					    const pattern_time_type pattern_time_;
 | 
				
			||||||
 | 
					    std::tm cached_tm_{};
 | 
				
			||||||
 | 
					    std::chrono::seconds last_log_secs_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
 | 
				
			||||||
 | 
					    std::tm get_time(const details::log_msg &msg)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (pattern_time_ == pattern_time_type::local)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return details::os::localtime(log_clock::to_time_t(msg.time));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return details::os::gmtime(log_clock::to_time_t(msg.time));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void handle_flag(char flag)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        switch (flag)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // logger name
 | 
				
			||||||
 | 
					        case 'n':
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::name_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 'l':
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::level_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 'L':
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::short_level_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('t'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::t_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('v'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::v_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('a'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::a_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('A'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::A_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('b'):
 | 
				
			||||||
 | 
					        case ('h'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::b_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('B'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::B_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case ('c'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::c_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('C'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::C_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('Y'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::Y_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('D'):
 | 
				
			||||||
 | 
					        case ('x'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::D_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('m'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::m_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('d'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::d_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('H'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::H_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('I'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::I_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('M'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::M_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('S'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::S_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('e'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::e_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('f'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::f_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case ('F'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::F_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('E'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::E_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('p'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::p_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('r'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::r_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('R'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::R_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('T'):
 | 
				
			||||||
 | 
					        case ('X'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::T_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('z'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::z_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('+'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::full_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('P'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::pid_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('i'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::i_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('^'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::color_start_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case ('$'):
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::color_stop_formatter());
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: // Unknown flag appears as is
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::ch_formatter('%'));
 | 
				
			||||||
 | 
					            formatters_.emplace_back(new details::ch_formatter(flag));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void compile_pattern(const std::string &pattern)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto end = pattern.end();
 | 
				
			||||||
 | 
					        std::unique_ptr<details::aggregate_formatter> user_chars;
 | 
				
			||||||
 | 
					        for (auto it = pattern.begin(); it != end; ++it)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (*it == '%')
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (user_chars) // append user chars found so far
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    formatters_.push_back(std::move(user_chars));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // if(
 | 
				
			||||||
 | 
					                if (++it != end)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    handle_flag(*it);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else // chars not following the % sign should be displayed as is
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (!user_chars)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                user_chars->add_ch(*it);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (user_chars) // append raw chars found so far
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            formatters_.push_back(std::move(user_chars));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					} // namespace spdlog
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,28 +20,6 @@ public:
 | 
				
			|||||||
    virtual ~formatter() = default;
 | 
					    virtual ~formatter() = default;
 | 
				
			||||||
    virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 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 &) = 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(const details::log_msg &msg);
 | 
					 | 
				
			||||||
    void handle_flag(char flag);
 | 
					 | 
				
			||||||
    void compile_pattern(const std::string &pattern);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
} // namespace spdlog
 | 
					} // namespace spdlog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "details/pattern_formatter_impl.h"
 | 
					#include "details/pattern_formatter_impl.h"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user