Don't inherit context from parse_context

This commit is contained in:
Victor Zverovich 2018-01-14 09:27:40 -08:00
parent 217e7c76f1
commit 67928eae28
4 changed files with 38 additions and 28 deletions

View File

@ -646,16 +646,6 @@ class basic_parse_context : private ErrorHandler {
basic_string_view<Char> format_str_; basic_string_view<Char> format_str_;
int next_arg_id_; 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: public:
using char_type = Char; using char_type = Char;
using iterator = typename basic_string_view<Char>::iterator; using iterator = typename basic_string_view<Char>::iterator;
@ -679,7 +669,14 @@ class basic_parse_context : private ErrorHandler {
// Returns the next argument index. // Returns the next argument index.
constexpr unsigned next_arg_id(); 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<Char>) {} void check_arg_id(basic_string_view<Char>) {}
constexpr void on_error(const char *message) { constexpr void on_error(const char *message) {
@ -750,8 +747,9 @@ class arg_map {
}; };
template <typename Range, typename Context> template <typename Range, typename Context>
class context_base : public basic_parse_context<typename Range::value_type> { class context_base {
private: private:
basic_parse_context<typename Range::value_type> parse_context_;
Range range_; Range range_;
basic_format_args<Context> args_; basic_format_args<Context> args_;
@ -761,7 +759,7 @@ class context_base : public basic_parse_context<typename Range::value_type> {
context_base(Range range, basic_string_view<char_type> format_str, context_base(Range range, basic_string_view<char_type> format_str,
basic_format_args<Context> args) basic_format_args<Context> args)
: basic_parse_context<char_type>(format_str), range_(range), args_(args) {} : parse_context_(format_str), range_(range), args_(args) {}
basic_format_args<Context> args() const { return args_; } basic_format_args<Context> args() const { return args_; }
@ -769,19 +767,28 @@ class context_base : public basic_parse_context<typename Range::value_type> {
format_arg do_get_arg(unsigned arg_id) { format_arg do_get_arg(unsigned arg_id) {
format_arg arg = args_[arg_id]; format_arg arg = args_[arg_id];
if (!arg) if (!arg)
this->on_error("argument index out of range"); parse_context_.on_error("argument index out of range");
return arg; return arg;
} }
// Checks if manual indexing is used and returns the argument with // Checks if manual indexing is used and returns the argument with
// specified index. // specified index.
format_arg get_arg(unsigned arg_id) { 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(); this->do_get_arg(arg_id) : format_arg();
} }
public: public:
basic_parse_context<char_type> &parse_context() { return *this; } constexpr basic_parse_context<char_type> &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_; } Range range() { return range_; }
}; };
@ -846,7 +853,9 @@ class basic_context :
basic_format_args<basic_context> args) basic_format_args<basic_context> args)
: base(range, format_str, 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); } 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 // Checks if manual indexing is used and returns the argument with
@ -959,7 +968,8 @@ class basic_format_args {
unsigned max_size() const { unsigned max_size() const {
int64_t signed_types = static_cast<int64_t>(types_); int64_t signed_types = static_cast<int64_t>(types_);
return signed_types < 0 ? -signed_types : internal::MAX_PACKED_ARGS; return signed_types < 0 ?
-signed_types : static_cast<int64_t>(internal::MAX_PACKED_ARGS);
} }
}; };

View File

@ -1556,7 +1556,7 @@ class specs_handler: public specs_setter<typename Context::char_type> {
template <typename Id> template <typename Id>
constexpr basic_arg<Context> get_arg(Id arg_id) { constexpr basic_arg<Context> 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); return context_.get_arg(arg_id);
} }
@ -2519,7 +2519,6 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
*format_ptr = '\0'; *format_ptr = '\0';
// Format using snprintf. // Format using snprintf.
char_type fill = internal::char_traits<char_type>::cast(spec.fill());
unsigned n = 0; unsigned n = 0;
char_type *start = 0; char_type *start = 0;
for (;;) { for (;;) {
@ -2908,7 +2907,7 @@ void vformat_to(typename ArgFormatter::range out,
void on_arg_id() { arg = context.next_arg(); } void on_arg_id() { arg = context.next_arg(); }
void on_arg_id(unsigned id) { void on_arg_id(unsigned id) {
context.check_arg_id(id); context.parse_context().check_arg_id(id);
arg = context.get_arg(id); arg = context.get_arg(id);
} }
void on_arg_id(basic_string_view<Char> id) { void on_arg_id(basic_string_view<Char> id) {
@ -2916,7 +2915,7 @@ void vformat_to(typename ArgFormatter::range out,
} }
void on_replacement_field(iterator it) { void on_replacement_field(iterator it) {
context.advance_to(pointer_from(it)); context.parse_context().advance_to(pointer_from(it));
using internal::custom_formatter; using internal::custom_formatter;
if (visit(custom_formatter<Char, Context>(context), arg)) if (visit(custom_formatter<Char, Context>(context), arg))
return; return;
@ -2925,10 +2924,11 @@ void vformat_to(typename ArgFormatter::range out,
} }
iterator on_format_specs(iterator it) { 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; using internal::custom_formatter;
if (visit(custom_formatter<Char, Context>(context), arg)) if (visit(custom_formatter<Char, Context>(context), arg))
return iterator(context); return iterator(parse_ctx);
basic_format_specs<Char> specs; basic_format_specs<Char> specs;
using internal::specs_handler; using internal::specs_handler;
internal::specs_checker<specs_handler<Context>> internal::specs_checker<specs_handler<Context>>
@ -2936,7 +2936,7 @@ void vformat_to(typename ArgFormatter::range out,
it = parse_format_specs(it, handler); it = parse_format_specs(it, handler);
if (*it != '}') if (*it != '}')
on_error("missing '}' in format string"); 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); visit(ArgFormatter(out, context, specs), arg);
return it; return it;
} }

View File

@ -373,7 +373,7 @@ typename basic_printf_context<Range, AF>::format_arg
basic_printf_context<Range, AF>::get_arg(iterator it, unsigned arg_index) { basic_printf_context<Range, AF>::get_arg(iterator it, unsigned arg_index) {
(void)it; (void)it;
if (arg_index == std::numeric_limits<unsigned>::max()) if (arg_index == std::numeric_limits<unsigned>::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); return Base::get_arg(arg_index - 1);
} }
@ -417,8 +417,7 @@ unsigned basic_printf_context<Range, AF>::parse_header(
template <typename Range, typename AF> template <typename Range, typename AF>
void basic_printf_context<Range, AF>::format() { void basic_printf_context<Range, AF>::format() {
auto &buffer = this->range().container(); auto &buffer = this->range().container();
Base &base = *this; auto start = iterator(this->parse_context());
auto start = iterator(base);
auto it = start; auto it = start;
using internal::pointer_from; using internal::pointer_from;
while (*it) { while (*it) {

View File

@ -1694,6 +1694,7 @@ struct test_context {
void on_error(const char *) {} void on_error(const char *) {}
constexpr test_context &parse_context() { return *this; }
constexpr test_context error_handler() { return *this; } constexpr test_context error_handler() { return *this; }
}; };