diff --git a/include/fmt/printf.h b/include/fmt/printf.h index cae32442..7194b81d 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -25,34 +25,25 @@ class basic_printf_parse_context : public basic_format_parse_context { }; template class basic_printf_context { + private: + OutputIt out_; + basic_format_args args_; + public: - /** The character type for the output. */ using char_type = Char; - using iterator = OutputIt; using format_arg = basic_format_arg; using parse_context_type = basic_printf_parse_context; template using formatter_type = printf_formatter; - private: - using format_specs = basic_format_specs; - - OutputIt out_; - basic_format_args args_; - parse_context_type parse_ctx_; - - static void parse_flags(format_specs& specs, const Char*& it, - const Char* end); - - public: /** \rst Constructs a ``printf_context`` object. References to the arguments are stored in the context object so make sure they have appropriate lifetimes. \endrst */ - basic_printf_context(OutputIt out, basic_string_view format_str, + basic_printf_context(OutputIt out, basic_format_args args) - : out_(out), args_(args), parse_ctx_(format_str) {} + : out_(out), args_(args) {} OutputIt out() { return out_; } void advance_to(OutputIt it) { out_ = it; } @@ -61,14 +52,8 @@ template class basic_printf_context { format_arg arg(int id) const { return args_.get(id); } - // Returns the argument with specified index or, if arg_index is -1, the next - // argument. - format_arg get_arg(int arg_index = -1); - - parse_context_type& parse_context() { return parse_ctx_; } - FMT_CONSTEXPR void on_error(const char* message) { - parse_ctx_.on_error(message); + detail::error_handler().on_error(message); } }; @@ -306,7 +291,9 @@ class printf_arg_formatter : public arg_formatter { /** Formats an argument of a custom (user-defined) type. */ OutputIt operator()(typename basic_format_arg::handle handle) { - handle.format(context_.parse_context(), context_); + auto parse_ctx = + basic_printf_parse_context(basic_string_view()); + handle.format(parse_ctx, context_); return this->out; } }; @@ -371,7 +358,7 @@ int parse_header(const Char*& it, const Char* end, } else if (*it == '*') { ++it; specs.width = static_cast(visit_format_arg( - detail::printf_width_handler(specs), get_arg())); + detail::printf_width_handler(specs), get_arg(-1))); } } return arg_index; @@ -382,8 +369,19 @@ void vprintf(buffer& buf, basic_string_view format, basic_format_args args) { using OutputIt = buffer_appender; auto out = OutputIt(buf); - auto context = basic_printf_context(out, format, args); - auto& parse_ctx = context.parse_context(); + auto context = basic_printf_context(out, args); + auto parse_ctx = basic_printf_parse_context(format); + + // Returns the argument with specified index or, if arg_index is -1, the next + // argument. + auto get_arg = [&](int arg_index) { + if (arg_index < 0) + arg_index = parse_ctx.next_arg_id(); + else + parse_ctx.check_arg_id(--arg_index); + return detail::get_arg(context, arg_index); + }; + const Char* start = parse_ctx.begin(); const Char* end = parse_ctx.end(); auto it = start; @@ -406,8 +404,7 @@ void vprintf(buffer& buf, basic_string_view format, specs.align = align::right; // Parse argument index, flags and width. - int arg_index = - parse_header(it, end, specs, [&]() { return context.get_arg(); }); + int arg_index = parse_header(it, end, specs, get_arg); if (arg_index == 0) parse_ctx.on_error("argument not found"); // Parse precision. @@ -419,14 +416,14 @@ void vprintf(buffer& buf, basic_string_view format, specs.precision = parse_nonnegative_int(it, end, eh); } else if (c == '*') { ++it; - specs.precision = static_cast(visit_format_arg( - detail::printf_precision_handler(), context.get_arg())); + specs.precision = static_cast( + visit_format_arg(detail::printf_precision_handler(), get_arg(-1))); } else { specs.precision = 0; } } - auto arg = context.get_arg(arg_index); + auto arg = get_arg(arg_index); // For d, i, o, u, x, and X conversion specifiers, if a precision is // specified, the '0' flag is ignored if (specs.precision >= 0 && arg.is_integral()) @@ -520,16 +517,6 @@ void vprintf(buffer& buf, basic_string_view format, } FMT_END_DETAIL_NAMESPACE -template -typename basic_printf_context::format_arg -basic_printf_context::get_arg(int arg_index) { - if (arg_index < 0) - arg_index = parse_ctx_.next_arg_id(); - else - parse_ctx_.check_arg_id(--arg_index); - return detail::get_arg(*this, arg_index); -} - template using basic_printf_context_t = basic_printf_context, Char>;