diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index a40576a1..7839c75d 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -2020,10 +2020,6 @@ struct formatter, Char> { } void on_error(const char* msg) { FMT_THROW(format_error(msg)); } - FMT_CONSTEXPR void on_fill(basic_string_view 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, Char> { FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context& 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}; diff --git a/include/fmt/core.h b/include/fmt/core.h index 968466c2..7c775e95 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -2362,11 +2362,18 @@ FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, : error_value; } -// Parses fill and alignment. -template -FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, - Handler&& handler) -> const Char* { +template struct parse_align_result { + const Char* end; + basic_string_view fill; + align_t align; +}; + +// Parses [[fill]align]. +template +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end) + -> parse_align_result { FMT_ASSERT(begin != end, ""); + auto fill = basic_string_view(); 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(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 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. diff --git a/test/core-test.cc b/test/core-test.cc index 6d1309fe..da39a73c 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -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 { diff --git a/test/format-test.cc b/test/format-test.cc index 69e2c4d6..4362c805 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -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");