88#include < cstddef>
99#include < format>
1010#include < source_location>
11+ #include < type_traits>
1112#include < utility>
1213
1314#include " runtime-light/k2-platform/k2-api.h"
@@ -24,25 +25,44 @@ namespace kphp::log {
2425
2526namespace impl {
2627
28+ template <typename T>
29+ requires std::is_floating_point_v<std::remove_cvref_t <T>>
30+ struct floating_wrapper final {
31+ T value{};
32+ };
33+
34+ template <typename T>
35+ constexpr auto wrap_log_argument (T&& t) noexcept -> decltype(auto ) {
36+ if constexpr (std::is_floating_point_v<std::remove_cvref_t <T>>) {
37+ return impl::floating_wrapper<std::remove_cvref_t <T>>{.value = std::forward<T>(t)};
38+ } else {
39+ return std::forward<T>(t);
40+ }
41+ }
42+
43+ template <typename T>
44+ using wrapped_arg_t = std::invoke_result_t <decltype (impl::wrap_log_argument<T>), T>;
45+
2746enum class level : size_t { error = 1 , warn, info, debug, trace };
2847
2948template <typename ... Args>
30- void log (level level, const std::format_string<Args...>& fmt, Args&&... args) noexcept {
49+ void log (level level, std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
3150 if (std::to_underlying (level) > k2::log_level_enabled ()) {
3251 return ;
3352 }
3453
3554 static constexpr size_t LOG_BUFFER_SIZE = 512 ;
3655 std::array<char , LOG_BUFFER_SIZE> log_buffer{};
37- const auto [out, size]{std::format_to_n (log_buffer.data (), log_buffer.size () - 1 , fmt, std::forward<Args>(args)...)};
56+ const auto [out, size]{std::format_to_n<decltype (log_buffer.data ()), impl::wrapped_arg_t <Args>...>(log_buffer.data (), log_buffer.size () - 1 , fmt,
57+ impl::wrap_log_argument (std::forward<Args>(args))...)};
3858 *out = ' \0 ' ;
3959 k2::log (std::to_underlying (level), size, log_buffer.data ());
4060}
4161
4262} // namespace impl
4363
4464template <typename ... Args>
45- [[noreturn]] void error (const std::format_string<Args...>& fmt, Args&&... args) noexcept {
65+ [[noreturn]] void error (std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
4666 impl::log (impl::level::error, fmt, std::forward<Args>(args)...);
4767 k2::exit (1 );
4868}
@@ -54,23 +74,35 @@ inline void assertion(bool condition, const std::source_location& location = std
5474}
5575
5676template <typename ... Args>
57- void warning (const std::format_string<Args...>& fmt, Args&&... args) noexcept {
77+ void warning (std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
5878 impl::log (impl::level::warn, fmt, std::forward<Args>(args)...);
5979}
6080
6181template <typename ... Args>
62- void info (const std::format_string<Args...>& fmt, Args&&... args) noexcept {
82+ void info (std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
6383 impl::log (impl::level::info, fmt, std::forward<Args>(args)...);
6484}
6585
6686template <typename ... Args>
67- void debug (const std::format_string<Args...>& fmt, Args&&... args) noexcept {
87+ void debug (std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
6888 impl::log (impl::level::debug, fmt, std::forward<Args>(args)...);
6989}
7090
7191template <typename ... Args>
72- void trace (const std::format_string<Args...>& fmt, Args&&... args) noexcept {
92+ void trace (std::format_string<impl:: wrapped_arg_t < Args> ...> fmt, Args&&... args) noexcept {
7393 impl::log (impl::level::trace, fmt, std::forward<Args>(args)...);
7494}
7595
7696} // namespace kphp::log
97+
98+ template <typename T>
99+ struct std ::formatter<kphp::log::impl::floating_wrapper<T>> {
100+ constexpr auto parse (std::format_parse_context& ctx) const noexcept {
101+ return ctx.begin ();
102+ }
103+
104+ template <typename FormatContext>
105+ auto format (const kphp::log::impl::floating_wrapper<T>& wrapper, FormatContext& ctx) const noexcept {
106+ return std::format_to (ctx.out (), " {:.4f}" , wrapper.value );
107+ }
108+ };
0 commit comments