forked from fmtlib/fmt
Improve spec parsing
This commit is contained in:
@@ -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;
|
constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
|
||||||
struct {
|
struct {
|
||||||
const Char*& begin;
|
const Char*& begin;
|
||||||
dynamic_format_specs<Char>& specs;
|
format_specs& specs;
|
||||||
type arg_type;
|
type arg_type;
|
||||||
|
|
||||||
FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
|
FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
|
||||||
if (!in(arg_type, set)) {
|
if (!in(arg_type, set)) report_error("invalid format specifier");
|
||||||
if (arg_type == type::none_type) return begin;
|
|
||||||
report_error("invalid format specifier");
|
|
||||||
}
|
|
||||||
specs.type = pres_type;
|
specs.type = pres_type;
|
||||||
return begin + 1;
|
return begin + 1;
|
||||||
}
|
}
|
||||||
@@ -2421,34 +2418,23 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
|
|||||||
++begin;
|
++begin;
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
case '-':
|
FMT_FALLTHROUGH;
|
||||||
case ' ':
|
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));
|
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;
|
++begin;
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
if (arg_type == type::none_type) return begin;
|
|
||||||
enter_state(state::hash, is_arithmetic_type(arg_type));
|
enter_state(state::hash, is_arithmetic_type(arg_type));
|
||||||
specs.alt = true;
|
specs.alt = true;
|
||||||
++begin;
|
++begin;
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
enter_state(state::zero);
|
enter_state(state::zero);
|
||||||
if (!is_arithmetic_type(arg_type)) {
|
if (!is_arithmetic_type(arg_type))
|
||||||
if (arg_type == type::none_type) return begin;
|
|
||||||
report_error("format specifier requires numeric argument");
|
report_error("format specifier requires numeric argument");
|
||||||
}
|
|
||||||
if (specs.align == align::none) {
|
if (specs.align == align::none) {
|
||||||
// Ignore 0 if align is specified for compatibility with std::format.
|
// Ignore 0 if align is specified for compatibility with std::format.
|
||||||
specs.align = align::numeric;
|
specs.align = align::numeric;
|
||||||
@@ -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);
|
begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx);
|
||||||
break;
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
if (arg_type == type::none_type) return begin;
|
|
||||||
enter_state(state::precision,
|
enter_state(state::precision,
|
||||||
in(arg_type, float_set | string_set | cstring_set));
|
in(arg_type, float_set | string_set | cstring_set));
|
||||||
begin = parse_precision(begin, end, specs.precision, specs.precision_ref,
|
begin = parse_precision(begin, end, specs.precision, specs.precision_ref,
|
||||||
ctx);
|
ctx);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
if (arg_type == type::none_type) return begin;
|
|
||||||
enter_state(state::locale, is_arithmetic_type(arg_type));
|
enter_state(state::locale, is_arithmetic_type(arg_type));
|
||||||
specs.localized = true;
|
specs.localized = true;
|
||||||
++begin;
|
++begin;
|
||||||
|
@@ -2315,7 +2315,6 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
|
|||||||
return format_decimal<Char>(out, abs_value, num_digits);
|
return format_decimal<Char>(out, abs_value, num_digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEPRECATED!
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||||
format_specs& specs) -> const Char* {
|
format_specs& specs) -> const Char* {
|
||||||
@@ -4068,12 +4067,16 @@ template <typename T, typename Char = char> struct nested_formatter {
|
|||||||
|
|
||||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||||
-> decltype(ctx.begin()) {
|
-> decltype(ctx.begin()) {
|
||||||
auto specs = detail::dynamic_format_specs<Char>();
|
auto it = ctx.begin(), end = ctx.end();
|
||||||
auto it = parse_format_specs(ctx.begin(), ctx.end(), specs, ctx,
|
if (it == end) return it;
|
||||||
detail::type::none_type);
|
auto specs = format_specs();
|
||||||
width_ = specs.width;
|
it = detail::parse_align(it, end, specs);
|
||||||
fill_ = specs.fill;
|
fill_ = specs.fill;
|
||||||
align_ = specs.align;
|
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);
|
ctx.advance_to(it);
|
||||||
return formatter_.parse(ctx);
|
return formatter_.parse(ctx);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user