mirror of
https://github.com/gabime/spdlog.git
synced 2025-10-02 11:29:01 +08:00
Merge branch 'v1.x' of https://github.com/gabime/spdlog into v1.x
This commit is contained in:
@@ -23,7 +23,7 @@ namespace spdlog {
|
||||
|
||||
// async logger factory - creates async loggers backed with thread pool.
|
||||
// if a global thread pool doesn't already exist, create it with default queue size of 8192 items and single thread.
|
||||
struct create_async
|
||||
struct async_factory
|
||||
{
|
||||
template<typename Sink, typename... SinkArgs>
|
||||
static std::shared_ptr<async_logger> create(const std::string &logger_name, SinkArgs &&... args)
|
||||
@@ -39,16 +39,16 @@ struct create_async
|
||||
}
|
||||
|
||||
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
|
||||
auto new_logger = std::make_shared<async_logger>(logger_name, std::move(sink), std::move(tp), async_overflow_policy::block_retry);
|
||||
auto new_logger = std::make_shared<async_logger>(logger_name, std::move(sink), std::move(tp), async_overflow_policy::block);
|
||||
registry::instance().register_and_init(new_logger);
|
||||
return new_logger;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Sink, typename... SinkArgs>
|
||||
inline std::shared_ptr<spdlog::logger> create_async_logger(const std::string &logger_name, SinkArgs &&... sink_args)
|
||||
inline std::shared_ptr<spdlog::logger> create_async(const std::string &logger_name, SinkArgs &&... sink_args)
|
||||
{
|
||||
return create_async::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...);
|
||||
return async_factory::create<Sink>(logger_name, std::forward<SinkArgs>(sink_args)...);
|
||||
}
|
||||
|
||||
// set global thread pool.
|
||||
|
@@ -34,13 +34,13 @@ class async_logger SPDLOG_FINAL : public std::enable_shared_from_this<async_logg
|
||||
public:
|
||||
template<class It>
|
||||
async_logger(const std::string &logger_name, const It &begin, const It &end, std::weak_ptr<details::thread_pool> tp,
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block_retry);
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block);
|
||||
|
||||
async_logger(const std::string &logger_name, sinks_init_list sinks, std::weak_ptr<details::thread_pool> tp,
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block_retry);
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block);
|
||||
|
||||
async_logger(const std::string &logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block_retry);
|
||||
async_overflow_policy overflow_policy = async_overflow_policy::block);
|
||||
|
||||
protected:
|
||||
void sink_it_(details::log_msg &msg) override;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_VERSION "0.16.4-rc"
|
||||
#define SPDLOG_VERSION "1.0.0-rc"
|
||||
|
||||
#include "spdlog/tweakme.h"
|
||||
|
||||
@@ -63,6 +63,7 @@ using log_clock = std::chrono::system_clock;
|
||||
using sink_ptr = std::shared_ptr<sinks::sink>;
|
||||
using sinks_init_list = std::initializer_list<sink_ptr>;
|
||||
using formatter_ptr = std::shared_ptr<spdlog::formatter>;
|
||||
|
||||
#if defined(SPDLOG_NO_ATOMIC_LEVELS)
|
||||
using level_t = details::null_atomic_int;
|
||||
#else
|
||||
@@ -126,8 +127,8 @@ using level_hasher = std::hash<int>;
|
||||
//
|
||||
enum class async_overflow_policy
|
||||
{
|
||||
block_retry, // Block until message can be enqueued
|
||||
overrun_oldeset // Discard oldest message in the queue if full when trying to add new item.
|
||||
block, // Block until message can be enqueued
|
||||
overrun_oldest // Discard oldest message in the queue if full when trying to add new item.
|
||||
};
|
||||
|
||||
//
|
||||
|
@@ -60,7 +60,7 @@ inline void spdlog::async_logger::flush_()
|
||||
}
|
||||
else
|
||||
{
|
||||
throw spdlog_ex("async flush: thread pool doens't exist anymore");
|
||||
throw spdlog_ex("async flush: thread pool doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
#include "stdio.h"
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
struct console_stdout_trait
|
||||
struct console_stdout_stream
|
||||
{
|
||||
static FILE *stream()
|
||||
{
|
||||
@@ -21,7 +21,7 @@ struct console_stdout_trait
|
||||
#endif
|
||||
};
|
||||
|
||||
struct console_stderr_trait
|
||||
struct console_stderr_stream
|
||||
{
|
||||
static FILE *stream()
|
||||
{
|
||||
@@ -35,7 +35,7 @@ struct console_stderr_trait
|
||||
#endif
|
||||
};
|
||||
|
||||
struct console_mutex_trait
|
||||
struct console_global_mutex
|
||||
{
|
||||
using mutex_t = std::mutex;
|
||||
static mutex_t &console_mutex()
|
||||
@@ -45,7 +45,7 @@ struct console_mutex_trait
|
||||
}
|
||||
};
|
||||
|
||||
struct console_null_mutex_trait
|
||||
struct console_global_nullmutex
|
||||
{
|
||||
using mutex_t = null_mutex;
|
||||
static mutex_t &console_mutex()
|
@@ -8,13 +8,16 @@
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
namespace fmt_helper {
|
||||
inline void append_str(const std::string &str, fmt::memory_buffer &dest)
|
||||
|
||||
template <size_t Buffer_Size>
|
||||
inline void append_str(const std::string &str, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
auto *str_ptr = str.data();
|
||||
dest.append(str_ptr, str_ptr + str.size());
|
||||
}
|
||||
|
||||
inline void append_c_str(const char *c_str, fmt::memory_buffer &dest)
|
||||
template <size_t Buffer_Size>
|
||||
inline void append_c_str(const char *c_str, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
char ch;
|
||||
while ((ch = *c_str) != '\0')
|
||||
@@ -24,21 +27,22 @@ inline void append_c_str(const char *c_str, fmt::memory_buffer &dest)
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t N1, size_t N2>
|
||||
inline void append_buf(const fmt::basic_memory_buffer<char, N1> &buf, fmt::basic_memory_buffer<char, N2> &dest)
|
||||
template<size_t Buffer_Size1, size_t Buffer_Size2>
|
||||
inline void append_buf(const fmt::basic_memory_buffer<char, Buffer_Size1> &buf, fmt::basic_memory_buffer<char, Buffer_Size2> &dest)
|
||||
{
|
||||
auto *buf_ptr = buf.data();
|
||||
dest.append(buf_ptr, buf_ptr + buf.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void append_int(T n, fmt::memory_buffer &dest)
|
||||
template<typename T, size_t Buffer_Size>
|
||||
inline void append_int(T n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
fmt::format_int i(n);
|
||||
dest.append(i.data(), i.data() + i.size());
|
||||
}
|
||||
|
||||
inline void pad2(int n, fmt::memory_buffer &dest)
|
||||
template <size_t Buffer_Size>
|
||||
inline void pad2(int n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
if (n > 99)
|
||||
{
|
||||
@@ -61,7 +65,8 @@ inline void pad2(int n, fmt::memory_buffer &dest)
|
||||
fmt::format_to(dest, "{:02}", n);
|
||||
}
|
||||
|
||||
inline void pad3(int n, fmt::memory_buffer &dest)
|
||||
template <size_t Buffer_Size>
|
||||
inline void pad3(int n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
if (n > 99)
|
||||
{
|
||||
@@ -86,8 +91,13 @@ inline void pad3(int n, fmt::memory_buffer &dest)
|
||||
fmt::format_to(dest, "{:03}", n);
|
||||
}
|
||||
|
||||
inline void pad6(size_t n, fmt::memory_buffer &dest)
|
||||
template <size_t Buffer_Size>
|
||||
inline void pad6(size_t n, fmt::basic_memory_buffer<char, Buffer_Size> &dest)
|
||||
{
|
||||
// todo: maybe replace this implementation with
|
||||
// pad3(n / 1000, dest);
|
||||
// pad3(n % 1000, dest);
|
||||
|
||||
if (n > 99999)
|
||||
{
|
||||
append_int(n, dest);
|
||||
@@ -122,7 +132,7 @@ inline void pad6(size_t n, fmt::memory_buffer &dest)
|
||||
dest.push_back('0');
|
||||
dest.push_back('0');
|
||||
dest.push_back('0');
|
||||
}
|
||||
}
|
||||
append_int(n, dest);
|
||||
}
|
||||
|
||||
|
@@ -46,9 +46,9 @@ inline void spdlog::logger::set_formatter(const Args &... args)
|
||||
}
|
||||
}
|
||||
|
||||
inline void spdlog::logger::set_pattern(const std::string &pattern, pattern_time_type pattern_time)
|
||||
inline void spdlog::logger::set_pattern(const std::string &pattern, pattern_time_type time_type)
|
||||
{
|
||||
set_formatter<spdlog::pattern_formatter>(pattern, pattern_time);
|
||||
set_formatter<spdlog::pattern_formatter>(pattern, time_type);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@@ -100,40 +100,40 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
|
||||
SPDLOG_CATCH_AND_HANDLE
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::trace(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::trace(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::trace, fmt, arg1, args...);
|
||||
log(level::trace, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::debug(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::debug(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::debug, fmt, arg1, args...);
|
||||
log(level::debug, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::info(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::info(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::info, fmt, arg1, args...);
|
||||
log(level::info, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::warn(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::warn(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::warn, fmt, arg1, args...);
|
||||
log(level::warn, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::error(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::error(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::err, fmt, arg1, args...);
|
||||
log(level::err, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
inline void spdlog::logger::critical(const char *fmt, const Arg1 &arg1, const Args &... args)
|
||||
template<typename... Args>
|
||||
inline void spdlog::logger::critical(const char *fmt, const Args &... args)
|
||||
{
|
||||
log(level::critical, fmt, arg1, args...);
|
||||
log(level::critical, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@@ -120,7 +120,16 @@ class c_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
|
||||
{
|
||||
fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday); //
|
||||
//fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], months[tm_time.tm_mon], tm_time.tm_mday);
|
||||
// date
|
||||
fmt_helper::append_str(days[tm_time.tm_wday], dest);
|
||||
dest.push_back(' ');
|
||||
fmt_helper::append_str(months[tm_time.tm_mon], dest);
|
||||
dest.push_back(' ');
|
||||
fmt_helper::append_int(tm_time.tm_mday, dest);
|
||||
dest.push_back(' ');
|
||||
// time
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_hour, dest);
|
||||
dest.push_back(':');
|
||||
fmt_helper::pad2(tm_time.tm_min, dest);
|
||||
@@ -176,7 +185,6 @@ class d_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
|
||||
{
|
||||
// fmt::format_to(dest, "{:02}", tm_time.tm_mday);
|
||||
fmt_helper::pad2(tm_time.tm_mday, dest);
|
||||
}
|
||||
};
|
||||
@@ -265,7 +273,7 @@ class p_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
|
||||
{
|
||||
fmt::format_to(dest, "{}", ampm(tm_time));
|
||||
fmt_helper::append_c_str(ampm(tm_time), dest);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -274,13 +282,13 @@ class r_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override
|
||||
{
|
||||
// fmt::format_to(dest, "{:02}:{:02}:{:02} {}", to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ampm(tm_time));
|
||||
fmt_helper::pad2(to12h(tm_time), dest);
|
||||
dest.push_back(':');
|
||||
fmt_helper::pad2(tm_time.tm_min, dest);
|
||||
dest.push_back(':');
|
||||
fmt_helper::pad2(tm_time.tm_sec, dest);
|
||||
fmt::format_to(dest, " {}", ampm(tm_time));
|
||||
dest.push_back(' ');
|
||||
fmt_helper::append_c_str(ampm(tm_time), dest);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -330,23 +338,19 @@ public:
|
||||
int total_minutes = os::utc_minutes_offset(tm_time);
|
||||
#endif
|
||||
bool is_negative = total_minutes < 0;
|
||||
char sign;
|
||||
if (is_negative)
|
||||
{
|
||||
total_minutes = -total_minutes;
|
||||
sign = '-';
|
||||
dest.push_back('-');
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = '+';
|
||||
dest.push_back('+');
|
||||
}
|
||||
|
||||
int h = total_minutes / 60;
|
||||
int m = total_minutes % 60;
|
||||
dest.push_back(sign);
|
||||
fmt_helper::pad2(h, dest);
|
||||
fmt_helper::pad2(total_minutes / 60, dest); // hours
|
||||
dest.push_back(':');
|
||||
fmt_helper::pad2(m, dest);
|
||||
fmt_helper::pad2(total_minutes % 60, dest); // minutes
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -371,7 +375,6 @@ class t_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
|
||||
{
|
||||
|
||||
fmt_helper::pad6(msg.thread_id, dest);
|
||||
}
|
||||
};
|
||||
@@ -390,7 +393,6 @@ class i_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override
|
||||
{
|
||||
|
||||
fmt_helper::pad6(msg.msg_id, dest);
|
||||
}
|
||||
};
|
||||
@@ -462,39 +464,48 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
#ifndef SPDLOG_NO_DATETIME
|
||||
|
||||
// each second cache the header
|
||||
// cache the date/time part for the next second.
|
||||
auto duration = msg.time.time_since_epoch();
|
||||
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
|
||||
if (cached_header_.size() == 0 || cached_seconds_ts_ != seconds)
|
||||
std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
|
||||
|
||||
if (cache_timestamp_ != seconds || cached_datetime_.size() == 0)
|
||||
{
|
||||
cached_header_ = fmt::memory_buffer();
|
||||
cached_header_.push_back('[');
|
||||
fmt_helper::append_int(tm_time.tm_year + 1900, cached_header_);
|
||||
cached_header_.push_back('-');
|
||||
cached_datetime_.resize(0);
|
||||
cached_datetime_.push_back('[');
|
||||
fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_);
|
||||
cached_datetime_.push_back('-');
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_mon + 1, cached_header_);
|
||||
cached_header_.push_back('-');
|
||||
fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_);
|
||||
cached_datetime_.push_back('-');
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_mday, cached_header_);
|
||||
cached_header_.push_back(' ');
|
||||
fmt_helper::pad2(tm_time.tm_mday, cached_datetime_);
|
||||
cached_datetime_.push_back(' ');
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_hour, cached_header_);
|
||||
cached_header_.push_back(':');
|
||||
fmt_helper::pad2(tm_time.tm_hour, cached_datetime_);
|
||||
cached_datetime_.push_back(':');
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_min, cached_header_);
|
||||
cached_header_.push_back(':');
|
||||
fmt_helper::pad2(tm_time.tm_min, cached_datetime_);
|
||||
cached_datetime_.push_back(':');
|
||||
|
||||
fmt_helper::pad2(tm_time.tm_sec, cached_header_);
|
||||
cached_header_.push_back('.');
|
||||
fmt_helper::pad2(tm_time.tm_sec, cached_datetime_);
|
||||
cached_datetime_.push_back('.');
|
||||
|
||||
cached_seconds_ts_ = seconds;
|
||||
cache_timestamp_ = seconds;
|
||||
}
|
||||
fmt_helper::append_buf(cached_header_, dest);
|
||||
fmt_helper::append_buf(cached_datetime_, dest);
|
||||
|
||||
// cache the millis part for the next milli.
|
||||
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
|
||||
fmt_helper::pad3(static_cast<int>(millis), dest);
|
||||
dest.push_back(']');
|
||||
dest.push_back(' ');
|
||||
if(millis != millis_cache_timestamp_ || cached_millis_.size() == 0)
|
||||
{
|
||||
cached_millis_.resize(0);
|
||||
fmt_helper::pad3(millis, cached_millis_);
|
||||
cached_millis_.push_back(']');
|
||||
cached_millis_.push_back(' ');
|
||||
millis_cache_timestamp_ = millis;
|
||||
}
|
||||
|
||||
fmt_helper::append_buf(cached_millis_, dest);
|
||||
#else // no datetime needed
|
||||
(void)tm_time;
|
||||
#endif
|
||||
@@ -517,8 +528,10 @@ class full_formatter SPDLOG_FINAL : public flag_formatter
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::seconds::rep cached_seconds_ts_{0};
|
||||
fmt::memory_buffer cached_header_;
|
||||
std::chrono::seconds cache_timestamp_ {0};
|
||||
std::chrono::milliseconds::rep millis_cache_timestamp_ {0};
|
||||
fmt::basic_memory_buffer<char, 128> cached_datetime_;
|
||||
fmt::basic_memory_buffer<char, 8> cached_millis_;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
@@ -526,14 +539,14 @@ private:
|
||||
class pattern_formatter SPDLOG_FINAL : public formatter
|
||||
{
|
||||
public:
|
||||
explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
|
||||
explicit pattern_formatter(const std::string &pattern, pattern_time_type time_type = pattern_time_type::local,
|
||||
std::string eol = spdlog::details::os::default_eol)
|
||||
: eol_(std::move(eol))
|
||||
, pattern_time_(pattern_time)
|
||||
, pattern_time_type_(time_type)
|
||||
, last_log_secs_(0)
|
||||
{
|
||||
std::memset(&cached_tm_, 0, sizeof(cached_tm_));
|
||||
compile_pattern(pattern);
|
||||
compile_pattern_(pattern);
|
||||
}
|
||||
|
||||
pattern_formatter(const pattern_formatter &) = default;
|
||||
@@ -544,7 +557,7 @@ public:
|
||||
auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch());
|
||||
if (secs != last_log_secs_)
|
||||
{
|
||||
cached_tm_ = get_time(msg);
|
||||
cached_tm_ = get_time_(msg);
|
||||
last_log_secs_ = secs;
|
||||
}
|
||||
#endif
|
||||
@@ -558,21 +571,22 @@ public:
|
||||
|
||||
private:
|
||||
const std::string eol_;
|
||||
const pattern_time_type pattern_time_;
|
||||
pattern_time_type pattern_time_type_;
|
||||
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)
|
||||
|
||||
std::tm get_time_(const details::log_msg &msg)
|
||||
{
|
||||
if (pattern_time_ == pattern_time_type::local)
|
||||
if (pattern_time_type_ == 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)
|
||||
void handle_flag_(char flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
@@ -717,7 +731,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void compile_pattern(const std::string &pattern)
|
||||
void compile_pattern_(const std::string &pattern)
|
||||
{
|
||||
auto end = pattern.end();
|
||||
std::unique_ptr<details::aggregate_formatter> user_chars;
|
||||
@@ -732,7 +746,7 @@ private:
|
||||
// if(
|
||||
if (++it != end)
|
||||
{
|
||||
handle_flag(*it);
|
||||
handle_flag_(*it);
|
||||
}
|
||||
else
|
||||
{
|
@@ -36,7 +36,7 @@ public:
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
auto logger_name = new_logger->name();
|
||||
throw_if_exists(logger_name);
|
||||
throw_if_exists_(logger_name);
|
||||
loggers_[logger_name] = new_logger;
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@ public:
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
auto logger_name = new_logger->name();
|
||||
throw_if_exists(logger_name);
|
||||
throw_if_exists_(logger_name);
|
||||
|
||||
// create default formatter if not exists
|
||||
|
||||
new_logger->set_pattern(formatter_pattern_);
|
||||
new_logger->set_formatter<pattern_formatter>(formatter_pattern_, pattern_time_type_);
|
||||
|
||||
if (err_handler_)
|
||||
{
|
||||
@@ -81,13 +81,14 @@ public:
|
||||
return tp_;
|
||||
}
|
||||
|
||||
void set_pattern(const std::string &pattern)
|
||||
void set_pattern(const std::string &pattern, pattern_time_type time_type)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
formatter_pattern_ = pattern;
|
||||
pattern_time_type_ = time_type;
|
||||
for (auto &l : loggers_)
|
||||
{
|
||||
l.second->set_pattern(pattern);
|
||||
l.second->set_pattern(pattern, time_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +163,7 @@ public:
|
||||
private:
|
||||
registry_t<Mutex>() = default;
|
||||
|
||||
void throw_if_exists(const std::string &logger_name)
|
||||
void throw_if_exists_(const std::string &logger_name)
|
||||
{
|
||||
if (loggers_.find(logger_name) != loggers_.end())
|
||||
{
|
||||
@@ -174,6 +175,7 @@ private:
|
||||
Mutex tp_mutex_;
|
||||
std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
|
||||
std::string formatter_pattern_ = "%+";
|
||||
pattern_time_type pattern_time_type_ = pattern_time_type::local;
|
||||
level::level_enum level_ = level::info;
|
||||
level::level_enum flush_level_ = level::off;
|
||||
log_err_handler err_handler_;
|
||||
|
@@ -29,7 +29,7 @@ struct async_msg
|
||||
level::level_enum level;
|
||||
log_clock::time_point time;
|
||||
size_t thread_id;
|
||||
fmt::basic_memory_buffer<char, 128> raw;
|
||||
fmt::basic_memory_buffer<char, 176> raw;
|
||||
|
||||
size_t msg_id;
|
||||
async_logger_ptr worker_ptr;
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
}
|
||||
for (size_t i = 0; i < threads_n; i++)
|
||||
{
|
||||
threads_.emplace_back(std::bind(&thread_pool::worker_loop, this));
|
||||
threads_.emplace_back(std::bind(&thread_pool::worker_loop_, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,14 +106,13 @@ public:
|
||||
{
|
||||
for (size_t i = 0; i < threads_.size(); i++)
|
||||
{
|
||||
post_async_msg(async_msg(async_msg_type::terminate), async_overflow_policy::block_retry);
|
||||
post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block);
|
||||
}
|
||||
|
||||
for (auto &t : threads_)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
// std::cout << "~thread_pool() msg_counter_: " << msg_counter_ << std::endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -123,12 +122,12 @@ public:
|
||||
void post_log(async_logger_ptr &&worker_ptr, details::log_msg &&msg, async_overflow_policy overflow_policy)
|
||||
{
|
||||
async_msg async_m(std::forward<async_logger_ptr>(worker_ptr), async_msg_type::log, std::forward<log_msg>(msg));
|
||||
post_async_msg(std::move(async_m), overflow_policy);
|
||||
post_async_msg_(std::move(async_m), overflow_policy);
|
||||
}
|
||||
|
||||
void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy)
|
||||
{
|
||||
post_async_msg(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy);
|
||||
post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -136,9 +135,9 @@ private:
|
||||
|
||||
std::vector<std::thread> threads_;
|
||||
|
||||
void post_async_msg(async_msg &&new_msg, async_overflow_policy overflow_policy)
|
||||
void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy)
|
||||
{
|
||||
if (overflow_policy == async_overflow_policy::block_retry)
|
||||
if (overflow_policy == async_overflow_policy::block)
|
||||
{
|
||||
q_.enqueue(std::move(new_msg));
|
||||
}
|
||||
@@ -148,14 +147,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void worker_loop()
|
||||
void worker_loop_()
|
||||
{
|
||||
while (process_next_msg()) {};
|
||||
while (process_next_msg_()) {};
|
||||
}
|
||||
|
||||
// process next message in the queue
|
||||
// return true if this thread should still be active (while no terminate msg was received)
|
||||
bool process_next_msg()
|
||||
bool process_next_msg_()
|
||||
{
|
||||
async_msg incoming_async_msg;
|
||||
bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10));
|
||||
|
@@ -196,12 +196,22 @@
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
// An implementation of declval for pre-C++11 compilers such as gcc 4.
|
||||
namespace internal {
|
||||
|
||||
// An implementation of declval for pre-C++11 compilers such as gcc 4.
|
||||
template<typename T>
|
||||
typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
|
||||
|
||||
// Casts nonnegative integer to unsigned.
|
||||
template<typename Int>
|
||||
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value)
|
||||
{
|
||||
FMT_ASSERT(value >= 0, "negative value");
|
||||
return static_cast<typename std::make_unsigned<Int>::type>(value);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
||||
subset of the API. ``fmt::basic_string_view`` is used for format strings even
|
||||
@@ -242,7 +252,7 @@ public:
|
||||
FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {}
|
||||
|
||||
/** Constructs a string reference object from a C string and a size. */
|
||||
FMT_CONSTEXPR basic_string_view(const Char *s, size_t str_size) FMT_NOEXCEPT : data_(s), size_(str_size) {}
|
||||
FMT_CONSTEXPR basic_string_view(const Char *s, size_t count) FMT_NOEXCEPT : data_(s), size_(count) {}
|
||||
|
||||
/**
|
||||
\rst
|
||||
@@ -354,11 +364,7 @@ private:
|
||||
std::size_t capacity_;
|
||||
|
||||
protected:
|
||||
basic_buffer(T *p = FMT_NULL, std::size_t buf_size = 0, std::size_t buf_capacity = 0) FMT_NOEXCEPT : ptr_(p),
|
||||
size_(buf_size),
|
||||
capacity_(buf_capacity)
|
||||
{
|
||||
}
|
||||
basic_buffer(T *p = FMT_NULL, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT : ptr_(p), size_(sz), capacity_(cap) {}
|
||||
|
||||
/** Sets the buffer data and capacity. */
|
||||
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT
|
||||
@@ -418,11 +424,11 @@ public:
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
/** Reserves space to store at least *buf_capacity* elements. */
|
||||
void reserve(std::size_t buf_capacity)
|
||||
/** Reserves space to store at least *capacity* elements. */
|
||||
void reserve(std::size_t new_capacity)
|
||||
{
|
||||
if (buf_capacity > capacity_)
|
||||
grow(buf_capacity);
|
||||
if (new_capacity > capacity_)
|
||||
grow(new_capacity);
|
||||
}
|
||||
|
||||
void push_back(const T &value)
|
||||
@@ -893,7 +899,7 @@ public:
|
||||
// Advances the begin iterator to ``it``.
|
||||
FMT_CONSTEXPR void advance_to(iterator it)
|
||||
{
|
||||
format_str_.remove_prefix(it - begin());
|
||||
format_str_.remove_prefix(internal::to_unsigned(it - begin()));
|
||||
}
|
||||
|
||||
// Returns the next argument index.
|
||||
@@ -1135,13 +1141,13 @@ struct get_type
|
||||
};
|
||||
|
||||
template<typename Context>
|
||||
FMT_CONSTEXPR uint64_t get_types()
|
||||
FMT_CONSTEXPR unsigned long long get_types()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Context, typename Arg, typename... Args>
|
||||
FMT_CONSTEXPR uint64_t get_types()
|
||||
FMT_CONSTEXPR unsigned long long get_types()
|
||||
{
|
||||
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
|
||||
}
|
||||
@@ -1187,27 +1193,29 @@ private:
|
||||
typedef typename std::conditional<IS_PACKED, internal::value<Context>, basic_format_arg<Context>>::type value_type;
|
||||
|
||||
// If the arguments are not packed, add one more element to mark the end.
|
||||
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
|
||||
static const size_t DATA_SIZE = NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1);
|
||||
value_type data_[DATA_SIZE];
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
|
||||
static FMT_CONSTEXPR int64_t get_types()
|
||||
static FMT_CONSTEXPR long long get_types()
|
||||
{
|
||||
return IS_PACKED ? static_cast<int64_t>(internal::get_types<Context, Args...>()) : -static_cast<int64_t>(NUM_ARGS);
|
||||
return IS_PACKED ? static_cast<long long>(internal::get_types<Context, Args...>()) : -static_cast<long long>(NUM_ARGS);
|
||||
}
|
||||
|
||||
public:
|
||||
#if FMT_USE_CONSTEXPR
|
||||
static constexpr int64_t TYPES = get_types();
|
||||
static constexpr long long TYPES = get_types();
|
||||
#else
|
||||
static const int64_t TYPES;
|
||||
static const long long TYPES;
|
||||
#endif
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
|
||||
// Workaround an array initialization bug in gcc 4.5 and earlier.
|
||||
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 405) || (FMT_MSC_VER && FMT_MSC_VER <= 1800)
|
||||
// Workaround array initialization issues in gcc <= 4.5 and MSVC <= 2013.
|
||||
format_arg_store(const Args &... args)
|
||||
{
|
||||
data_ = {internal::make_arg<IS_PACKED, Context>(args)...};
|
||||
value_type init[DATA_SIZE] = {internal::make_arg<IS_PACKED, Context>(args)...};
|
||||
std::memcpy(data_, init, sizeof(init));
|
||||
}
|
||||
#else
|
||||
format_arg_store(const Args &... args)
|
||||
@@ -1219,7 +1227,7 @@ public:
|
||||
|
||||
#if !FMT_USE_CONSTEXPR
|
||||
template<typename Context, typename... Args>
|
||||
const int64_t format_arg_store<Context, Args...>::TYPES = get_types();
|
||||
const long long format_arg_store<Context, Args...>::TYPES = get_types();
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1252,7 +1260,7 @@ public:
|
||||
private:
|
||||
// To reduce compiled code size per formatting function call, types of first
|
||||
// max_packed_args arguments are passed in the types_ field.
|
||||
uint64_t types_;
|
||||
unsigned long long types_;
|
||||
union
|
||||
{
|
||||
// If the number of arguments is less than max_packed_args, the argument
|
||||
@@ -1267,7 +1275,7 @@ private:
|
||||
typename internal::type type(unsigned index) const
|
||||
{
|
||||
unsigned shift = index * 4;
|
||||
uint64_t mask = 0xf;
|
||||
unsigned long long mask = 0xf;
|
||||
return static_cast<typename internal::type>((types_ & (mask << shift)) >> shift);
|
||||
}
|
||||
|
||||
@@ -1284,10 +1292,10 @@ private:
|
||||
|
||||
format_arg do_get(size_type index) const
|
||||
{
|
||||
int64_t signed_types = static_cast<int64_t>(types_);
|
||||
long long signed_types = static_cast<long long>(types_);
|
||||
if (signed_types < 0)
|
||||
{
|
||||
uint64_t num_args = -signed_types;
|
||||
unsigned long long num_args = static_cast<unsigned long long>(-signed_types);
|
||||
return index < num_args ? args_[index] : format_arg();
|
||||
}
|
||||
format_arg arg;
|
||||
@@ -1314,7 +1322,7 @@ public:
|
||||
*/
|
||||
template<typename... Args>
|
||||
basic_format_args(const format_arg_store<Context, Args...> &store)
|
||||
: types_(store.TYPES)
|
||||
: types_(static_cast<unsigned long long>(store.TYPES))
|
||||
{
|
||||
set_data(store.data_);
|
||||
}
|
||||
@@ -1328,8 +1336,8 @@ public:
|
||||
|
||||
unsigned max_size() const
|
||||
{
|
||||
int64_t signed_types = static_cast<int64_t>(types_);
|
||||
return static_cast<unsigned>(signed_types < 0 ? -signed_types : static_cast<int64_t>(internal::max_packed_args));
|
||||
long long signed_types = static_cast<long long>(types_);
|
||||
return static_cast<unsigned>(signed_types < 0 ? -signed_types : static_cast<long long>(internal::max_packed_args));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1414,6 +1422,8 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg)
|
||||
template<typename S, typename T, typename Char>
|
||||
void arg(S, internal::named_arg<T, Char>) FMT_DELETED;
|
||||
|
||||
#ifndef FMT_EXTENDED_COLORS
|
||||
// color and (v)print_colored are deprecated.
|
||||
enum color
|
||||
{
|
||||
black,
|
||||
@@ -1425,27 +1435,19 @@ enum color
|
||||
cyan,
|
||||
white
|
||||
};
|
||||
|
||||
FMT_API void vprint_colored(color c, string_view format, format_args args);
|
||||
FMT_API void vprint_colored(color c, wstring_view format, wformat_args args);
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
specify color (experimental).
|
||||
Example:
|
||||
fmt::print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template<typename... Args>
|
||||
inline void print_colored(color c, string_view format_str, const Args &... args)
|
||||
{
|
||||
vprint_colored(c, format_str, make_format_args(args...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void print_colored(color c, wstring_view format_str, const Args &... args)
|
||||
{
|
||||
vprint_colored(c, format_str, make_format_args<wformat_context>(args...));
|
||||
}
|
||||
#endif
|
||||
|
||||
format_context::iterator vformat_to(internal::buffer &buf, string_view format_str, format_args args);
|
||||
wformat_context::iterator vformat_to(internal::wbuffer &buf, wstring_view format_str, wformat_args args);
|
||||
|
@@ -89,9 +89,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...)
|
||||
#define FMT_SWPRINTF swprintf
|
||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
|
||||
const char RESET_COLOR[] = "\x1b[0m";
|
||||
const wchar_t WRESET_COLOR[] = L"\x1b[0m";
|
||||
|
||||
typedef void (*FormatFunc)(internal::buffer &, int, string_view);
|
||||
|
||||
// Portable thread-safe version of strerror.
|
||||
@@ -300,6 +297,11 @@ const int16_t basic_data<T>::POW10_EXPONENTS[] = {-1220, -1193, -1166, -1140, -1
|
||||
-289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375,
|
||||
402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
|
||||
|
||||
template<typename T>
|
||||
const char basic_data<T>::RESET_COLOR[] = "\x1b[0m";
|
||||
template<typename T>
|
||||
const wchar_t basic_data<T>::WRESET_COLOR[] = L"\x1b[0m";
|
||||
|
||||
FMT_FUNC fp operator*(fp x, fp y)
|
||||
{
|
||||
// Multiply 32-bit parts of significands.
|
||||
@@ -502,13 +504,14 @@ FMT_FUNC void vprint(wstring_view format_str, wformat_args args)
|
||||
vprint(stdout, format_str, args);
|
||||
}
|
||||
|
||||
#ifndef FMT_EXTENDED_COLORS
|
||||
FMT_FUNC void vprint_colored(color c, string_view format, format_args args)
|
||||
{
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
std::fputs(escape, stdout);
|
||||
vprint(format, args);
|
||||
std::fputs(RESET_COLOR, stdout);
|
||||
std::fputs(internal::data::RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args)
|
||||
@@ -517,8 +520,48 @@ FMT_FUNC void vprint_colored(color c, wstring_view format, wformat_args args)
|
||||
escape[3] = static_cast<wchar_t>('0' + c);
|
||||
std::fputws(escape, stdout);
|
||||
vprint(format, args);
|
||||
std::fputws(WRESET_COLOR, stdout);
|
||||
std::fputws(internal::data::WRESET_COLOR, stdout);
|
||||
}
|
||||
#else
|
||||
namespace internal {
|
||||
FMT_CONSTEXPR void to_esc(uint8_t c, char out[], int offset)
|
||||
{
|
||||
out[offset + 0] = static_cast<char>('0' + c / 100);
|
||||
out[offset + 1] = static_cast<char>('0' + c / 10 % 10);
|
||||
out[offset + 2] = static_cast<char>('0' + c % 10);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
FMT_FUNC void vprint_rgb(rgb fd, string_view format, format_args args)
|
||||
{
|
||||
char escape_fd[] = "\x1b[38;2;000;000;000m";
|
||||
internal::to_esc(fd.r, escape_fd, 7);
|
||||
internal::to_esc(fd.g, escape_fd, 11);
|
||||
internal::to_esc(fd.b, escape_fd, 15);
|
||||
|
||||
std::fputs(escape_fd, stdout);
|
||||
vprint(format, args);
|
||||
std::fputs(internal::data::RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
FMT_FUNC void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args)
|
||||
{
|
||||
char escape_fd[] = "\x1b[38;2;000;000;000m"; // foreground color
|
||||
char escape_bg[] = "\x1b[48;2;000;000;000m"; // background color
|
||||
internal::to_esc(fd.r, escape_fd, 7);
|
||||
internal::to_esc(fd.g, escape_fd, 11);
|
||||
internal::to_esc(fd.b, escape_fd, 15);
|
||||
|
||||
internal::to_esc(bg.r, escape_bg, 7);
|
||||
internal::to_esc(bg.g, escape_bg, 11);
|
||||
internal::to_esc(bg.b, escape_bg, 15);
|
||||
|
||||
std::fputs(escape_fd, stdout);
|
||||
std::fputs(escape_bg, stdout);
|
||||
vprint(format, args);
|
||||
std::fputs(internal::data::RESET_COLOR, stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_FUNC locale locale_provider::locale()
|
||||
{
|
||||
|
@@ -1,46 +0,0 @@
|
||||
// Formatting library for C++
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "fmt/format-inl.h"
|
||||
|
||||
namespace fmt {
|
||||
|
||||
template struct internal::basic_data<void>;
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template FMT_API char internal::thousands_sep(locale_provider *lp);
|
||||
|
||||
template void basic_fixed_buffer<char>::grow(std::size_t);
|
||||
|
||||
template void internal::arg_map<format_context>::init(
|
||||
const basic_format_args<format_context> &args);
|
||||
|
||||
template FMT_API int internal::char_traits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template FMT_API int internal::char_traits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template FMT_API wchar_t internal::thousands_sep(locale_provider *lp);
|
||||
|
||||
template void basic_fixed_buffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void internal::arg_map<wformat_context>::init(const wformat_args &args);
|
||||
|
||||
template FMT_API int internal::char_traits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template FMT_API int internal::char_traits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, long double value);
|
||||
} // namespace fmt
|
@@ -168,7 +168,7 @@ FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
// A workaround for gcc 4.4 that doesn't support union members with ctors.
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
|
||||
#if (FMT_GCC_VERSION && FMT_GCC_VERSION <= 404) || (FMT_MSC_VER && FMT_MSC_VER <= 1800)
|
||||
#define FMT_UNION struct
|
||||
#else
|
||||
#define FMT_UNION union
|
||||
@@ -531,14 +531,6 @@ public:
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Casts nonnegative integer to unsigned.
|
||||
template<typename Int>
|
||||
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value)
|
||||
{
|
||||
FMT_ASSERT(value >= 0, "negative value");
|
||||
return static_cast<typename std::make_unsigned<Int>::type>(value);
|
||||
}
|
||||
|
||||
#if FMT_SECURE_SCL
|
||||
template<typename T>
|
||||
struct checked
|
||||
@@ -1072,6 +1064,8 @@ struct FMT_API basic_data
|
||||
static const uint64_t POW10_SIGNIFICANDS[];
|
||||
static const int16_t POW10_EXPONENTS[];
|
||||
static const char DIGITS[];
|
||||
static const char RESET_COLOR[];
|
||||
static const wchar_t WRESET_COLOR[];
|
||||
};
|
||||
|
||||
#if FMT_USE_EXTERN_TEMPLATES
|
||||
@@ -1172,7 +1166,7 @@ public:
|
||||
uint64_t t = ((1ULL << (32 + a)) / data::POWERS_OF_10_32[n] + 1 - n / 9);
|
||||
t = ((t * u) >> a) + n / 5 * 4;
|
||||
write_pair(0, t >> 32);
|
||||
for (int i = 2; i < N; i += 2)
|
||||
for (unsigned i = 2; i < N; i += 2)
|
||||
{
|
||||
t = 100ULL * static_cast<uint32_t>(t);
|
||||
write_pair(i, t >> 32);
|
||||
@@ -1561,31 +1555,6 @@ struct align_spec : empty_spec
|
||||
template<typename Char>
|
||||
class basic_format_specs : public align_spec
|
||||
{
|
||||
private:
|
||||
template<typename FillChar>
|
||||
typename std::enable_if<std::is_same<FillChar, Char>::value || std::is_same<FillChar, char>::value, void>::type set(
|
||||
fill_spec<FillChar> fill)
|
||||
{
|
||||
fill_ = fill.value();
|
||||
}
|
||||
|
||||
void set(width_spec width)
|
||||
{
|
||||
width_ = width.value();
|
||||
}
|
||||
|
||||
void set(type_spec type)
|
||||
{
|
||||
type_ = type.value();
|
||||
}
|
||||
|
||||
template<typename Spec, typename... Specs>
|
||||
void set(Spec spec, Specs... tail)
|
||||
{
|
||||
set(spec);
|
||||
set(tail...);
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned flags_;
|
||||
int precision_;
|
||||
@@ -1599,16 +1568,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<typename... FormatSpecs>
|
||||
explicit basic_format_specs(FormatSpecs... specs)
|
||||
: align_spec(0, ' ')
|
||||
, flags_(0)
|
||||
, precision_(-1)
|
||||
, type_(0)
|
||||
{
|
||||
set(specs...);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR bool flag(unsigned f) const
|
||||
{
|
||||
return (flags_ & f) != 0;
|
||||
@@ -1929,7 +1888,22 @@ public:
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, iterator>::type operator()(T value)
|
||||
{
|
||||
writer_.write_int(value, specs_);
|
||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||
// use std::is_same instead.
|
||||
if (std::is_same<T, bool>::value)
|
||||
{
|
||||
if (specs_.type_)
|
||||
return (*this)(value ? 1 : 0);
|
||||
write(value != 0);
|
||||
}
|
||||
else if (std::is_same<T, char_type>::value)
|
||||
{
|
||||
internal::handle_char_specs(specs_, char_spec_handler(*this, static_cast<char_type>(value)));
|
||||
}
|
||||
else
|
||||
{
|
||||
writer_.write_int(value, specs_);
|
||||
}
|
||||
return out();
|
||||
}
|
||||
|
||||
@@ -1940,14 +1914,6 @@ public:
|
||||
return out();
|
||||
}
|
||||
|
||||
iterator operator()(bool value)
|
||||
{
|
||||
if (specs_.type_)
|
||||
return (*this)(value ? 1 : 0);
|
||||
write(value);
|
||||
return out();
|
||||
}
|
||||
|
||||
struct char_spec_handler : internal::error_handler
|
||||
{
|
||||
arg_formatter_base &formatter;
|
||||
@@ -1969,12 +1935,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
iterator operator()(char_type value)
|
||||
{
|
||||
internal::handle_char_specs(specs_, char_spec_handler(*this, value));
|
||||
return out();
|
||||
}
|
||||
|
||||
struct cstring_spec_handler : internal::error_handler
|
||||
{
|
||||
arg_formatter_base &formatter;
|
||||
@@ -2047,7 +2007,7 @@ FMT_CONSTEXPR unsigned parse_nonnegative_int(Iterator &it, ErrorHandler &&eh)
|
||||
value = max_int + 1;
|
||||
break;
|
||||
}
|
||||
value = value * 10 + (*it - '0');
|
||||
value = value * 10 + unsigned(*it - '0');
|
||||
// Workaround for MSVC "setup_exception stack overflow" error:
|
||||
auto next = it;
|
||||
++next;
|
||||
@@ -2107,7 +2067,7 @@ public:
|
||||
{
|
||||
if (is_negative(value))
|
||||
handler_.on_error("negative width");
|
||||
return value;
|
||||
return static_cast<unsigned long long>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -2135,7 +2095,7 @@ public:
|
||||
{
|
||||
if (is_negative(value))
|
||||
handler_.on_error("negative precision");
|
||||
return value;
|
||||
return static_cast<unsigned long long>(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -2201,7 +2161,7 @@ public:
|
||||
}
|
||||
FMT_CONSTEXPR void on_precision(unsigned precision)
|
||||
{
|
||||
specs_.precision_ = precision;
|
||||
specs_.precision_ = static_cast<int>(precision);
|
||||
}
|
||||
FMT_CONSTEXPR void end_precision() {}
|
||||
|
||||
@@ -2300,7 +2260,7 @@ FMT_CONSTEXPR void set_dynamic_spec(T &value, basic_format_arg<Context> arg, Err
|
||||
unsigned long long big_value = visit(Handler<ErrorHandler>(eh), arg);
|
||||
if (big_value > (std::numeric_limits<int>::max)())
|
||||
eh.on_error("number is too big");
|
||||
value = static_cast<int>(big_value);
|
||||
value = static_cast<T>(big_value);
|
||||
}
|
||||
|
||||
struct auto_id
|
||||
@@ -2494,7 +2454,7 @@ FMT_CONSTEXPR Iterator parse_arg_id(Iterator it, IDHandler &&handler)
|
||||
{
|
||||
c = *++it;
|
||||
} while (is_name_start(c) || ('0' <= c && c <= '9'));
|
||||
handler(basic_string_view<char_type>(pointer_from(start), it - start));
|
||||
handler(basic_string_view<char_type>(pointer_from(start), to_unsigned(it - start)));
|
||||
return it;
|
||||
}
|
||||
|
||||
@@ -3063,8 +3023,8 @@ private:
|
||||
}
|
||||
else if (spec.precision() > static_cast<int>(num_digits))
|
||||
{
|
||||
size = prefix.size() + spec.precision();
|
||||
padding = spec.precision() - num_digits;
|
||||
size = prefix.size() + static_cast<std::size_t>(spec.precision());
|
||||
padding = static_cast<std::size_t>(spec.precision()) - num_digits;
|
||||
fill = '0';
|
||||
}
|
||||
align_spec as = spec;
|
||||
@@ -3941,8 +3901,7 @@ struct formatter<T, Char, typename std::enable_if<internal::format_type<typename
|
||||
internal::handle_dynamic_spec<internal::width_checker>(specs_.width_, specs_.width_ref, ctx);
|
||||
internal::handle_dynamic_spec<internal::precision_checker>(specs_.precision_, specs_.precision_ref, ctx);
|
||||
typedef output_range<typename FormatContext::iterator, typename FormatContext::char_type> range_type;
|
||||
visit(arg_formatter<range_type>(ctx, specs_), internal::make_arg<FormatContext>(val));
|
||||
return ctx.out();
|
||||
return visit(arg_formatter<range_type>(ctx, specs_), internal::make_arg<FormatContext>(val));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -4059,7 +4018,7 @@ struct format_handler : internal::error_handler
|
||||
|
||||
void on_text(iterator begin, iterator end)
|
||||
{
|
||||
size_t size = end - begin;
|
||||
auto size = internal::to_unsigned(end - begin);
|
||||
auto out = context.out();
|
||||
auto &&it = internal::reserve(out, size);
|
||||
it = std::copy_n(begin, size, it);
|
||||
@@ -4226,10 +4185,10 @@ std::wstring to_wstring(const T &value)
|
||||
return str;
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
std::basic_string<Char> to_string(const basic_memory_buffer<Char> &buffer)
|
||||
template<typename Char, std::size_t SIZE>
|
||||
std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE> &buf)
|
||||
{
|
||||
return std::basic_string<Char>(buffer.data(), buffer.size());
|
||||
return std::basic_string<Char>(buf.data(), buf.size());
|
||||
}
|
||||
|
||||
inline format_context::iterator vformat_to(internal::buffer &buf, string_view format_str, format_args args)
|
||||
@@ -4244,14 +4203,14 @@ inline wformat_context::iterator vformat_to(internal::wbuffer &buf, wstring_view
|
||||
return vformat_to<arg_formatter<range>>(buf, format_str, args);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline format_context::iterator format_to(memory_buffer &buf, string_view format_str, const Args &... args)
|
||||
template<typename... Args, std::size_t SIZE = inline_buffer_size>
|
||||
inline format_context::iterator format_to(basic_memory_buffer<char, SIZE> &buf, string_view format_str, const Args &... args)
|
||||
{
|
||||
return vformat_to(buf, format_str, make_format_args(args...));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline wformat_context::iterator format_to(wmemory_buffer &buf, wstring_view format_str, const Args &... args)
|
||||
template<typename... Args, std::size_t SIZE = inline_buffer_size>
|
||||
inline wformat_context::iterator format_to(basic_memory_buffer<wchar_t, SIZE> &buf, wstring_view format_str, const Args &... args)
|
||||
{
|
||||
return vformat_to(buf, format_str, make_format_args<wformat_context>(args...));
|
||||
}
|
||||
@@ -4276,6 +4235,12 @@ inline OutputIt vformat_to(OutputIt out, string_view format_str, typename format
|
||||
typedef output_range<OutputIt, char> range;
|
||||
return vformat_to<arg_formatter<range>>(range(out), format_str, args);
|
||||
}
|
||||
template<typename OutputIt, typename... Args>
|
||||
inline OutputIt vformat_to(OutputIt out, wstring_view format_str, typename format_args_t<OutputIt, wchar_t>::type args)
|
||||
{
|
||||
typedef output_range<OutputIt, wchar_t> range;
|
||||
return vformat_to<arg_formatter<range>>(range(out), format_str, args);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
@@ -4317,6 +4282,26 @@ struct format_to_n_result
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
template<typename OutputIt>
|
||||
using format_to_n_context = typename fmt::format_context_t<fmt::internal::truncating_iterator<OutputIt>>::type;
|
||||
|
||||
template<typename OutputIt>
|
||||
using format_to_n_args = fmt::basic_format_args<format_to_n_context<OutputIt>>;
|
||||
|
||||
template<typename OutputIt, typename... Args>
|
||||
inline format_arg_store<format_to_n_context<OutputIt>, Args...> make_format_to_n_args(const Args &... args)
|
||||
{
|
||||
return format_arg_store<format_to_n_context<OutputIt>, Args...>(args...);
|
||||
}
|
||||
|
||||
template<typename OutputIt, typename... Args>
|
||||
inline format_to_n_result<OutputIt> vformat_to_n(OutputIt out, std::size_t n, string_view format_str, format_to_n_args<OutputIt> args)
|
||||
{
|
||||
typedef internal::truncating_iterator<OutputIt> It;
|
||||
auto it = vformat_to(It(out, n), format_str, args);
|
||||
return {it.base(), it.count()};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments, writes up to ``n`` characters of the result to the output
|
||||
@@ -4326,9 +4311,14 @@ struct format_to_n_result
|
||||
*/
|
||||
template<typename OutputIt, typename... Args>
|
||||
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, std::size_t n, string_view format_str, const Args &... args)
|
||||
{
|
||||
return vformat_to_n<OutputIt>(out, n, format_str, make_format_to_n_args<OutputIt>(args...));
|
||||
}
|
||||
template<typename OutputIt, typename... Args>
|
||||
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, std::size_t n, wstring_view format_str, const Args &... args)
|
||||
{
|
||||
typedef internal::truncating_iterator<OutputIt> It;
|
||||
auto it = vformat_to(It(out, n), format_str, make_format_args<typename format_context_t<It>::type>(args...));
|
||||
auto it = vformat_to(It(out, n), format_str, make_format_args<typename format_context_t<It, wchar_t>::type>(args...));
|
||||
return {it.base(), it.count()};
|
||||
}
|
||||
|
||||
@@ -4361,8 +4351,8 @@ inline typename std::enable_if<internal::is_format_string<String>::value>::type
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of characters in the output of
|
||||
``format(format_str, args...)``.
|
||||
Returns the number of characters in the output of
|
||||
``format(format_str, args...)``.
|
||||
*/
|
||||
template<typename... Args>
|
||||
inline std::size_t formatted_size(string_view format_str, const Args &... args)
|
||||
@@ -4371,6 +4361,215 @@ inline std::size_t formatted_size(string_view format_str, const Args &... args)
|
||||
return it.count();
|
||||
}
|
||||
|
||||
// Experimental color support.
|
||||
#ifdef FMT_EXTENDED_COLORS
|
||||
enum class color : uint32_t
|
||||
{
|
||||
alice_blue = 0xF0F8FF, // rgb(240,248,255)
|
||||
antique_white = 0xFAEBD7, // rgb(250,235,215)
|
||||
aqua = 0x00FFFF, // rgb(0,255,255)
|
||||
aquamarine = 0x7FFFD4, // rgb(127,255,212)
|
||||
azure = 0xF0FFFF, // rgb(240,255,255)
|
||||
beige = 0xF5F5DC, // rgb(245,245,220)
|
||||
bisque = 0xFFE4C4, // rgb(255,228,196)
|
||||
black = 0x000000, // rgb(0,0,0)
|
||||
blanched_almond = 0xFFEBCD, // rgb(255,235,205)
|
||||
blue = 0x0000FF, // rgb(0,0,255)
|
||||
blue_violet = 0x8A2BE2, // rgb(138,43,226)
|
||||
brown = 0xA52A2A, // rgb(165,42,42)
|
||||
burly_wood = 0xDEB887, // rgb(222,184,135)
|
||||
cadet_blue = 0x5F9EA0, // rgb(95,158,160)
|
||||
chartreuse = 0x7FFF00, // rgb(127,255,0)
|
||||
chocolate = 0xD2691E, // rgb(210,105,30)
|
||||
coral = 0xFF7F50, // rgb(255,127,80)
|
||||
cornflower_blue = 0x6495ED, // rgb(100,149,237)
|
||||
cornsilk = 0xFFF8DC, // rgb(255,248,220)
|
||||
crimson = 0xDC143C, // rgb(220,20,60)
|
||||
cyan = 0x00FFFF, // rgb(0,255,255)
|
||||
dark_blue = 0x00008B, // rgb(0,0,139)
|
||||
dark_cyan = 0x008B8B, // rgb(0,139,139)
|
||||
dark_golden_rod = 0xB8860B, // rgb(184,134,11)
|
||||
dark_gray = 0xA9A9A9, // rgb(169,169,169)
|
||||
dark_green = 0x006400, // rgb(0,100,0)
|
||||
dark_khaki = 0xBDB76B, // rgb(189,183,107)
|
||||
dark_magenta = 0x8B008B, // rgb(139,0,139)
|
||||
dark_olive_green = 0x556B2F, // rgb(85,107,47)
|
||||
dark_orange = 0xFF8C00, // rgb(255,140,0)
|
||||
dark_orchid = 0x9932CC, // rgb(153,50,204)
|
||||
dark_red = 0x8B0000, // rgb(139,0,0)
|
||||
dark_salmon = 0xE9967A, // rgb(233,150,122)
|
||||
dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
|
||||
dark_slate_blue = 0x483D8B, // rgb(72,61,139)
|
||||
dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
|
||||
dark_turquoise = 0x00CED1, // rgb(0,206,209)
|
||||
dark_violet = 0x9400D3, // rgb(148,0,211)
|
||||
deep_pink = 0xFF1493, // rgb(255,20,147)
|
||||
deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
|
||||
dim_gray = 0x696969, // rgb(105,105,105)
|
||||
dodger_blue = 0x1E90FF, // rgb(30,144,255)
|
||||
fire_brick = 0xB22222, // rgb(178,34,34)
|
||||
floral_white = 0xFFFAF0, // rgb(255,250,240)
|
||||
forest_green = 0x228B22, // rgb(34,139,34)
|
||||
fuchsia = 0xFF00FF, // rgb(255,0,255)
|
||||
gainsboro = 0xDCDCDC, // rgb(220,220,220)
|
||||
ghost_white = 0xF8F8FF, // rgb(248,248,255)
|
||||
gold = 0xFFD700, // rgb(255,215,0)
|
||||
golden_rod = 0xDAA520, // rgb(218,165,32)
|
||||
gray = 0x808080, // rgb(128,128,128)
|
||||
green = 0x008000, // rgb(0,128,0)
|
||||
green_yellow = 0xADFF2F, // rgb(173,255,47)
|
||||
honey_dew = 0xF0FFF0, // rgb(240,255,240)
|
||||
hot_pink = 0xFF69B4, // rgb(255,105,180)
|
||||
indian_red = 0xCD5C5C, // rgb(205,92,92)
|
||||
indigo = 0x4B0082, // rgb(75,0,130)
|
||||
ivory = 0xFFFFF0, // rgb(255,255,240)
|
||||
khaki = 0xF0E68C, // rgb(240,230,140)
|
||||
lavender = 0xE6E6FA, // rgb(230,230,250)
|
||||
lavender_blush = 0xFFF0F5, // rgb(255,240,245)
|
||||
lawn_green = 0x7CFC00, // rgb(124,252,0)
|
||||
lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
|
||||
light_blue = 0xADD8E6, // rgb(173,216,230)
|
||||
light_coral = 0xF08080, // rgb(240,128,128)
|
||||
light_cyan = 0xE0FFFF, // rgb(224,255,255)
|
||||
light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
|
||||
light_gray = 0xD3D3D3, // rgb(211,211,211)
|
||||
light_green = 0x90EE90, // rgb(144,238,144)
|
||||
light_pink = 0xFFB6C1, // rgb(255,182,193)
|
||||
light_salmon = 0xFFA07A, // rgb(255,160,122)
|
||||
light_sea_green = 0x20B2AA, // rgb(32,178,170)
|
||||
light_sky_blue = 0x87CEFA, // rgb(135,206,250)
|
||||
light_slate_gray = 0x778899, // rgb(119,136,153)
|
||||
light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
|
||||
light_yellow = 0xFFFFE0, // rgb(255,255,224)
|
||||
lime = 0x00FF00, // rgb(0,255,0)
|
||||
lime_green = 0x32CD32, // rgb(50,205,50)
|
||||
linen = 0xFAF0E6, // rgb(250,240,230)
|
||||
magenta = 0xFF00FF, // rgb(255,0,255)
|
||||
maroon = 0x800000, // rgb(128,0,0)
|
||||
medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
|
||||
medium_blue = 0x0000CD, // rgb(0,0,205)
|
||||
medium_orchid = 0xBA55D3, // rgb(186,85,211)
|
||||
medium_purple = 0x9370DB, // rgb(147,112,219)
|
||||
medium_sea_green = 0x3CB371, // rgb(60,179,113)
|
||||
medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
|
||||
medium_spring_green = 0x00FA9A, // rgb(0,250,154)
|
||||
medium_turquoise = 0x48D1CC, // rgb(72,209,204)
|
||||
medium_violet_red = 0xC71585, // rgb(199,21,133)
|
||||
midnight_blue = 0x191970, // rgb(25,25,112)
|
||||
mint_cream = 0xF5FFFA, // rgb(245,255,250)
|
||||
misty_rose = 0xFFE4E1, // rgb(255,228,225)
|
||||
moccasin = 0xFFE4B5, // rgb(255,228,181)
|
||||
navajo_white = 0xFFDEAD, // rgb(255,222,173)
|
||||
navy = 0x000080, // rgb(0,0,128)
|
||||
old_lace = 0xFDF5E6, // rgb(253,245,230)
|
||||
olive = 0x808000, // rgb(128,128,0)
|
||||
olive_drab = 0x6B8E23, // rgb(107,142,35)
|
||||
orange = 0xFFA500, // rgb(255,165,0)
|
||||
orange_red = 0xFF4500, // rgb(255,69,0)
|
||||
orchid = 0xDA70D6, // rgb(218,112,214)
|
||||
pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
|
||||
pale_green = 0x98FB98, // rgb(152,251,152)
|
||||
pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
|
||||
pale_violet_red = 0xDB7093, // rgb(219,112,147)
|
||||
papaya_whip = 0xFFEFD5, // rgb(255,239,213)
|
||||
peach_puff = 0xFFDAB9, // rgb(255,218,185)
|
||||
peru = 0xCD853F, // rgb(205,133,63)
|
||||
pink = 0xFFC0CB, // rgb(255,192,203)
|
||||
plum = 0xDDA0DD, // rgb(221,160,221)
|
||||
powder_blue = 0xB0E0E6, // rgb(176,224,230)
|
||||
purple = 0x800080, // rgb(128,0,128)
|
||||
rebecca_purple = 0x663399, // rgb(102,51,153)
|
||||
red = 0xFF0000, // rgb(255,0,0)
|
||||
rosy_brown = 0xBC8F8F, // rgb(188,143,143)
|
||||
royal_blue = 0x4169E1, // rgb(65,105,225)
|
||||
saddle_brown = 0x8B4513, // rgb(139,69,19)
|
||||
salmon = 0xFA8072, // rgb(250,128,114)
|
||||
sandy_brown = 0xF4A460, // rgb(244,164,96)
|
||||
sea_green = 0x2E8B57, // rgb(46,139,87)
|
||||
sea_shell = 0xFFF5EE, // rgb(255,245,238)
|
||||
sienna = 0xA0522D, // rgb(160,82,45)
|
||||
silver = 0xC0C0C0, // rgb(192,192,192)
|
||||
sky_blue = 0x87CEEB, // rgb(135,206,235)
|
||||
slate_blue = 0x6A5ACD, // rgb(106,90,205)
|
||||
slate_gray = 0x708090, // rgb(112,128,144)
|
||||
snow = 0xFFFAFA, // rgb(255,250,250)
|
||||
spring_green = 0x00FF7F, // rgb(0,255,127)
|
||||
steel_blue = 0x4682B4, // rgb(70,130,180)
|
||||
tan = 0xD2B48C, // rgb(210,180,140)
|
||||
teal = 0x008080, // rgb(0,128,128)
|
||||
thistle = 0xD8BFD8, // rgb(216,191,216)
|
||||
tomato = 0xFF6347, // rgb(255,99,71)
|
||||
turquoise = 0x40E0D0, // rgb(64,224,208)
|
||||
violet = 0xEE82EE, // rgb(238,130,238)
|
||||
wheat = 0xF5DEB3, // rgb(245,222,179)
|
||||
white = 0xFFFFFF, // rgb(255,255,255)
|
||||
white_smoke = 0xF5F5F5, // rgb(245,245,245)
|
||||
yellow = 0xFFFF00, // rgb(255,255,0)
|
||||
yellow_green = 0x9ACD32, // rgb(154,205,50)
|
||||
}; // enum class color
|
||||
|
||||
// rgb is a struct for red, green and blue colors.
|
||||
// We use rgb as name because some editors will show it as color direct in the
|
||||
// editor.
|
||||
struct rgb
|
||||
{
|
||||
FMT_CONSTEXPR_DECL rgb()
|
||||
: r(0)
|
||||
, g(0)
|
||||
, b(0)
|
||||
{
|
||||
}
|
||||
FMT_CONSTEXPR_DECL rgb(uint8_t r_, uint8_t g_, uint8_t b_)
|
||||
: r(r_)
|
||||
, g(g_)
|
||||
, b(b_)
|
||||
{
|
||||
}
|
||||
FMT_CONSTEXPR_DECL rgb(uint32_t hex)
|
||||
: r((hex >> 16) & 0xFF)
|
||||
, g((hex >> 8) & 0xFF)
|
||||
, b((hex)&0xFF)
|
||||
{
|
||||
}
|
||||
FMT_CONSTEXPR_DECL rgb(color hex)
|
||||
: r((uint32_t(hex) >> 16) & 0xFF)
|
||||
, g((uint32_t(hex) >> 8) & 0xFF)
|
||||
, b(uint32_t(hex) & 0xFF)
|
||||
{
|
||||
}
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
void vprint_rgb(rgb fd, string_view format, format_args args);
|
||||
void vprint_rgb(rgb fd, rgb bg, string_view format, format_args args);
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
specify foreground color 'fd'.
|
||||
Example:
|
||||
fmt::print(fmt::color::red, "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template<typename... Args>
|
||||
inline void print(rgb fd, string_view format_str, const Args &... args)
|
||||
{
|
||||
vprint_rgb(fd, format_str, make_format_args(args...));
|
||||
}
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
specify foreground color 'fd' and background color 'bg'.
|
||||
Example:
|
||||
fmt::print(fmt::color::red, fmt::color::black, "Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template<typename... Args>
|
||||
inline void print(rgb fd, rgb bg, string_view format_str, const Args &... args)
|
||||
{
|
||||
vprint_rgb(fd, bg, format_str, make_format_args(args...));
|
||||
}
|
||||
#endif // FMT_EXTENDED_COLORS
|
||||
|
||||
#if FMT_USE_USER_DEFINED_LITERALS
|
||||
namespace internal {
|
||||
|
||||
|
@@ -290,27 +290,38 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
using base::operator();
|
||||
|
||||
/** Formats an argument of type ``bool``. */
|
||||
iterator operator()(bool value)
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value, iterator>::type operator()(T value)
|
||||
{
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return (*this)(value ? 1 : 0);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value);
|
||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||
// use std::is_same instead.
|
||||
if (std::is_same<T, bool>::value)
|
||||
{
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return base::operator()(value ? 1 : 0);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value != 0);
|
||||
}
|
||||
else if (std::is_same<T, char_type>::value)
|
||||
{
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_spec.flags_ = 0;
|
||||
fmt_spec.align_ = ALIGN_RIGHT;
|
||||
return base::operator()(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base::operator()(value);
|
||||
}
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats a character. */
|
||||
iterator operator()(char_type value)
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value, iterator>::type operator()(T value)
|
||||
{
|
||||
format_specs &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_spec.flags_ = 0;
|
||||
fmt_spec.align_ = ALIGN_RIGHT;
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
@@ -338,6 +349,16 @@ public:
|
||||
return this->out();
|
||||
}
|
||||
|
||||
iterator operator()(basic_string_view<char_type> value)
|
||||
{
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
iterator operator()(monostate value)
|
||||
{
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
/** Formats a pointer. */
|
||||
iterator operator()(const void *value)
|
||||
{
|
||||
|
@@ -114,12 +114,14 @@ struct is_range_ : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
|
||||
template<typename T>
|
||||
struct is_range_<T, typename std::conditional<false,
|
||||
conditional_helper<decltype(internal::declval<T>().begin()), decltype(internal::declval<T>().end())>, void>::type>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
/// tuple_size and tuple_element check.
|
||||
template<typename T>
|
||||
@@ -171,7 +173,7 @@ using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
#endif
|
||||
|
||||
template<class Tuple, class F, size_t... Is>
|
||||
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) noexcept
|
||||
void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT
|
||||
{
|
||||
using std::get;
|
||||
// using free function get<I>(T) now.
|
||||
|
@@ -17,5 +17,3 @@ public:
|
||||
virtual void format(const details::log_msg &msg, fmt::memory_buffer &dest) = 0;
|
||||
};
|
||||
} // namespace spdlog
|
||||
|
||||
#include "details/pattern_formatter_impl.h"
|
||||
|
@@ -45,23 +45,23 @@ public:
|
||||
template<typename... Args>
|
||||
void log(level::level_enum lvl, const char *msg);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void trace(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void trace(const char *fmt, const Args &... args);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void debug(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void debug(const char *fmt, const Args &... args);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void info(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void info(const char *fmt, const Args &... args);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void warn(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void warn(const char *fmt, const Args &... args);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void error(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void error(const char *fmt, const Args &... args);
|
||||
|
||||
template<typename Arg1, typename... Args>
|
||||
void critical(const char *fmt, const Arg1 &, const Args &... args);
|
||||
template<typename... Args>
|
||||
void critical(const char *fmt, const Args &... args);
|
||||
|
||||
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
||||
template<typename... Args>
|
||||
@@ -117,10 +117,10 @@ public:
|
||||
|
||||
// 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_pattern(const std::string &pattern, pattern_time_type time_type = pattern_time_type::local);
|
||||
|
||||
// create a FormatterT formatter all the sinks in this logger.
|
||||
// each sink gets itw own private copy of a formatter object.
|
||||
// create a FormatterT formatter for each sink in this logger.
|
||||
// each sink gets its own private copy of a formatter object.
|
||||
template<class FormatterT, typename... Args>
|
||||
void set_formatter(const Args &... args);
|
||||
|
||||
|
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
void log(const details::log_msg &msg) override
|
||||
{
|
||||
const android_LogPriority priority = convert_to_android(msg.level);
|
||||
const android_LogPriority priority = convert_to_android_(msg.level);
|
||||
fmt::memory_buffer formatted;
|
||||
if (use_raw_msg_)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
void flush() override {}
|
||||
|
||||
private:
|
||||
static android_LogPriority convert_to_android(spdlog::level::level_enum level)
|
||||
static android_LogPriority convert_to_android_(spdlog::level::level_enum level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
|
@@ -5,9 +5,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/os.h"
|
||||
#include "spdlog/details/traits.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -22,14 +22,14 @@ namespace sinks {
|
||||
* of the message.
|
||||
* If no color terminal detected, omit the escape codes.
|
||||
*/
|
||||
template<class StreamTrait, class ConsoleMutexTrait>
|
||||
template<class TargetStream, class ConsoleMutex>
|
||||
class ansicolor_sink : public sink
|
||||
{
|
||||
public:
|
||||
using mutex_t = typename ConsoleMutexTrait::mutex_t;
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
ansicolor_sink()
|
||||
: target_file_(StreamTrait::stream())
|
||||
, mutex_(ConsoleMutexTrait::console_mutex())
|
||||
: target_file_(TargetStream::stream())
|
||||
, mutex_(ConsoleMutex::console_mutex())
|
||||
|
||||
{
|
||||
should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal();
|
||||
@@ -132,10 +132,11 @@ private:
|
||||
std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_;
|
||||
};
|
||||
|
||||
using ansicolor_stdout_sink_mt = ansicolor_sink<details::console_stdout_trait, details::console_mutex_trait>;
|
||||
using ansicolor_stdout_sink_st = ansicolor_sink<details::console_stdout_trait, details::console_null_mutex_trait>;
|
||||
using ansicolor_stderr_sink_mt = ansicolor_sink<details::console_stderr_trait, details::console_mutex_trait>;
|
||||
using ansicolor_stderr_sink_st = ansicolor_sink<details::console_stderr_trait, details::console_null_mutex_trait>;
|
||||
using ansicolor_stdout_sink_mt = ansicolor_sink<details::console_stdout_stream, details::console_global_mutex>;
|
||||
using ansicolor_stdout_sink_st = ansicolor_sink<details::console_stdout_stream, details::console_global_nullmutex>;
|
||||
|
||||
using ansicolor_stderr_sink_mt = ansicolor_sink<details::console_stderr_stream, details::console_global_mutex>;
|
||||
using ansicolor_stderr_sink_st = ansicolor_sink<details::console_stderr_stream, details::console_global_nullmutex>;
|
||||
|
||||
} // namespace sinks
|
||||
|
||||
|
@@ -6,8 +6,8 @@
|
||||
#pragma once
|
||||
//
|
||||
// base sink templated over a mutex (either dummy or real)
|
||||
// concrete implementation should only override the sink_it_ method.
|
||||
// all locking is taken care of here so no locking needed by the implementers..
|
||||
// concrete implementation should override the sink_it_() and flush_() methods.
|
||||
// locking is taken care of in this class - no locking needed by the implementers..
|
||||
//
|
||||
|
||||
#include "spdlog/common.h"
|
||||
@@ -26,16 +26,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -18,28 +18,18 @@ namespace sinks {
|
||||
* Trivial file sink with single file as target
|
||||
*/
|
||||
template<class Mutex>
|
||||
class simple_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
class basic_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
explicit simple_file_sink(const filename_t &filename, bool truncate = false)
|
||||
: force_flush_(false)
|
||||
explicit basic_file_sink(const filename_t &filename, bool truncate = false)
|
||||
{
|
||||
file_helper_.open(filename, truncate);
|
||||
}
|
||||
|
||||
void set_force_flush(bool force_flush)
|
||||
{
|
||||
force_flush_ = force_flush;
|
||||
}
|
||||
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
|
||||
{
|
||||
file_helper_.write(formatted);
|
||||
if (force_flush_)
|
||||
{
|
||||
file_helper_.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override
|
||||
@@ -49,11 +39,10 @@ protected:
|
||||
|
||||
private:
|
||||
details::file_helper file_helper_;
|
||||
bool force_flush_;
|
||||
};
|
||||
|
||||
using simple_file_sink_mt = simple_file_sink<std::mutex>;
|
||||
using simple_file_sink_st = simple_file_sink<details::null_mutex>;
|
||||
using basic_file_sink_mt = basic_file_sink<std::mutex>;
|
||||
using basic_file_sink_st = basic_file_sink<details::null_mutex>;
|
||||
|
||||
} // namespace sinks
|
||||
|
||||
@@ -63,13 +52,13 @@ using simple_file_sink_st = simple_file_sink<details::null_mutex>;
|
||||
template<typename Factory = default_factory>
|
||||
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename, bool truncate = false)
|
||||
{
|
||||
return Factory::template create<sinks::simple_file_sink_mt>(logger_name, filename, truncate);
|
||||
return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate);
|
||||
}
|
||||
|
||||
template<typename Factory = default_factory>
|
||||
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name, const filename_t &filename, bool truncate = false)
|
||||
{
|
||||
return Factory::template create<sinks::simple_file_sink_st>(logger_name, filename, truncate);
|
||||
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate);
|
||||
}
|
||||
|
||||
} // namespace spdlog
|
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "spdlog/details/log_msg.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/sink/base_sink.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@@ -18,22 +17,18 @@
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
template<class Mutex>
|
||||
class dist_sink : public base_sink<Mutex>
|
||||
|
||||
template<typename Mutex>
|
||||
class dist_sink : public sink
|
||||
{
|
||||
public:
|
||||
explicit dist_sink()
|
||||
: sinks_()
|
||||
{
|
||||
}
|
||||
dist_sink() = default;
|
||||
dist_sink(const dist_sink &) = delete;
|
||||
dist_sink &operator=(const dist_sink &) = delete;
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<sink>> sinks_;
|
||||
|
||||
void sink_it_(const details::log_msg &msg) override
|
||||
void log(const details::log_msg &msg) SPDLOG_FINAL override
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
for (auto &sink : sinks_)
|
||||
{
|
||||
if (sink->should_log(msg.level))
|
||||
@@ -43,24 +38,28 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override
|
||||
void flush() SPDLOG_FINAL override
|
||||
{
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
for (auto &sink : sinks_)
|
||||
sink->flush();
|
||||
}
|
||||
|
||||
public:
|
||||
void add_sink(std::shared_ptr<sink> sink)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
sinks_.push_back(sink);
|
||||
}
|
||||
|
||||
void remove_sink(std::shared_ptr<sink> sink)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||
std::lock_guard<Mutex> lock(mutex_);
|
||||
sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink), sinks_.end());
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex mutex_;
|
||||
std::vector<std::shared_ptr<sink>> sinks_;
|
||||
};
|
||||
|
||||
using dist_sink_mt = dist_sink<std::mutex>;
|
||||
|
@@ -27,9 +27,9 @@ public:
|
||||
explicit msvc_sink() {}
|
||||
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &msg) override
|
||||
void sink_it_(const details::log_msg &, const fmt::memory_buffer &formatted) override
|
||||
{
|
||||
OutputDebugStringA(msg.formatted.c_str());
|
||||
OutputDebugStringA(fmt::to_string(formatted).c_str());
|
||||
}
|
||||
|
||||
void flush_() override {}
|
||||
@@ -38,6 +38,9 @@ protected:
|
||||
using msvc_sink_mt = msvc_sink<std::mutex>;
|
||||
using msvc_sink_st = msvc_sink<details::null_mutex>;
|
||||
|
||||
using windebug_sink_mt = msvc_sink_mt;
|
||||
using windebug_sink_st = msvc_sink_st;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "spdlog/details/log_msg.h"
|
||||
#include "spdlog/details/pattern_formatter.h"
|
||||
#include "spdlog/formatter.h"
|
||||
|
||||
namespace spdlog {
|
||||
@@ -19,17 +20,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -39,10 +29,12 @@ public:
|
||||
{
|
||||
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));
|
||||
@@ -58,11 +50,6 @@ public:
|
||||
formatter_ = std::move(sink_formatter);
|
||||
}
|
||||
|
||||
spdlog::formatter *formatter()
|
||||
{
|
||||
return formatter_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
level_t level_{level::trace};
|
||||
std::unique_ptr<spdlog::formatter> formatter_;
|
||||
|
@@ -5,26 +5,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/traits.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <spdlog/details/console_globals.h>
|
||||
|
||||
namespace spdlog {
|
||||
|
||||
namespace sinks {
|
||||
|
||||
template<class StdoutTrait, class ConsoleMutexTrait>
|
||||
template<class TargetStream, class ConsoleMutex>
|
||||
class stdout_sink : public sink
|
||||
{
|
||||
public:
|
||||
using mutex_t = typename ConsoleMutexTrait::mutex_t;
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
stdout_sink()
|
||||
: mutex_(ConsoleMutexTrait::console_mutex())
|
||||
, file_(StdoutTrait::stream())
|
||||
: mutex_(ConsoleMutex::console_mutex())
|
||||
, file_(TargetStream::stream())
|
||||
{
|
||||
}
|
||||
~stdout_sink() = default;
|
||||
@@ -35,14 +36,16 @@ public:
|
||||
void log(const details::log_msg &msg) override
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), file_);
|
||||
fflush(StdoutTrait::stream());
|
||||
fmt::memory_buffer formatted;
|
||||
formatter_->format(msg, formatted);
|
||||
fwrite(formatted.data(), sizeof(char), formatted.size(), file_);
|
||||
fflush(TargetStream::stream());
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
fflush(StdoutTrait::stream());
|
||||
fflush(TargetStream::stream());
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -50,10 +53,11 @@ private:
|
||||
FILE *file_;
|
||||
};
|
||||
|
||||
using stdout_sink_mt = stdout_sink<details::console_stdout_trait, details::console_mutex_trait>;
|
||||
using stdout_sink_st = stdout_sink<details::console_stdout_trait, details::console_null_mutex_trait>;
|
||||
using stderr_sink_mt = stdout_sink<details::console_stderr_trait, details::console_mutex_trait>;
|
||||
using stderr_sink_st = stdout_sink<details::console_stderr_trait, details::console_null_mutex_trait>;
|
||||
using stdout_sink_mt = stdout_sink<details::console_stdout_stream, details::console_global_mutex>;
|
||||
using stdout_sink_st = stdout_sink<details::console_stdout_stream, details::console_global_nullmutex>;
|
||||
|
||||
using stderr_sink_mt = stdout_sink<details::console_stderr_stream, details::console_global_mutex>;
|
||||
using stderr_sink_st = stdout_sink<details::console_stderr_stream, details::console_global_nullmutex>;
|
||||
|
||||
} // namespace sinks
|
||||
|
||||
|
@@ -7,8 +7,8 @@
|
||||
|
||||
#include "../fmt/fmt.h"
|
||||
#include "spdlog/common.h"
|
||||
#include "spdlog/details/console_globals.h"
|
||||
#include "spdlog/details/null_mutex.h"
|
||||
#include "spdlog/details/traits.h"
|
||||
#include "spdlog/sinks/sink.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -22,7 +22,7 @@ namespace sinks {
|
||||
/*
|
||||
* Windows color console sink. Uses WriteConsoleA to write to the console with colors
|
||||
*/
|
||||
template<class HandleTrait, class ConsoleMutexTrait>
|
||||
template<class OutHandle, class ConsoleMutex>
|
||||
class wincolor_sink : public sink
|
||||
{
|
||||
public:
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
|
||||
|
||||
wincolor_sink()
|
||||
: out_handle_(HandleTrait::handle())
|
||||
, mutex_(ConsoleMutexTrait::console_mutex())
|
||||
: out_handle_(OutHandle::handle())
|
||||
, mutex_(ConsoleMutex::console_mutex())
|
||||
{
|
||||
colors_[level::trace] = WHITE;
|
||||
colors_[level::debug] = CYAN;
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
using mutex_t = typename ConsoleMutexTrait::mutex_t;
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
// set color and return the orig console attributes (for resetting later)
|
||||
WORD set_console_attribs(WORD attribs)
|
||||
{
|
||||
@@ -116,11 +116,11 @@ private:
|
||||
std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
|
||||
};
|
||||
|
||||
using wincolor_stdout_sink_mt = wincolor_sink<details::console_stdout_trait, details::console_mutex_trait>;
|
||||
using wincolor_stdout_sink_st = wincolor_sink<details::console_stdout_trait, details::console_null_mutex_trait>;
|
||||
using wincolor_stdout_sink_mt = wincolor_sink<details::console_stdout_stream, details::console_global_mutex>;
|
||||
using wincolor_stdout_sink_st = wincolor_sink<details::console_stdout_stream, details::console_global_nullmutex>;
|
||||
|
||||
using wincolor_stderr_sink_mt = wincolor_sink<details::console_stderr_trait, details::console_mutex_trait>;
|
||||
using wincolor_stderr_sink_st = wincolor_sink<details::console_stderr_trait, details::console_null_mutex_trait>;
|
||||
using wincolor_stderr_sink_mt = wincolor_sink<details::console_stderr_stream, details::console_global_mutex>;
|
||||
using wincolor_stderr_sink_st = wincolor_sink<details::console_stderr_stream, details::console_global_nullmutex>;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// Copyright(c) 2017 Alexander Dalshov.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "spdlog/sinks/msvc_sink.h"
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
/*
|
||||
* Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink)
|
||||
*/
|
||||
template<class Mutex>
|
||||
using windebug_sink = msvc_sink<Mutex>;
|
||||
|
||||
using windebug_sink_mt = msvc_sink_mt;
|
||||
using windebug_sink_st = msvc_sink_st;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
||||
#endif
|
@@ -19,7 +19,7 @@
|
||||
namespace spdlog {
|
||||
|
||||
// Default logger factory- creates synchronous loggers
|
||||
struct create_synchronous
|
||||
struct synchronous_factory
|
||||
{
|
||||
template<typename Sink, typename... SinkArgs>
|
||||
|
||||
@@ -32,7 +32,7 @@ struct create_synchronous
|
||||
}
|
||||
};
|
||||
|
||||
using default_factory = create_synchronous;
|
||||
using default_factory = synchronous_factory;
|
||||
|
||||
// Create and register a logger with a templated sink type
|
||||
// The logger's level, formatter and flush level will be set according the global settings.
|
||||
@@ -57,9 +57,9 @@ inline std::shared_ptr<logger> get(const std::string &name)
|
||||
// Set global formatting
|
||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
||||
//
|
||||
inline void set_pattern(const std::string &format_string)
|
||||
inline void set_pattern(const std::string &format_string, pattern_time_type time_type = pattern_time_type::local)
|
||||
{
|
||||
details::registry::instance().set_pattern(format_string);
|
||||
details::registry::instance().set_pattern(format_string, time_type);
|
||||
}
|
||||
|
||||
//
|
||||
|
Reference in New Issue
Block a user