diff --git a/include/fmt/core.h b/include/fmt/core.h index 3cc4b8a3..92797da3 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -646,16 +646,6 @@ class basic_parse_context : private ErrorHandler { basic_string_view format_str_; int next_arg_id_; - protected: - constexpr bool check_no_auto_index() { - if (next_arg_id_ > 0) { - on_error("cannot switch from automatic to manual argument indexing"); - return false; - } - next_arg_id_ = -1; - return true; - } - public: using char_type = Char; using iterator = typename basic_string_view::iterator; @@ -679,7 +669,14 @@ class basic_parse_context : private ErrorHandler { // Returns the next argument index. constexpr unsigned next_arg_id(); - constexpr void check_arg_id(unsigned) { check_no_auto_index(); } + constexpr bool check_arg_id(unsigned) { + if (next_arg_id_ > 0) { + on_error("cannot switch from automatic to manual argument indexing"); + return false; + } + next_arg_id_ = -1; + return true; + } void check_arg_id(basic_string_view) {} constexpr void on_error(const char *message) { @@ -750,8 +747,9 @@ class arg_map { }; template -class context_base : public basic_parse_context { +class context_base { private: + basic_parse_context parse_context_; Range range_; basic_format_args args_; @@ -761,7 +759,7 @@ class context_base : public basic_parse_context { context_base(Range range, basic_string_view format_str, basic_format_args args) - : basic_parse_context(format_str), range_(range), args_(args) {} + : parse_context_(format_str), range_(range), args_(args) {} basic_format_args args() const { return args_; } @@ -769,19 +767,28 @@ class context_base : public basic_parse_context { format_arg do_get_arg(unsigned arg_id) { format_arg arg = args_[arg_id]; if (!arg) - this->on_error("argument index out of range"); + parse_context_.on_error("argument index out of range"); return arg; } // Checks if manual indexing is used and returns the argument with // specified index. format_arg get_arg(unsigned arg_id) { - return this->check_no_auto_index() ? + return this->parse_context().check_arg_id(arg_id) ? this->do_get_arg(arg_id) : format_arg(); } public: - basic_parse_context &parse_context() { return *this; } + constexpr basic_parse_context &parse_context() { + return parse_context_; + } + + internal::error_handler error_handler() { + return parse_context_.error_handler(); + } + + void on_error(const char *message) { parse_context_.on_error(message); } + Range range() { return range_; } }; @@ -846,7 +853,9 @@ class basic_context : basic_format_args args) : base(range, format_str, args) {} - format_arg next_arg() { return this->do_get_arg(this->next_arg_id()); } + format_arg next_arg() { + return this->do_get_arg(this->parse_context().next_arg_id()); + } format_arg get_arg(unsigned arg_id) { return this->do_get_arg(arg_id); } // Checks if manual indexing is used and returns the argument with @@ -959,7 +968,8 @@ class basic_format_args { unsigned max_size() const { int64_t signed_types = static_cast(types_); - return signed_types < 0 ? -signed_types : internal::MAX_PACKED_ARGS; + return signed_types < 0 ? + -signed_types : static_cast(internal::MAX_PACKED_ARGS); } }; diff --git a/include/fmt/format.h b/include/fmt/format.h index 58ea7d9c..f78294cc 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1556,7 +1556,7 @@ class specs_handler: public specs_setter { template constexpr basic_arg get_arg(Id arg_id) { - context_.check_arg_id(arg_id); + context_.parse_context().check_arg_id(arg_id); return context_.get_arg(arg_id); } @@ -2519,7 +2519,6 @@ void basic_writer::write_double(T value, const format_specs &spec) { *format_ptr = '\0'; // Format using snprintf. - char_type fill = internal::char_traits::cast(spec.fill()); unsigned n = 0; char_type *start = 0; for (;;) { @@ -2908,7 +2907,7 @@ void vformat_to(typename ArgFormatter::range out, void on_arg_id() { arg = context.next_arg(); } void on_arg_id(unsigned id) { - context.check_arg_id(id); + context.parse_context().check_arg_id(id); arg = context.get_arg(id); } void on_arg_id(basic_string_view id) { @@ -2916,7 +2915,7 @@ void vformat_to(typename ArgFormatter::range out, } void on_replacement_field(iterator it) { - context.advance_to(pointer_from(it)); + context.parse_context().advance_to(pointer_from(it)); using internal::custom_formatter; if (visit(custom_formatter(context), arg)) return; @@ -2925,10 +2924,11 @@ void vformat_to(typename ArgFormatter::range out, } iterator on_format_specs(iterator it) { - context.advance_to(pointer_from(it)); + auto& parse_ctx = context.parse_context(); + parse_ctx.advance_to(pointer_from(it)); using internal::custom_formatter; if (visit(custom_formatter(context), arg)) - return iterator(context); + return iterator(parse_ctx); basic_format_specs specs; using internal::specs_handler; internal::specs_checker> @@ -2936,7 +2936,7 @@ void vformat_to(typename ArgFormatter::range out, it = parse_format_specs(it, handler); if (*it != '}') on_error("missing '}' in format string"); - context.advance_to(pointer_from(it)); + parse_ctx.advance_to(pointer_from(it)); visit(ArgFormatter(out, context, specs), arg); return it; } diff --git a/include/fmt/printf.h b/include/fmt/printf.h index 856c62a6..24019082 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -373,7 +373,7 @@ typename basic_printf_context::format_arg basic_printf_context::get_arg(iterator it, unsigned arg_index) { (void)it; if (arg_index == std::numeric_limits::max()) - return this->do_get_arg(this->next_arg_id()); + return this->do_get_arg(this->parse_context().next_arg_id()); return Base::get_arg(arg_index - 1); } @@ -417,8 +417,7 @@ unsigned basic_printf_context::parse_header( template void basic_printf_context::format() { auto &buffer = this->range().container(); - Base &base = *this; - auto start = iterator(base); + auto start = iterator(this->parse_context()); auto it = start; using internal::pointer_from; while (*it) { diff --git a/test/format-test.cc b/test/format-test.cc index 58347d9e..f728faeb 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1694,6 +1694,7 @@ struct test_context { void on_error(const char *) {} + constexpr test_context &parse_context() { return *this; } constexpr test_context error_handler() { return *this; } };