Do not pass empty format_str to UDT formatters

This commit is contained in:
Fred Miller 2020-07-14 23:08:51 +08:00
parent c108ee1d59
commit d329abc7cb
5 changed files with 19 additions and 12 deletions

View File

@ -94,7 +94,7 @@ template <typename Char> struct part_counter {
return ++num_parts, 0; return ++num_parts, 0;
} }
FMT_CONSTEXPR void on_replacement_field(int, const Char*) {} FMT_CONSTEXPR void on_replacement_field(int, const Char*, const Char*) {}
FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin, FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin,
const Char* end) { const Char* end) {
@ -160,7 +160,7 @@ class format_string_compiler : public error_handler {
return 0; return 0;
} }
FMT_CONSTEXPR void on_replacement_field(int, const Char* ptr) { FMT_CONSTEXPR void on_replacement_field(int, const Char* ptr, const Char*) {
part_.arg_id_end = ptr; part_.arg_id_end = ptr;
handler_(part_); handler_(part_);
} }

View File

@ -1826,6 +1826,7 @@ template <typename OutputIt, typename Char> struct default_arg_formatter {
using context = basic_format_context<OutputIt, Char>; using context = basic_format_context<OutputIt, Char>;
OutputIt out; OutputIt out;
basic_string_view<Char> format_str;
basic_format_args<context> args; basic_format_args<context> args;
locale_ref loc; locale_ref loc;
@ -1834,7 +1835,7 @@ template <typename OutputIt, typename Char> struct default_arg_formatter {
} }
OutputIt operator()(typename basic_format_arg<context>::handle handle) { OutputIt operator()(typename basic_format_arg<context>::handle handle) {
basic_format_parse_context<Char> parse_ctx({}); basic_format_parse_context<Char> parse_ctx(format_str);
basic_format_context<OutputIt, Char> format_ctx(out, args, loc); basic_format_context<OutputIt, Char> format_ctx(out, args, loc);
handle.format(parse_ctx, format_ctx); handle.format(parse_ctx, format_ctx);
return format_ctx.out(); return format_ctx.out();
@ -2629,7 +2630,7 @@ FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin,
++begin; ++begin;
if (begin == end) return handler.on_error("invalid format string"), end; if (begin == end) return handler.on_error("invalid format string"), end;
if (static_cast<char>(*begin) == '}') { if (static_cast<char>(*begin) == '}') {
handler.on_replacement_field(handler.on_arg_id(), begin); handler.on_replacement_field(handler.on_arg_id(), begin, end);
} else if (*begin == '{') { } else if (*begin == '{') {
handler.on_text(begin, begin + 1); handler.on_text(begin, begin + 1);
} else { } else {
@ -2637,7 +2638,7 @@ FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin,
begin = parse_arg_id(begin, end, adapter); begin = parse_arg_id(begin, end, adapter);
Char c = begin != end ? *begin : Char(); Char c = begin != end ? *begin : Char();
if (c == '}') { if (c == '}') {
handler.on_replacement_field(adapter.arg_id, begin); handler.on_replacement_field(adapter.arg_id, begin, end);
} else if (c == ':') { } else if (c == ':') {
begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
if (begin == end || *begin != '}') if (begin == end || *begin != '}')
@ -2740,11 +2741,15 @@ struct format_handler : detail::error_handler {
return arg_id; return arg_id;
} }
FMT_INLINE void on_replacement_field(int id, const Char*) { FMT_INLINE void on_replacement_field(int id, const Char* begin,
const Char* end) {
auto arg = get_arg(context, id); auto arg = get_arg(context, id);
context.advance_to(visit_format_arg( context.advance_to(visit_format_arg(
default_arg_formatter<typename ArgFormatter::iterator, Char>{ default_arg_formatter<typename ArgFormatter::iterator, Char>{
context.out(), context.args(), context.locale()}, context.out(),
{begin, static_cast<size_t>(end - begin)},
context.args(),
context.locale()},
arg)); arg));
} }
@ -2814,7 +2819,7 @@ class format_string_checker {
return 0; return 0;
} }
FMT_CONSTEXPR void on_replacement_field(int, const Char*) {} FMT_CONSTEXPR void on_replacement_field(int, const Char*, const Char*) {}
FMT_CONSTEXPR const Char* on_format_specs(int id, const Char* begin, FMT_CONSTEXPR const Char* on_format_specs(int id, const Char* begin,
const Char*) { const Char*) {
@ -3303,7 +3308,9 @@ typename Context::iterator vformat_to(
if (!arg) detail::error_handler().on_error("argument not found"); if (!arg) detail::error_handler().on_error("argument not found");
using iterator = typename ArgFormatter::iterator; using iterator = typename ArgFormatter::iterator;
return visit_format_arg( return visit_format_arg(
detail::default_arg_formatter<iterator, Char>{out, args, loc}, arg); detail::default_arg_formatter<iterator, Char>{out, format_str, args,
loc},
arg);
} }
detail::format_handler<ArgFormatter, Char, Context> h(out, format_str, args, detail::format_handler<ArgFormatter, Char, Context> h(out, format_str, args,
loc); loc);

View File

@ -600,7 +600,7 @@ struct format_handler : detail::error_handler {
int on_arg_id(unsigned id) { return parse_ctx.check_arg_id(id), id; } int on_arg_id(unsigned id) { return parse_ctx.check_arg_id(id), id; }
int on_arg_id(fmt::basic_string_view<Char>) { return 0; } int on_arg_id(fmt::basic_string_view<Char>) { return 0; }
void on_replacement_field(int id, const Char* p) { void on_replacement_field(int id, const Char* p, const Char*) {
auto arg = context.arg(id); auto arg = context.arg(id);
parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin())); parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin()));
custom_formatter<Context> f(parse_ctx, context); custom_formatter<Context> f(parse_ctx, context);

View File

@ -2246,7 +2246,7 @@ struct test_format_string_handler {
template <typename T> FMT_CONSTEXPR int on_arg_id(T) { return 0; } template <typename T> FMT_CONSTEXPR int on_arg_id(T) { return 0; }
FMT_CONSTEXPR void on_replacement_field(int, const char*) {} FMT_CONSTEXPR void on_replacement_field(int, const char*, const char*) {}
FMT_CONSTEXPR const char* on_format_specs(int, const char* begin, FMT_CONSTEXPR const char* on_format_specs(int, const char* begin,
const char*) { const char*) {

View File

@ -177,7 +177,7 @@ struct scan_handler : error_handler {
} }
int on_arg_id(string_view) { return on_error("invalid format"), 0; } int on_arg_id(string_view) { return on_error("invalid format"), 0; }
void on_replacement_field(int, const char*) { void on_replacement_field(int, const char*, const char*) {
auto it = scan_ctx_.begin(), end = scan_ctx_.end(); auto it = scan_ctx_.begin(), end = scan_ctx_.end();
switch (arg_.type) { switch (arg_.type) {
case scan_type::int_type: case scan_type::int_type: