diff --git a/include/fmt/core.h b/include/fmt/core.h index 7df62b00..87ed402b 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -1320,10 +1320,8 @@ template class basic_format_context { : out_(out), args_(ctx_args), loc_(loc) {} format_arg arg(int id) const { return args_.get(id); } - - // Checks if manual indexing is used and returns the argument with the - // specified name. format_arg arg(basic_string_view name) { return args_.get(name); } + int arg_id(basic_string_view name) { return args_.get_id(name); } detail::error_handler error_handler() { return {}; } void on_error(const char* message) { error_handler().on_error(message); } @@ -1687,13 +1685,18 @@ template class basic_format_args { } template format_arg get(basic_string_view name) const { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template int get_id(basic_string_view name) const { if (!has_named_args()) return {}; const auto& named_args = (is_packed() ? values_[-1] : args_[-1].value_).named_args; for (size_t i = 0; i < named_args.size; ++i) { - if (named_args.data[i].name == name) return get(named_args.data[i].id); + if (named_args.data[i].name == name) return named_args.data[i].id; } - return {}; + return -1; } int max_size() const { diff --git a/include/fmt/format.h b/include/fmt/format.h index de55d644..c4cc87b7 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -2546,9 +2546,12 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs( template struct format_handler : detail::error_handler { - using iterator = typename ArgFormatter::iterator; + basic_format_parse_context parse_context; + Context context; + int arg_id; - format_handler(iterator out, basic_string_view str, + format_handler(typename ArgFormatter::iterator out, + basic_string_view str, basic_format_args format_args, detail::locale_ref loc) : parse_context(str), context(out, format_args, loc) {} @@ -2560,25 +2563,23 @@ struct format_handler : detail::error_handler { context.advance_to(out); } - template void get_arg(ID id) { - arg = detail::get_arg(context, id); - } - - void on_arg_id() { get_arg(parse_context.next_arg_id()); } + void on_arg_id() { arg_id = parse_context.next_arg_id(); } void on_arg_id(int id) { parse_context.check_arg_id(id); - get_arg(id); + arg_id = id; } - void on_arg_id(basic_string_view id) { get_arg(id); } + void on_arg_id(basic_string_view id) { arg_id = context.arg_id(id); } void on_replacement_field(const Char* p) { advance_to(parse_context, p); + auto arg = get_arg(context, arg_id); context.advance_to( visit_format_arg(ArgFormatter(context, &parse_context), arg)); } const Char* on_format_specs(const Char* begin, const Char* end) { advance_to(parse_context, begin); + auto arg = get_arg(context, arg_id); detail::custom_formatter f(parse_context, context); if (visit_format_arg(f, arg)) return parse_context.begin(); basic_format_specs specs; @@ -2594,10 +2595,6 @@ struct format_handler : detail::error_handler { visit_format_arg(ArgFormatter(context, &parse_context, &specs), arg)); return begin; } - - basic_format_parse_context parse_context; - Context context; - basic_format_arg arg; }; // A parse context with extra argument id checks. It is only used at compile @@ -3143,7 +3140,8 @@ typename Context::iterator vformat_to( typename ArgFormatter::iterator out, basic_string_view format_str, basic_format_args args, detail::locale_ref loc = detail::locale_ref()) { - detail::format_handler h(out, format_str, args, loc); + detail::format_handler h(out, format_str, args, + loc); if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) { auto arg = detail::get_arg(h.context, 0); h.parse_context.advance_to(&format_str[1]);