Simplify arg_formatter

This commit is contained in:
Victor Zverovich 2021-03-10 09:18:52 -08:00
parent 30e1302e73
commit 60f5d24411
3 changed files with 18 additions and 43 deletions

View File

@ -302,9 +302,13 @@ template <typename OutputIt, typename Context, typename Id>
void format_arg(
basic_format_parse_context<typename Context::char_type>& parse_ctx,
Context& ctx, Id arg_id) {
ctx.advance_to(visit_format_arg(
arg_formatter<OutputIt, typename Context::char_type>(ctx, &parse_ctx),
ctx.arg(arg_id)));
auto arg = ctx.arg(arg_id);
if (arg.type() == type::custom_type) {
visit_format_arg(custom_formatter<Context>(parse_ctx, ctx), arg);
} else {
ctx.advance_to(visit_format_arg(
arg_formatter<OutputIt, typename Context::char_type>(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<OutputIt, typename Context::char_type>(
ctx, nullptr, &specs),
ctx, &specs),
arg));
break;
}

View File

@ -2450,8 +2450,6 @@ class arg_formatter : public arg_formatter_base<OutputIt, Char> {
using context_type = basic_format_context<OutputIt, Char>;
context_type& ctx_;
basic_format_parse_context<char_type>* parse_ctx_;
const Char* ptr_;
public:
using iterator = typename base::iterator;
@ -2464,21 +2462,15 @@ class arg_formatter : public arg_formatter_base<OutputIt, Char> {
*specs* contains format specifier information for standard argument types.
\endrst
*/
constexpr explicit arg_formatter(
context_type& ctx,
basic_format_parse_context<char_type>* 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<context_type>::handle handle) {
if (ptr_) advance_to(*parse_ctx_, ptr_);
handle.format(*parse_ctx_, ctx_);
iterator operator()(typename basic_format_arg<context_type>::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<OutputIt, Char>(context, &parse_context, &specs), arg));
context.advance_to(
visit_format_arg(arg_formatter<OutputIt, Char>(context, &specs), arg));
return begin;
}
};
@ -3623,7 +3615,7 @@ struct formatter<T, Char,
specs.precision, specs.precision_ref, ctx);
using af = detail::arg_formatter<typename FormatContext::iterator,
typename FormatContext::char_type>;
return visit_format_arg(af(ctx, nullptr, &specs),
return visit_format_arg(af(ctx, &specs),
detail::make_arg<FormatContext>(val));
}
@ -3726,8 +3718,7 @@ template <typename Char = char> class dynamic_formatter {
if (specs_.precision >= 0) checker.end_precision();
using af = detail::arg_formatter<typename FormatContext::iterator,
typename FormatContext::char_type>;
visit_format_arg(af(ctx, nullptr, &specs_),
detail::make_arg<FormatContext>(val));
visit_format_arg(af(ctx, &specs_), detail::make_arg<FormatContext>(val));
return ctx.out();
}

View File

@ -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_context::iterator, char> {
fmt::format_parse_context parse_ctx;
test_arg_formatter(fmt::format_context& ctx, fmt::format_specs& s)
: fmt::detail::arg_formatter<fmt::format_context::iterator, char>(
ctx, &parse_ctx, &s),
parse_ctx("") {}
};
TEST(OStreamTest, CustomArg) {
fmt::memory_buffer buffer;
fmt::format_context ctx(fmt::detail::buffer_appender<char>{buffer},
fmt::format_args());
fmt::format_specs spec;
test_arg_formatter af(ctx, spec);
fmt::visit_format_arg(
af, fmt::detail::make_arg<fmt::format_context>(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));