From 60f5d244114bad7aefd4f3904424f8bbe2aa9ef4 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 10 Mar 2021 09:18:52 -0800 Subject: [PATCH] Simplify arg_formatter --- include/fmt/compile.h | 12 ++++++++---- include/fmt/format.h | 29 ++++++++++------------------- test/ostream-test.cc | 20 -------------------- 3 files changed, 18 insertions(+), 43 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 819d4abd..49774099 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -302,9 +302,13 @@ template void format_arg( basic_format_parse_context& parse_ctx, Context& ctx, Id arg_id) { - ctx.advance_to(visit_format_arg( - arg_formatter(ctx, &parse_ctx), - ctx.arg(arg_id))); + auto arg = ctx.arg(arg_id); + if (arg.type() == type::custom_type) { + visit_format_arg(custom_formatter(parse_ctx, ctx), arg); + } else { + ctx.advance_to(visit_format_arg( + arg_formatter(ctx), arg)); + } } // vformat_to is defined in a subnamespace to prevent ADL. @@ -366,7 +370,7 @@ auto vformat_to(OutputIt out, CompiledFormat& cf, advance_to(parse_ctx, part.arg_id_end); ctx.advance_to( visit_format_arg(arg_formatter( - ctx, nullptr, &specs), + ctx, &specs), arg)); break; } diff --git a/include/fmt/format.h b/include/fmt/format.h index f4a387d7..e12c5c35 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2450,8 +2450,6 @@ class arg_formatter : public arg_formatter_base { using context_type = basic_format_context; context_type& ctx_; - basic_format_parse_context* parse_ctx_; - const Char* ptr_; public: using iterator = typename base::iterator; @@ -2464,21 +2462,15 @@ class arg_formatter : public arg_formatter_base { *specs* contains format specifier information for standard argument types. \endrst */ - constexpr explicit arg_formatter( - context_type& ctx, - basic_format_parse_context* parse_ctx = nullptr, - format_specs* specs = nullptr, const Char* ptr = nullptr) - : base(ctx.out(), specs, ctx.locale()), - ctx_(ctx), - parse_ctx_(parse_ctx), - ptr_(ptr) {} + constexpr explicit arg_formatter(context_type& ctx, + format_specs* specs = nullptr) + : base(ctx.out(), specs, ctx.locale()), ctx_(ctx) {} 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_); + iterator operator()(typename basic_format_arg::handle) { + // User-defined types are handled separately because they require access to + // the parse context. return ctx_.out(); } }; @@ -3245,8 +3237,8 @@ struct format_handler : detail::error_handler { arg.type()); begin = parse_format_specs(begin, end, handler); if (begin == end || *begin != '}') on_error("missing '}' in format string"); - context.advance_to(visit_format_arg( - arg_formatter(context, &parse_context, &specs), arg)); + context.advance_to( + visit_format_arg(arg_formatter(context, &specs), arg)); return begin; } }; @@ -3623,7 +3615,7 @@ struct formatter; - return visit_format_arg(af(ctx, nullptr, &specs), + return visit_format_arg(af(ctx, &specs), detail::make_arg(val)); } @@ -3726,8 +3718,7 @@ template class dynamic_formatter { if (specs_.precision >= 0) checker.end_precision(); using af = detail::arg_formatter; - visit_format_arg(af(ctx, nullptr, &specs_), - detail::make_arg(val)); + visit_format_arg(af(ctx, &specs_), detail::make_arg(val)); return ctx.out(); } diff --git a/test/ostream-test.cc b/test/ostream-test.cc index 03e64392..b24fbf60 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -64,26 +64,6 @@ TEST(OStreamTest, Enum) { EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum())); } -struct test_arg_formatter - : fmt::detail::arg_formatter { - fmt::format_parse_context parse_ctx; - test_arg_formatter(fmt::format_context& ctx, fmt::format_specs& s) - : fmt::detail::arg_formatter( - ctx, &parse_ctx, &s), - parse_ctx("") {} -}; - -TEST(OStreamTest, CustomArg) { - fmt::memory_buffer buffer; - fmt::format_context ctx(fmt::detail::buffer_appender{buffer}, - fmt::format_args()); - fmt::format_specs spec; - test_arg_formatter af(ctx, spec); - fmt::visit_format_arg( - af, fmt::detail::make_arg(streamable_enum())); - EXPECT_EQ("streamable_enum", std::string(buffer.data(), buffer.size())); -} - TEST(OStreamTest, Format) { EXPECT_EQ("a string", format("{0}", TestString("a string"))); std::string s = format("The date is {0}", Date(2012, 12, 9));