From d329abc7cb2e5cc88454de1c4f8a483df6ed15d1 Mon Sep 17 00:00:00 2001 From: Fred Miller Date: Tue, 14 Jul 2020 23:08:51 +0800 Subject: [PATCH] Do not pass empty format_str to UDT formatters --- include/fmt/compile.h | 4 ++-- include/fmt/format.h | 21 ++++++++++++++------- test/format | 2 +- test/format-test.cc | 2 +- test/scan.h | 2 +- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 679da4f2..c45b3e87 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -94,7 +94,7 @@ template struct part_counter { 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, const Char* end) { @@ -160,7 +160,7 @@ class format_string_compiler : public error_handler { 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; handler_(part_); } diff --git a/include/fmt/format.h b/include/fmt/format.h index d0908038..49337568 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1826,6 +1826,7 @@ template struct default_arg_formatter { using context = basic_format_context; OutputIt out; + basic_string_view format_str; basic_format_args args; locale_ref loc; @@ -1834,7 +1835,7 @@ template struct default_arg_formatter { } OutputIt operator()(typename basic_format_arg::handle handle) { - basic_format_parse_context parse_ctx({}); + basic_format_parse_context parse_ctx(format_str); basic_format_context format_ctx(out, args, loc); handle.format(parse_ctx, format_ctx); return format_ctx.out(); @@ -2629,7 +2630,7 @@ FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin, ++begin; if (begin == end) return handler.on_error("invalid format string"), end; if (static_cast(*begin) == '}') { - handler.on_replacement_field(handler.on_arg_id(), begin); + handler.on_replacement_field(handler.on_arg_id(), begin, end); } else if (*begin == '{') { handler.on_text(begin, begin + 1); } else { @@ -2637,7 +2638,7 @@ FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin, begin = parse_arg_id(begin, end, adapter); Char c = begin != end ? *begin : Char(); if (c == '}') { - handler.on_replacement_field(adapter.arg_id, begin); + handler.on_replacement_field(adapter.arg_id, begin, end); } else if (c == ':') { begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); if (begin == end || *begin != '}') @@ -2740,11 +2741,15 @@ struct format_handler : detail::error_handler { 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); context.advance_to(visit_format_arg( default_arg_formatter{ - context.out(), context.args(), context.locale()}, + context.out(), + {begin, static_cast(end - begin)}, + context.args(), + context.locale()}, arg)); } @@ -2814,7 +2819,7 @@ class format_string_checker { 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, const Char*) { @@ -3303,7 +3308,9 @@ typename Context::iterator vformat_to( if (!arg) detail::error_handler().on_error("argument not found"); using iterator = typename ArgFormatter::iterator; return visit_format_arg( - detail::default_arg_formatter{out, args, loc}, arg); + detail::default_arg_formatter{out, format_str, args, + loc}, + arg); } detail::format_handler h(out, format_str, args, loc); diff --git a/test/format b/test/format index 76ac5476..383099f8 100644 --- a/test/format +++ b/test/format @@ -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(fmt::basic_string_view) { 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); parse_ctx.advance_to(parse_ctx.begin() + (p - &*parse_ctx.begin())); custom_formatter f(parse_ctx, context); diff --git a/test/format-test.cc b/test/format-test.cc index 31f8595f..9f8b8def 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2246,7 +2246,7 @@ struct test_format_string_handler { template 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, const char*) { diff --git a/test/scan.h b/test/scan.h index de82067a..e7a6fc9e 100644 --- a/test/scan.h +++ b/test/scan.h @@ -177,7 +177,7 @@ struct scan_handler : error_handler { } 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(); switch (arg_.type) { case scan_type::int_type: