diff --git a/include/fmt/fmtlog.h b/include/fmt/async.h similarity index 72% rename from include/fmt/fmtlog.h rename to include/fmt/async.h index b1492320..644e1fb1 100644 --- a/include/fmt/fmtlog.h +++ b/include/fmt/async.h @@ -4,10 +4,9 @@ #include "format.h" #include -namespace fmtlog { -using namespace fmt; +namespace fmt { -template struct basic_format_entry { +template struct basic_async_entry { protected: using char_type = typename Context::char_type; using format_arg = typename basic_format_args::format_arg; @@ -17,60 +16,66 @@ protected: unsigned long long desc_; arg_destructor dtor_; - FMT_CONSTEXPR basic_format_entry(basic_string_view format) : format_(format), desc_(0), dtor_(0) {} + FMT_CONSTEXPR basic_async_entry(basic_string_view format) : format_(format), desc_(0), dtor_(0) {} const format_arg* get_format_args() const; template - using enable_out = std::enable_if_t::value, T>; -public: + using enable_out = std::enable_if_t::value, T>; + void destruct() { if (dtor_) dtor_(this); } +public: + struct dtor_sentry { + dtor_sentry(basic_async_entry& entry) : entry_(entry) {} + ~dtor_sentry() { entry_.destruct(); } + basic_async_entry& entry_; + }; // libfmt public APIs - std::basic_string format() const { return fmt::vformat(format_, {desc_, get_format_args()}); } + std::basic_string format() const { return vformat(format_, {desc_, get_format_args()}); } template auto format_to(OutIt out) const -> enable_out { - return fmt::vformat_to(out, format_, {desc_, get_format_args()}); + return vformat_to(out, format_, {desc_, get_format_args()}); } template auto format_to_n(OutIt out, size_t n) const -> enable_out> { - return fmt::vformat_to(fmt::detail::truncating_iterator(out, n), format_, {desc_, get_format_args()}); + return vformat_to(detail::truncating_iterator(out, n), format_, {desc_, get_format_args()}); } size_t formatted_size() const { - fmt::detail::counting_buffer<> buf; + detail::counting_buffer<> buf; format_to(buf); return buf.count(); } - void print(std::FILE* file = stdout) const { return fmt::vprint(file, format_, {desc_, get_format_args()}); } + void print(std::FILE* file = stdout) const { return vprint(file, format_, {desc_, get_format_args()}); } }; -template struct format_entry : basic_format_entry { - using entry = basic_format_entry; +template struct async_entry : basic_async_entry { + using entry = basic_async_entry; format_arg_store arg_store_; template - FMT_CONSTEXPR format_entry(const S& format_str, const Args&... args) : entry(to_string_view(format_str)), arg_store_(args...) { + FMT_CONSTEXPR async_entry(const S& format_str, const Args&... args) : entry(to_string_view(format_str)), arg_store_(args...) { entry::desc_ = arg_store_.desc; } FMT_CONSTEXPR void set_dtor(typename entry::arg_destructor dtor) { this->dtor_ = dtor; } }; template -inline const typename basic_format_entry::format_arg* basic_format_entry::get_format_args() const { +inline const typename basic_async_entry::format_arg* basic_async_entry::get_format_args() const { union obfuscated_args { - const fmt::detail::value* values_; + const detail::value* values_; const format_arg* args_; intptr_t pointer_; // more efficient to add integer with size, as the compiler is able to avoid emitting branch } args; - auto& entry = static_cast&>(*this); + auto& entry = static_cast&>(*this); args.values_ = entry.arg_store_.data_.args_; - if (entry.desc_ & fmt::detail::has_named_args_bit) { - args.pointer_ += (desc_ & fmt::detail::is_unpacked_bit) ? sizeof(*args.args_) : sizeof(*args.values_); + if (entry.desc_ & detail::has_named_args_bit) { + args.pointer_ += (desc_ & detail::is_unpacked_bit) ? sizeof(*args.args_) : sizeof(*args.values_); } return args.args_; } @@ -78,7 +83,7 @@ inline const typename basic_format_entry::format_arg* basic_format_entr // // A stored entry looks like: // ----------------------------------------------------------------------- -// | basic_format_entry | arg_store | stored_objs... | stored_buffers... | +// | basic_async_entry | arg_store | stored_objs... | stored_buffers... | // ----------------------------------------------------------------------- // @@ -96,9 +101,9 @@ using store_as_object = store_method_constant; using store_as_buffer = store_method_constant; template -using stored_as_numeric = std::integral_constant; +using stored_as_numeric = std::integral_constant; template -using stored_as_string = std::integral_constant; +using stored_as_string = std::integral_constant; template struct is_basic_string : std::false_type {}; template struct is_basic_string> : std::true_type {}; template @@ -120,7 +125,7 @@ struct custom_store_method { using store_type = std::conditional_t, 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) : @@ -179,26 +184,26 @@ struct arg_transformer { template using objoffset_at = std::conditional_t, objsizesum_at>; }; -template , Context>> +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 -struct format_entry_constructor { - using Entry = format_entry>...>; +struct async_entry_constructor { + using Entry = async_entry>...>; using Dtor = stored_objs_dtor; using Trans = arg_transformer; template static size_t construct(void* buf, const S& format_str, Args... args) { - return format_entry_constructor(buf, format_str, range(), std::forward(args)...).get_total_size(); + return async_entry_constructor(buf, format_str, range(), std::forward(args)...).get_total_size(); } private: using range = typename range_builder<0, sizeof...(Args)>::type; template - constexpr format_entry_constructor(void* buf, const S& format_str, index_list, Args... args) : pEntry(reinterpret_cast(buf)), pBuffer(get_buffer_store(buf)) { + constexpr async_entry_constructor(void* buf, const S& format_str, index_list, Args... args) : pEntry(reinterpret_cast(buf)), pBuffer(get_buffer_store(buf)) { auto p = new(buf) Entry(format_str, store(std::forward(args))...); p->set_dtor(Dtor::value ? Dtor::destruct : nullptr); } @@ -207,16 +212,14 @@ 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 = fmt::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>; - // fmt::print("store custom arg {} @ {}\n", N, (void*)pBuffer); return Formatter::store(pBuffer, std::forward(arg)); } else if constexpr (stored_as_string::value && !stored_as_string_object::value) { - // fmt::print("store string arg {} @ {}({})\n", N, (void*)pBuffer, fmt::detail::arg_mapper().map(std::forward(arg))); - return copy_string(pBuffer, fmt::detail::arg_mapper().map(std::forward(arg))); + return copy_string(pBuffer, detail::arg_mapper().map(std::forward(arg))); } else if constexpr (stored_as_numeric::value) { return std::forward(arg); @@ -235,14 +238,12 @@ private: wchar_t* pStart = reinterpret_cast(pBuffer); wchar_t* pEnd = wcpcpy(pStart, cstr); pBuffer = reinterpret_cast(pEnd); - // fmt::print("copied wstring ({}) @ {}\n", basic_string_view(pStart, pEnd - pStart), (void*)pStart); return basic_string_view(pStart, pEnd - pStart); } else { char* pStart = pBuffer; char* pEnd = stpcpy(pStart, cstr); pBuffer = pEnd; - // fmt::print("copied string ({}) @ {}\n", basic_string_view(pStart, pEnd - pStart), (void*)pStart); return basic_string_view(pStart, pEnd - pStart); } } @@ -258,7 +259,6 @@ private: char* const pentry = reinterpret_cast(buf); // entry will be constructed here char* const pobjs = pentry + sizeof(Entry); // objects will be stored starting here char* const pbufs = pobjs + get_obj_size(); // buffers will be stored starting here - // fmt::print("creating custom arg entry @ {}, {}, {}\n", (void*)pentry, (void*)pobjs, (void*)pbufs); return pbufs; } static constexpr size_t get_obj_size() { return Trans::template objsizesum_at::value; } @@ -267,48 +267,40 @@ private: char* pBuffer; }; -template -struct entry_destruct_sentry { - using Entry = basic_format_entry; - entry_destruct_sentry(Entry& entry) : entry_(entry) {} - ~entry_destruct_sentry() { entry_.destruct(); } - Entry& entry_; -}; - } template > -inline size_t store_format_entry(void* buf, const S& format_str, Args&&... args) { +inline size_t store_async_entry(void* buf, const S& format_str, Args&&... args) { using Context = buffer_context; - using Constructor = detail::format_entry_constructor; + using Constructor = detail::async_entry_constructor; return Constructor::construct(buf, format_str, std::forward(args)...); } template -inline auto format_entry_to_string(basic_format_entry& entry) -> decltype(entry.format()) { - detail::entry_destruct_sentry _(entry); +inline auto async_entry_to_string(basic_async_entry& entry) -> decltype(entry.format()) { + typename basic_async_entry::dtor_sentry _(entry); return entry.format(); } template -inline auto format_entry_to(OutIt out, basic_format_entry& entry) -> decltype(entry.format_to(out)) { - detail::entry_destruct_sentry _(entry); +inline auto async_entry_to(OutIt out, basic_async_entry& entry) -> decltype(entry.format_to(out)) { + typename basic_async_entry::dtor_sentry _(entry); return entry.format_to(out); } template -inline auto format_entry_to_n(OutIt out, size_t n, basic_format_entry& entry) -> decltype(entry.format_to_n(out, n)) { - detail::entry_destruct_sentry _(entry); +inline auto async_entry_to_n(OutIt out, size_t n, basic_async_entry& entry) -> decltype(entry.format_to_n(out, n)) { + typename basic_async_entry::dtor_sentry _(entry); return entry.format_to(out, n); } template -inline void print_format_entry(std::FILE* f, basic_format_entry& entry) { - detail::entry_destruct_sentry _(entry); +inline void print_async_entry(std::FILE* f, basic_async_entry& entry) { + typename basic_async_entry::dtor_sentry _(entry); entry.print(f); } -template inline void print_format_entry(basic_format_entry& entry) { print_format_entry(stdout, entry); } +template inline void print_async_entry(basic_async_entry& entry) { print_async_entry(stdout, entry); } } #endif \ No newline at end of file diff --git a/include/fmt/test.cpp b/include/fmt/test.cpp index b7fdc05f..133c421a 100644 --- a/include/fmt/test.cpp +++ b/include/fmt/test.cpp @@ -1,10 +1,10 @@ #define FMT_HEADER_ONLY -#include "fmtlog.h" +#include "async.h" -using namespace fmtlog; +using namespace fmt; template > -inline auto mk_format_entry(const S& format_str, Args&&... args) -> format_entry, remove_reference_t...> { +inline auto mk_async_entry(const S& format_str, Args&&... args) -> async_entry, remove_reference_t...> { return { format_str, args... }; } @@ -14,16 +14,16 @@ inline auto mk_format_entry(const S& format_str, Args&&... args) -> format_entry int main() { - fmt::print("entry header: {}\n", sizeof(basic_format_entry)); - auto entry = mk_format_entry("The answer is {}\n", 42); - print_format_entry(entry); + fmt::print("entry header: {}\n", sizeof(basic_async_entry)); + auto entry = mk_async_entry("The answer is {}\n", 42); + print_async_entry(entry); char buf[2000]; - size_t size = store_format_entry(buf, "This {} is {}{}\n", "answer", std::to_string(4), 2); + 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_format_entry(entryref); + print_async_entry(entryref); std::cout << &entryref << "\n" << &(entryref.arg_store_) << "\n" << sizeof(entryref.arg_store_) << std::endl; }