From 15f939c3de44d4e7521432b0c9d82f9358b24c2a Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 4 Aug 2024 09:25:50 -0700 Subject: [PATCH] Improve handling of dynamic specs --- include/fmt/format.h | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 13cac3d9..e15c2d5c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3698,17 +3698,22 @@ FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> basic_format_arg { } template -FMT_CONSTEXPR void handle_dynamic_spec(int& value, - arg_ref ref, - Context& ctx) { - if (ref.kind == arg_id_kind::none) return; +FMT_CONSTEXPR int get_dynamic_spec( + const arg_ref& ref, Context& ctx) { + FMT_ASSERT(ref.kind != arg_id_kind::none, ""); auto arg = ref.kind == arg_id_kind::index ? ctx.arg(ref.val.index) : ctx.arg(ref.val.name); if (!arg) report_error("argument not found"); - unsigned long long arg_value = arg.visit(dynamic_spec_getter()); - if (arg_value > to_unsigned(max_value())) + unsigned long long value = arg.visit(dynamic_spec_getter()); + if (value > to_unsigned(max_value())) report_error("width/precision is out of range"); - value = static_cast(arg_value); + return static_cast(value); +} + +template +FMT_CONSTEXPR void handle_dynamic_spec( + int& value, const arg_ref& ref, Context& ctx) { + if (ref.kind != arg_id_kind::none) value = get_dynamic_spec(ref, ctx); } #if FMT_USE_USER_DEFINED_LITERALS @@ -4168,9 +4173,12 @@ void vformat_to(buffer& buf, basic_string_view fmt, return parse_context.begin(); auto specs = detail::dynamic_format_specs(); begin = parse_format_specs(begin, end, specs, parse_context, arg.type()); - detail::handle_dynamic_spec(specs.width, specs.width_ref, context); - detail::handle_dynamic_spec(specs.precision, specs.precision_ref, - context); + if (specs.width_ref.kind != detail::arg_id_kind::none) + specs.width = detail::get_dynamic_spec(specs.width_ref, context); + if (specs.precision_ref.kind != detail::arg_id_kind::none) { + specs.precision = + detail::get_dynamic_spec(specs.precision_ref, context); + } if (begin == end || *begin != '}') report_error("missing '}' in format string"); context.advance_to(arg.visit(