| 3971 | } |
| 3972 | |
| 3973 | struct format_handler : error_handler { |
| 3974 | basic_format_parse_context<Char> parse_context; |
| 3975 | buffer_context<Char> context; |
| 3976 | |
| 3977 | format_handler(buffer_appender<Char> p_out, basic_string_view<Char> str, |
| 3978 | basic_format_args<buffer_context<Char>> p_args, locale_ref p_loc) |
| 3979 | : parse_context(str), context(p_out, p_args, p_loc) {} |
| 3980 | |
| 3981 | void on_text(const Char* begin, const Char* end) { |
| 3982 | auto text = basic_string_view<Char>(begin, to_unsigned(end - begin)); |
| 3983 | context.advance_to(write<Char>(context.out(), text)); |
| 3984 | } |
| 3985 | |
| 3986 | FMT_CONSTEXPR auto on_arg_id() -> int { return parse_context.next_arg_id(); } |
| 3987 | |
| 3988 | FMT_CONSTEXPR auto on_arg_id(int id) -> int { return parse_context.check_arg_id(id), id; } |
| 3989 | |
| 3990 | FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { |
| 3991 | int arg_id = context.arg_id(id); |
| 3992 | if (arg_id < 0) on_error("argument not found"); |
| 3993 | return arg_id; |
| 3994 | } |
| 3995 | |
| 3996 | FMT_INLINE void on_replacement_field(int id, const Char*) { |
| 3997 | auto arg = get_arg(context, id); |
| 3998 | context.advance_to(visit_format_arg( |
| 3999 | default_arg_formatter<Char> {context.out(), context.args(), context.locale()}, arg)); |
| 4000 | } |
| 4001 | |
| 4002 | auto on_format_specs(int id, const Char* begin, const Char* end) -> const Char* { |
| 4003 | auto arg = get_arg(context, id); |
| 4004 | if (arg.type() == type::custom_type) { |
| 4005 | parse_context.advance_to(begin); |
| 4006 | visit_format_arg(custom_formatter<Char> {parse_context, context}, arg); |
| 4007 | return parse_context.begin(); |
| 4008 | } |
| 4009 | auto specs = detail::dynamic_format_specs<Char>(); |
| 4010 | begin = parse_format_specs(begin, end, specs, parse_context, arg.type()); |
| 4011 | detail::handle_dynamic_spec<detail::width_checker>(specs.width, specs.width_ref, context); |
| 4012 | detail::handle_dynamic_spec<detail::precision_checker>(specs.precision, specs.precision_ref, context); |
| 4013 | if (begin == end || *begin != '}') on_error("missing '}' in format string"); |
| 4014 | auto f = arg_formatter<Char> {context.out(), specs, context.locale()}; |
| 4015 | context.advance_to(visit_format_arg(f, arg)); |
| 4016 | return begin; |
| 4017 | } |
| 4018 | }; |
| 4019 | |
| 4020 | detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc)); |
| 4021 | } |