From 50bad7d62d40424364c9e137d5674934067177f3 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 6 Jun 2020 08:51:17 -0700 Subject: [PATCH] Optimize format string parsing --- include/fmt/format.h | 17 ++++++++++------- test/custom-formatter-test.cc | 3 ++- test/format-test.cc | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 8f584165..65818ab3 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2569,10 +2569,9 @@ struct format_handler : detail::error_handler { int on_arg_id(basic_string_view id) { return context.arg_id(id); } void on_replacement_field(int id, const Char* p) { - advance_to(parse_context, p); auto arg = get_arg(context, id); - context.advance_to( - visit_format_arg(ArgFormatter(context, &parse_context), arg)); + context.advance_to(visit_format_arg( + ArgFormatter(context, &parse_context, nullptr, p), arg)); } const Char* on_format_specs(int id, const Char* begin, const Char* end) { @@ -2754,6 +2753,7 @@ class arg_formatter : public detail::arg_formatter_base { context_type& ctx_; basic_format_parse_context* parse_ctx_; + const Char* ptr_; public: using iterator = typename base::iterator; @@ -2769,15 +2769,17 @@ class arg_formatter : public detail::arg_formatter_base { explicit arg_formatter( context_type& ctx, basic_format_parse_context* parse_ctx = nullptr, - format_specs* specs = nullptr) + format_specs* specs = nullptr, const Char* ptr = nullptr) : base(ctx.out(), specs, ctx.locale()), ctx_(ctx), - parse_ctx_(parse_ctx) {} + parse_ctx_(parse_ctx), + ptr_(ptr) {} using base::operator(); /** Formats an argument of a user-defined type. */ iterator operator()(typename basic_format_arg::handle handle) { + if (ptr_) advance_to(*parse_ctx_, ptr_); handle.format(*parse_ctx_, ctx_); return ctx_.out(); } @@ -3139,8 +3141,9 @@ typename Context::iterator vformat_to( loc); if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) { auto arg = detail::get_arg(h.context, 0); - h.parse_context.advance_to(&format_str[1]); - return visit_format_arg(ArgFormatter(h.context, &h.parse_context), arg); + return visit_format_arg( + ArgFormatter(h.context, &h.parse_context, nullptr, &format_str[1]), + arg); } detail::parse_format_string(format_str, h); return h.context.out(); diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc index c15aaef8..68d32906 100644 --- a/test/custom-formatter-test.cc +++ b/test/custom-formatter-test.cc @@ -24,7 +24,8 @@ class custom_arg_formatter custom_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context* parse_ctx, - fmt::format_specs* s = nullptr) + fmt::format_specs* s = nullptr, + const char* = nullptr) : base(ctx, parse_ctx, s) {} using base::operator(); diff --git a/test/format-test.cc b/test/format-test.cc index 1de2df68..5edd9460 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1821,7 +1821,7 @@ class mock_arg_formatter using base = fmt::detail::arg_formatter_base; mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*, - fmt::format_specs* s = nullptr) + fmt::format_specs* s = nullptr, const char* = nullptr) : base(ctx.out(), s, ctx.locale()) { EXPECT_CALL(*this, call(42)); }