mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-25 15:21:54 +00:00
Simplify fill and alignment parsing
This commit is contained in:
parent
040dc2a5d4
commit
bde1a6070d
@ -2020,10 +2020,6 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
}
|
||||
|
||||
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
||||
FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {
|
||||
f.specs.fill = fill;
|
||||
}
|
||||
FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; }
|
||||
FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; }
|
||||
FMT_CONSTEXPR void on_precision(int _precision) {
|
||||
f.precision = _precision;
|
||||
@ -2048,8 +2044,11 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) {
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
if (begin == end || *begin == '}') return {begin, begin};
|
||||
spec_handler handler{*this, ctx, format_str};
|
||||
begin = detail::parse_align(begin, end, handler);
|
||||
auto handler = spec_handler{*this, ctx, format_str};
|
||||
auto result = detail::parse_align(begin, end);
|
||||
begin = result.end;
|
||||
specs.align = result.align;
|
||||
if (result.fill.size() != 0) specs.fill = result.fill;
|
||||
if (begin == end) return {begin, begin};
|
||||
begin = detail::parse_width(begin, end, handler);
|
||||
if (begin == end) return {begin, begin};
|
||||
|
@ -2362,11 +2362,18 @@ FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
|
||||
: error_value;
|
||||
}
|
||||
|
||||
// Parses fill and alignment.
|
||||
template <typename Char, typename Handler>
|
||||
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||
Handler&& handler) -> const Char* {
|
||||
template <typename Char> struct parse_align_result {
|
||||
const Char* end;
|
||||
basic_string_view<Char> fill;
|
||||
align_t align;
|
||||
};
|
||||
|
||||
// Parses [[fill]align].
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end)
|
||||
-> parse_align_result<Char> {
|
||||
FMT_ASSERT(begin != end, "");
|
||||
auto fill = basic_string_view<Char>();
|
||||
auto align = align::none;
|
||||
auto p = begin + code_point_length(begin);
|
||||
if (end - p <= 0) p = begin;
|
||||
@ -2381,27 +2388,27 @@ FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
|
||||
case '^':
|
||||
align = align::center;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (align != align::none) {
|
||||
if (p != begin) {
|
||||
auto c = *begin;
|
||||
if (c == '{')
|
||||
return handler.on_error("invalid fill character '{'"), begin;
|
||||
if (c == '}') return begin;
|
||||
handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));
|
||||
if (c == '}') return {begin, {}, align::none};
|
||||
if (c == '{') {
|
||||
throw_format_error("invalid fill character '{'");
|
||||
return {begin, {}, align::none};
|
||||
}
|
||||
fill = {begin, to_unsigned(p - begin)};
|
||||
begin = p + 1;
|
||||
} else
|
||||
} else {
|
||||
++begin;
|
||||
handler.on_align(align);
|
||||
}
|
||||
break;
|
||||
} else if (p == begin) {
|
||||
break;
|
||||
}
|
||||
p = begin;
|
||||
}
|
||||
return begin;
|
||||
return {begin, fill, align};
|
||||
}
|
||||
|
||||
template <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) {
|
||||
@ -2581,7 +2588,12 @@ FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin,
|
||||
|
||||
if (begin == end) return begin;
|
||||
|
||||
begin = parse_align(begin, end, handler);
|
||||
auto result = parse_align(begin, end);
|
||||
begin = result.end;
|
||||
if (result.align != align::none) {
|
||||
if (result.fill.size() != 0) handler.on_fill(result.fill);
|
||||
handler.on_align(result.align);
|
||||
}
|
||||
if (begin == end) return begin;
|
||||
|
||||
// Parse sign.
|
||||
|
@ -586,7 +586,6 @@ TEST(core_test, constexpr_parse_format_specs) {
|
||||
static_assert(parse_test_specs(".42").precision == 42, "");
|
||||
static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, "");
|
||||
static_assert(parse_test_specs("d").type == fmt::presentation_type::dec, "");
|
||||
static_assert(parse_test_specs("{<").res == handler::error, "");
|
||||
}
|
||||
|
||||
struct test_parse_context {
|
||||
@ -652,7 +651,6 @@ TEST(format_test, constexpr_specs_checker) {
|
||||
static_assert(check_specs(".42").precision == 42, "");
|
||||
static_assert(check_specs(".{42}").precision_ref.val.index == 42, "");
|
||||
static_assert(check_specs("d").type == fmt::presentation_type::dec, "");
|
||||
static_assert(check_specs("{<").res == handler::error, "");
|
||||
}
|
||||
|
||||
struct test_format_string_handler {
|
||||
|
@ -2214,7 +2214,6 @@ TEST(format_test, format_string_errors) {
|
||||
EXPECT_ERROR("{0:s", "unknown format specifier", date);
|
||||
# if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1916
|
||||
// This causes an detail compiler error in MSVC2017.
|
||||
EXPECT_ERROR("{:{<}", "invalid fill character '{'", int);
|
||||
EXPECT_ERROR("{:10000000000}", "number is too big", int);
|
||||
EXPECT_ERROR("{:.10000000000}", "number is too big", int);
|
||||
EXPECT_ERROR_NOARGS("{:x}", "argument not found");
|
||||
|
Loading…
Reference in New Issue
Block a user