From 1fd1a95c5208367a0079c60d26364cb9365d0427 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 4 Oct 2023 18:22:09 +0800 Subject: [PATCH 1/3] update --- include/easylog.hpp | 2 +- include/easylog/record.hpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/easylog.hpp b/include/easylog.hpp index 538d524..e7841a6 100644 --- a/include/easylog.hpp +++ b/include/easylog.hpp @@ -201,7 +201,7 @@ inline void add_appender(std::function fn) { easylog::logger::instance() += \ easylog::record_t(std::chrono::system_clock::now(), severity, \ GET_STRING(__FILE__, __LINE__)) \ - .format(prefix::format(format_str, __VA_ARGS__)); \ + .format(format_str, __VA_ARGS__); \ if (severity == easylog::Severity::CRITICAL) { \ easylog::flush(); \ std::exit(EXIT_FAILURE); \ diff --git a/include/easylog/record.hpp b/include/easylog/record.hpp index af14b23..de037cd 100644 --- a/include/easylog/record.hpp +++ b/include/easylog/record.hpp @@ -176,8 +176,9 @@ class record_t { return *this; } - template record_t &format(String &&str) { - ss_.append(str.data()); + template + record_t &format(const char *fmt, Args &&...args) { + ss_.append(fmt::format(fmt, std::forward(args)...)); return *this; } From 0f3021fa131aa78c40a64d028f6c53c8da8425e7 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 4 Oct 2023 20:04:41 +0800 Subject: [PATCH 2/3] cache args..., lazy format --- example/main.cpp | 3 +- include/easylog.hpp | 6 ++-- include/easylog/appender.hpp | 1 + include/easylog/record.hpp | 66 ++++++++++++++++++++++++++++++++---- include/util/type_traits.h | 38 +++++++++++++++++++-- 5 files changed, 101 insertions(+), 13 deletions(-) diff --git a/example/main.cpp b/example/main.cpp index 347ff65..2d52d43 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -6,7 +6,8 @@ int main() { std::filesystem::remove(filename); easylog::init_log(easylog::Severity::DEBUG, filename, true, 5000, 1, true); - ELOGFMT(INFO, "test {}", 42); + std::string str = "world"; + ELOGFMT(INFO, "test {} {} {}", 42, "hello", str); ELOG_INFO << 42; ELOG_INFO << 42 << " " << 4.5 << 'a' << easylog::Severity::DEBUG; diff --git a/include/easylog.hpp b/include/easylog.hpp index e7841a6..ee71152 100644 --- a/include/easylog.hpp +++ b/include/easylog.hpp @@ -175,7 +175,8 @@ inline void add_appender(std::function fn) { easylog::logger::instance() += \ easylog::record_t(std::chrono::system_clock::now(), severity, \ GET_STRING(__FILE__, __LINE__)) \ - .sprintf(fmt, __VA_ARGS__); \ + .format(easylog::get_async(), \ + fmt, __VA_ARGS__); \ if (severity == easylog::Severity::CRITICAL) { \ easylog::flush(); \ std::exit(EXIT_FAILURE); \ @@ -201,7 +202,8 @@ inline void add_appender(std::function fn) { easylog::logger::instance() += \ easylog::record_t(std::chrono::system_clock::now(), severity, \ GET_STRING(__FILE__, __LINE__)) \ - .format(format_str, __VA_ARGS__); \ + .format(easylog::get_async(), \ + format_str, __VA_ARGS__); \ if (severity == easylog::Severity::CRITICAL) { \ easylog::flush(); \ std::exit(EXIT_FAILURE); \ diff --git a/include/easylog/appender.hpp b/include/easylog/appender.hpp index dc4edc2..af82e5a 100644 --- a/include/easylog/appender.hpp +++ b/include/easylog/appender.hpp @@ -140,6 +140,7 @@ class appender { template void write_record(record_t &record) { + record.gen_content(); std::lock_guard guard(get_mutex()); if constexpr (sync == true) { if (max_files_ > 0 && file_size_ > max_file_size_ && diff --git a/include/easylog/record.hpp b/include/easylog/record.hpp index de037cd..9d646e7 100644 --- a/include/easylog/record.hpp +++ b/include/easylog/record.hpp @@ -2,7 +2,10 @@ #include #include +#include #include +#include +#include #include "util/time_util.hpp" #ifdef __linux__ @@ -68,6 +71,11 @@ template constexpr inline bool has_str_v = has_str>::value; } // namespace detail +enum class FormatType { + SPRINTF, + FORMAT, +}; + enum class Severity { NONE, TRACE, @@ -170,15 +178,58 @@ class record_t { return *this; } - template - record_t &sprintf(const char *fmt, Args &&...args) { - ss_.append(fmt::sprintf(fmt, std::forward(args)...)); - return *this; + void gen_content() { + if (args_cache_) { + ss_.append(args_cache_()); + args_cache_ = {}; + } } - template - record_t &format(const char *fmt, Args &&...args) { - ss_.append(fmt::format(fmt, std::forward(args)...)); + template decltype(auto) transform(T &t) { + using U = std::remove_reference_t; + + if constexpr (std::is_same_v || fixed_array_v || + string_view_v) { + return std::string(t); + } else if constexpr (string_v) { + return std::move(t); + } else { + return t; + } + } + + template + auto get_args_impl(Tuple &&tp, std::index_sequence) { + std::tuple<> t; + return std::tuple_cat(t, std::make_tuple(transform(std::get(tp)))...); + } + + template + record_t &format(bool async, const char *fmt, Args &&...args) { + size_t len = strlen(fmt); + std::string str; + str.reserve(len); + str.append(fmt); + args_cache_ = [str = std::move(str), + args1 = get_args_impl( + std::make_tuple(std::forward(args)...), + std::make_index_sequence{})]() mutable { + return std::apply( + [str = std::move(str)](auto &&...args) mutable { + if constexpr (fmt_type == FormatType::FORMAT) { + return fmt::format(str.data(), std::move(args)...); + } else { + return fmt::sprintf(str.data(), std::move(args)...); + } + }, + args1); + }; + + if (!async) { + ss_.append(args_cache_()); + args_cache_ = {}; + } + return *this; } @@ -243,6 +294,7 @@ class record_t { #else std::string ss_; #endif + std::function args_cache_; }; #define TO_STR(s) #s diff --git a/include/util/type_traits.h b/include/util/type_traits.h index 0172683..ba45560 100644 --- a/include/util/type_traits.h +++ b/include/util/type_traits.h @@ -1,12 +1,46 @@ #pragma once #include #include +#include +#include template struct remove_cvref { typedef std::remove_cv_t> type; }; template using remove_cvref_t = typename remove_cvref::type; +template +constexpr inline bool c_array_v = + std::is_array_v> &&std::extent_v> > 0; + +template struct is_array : std::false_type {}; + +template +struct is_array< + T, std::void_t().size()), + typename std::enable_if_t<(std::tuple_size::value != 0)>>> + : std::true_type {}; + +template +constexpr inline bool array_v = is_array>::value; + +template +constexpr inline bool fixed_array_v = c_array_v || array_v; + +template