mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
fix: [log] adjust code interface and fix bugs
This commit is contained in:
parent
e1de7f9638
commit
df3890d0c5
@ -5,6 +5,13 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
void BM_imp_log_no_output(benchmark::State& state) {
|
||||||
|
imp::log::gripper log {{}, __func__};
|
||||||
|
for (auto _ : state) {
|
||||||
|
log.debug("hello log.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BM_imp_log_gripper(benchmark::State& state) {
|
void BM_imp_log_gripper(benchmark::State& state) {
|
||||||
imp::log::gripper log {{}, __func__};
|
imp::log::gripper log {{}, __func__};
|
||||||
for (auto _ : state) {
|
for (auto _ : state) {
|
||||||
@ -14,4 +21,5 @@ void BM_imp_log_gripper(benchmark::State& state) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
BENCHMARK(BM_imp_log_no_output);
|
||||||
BENCHMARK(BM_imp_log_gripper);
|
BENCHMARK(BM_imp_log_gripper);
|
||||||
@ -16,108 +16,9 @@
|
|||||||
#include "libimp/def.h"
|
#include "libimp/def.h"
|
||||||
#include "libimp/detect_plat.h"
|
#include "libimp/detect_plat.h"
|
||||||
#include "libimp/export.h"
|
#include "libimp/export.h"
|
||||||
|
#include "libimp/enum_cast.h"
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
namespace detail_log {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class has_fn_info {
|
|
||||||
static std::false_type check(...);
|
|
||||||
template <typename U>
|
|
||||||
static auto check(U *u) -> decltype(u->info(std::declval<std::string>()), std::true_type{});
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = decltype(check(static_cast<T *>(nullptr)));
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool has_fn_info_v = has_fn_info<T>::type::value;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class has_fn_error {
|
|
||||||
static std::false_type check(...);
|
|
||||||
template <typename U>
|
|
||||||
static auto check(U *u) -> decltype(u->error(std::declval<std::string>()), std::true_type{});
|
|
||||||
|
|
||||||
public:
|
|
||||||
using type = decltype(check(static_cast<T *>(nullptr)));
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool has_fn_error_v = has_fn_error<T>::type::value;
|
|
||||||
|
|
||||||
struct vtable_t {
|
|
||||||
void (*info )(void *, std::string &&);
|
|
||||||
void (*error)(void *, std::string &&);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class traits {
|
|
||||||
template <typename U>
|
|
||||||
static auto make_fn_info() noexcept
|
|
||||||
-> std::enable_if_t<has_fn_info_v<U>, void (*)(void *, std::string &&)> {
|
|
||||||
return [](void *p, std::string &&s) {
|
|
||||||
static_cast<U *>(p)->info(std::move(s));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
template <typename U>
|
|
||||||
static auto make_fn_info() noexcept
|
|
||||||
-> std::enable_if_t<!has_fn_info_v<U>, void (*)(void *, std::string &&)> {
|
|
||||||
return [](void *, std::string &&) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
static auto make_fn_error() noexcept
|
|
||||||
-> std::enable_if_t<has_fn_error_v<U>, void (*)(void *, std::string &&)> {
|
|
||||||
return [](void *p, std::string &&s) {
|
|
||||||
static_cast<U *>(p)->error(std::move(s));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
template <typename U>
|
|
||||||
static auto make_fn_error() noexcept
|
|
||||||
-> std::enable_if_t<!has_fn_error_v<U>, void (*)(void *, std::string &&)> {
|
|
||||||
return [](void *, std::string &&) {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static auto make_vtable() noexcept {
|
|
||||||
static vtable_t vt {
|
|
||||||
make_fn_info <T>(),
|
|
||||||
make_fn_error<T>(),
|
|
||||||
};
|
|
||||||
return &vt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail_log
|
|
||||||
|
|
||||||
class LIBIMP_EXPORT log_printer {
|
|
||||||
void *objp_ {nullptr};
|
|
||||||
detail_log::vtable_t *vtable_ {nullptr};
|
|
||||||
|
|
||||||
public:
|
|
||||||
log_printer() noexcept = default;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
log_printer(T &p) noexcept
|
|
||||||
: objp_ (static_cast<void *>(&p))
|
|
||||||
, vtable_(detail_log::traits<T>::make_vtable()) {}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept;
|
|
||||||
|
|
||||||
void info (std::string &&);
|
|
||||||
void error(std::string &&);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LIBIMP_EXPORT log_std_t {
|
|
||||||
public:
|
|
||||||
void info (std::string &&) const;
|
|
||||||
void error(std::string &&) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
LIBIMP_EXPORT extern log_std_t log_std;
|
|
||||||
|
|
||||||
namespace log {
|
namespace log {
|
||||||
|
|
||||||
template <typename Fmt, typename... A>
|
template <typename Fmt, typename... A>
|
||||||
@ -125,30 +26,137 @@ std::string fmt(Fmt &&ft, A &&... args) {
|
|||||||
return ::fmt::format(std::forward<Fmt>(ft), std::forward<A>(args)...);
|
return ::fmt::format(std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LIBIMP_EXPORT gripper {
|
enum class level : std::int32_t {
|
||||||
log_printer printer_;
|
trace,
|
||||||
char const *func_;
|
debug,
|
||||||
|
info,
|
||||||
|
warning,
|
||||||
|
error,
|
||||||
|
failed,
|
||||||
|
};
|
||||||
|
|
||||||
gripper &output(void (log_printer::*out_fn)(std::string &&), char type, std::string &&log_str) {
|
} // namespace log
|
||||||
auto tm = std::chrono::system_clock::now();
|
|
||||||
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(tm).time_since_epoch().count() % 1000;
|
namespace detail_log {
|
||||||
auto px = fmt("[{}][{:%Y-%m-%d %H:%M:%S}.{:03}][{}]\n", type, tm, ms, func_);
|
|
||||||
(printer_.*out_fn)(std::move(px += std::move(log_str)));
|
template <typename T>
|
||||||
|
class has_fn_output {
|
||||||
|
static std::false_type check(...);
|
||||||
|
template <typename U>
|
||||||
|
static auto check(U *u) -> decltype(u->output(log::level::trace, std::declval<std::string>()), std::true_type{});
|
||||||
|
|
||||||
|
public:
|
||||||
|
using type = decltype(check(static_cast<T *>(nullptr)));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool has_fn_output_v = has_fn_output<T>::type::value;
|
||||||
|
|
||||||
|
struct vtable_t {
|
||||||
|
void (*output)(void *, log::level, std::string &&);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class traits {
|
||||||
|
template <typename U>
|
||||||
|
static auto make_fn_output() noexcept
|
||||||
|
-> std::enable_if_t<has_fn_output_v<U>, void (*)(void *, log::level, std::string &&)> {
|
||||||
|
return [](void *p, log::level l, std::string &&s) {
|
||||||
|
static_cast<U *>(p)->output(l, std::move(s));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
static auto make_fn_output() noexcept
|
||||||
|
-> std::enable_if_t<!has_fn_output_v<U>, void (*)(void *, log::level, std::string &&)> {
|
||||||
|
return [](void *, log::level, std::string &&) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static auto make_vtable() noexcept {
|
||||||
|
static vtable_t vt {
|
||||||
|
make_fn_output<T>(),
|
||||||
|
};
|
||||||
|
return &vt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail_log
|
||||||
|
|
||||||
|
namespace log {
|
||||||
|
|
||||||
|
class LIBIMP_EXPORT printer {
|
||||||
|
void *objp_ {nullptr};
|
||||||
|
detail_log::vtable_t *vtable_ {nullptr};
|
||||||
|
|
||||||
|
public:
|
||||||
|
printer() noexcept = default;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
printer(T &p) noexcept
|
||||||
|
: objp_ (static_cast<void *>(&p))
|
||||||
|
, vtable_(detail_log::traits<T>::make_vtable()) {}
|
||||||
|
|
||||||
|
explicit operator bool() const noexcept;
|
||||||
|
|
||||||
|
void output(log::level, std::string &&);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBIMP_EXPORT std_t {
|
||||||
|
public:
|
||||||
|
void output(log::level, std::string &&);
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBIMP_EXPORT extern std_t std_out;
|
||||||
|
|
||||||
|
class gripper {
|
||||||
|
printer printer_;
|
||||||
|
char const *func_;
|
||||||
|
level level_limit_;
|
||||||
|
|
||||||
|
template <typename Fmt, typename... A>
|
||||||
|
gripper &output(log::level l, Fmt &&ft, A &&... args) {
|
||||||
|
if (!printer_ || (enum_cast(l) < enum_cast(level_limit_))) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr static char types[] = {
|
||||||
|
'T', 'D', 'I', 'W', 'E', 'F'
|
||||||
|
};
|
||||||
|
auto tp = std::chrono::system_clock::now();
|
||||||
|
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(tp).time_since_epoch().count() % 1000;
|
||||||
|
auto px = fmt("[{}][{:%Y-%m-%d %H:%M:%S}.{:03}][{}] ", types[enum_cast(l)], tp, ms, func_);
|
||||||
|
printer_.output(l, std::move(px += fmt(std::forward<Fmt>(ft), std::forward<A>(args)...)));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
gripper(log_printer printer, char const *func) noexcept
|
gripper(printer printer, char const *func, level level_limit = level::info) noexcept
|
||||||
: printer_(printer)
|
: printer_ (printer)
|
||||||
, func_ (func) {}
|
, func_ (func)
|
||||||
|
, level_limit_(level_limit) {}
|
||||||
|
|
||||||
|
template <typename Fmt, typename... A>
|
||||||
|
gripper &trace(Fmt &&ft, A &&... args) {
|
||||||
|
return output(log::level::trace, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
|
}
|
||||||
|
template <typename Fmt, typename... A>
|
||||||
|
gripper &debug(Fmt &&ft, A &&... args) {
|
||||||
|
return output(log::level::debug, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
|
}
|
||||||
template <typename Fmt, typename... A>
|
template <typename Fmt, typename... A>
|
||||||
gripper &info(Fmt &&ft, A &&... args) {
|
gripper &info(Fmt &&ft, A &&... args) {
|
||||||
return output(&log_printer::info, 'I', fmt(std::forward<Fmt>(ft), std::forward<A>(args)...));
|
return output(log::level::info, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
|
}
|
||||||
|
template <typename Fmt, typename... A>
|
||||||
|
gripper &warning(Fmt &&ft, A &&... args) {
|
||||||
|
return output(log::level::warning, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
template <typename Fmt, typename... A>
|
template <typename Fmt, typename... A>
|
||||||
gripper &error(Fmt &&ft, A &&... args) {
|
gripper &error(Fmt &&ft, A &&... args) {
|
||||||
return output(&log_printer::error, 'E', fmt(std::forward<Fmt>(ft), std::forward<A>(args)...));
|
return output(log::level::error, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
|
}
|
||||||
|
template <typename Fmt, typename... A>
|
||||||
|
gripper &failed(Fmt &&ft, A &&... args) {
|
||||||
|
return output(log::level::failed, std::forward<Fmt>(ft), std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,29 +5,35 @@
|
|||||||
#include "libimp/log.h"
|
#include "libimp/log.h"
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
namespace log {
|
||||||
|
|
||||||
log_printer::operator bool() const noexcept {
|
printer::operator bool() const noexcept {
|
||||||
return (objp_ != nullptr) && (vtable_ != nullptr);
|
return (objp_ != nullptr) && (vtable_ != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_printer::info(std::string && s) {
|
void printer::output(log::level l, std::string &&s) {
|
||||||
if (!*this) return;
|
if (!*this) return;
|
||||||
vtable_->info(objp_, std::move(s));
|
vtable_->output(objp_, l, std::move(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_printer::error(std::string && s) {
|
std_t std_out;
|
||||||
if (!*this) return;
|
|
||||||
vtable_->error(objp_, std::move(s));
|
void std_t::output(log::level l, std::string &&s) {
|
||||||
}
|
switch (l) {
|
||||||
|
case level::trace:
|
||||||
log_std_t log_std;
|
case level::debug:
|
||||||
|
case level::info:
|
||||||
void log_std_t::info(std::string && s) const {
|
std::fprintf(stdout, "%s\n", s.c_str());
|
||||||
std::fprintf(stdin, "%s", s.c_str());
|
break;
|
||||||
}
|
case level::warning:
|
||||||
|
case level::error:
|
||||||
void log_std_t::error(std::string && s) const {
|
case level::failed:
|
||||||
std::fprintf(stderr, "%s", s.c_str());
|
std::fprintf(stderr, "%s\n", s.c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace log
|
||||||
LIBIMP_NAMESPACE_END_
|
LIBIMP_NAMESPACE_END_
|
||||||
|
|||||||
@ -4,49 +4,43 @@
|
|||||||
#include "libimp/log.h"
|
#include "libimp/log.h"
|
||||||
|
|
||||||
TEST(log, detail) {
|
TEST(log, detail) {
|
||||||
EXPECT_FALSE(imp::detail_log::has_fn_info_v<int>);
|
EXPECT_FALSE(imp::detail_log::has_fn_output_v<int>);
|
||||||
EXPECT_FALSE(imp::detail_log::has_fn_error_v<int>);
|
|
||||||
|
|
||||||
struct foo {
|
struct foo {
|
||||||
int info(std::string);
|
int info(std::string);
|
||||||
};
|
};
|
||||||
EXPECT_TRUE (imp::detail_log::has_fn_info_v<foo>);
|
EXPECT_FALSE(imp::detail_log::has_fn_output_v<foo>);
|
||||||
EXPECT_FALSE(imp::detail_log::has_fn_error_v<foo>);
|
|
||||||
|
|
||||||
struct bar {
|
struct bar {
|
||||||
int info(char const *);
|
int info(char const *);
|
||||||
void error(std::string &&);
|
void output(imp::log::level, std::string &&);
|
||||||
};
|
};
|
||||||
EXPECT_FALSE(imp::detail_log::has_fn_info_v<bar>);
|
EXPECT_TRUE(imp::detail_log::has_fn_output_v<bar>);
|
||||||
EXPECT_TRUE (imp::detail_log::has_fn_error_v<bar>);
|
|
||||||
|
|
||||||
struct str {
|
struct str {
|
||||||
str(std::string const &);
|
str(std::string const &);
|
||||||
};
|
};
|
||||||
struct foo_bar {
|
struct foo_bar {
|
||||||
void info(std::string const &);
|
void output(imp::log::level, str);
|
||||||
void error(str);
|
|
||||||
};
|
};
|
||||||
EXPECT_TRUE(imp::detail_log::has_fn_info_v<foo_bar>);
|
EXPECT_TRUE(imp::detail_log::has_fn_output_v<foo_bar>);
|
||||||
EXPECT_TRUE(imp::detail_log::has_fn_error_v<foo_bar>);
|
|
||||||
|
|
||||||
auto vt_int = imp::detail_log::traits<int>::make_vtable();
|
auto vt_int = imp::detail_log::traits<int>::make_vtable();
|
||||||
EXPECT_NE(vt_int, nullptr);
|
EXPECT_NE(vt_int, nullptr);
|
||||||
vt_int->info (nullptr, "123");
|
vt_int->output(nullptr, imp::log::level::debug, "123");
|
||||||
vt_int->error(nullptr, "321");
|
|
||||||
|
|
||||||
struct log {
|
struct log {
|
||||||
std::string what;
|
std::string what;
|
||||||
void error(std::string &&s) {
|
void output(imp::log::level l, std::string &&s) {
|
||||||
what += s;
|
if (l == imp::log::level::error) what += s;
|
||||||
}
|
}
|
||||||
} ll;
|
} ll;
|
||||||
auto vt_log = imp::detail_log::traits<log>::make_vtable();
|
auto vt_log = imp::detail_log::traits<log>::make_vtable();
|
||||||
EXPECT_NE(vt_log, nullptr);
|
EXPECT_NE(vt_log, nullptr);
|
||||||
vt_log->info (&ll, "123");
|
vt_log->output(&ll, imp::log::level::info , "123");
|
||||||
vt_log->error(&ll, "321");
|
vt_log->output(&ll, imp::log::level::error, "321");
|
||||||
vt_log->info (&ll, "654");
|
vt_log->output(&ll, imp::log::level::info , "654");
|
||||||
vt_log->error(&ll, "456");
|
vt_log->output(&ll, imp::log::level::error, "456");
|
||||||
EXPECT_EQ(ll.what, "321456");
|
EXPECT_EQ(ll.what, "321456");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,27 +48,26 @@ TEST(log, log_printer) {
|
|||||||
struct log {
|
struct log {
|
||||||
std::string i;
|
std::string i;
|
||||||
std::string e;
|
std::string e;
|
||||||
void info(std::string &&s) {
|
|
||||||
i += s;
|
void output(imp::log::level l, std::string &&s) {
|
||||||
}
|
if (l == imp::log::level::error) e += s;
|
||||||
void error(std::string &&s) {
|
else if (l == imp::log::level::info) i += s;
|
||||||
e += s;
|
|
||||||
}
|
}
|
||||||
} ll;
|
} ll;
|
||||||
|
|
||||||
imp::log_printer pt = ll;
|
imp::log::printer pt = ll;
|
||||||
pt.info("hello ");
|
pt.output(imp::log::level::info , "hello ");
|
||||||
pt.error("failed: ");
|
pt.output(imp::log::level::error, "failed: ");
|
||||||
pt.info("log-pt");
|
pt.output(imp::log::level::info , "log-pt");
|
||||||
pt.error("whatever");
|
pt.output(imp::log::level::error, "whatever");
|
||||||
EXPECT_EQ(ll.i, "hello log-pt");
|
EXPECT_EQ(ll.i, "hello log-pt");
|
||||||
EXPECT_EQ(ll.e, "failed: whatever");
|
EXPECT_EQ(ll.e, "failed: whatever");
|
||||||
|
|
||||||
imp::log_printer ps = imp::log_std;
|
imp::log::printer ps = imp::log::std_out;
|
||||||
ps.info("hello world\n");
|
ps.output(imp::log::level::info, "hello world\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(log, gripper) {
|
TEST(log, gripper) {
|
||||||
imp::log::gripper log {imp::log_std, __func__};
|
imp::log::gripper log {imp::log::std_out, __func__};
|
||||||
log.info("hello");
|
log.info("hello");
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user