Skip to content

Commit

Permalink
Improve spec parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Aug 2, 2024
1 parent 8445327 commit b9c0e4d
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 28 deletions.
30 changes: 7 additions & 23 deletions include/fmt/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -2398,14 +2398,11 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
struct {
const Char*& begin;
dynamic_format_specs<Char>& specs;
format_specs& specs;
type arg_type;

FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
if (!in(arg_type, set)) {
if (arg_type == type::none_type) return begin;
report_error("invalid format specifier");
}
if (!in(arg_type, set)) report_error("invalid format specifier");
specs.type = pres_type;
return begin + 1;
}
Expand All @@ -2421,34 +2418,23 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
++begin;
break;
case '+':
case '-':
FMT_FALLTHROUGH;
case ' ':
if (arg_type == type::none_type) return begin;
specs.sign = c == ' ' ? sign::space : sign::plus;
FMT_FALLTHROUGH;
case '-':
enter_state(state::sign, in(arg_type, sint_set | float_set));
switch (c) {
case '+':
specs.sign = sign::plus;
break;
case '-':
break;
case ' ':
specs.sign = sign::space;
break;
}
++begin;
break;
case '#':
if (arg_type == type::none_type) return begin;
enter_state(state::hash, is_arithmetic_type(arg_type));
specs.alt = true;
++begin;
break;
case '0':
enter_state(state::zero);
if (!is_arithmetic_type(arg_type)) {
if (arg_type == type::none_type) return begin;
if (!is_arithmetic_type(arg_type))
report_error("format specifier requires numeric argument");
}
if (specs.align == align::none) {
// Ignore 0 if align is specified for compatibility with std::format.
specs.align = align::numeric;
Expand All @@ -2470,14 +2456,12 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx);
break;
case '.':
if (arg_type == type::none_type) return begin;
enter_state(state::precision,
in(arg_type, float_set | string_set | cstring_set));
begin = parse_precision(begin, end, specs.precision, specs.precision_ref,
ctx);
break;
case 'L':
if (arg_type == type::none_type) return begin;
enter_state(state::locale, is_arithmetic_type(arg_type));
specs.localized = true;
++begin;
Expand Down
13 changes: 8 additions & 5 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2315,7 +2315,6 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
return format_decimal<Char>(out, abs_value, num_digits);
}

// DEPRECATED!
template <typename Char>
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
format_specs& specs) -> const Char* {
Expand Down Expand Up @@ -4068,12 +4067,16 @@ template <typename T, typename Char = char> struct nested_formatter {

FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto specs = detail::dynamic_format_specs<Char>();
auto it = parse_format_specs(ctx.begin(), ctx.end(), specs, ctx,
detail::type::none_type);
width_ = specs.width;
auto it = ctx.begin(), end = ctx.end();
if (it == end) return it;
auto specs = format_specs();
it = detail::parse_align(it, end, specs);
fill_ = specs.fill;
align_ = specs.align;
Char c = *it;
auto width_ref = detail::arg_ref<Char>();
if ((c >= '0' && c <= '9') || c == '{')
it = detail::parse_dynamic_spec(it, end, width_, width_ref, ctx);
ctx.advance_to(it);
return formatter_.parse(ctx);
}
Expand Down

0 comments on commit b9c0e4d

Please sign in to comment.