diff --git a/include/fmt/async.h b/include/fmt/async.h index 644e1fb1..9938d7c7 100644 --- a/include/fmt/async.h +++ b/include/fmt/async.h @@ -1,5 +1,5 @@ -#ifndef FMT_FMTLOG_H_ -#define FMT_FMTLOG_H_ +#ifndef FMT_ASYNC_H_ +#define FMT_ASYNC_H_ #include "format.h" #include @@ -20,7 +20,7 @@ protected: const format_arg* get_format_args() const; template - using enable_out = std::enable_if_t::value, T>; + using enable_out = enable_if_t::value, T>; void destruct() { if (dtor_) dtor_(this); } public: @@ -39,7 +39,7 @@ public: } template - auto format_to_n(OutIt out, size_t n) const -> enable_out> { + auto format_to(OutIt out, size_t n) const -> enable_out> { return vformat_to(detail::truncating_iterator(out, n), format_, {desc_, get_format_args()}); } @@ -86,8 +86,10 @@ inline const typename basic_async_entry::format_arg* basic_async_entry< // | basic_async_entry | arg_store | stored_objs... | stored_buffers... | // ----------------------------------------------------------------------- // - +namespace async { namespace detail { +namespace detail = fmt::detail; +template using decay_t = typename std::decay::type; enum class store_method { numeric, // stored by libfmt as numeric value, no need for extra storage @@ -107,13 +109,13 @@ using stored_as_string = std::integral_constant struct is_basic_string : std::false_type {}; template struct is_basic_string> : std::true_type {}; template -using stored_as_string_object = std::integral_constant::value && is_basic_string>::value && std::is_rvalue_reference::value>; +using stored_as_string_object = std::integral_constant::value && is_basic_string>::value && std::is_rvalue_reference::value>; struct custom_store_method_checker { - template , typename Formatter = typename Context::template formatter_type> - static std::enable_if_t::value, std::tuple(), std::declval()))>> test(double); - template , typename Formatter = typename Context::template formatter_type> - static std::enable_if_t::value, std::tuple(), std::declval()))>> test(int); + template , typename Formatter = typename Context::template formatter_type> + static enable_if_t::value, std::tuple(), std::declval()))>> test(double); + template , typename Formatter = typename Context::template formatter_type> + static enable_if_t::value, std::tuple(), std::declval()))>> test(int); template static std::tuple test(...); }; @@ -121,11 +123,11 @@ struct custom_store_method_checker { template struct custom_store_method { using transformed_type = typename std::tuple_element<1, decltype(custom_store_method_checker::template test(0))>::type; - static constexpr bool custom_store = std::tuple_element<0, decltype(custom_store_method_checker::template test(0))>::type::value && !std::is_same_v; - using store_type = std::conditional_t, store_as_object, store_as_buffer>; + static constexpr bool custom_store = std::tuple_element<0, decltype(custom_store_method_checker::template test(0))>::type::value && !std::is_same::value; + using store_type = conditional_t::value, store_as_object, store_as_buffer>; }; -template , Context>> +template , Context>> struct stored_method_constant : std::integral_constant::value ? store_method::numeric : stored_as_string::value ? (stored_as_string_object::value ? store_method::object : store_method::buffer) : @@ -146,10 +148,10 @@ struct stored_objs_dtor_gen : std::integral_constant struct stored_objs_dtor_select { - using RawT = std::remove_reference_t; - using type = std::conditional_t::value == store_method::object, - typename stored_objs_dtor_select, Args...>::type, - typename stored_objs_dtor_select::type>; + using RawT = remove_reference_t; + using type = conditional_t::value == store_method::object, + typename stored_objs_dtor_select, Args...>::type, + typename stored_objs_dtor_select::type>; }; template @@ -176,22 +178,22 @@ template struct arg_transformer { using arg_tuple = std::tuple; template using arg_at = typename std::tuple_element::type; - using type_tuple = std::tuple...>; + using type_tuple = std::tuple...>; template using type_at = typename std::tuple_element::type; template using size_at = std::integral_constant)>; - template using objsize_at = std::conditional_t, Context>::value == store_method::object, size_at, std::integral_constant>; - template struct objsizesum_at : std::integral_constant, objsizesum_at>::value + objsize_at::value> {}; - template using objoffset_at = std::conditional_t, objsizesum_at>; + template using objsize_at = conditional_t, Context>::value == store_method::object, size_at, std::integral_constant>; + template struct objsizesum_at : std::integral_constant, objsizesum_at>::value + objsize_at::value> {}; + template using objoffset_at = conditional_t, objsizesum_at>; }; -template , Context>> -using transformed_arg_type = std::conditional_t::custom_store, typename custom_store_method::transformed_type, - std::conditional_t::value && !stored_as_string_object::value, basic_string_view, std::add_const_t>&> +template , Context>> +using transformed_arg_type = conditional_t::custom_store, typename custom_store_method::transformed_type, + conditional_t::value && !stored_as_string_object::value, basic_string_view, std::add_const_t>&> >; template struct async_entry_constructor { - using Entry = async_entry>...>; + using Entry = async_entry>...>; using Dtor = stored_objs_dtor; using Trans = arg_transformer; @@ -212,9 +214,9 @@ private: template transformed_arg_type, Context> store(typename Trans::template arg_at arg) { using Arg = typename Trans::template arg_at; using select_store_method = custom_store_method; - using MappedType = detail::mapped_type_constant, Context>; + using MappedType = detail::mapped_type_constant, Context>; if constexpr (select_store_method::custom_store == true) { - using Formatter = typename Context::template formatter_type>; + using Formatter = typename Context::template formatter_type>; return Formatter::store(pBuffer, std::forward(arg)); } @@ -234,7 +236,7 @@ private: } static basic_string_view copy_string(char*& pBuffer, const typename Context::char_type* cstr) { - if constexpr (std::is_same_v) { + if constexpr (std::is_same::value) { wchar_t* pStart = reinterpret_cast(pBuffer); wchar_t* pEnd = wcpcpy(pStart, cstr); pBuffer = reinterpret_cast(pEnd); @@ -267,40 +269,57 @@ private: char* pBuffer; }; -} +} // namespace detail template > -inline size_t store_async_entry(void* buf, const S& format_str, Args&&... args) { +inline size_t store(void* buf, const S& format_str, Args&&... args) { using Context = buffer_context; using Constructor = detail::async_entry_constructor; return Constructor::construct(buf, format_str, std::forward(args)...); } template -inline auto async_entry_to_string(basic_async_entry& entry) -> decltype(entry.format()) { +inline auto format(basic_async_entry& entry) -> decltype(entry.format()) { typename basic_async_entry::dtor_sentry _(entry); return entry.format(); } template -inline auto async_entry_to(OutIt out, basic_async_entry& entry) -> decltype(entry.format_to(out)) { +inline auto format_to(basic_async_entry& entry, OutIt out) -> decltype(entry.format_to(out)) { typename basic_async_entry::dtor_sentry _(entry); return entry.format_to(out); } template -inline auto async_entry_to_n(OutIt out, size_t n, basic_async_entry& entry) -> decltype(entry.format_to_n(out, n)) { +inline auto format_to(basic_async_entry& entry, OutIt out, size_t n) -> decltype(entry.format_to_n(out, n)) { typename basic_async_entry::dtor_sentry _(entry); return entry.format_to(out, n); } template -inline void print_async_entry(std::FILE* f, basic_async_entry& entry) { +inline void print(basic_async_entry& entry, std::FILE* f = stdout) { typename basic_async_entry::dtor_sentry _(entry); entry.print(f); } -template inline void print_async_entry(basic_async_entry& entry) { print_async_entry(stdout, entry); } +// TODO should we add wrappers like this? +// template +// inline auto format(void* entry) -> decltype(format(std::declval&>())) { +// return format(*reinterpret_cast*>(entry)); +// } +// inline auto wformat(void* entry) -> decltype(format(entry)) { return format(entry); } +} // namespace async + +template > +inline auto make_async_entry(const S& format_str, Args&&... args) -> async_entry, remove_reference_t...> { + return { format_str, args... }; } -#endif \ No newline at end of file + +template > +inline size_t store_async_entry(void* buf, const S& format_str, Args&&... args) { + return async::store(buf, format_str, std::forward(args)...); +} + +} // namespace fmt +#endif // FMT_CORE_H_ diff --git a/include/fmt/test.cpp b/include/fmt/test.cpp index 133c421a..ddfbc87a 100644 --- a/include/fmt/test.cpp +++ b/include/fmt/test.cpp @@ -3,27 +3,21 @@ using namespace fmt; -template > -inline auto mk_async_entry(const S& format_str, Args&&... args) -> async_entry, remove_reference_t...> { - return { format_str, args... }; -} - - #include int main() { fmt::print("entry header: {}\n", sizeof(basic_async_entry)); - auto entry = mk_async_entry("The answer is {}\n", 42); - print_async_entry(entry); + auto entry = make_async_entry("The answer is {}\n", 42); + async::print(entry); char buf[2000]; size_t size = store_async_entry(buf, "This {} is {}{}\n", "answer", std::to_string(4), 2); fmt::print("entry size: {}\n", size); auto& entryref1 = entry; auto& entryref = reinterpret_cast(buf[0]); - print_async_entry(entryref); + async::print(entryref); std::cout << &entryref << "\n" << &(entryref.arg_store_) << "\n" << sizeof(entryref.arg_store_) << std::endl; }