From e4f2cf455e4ff3a065ff931e40b50dae182b4d6f Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 17 Jan 2021 09:01:00 -0800 Subject: [PATCH] Make 'L' a modifier --- include/fmt/format.h | 18 +++++++++++++++++- test/format-test.cc | 6 ++++-- test/locale-test.cc | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 9cb73c38..082a8840 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1252,6 +1252,7 @@ template struct basic_format_specs { align_t align : 4; sign_t sign : 3; bool alt : 1; // Alternate form ('#'). + bool localized : 1; detail::fill_t fill; constexpr basic_format_specs() @@ -1260,7 +1261,8 @@ template struct basic_format_specs { type(0), align(align::none), sign(sign::none), - alt(false) {} + alt(false), + localized(false) {} }; using format_specs = basic_format_specs; @@ -1427,6 +1429,7 @@ FMT_CONSTEXPR float_specs parse_float_type_spec( const basic_format_specs& specs, ErrorHandler&& eh = {}) { auto result = float_specs(); result.showpoint = specs.alt; + result.locale = specs.localized; switch (specs.type) { case 0: result.format = float_format::general; @@ -1693,6 +1696,7 @@ template struct int_writer { } FMT_CONSTEXPR void on_dec() { + if (specs.localized) return on_num(); auto num_digits = count_digits(abs_value); out = write_int( out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) { @@ -2527,6 +2531,7 @@ template class specs_setter { FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; } FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; } FMT_CONSTEXPR void on_hash() { specs_.alt = true; } + FMT_CONSTEXPR void on_localized() { specs_.localized = true; } FMT_CONSTEXPR void on_zero() { specs_.align = align::numeric; @@ -2616,6 +2621,11 @@ template class specs_checker : public Handler { Handler::on_hash(); } + FMT_CONSTEXPR void on_localized() { + checker_.require_numeric_argument(); + Handler::on_localized(); + } + FMT_CONSTEXPR void on_zero() { checker_.require_numeric_argument(); Handler::on_zero(); @@ -2996,6 +3006,12 @@ FMT_CONSTEXPR const Char* parse_format_specs(const Char* begin, const Char* end, // Parse precision. if (*begin == '.') { begin = parse_precision(begin, end, handler); + if (begin == end) return begin; + } + + if (*begin == 'L') { + handler.on_localized(); + ++begin; } // Parse type. diff --git a/test/format-test.cc b/test/format-test.cc index 74743e7a..6c5b1fd0 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1112,7 +1112,7 @@ TEST(FormatterTest, RuntimePrecision) { template void check_unknown_types(const T& value, const char* types, const char*) { char format_str[BUFFER_SIZE]; - const char* special = ".0123456789}"; + const char* special = ".0123456789L}"; for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) { char c = static_cast(i); if (std::strchr(types, c) || std::strchr(special, c) || !c) continue; @@ -2140,7 +2140,7 @@ TEST(FormatTest, ConstexprParseArgID) { } struct test_format_specs_handler { - enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR }; + enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, LOC, ERROR }; Result res = NONE; fmt::align_t alignment = fmt::align::none; @@ -2172,6 +2172,7 @@ struct test_format_specs_handler { FMT_CONSTEXPR void on_space() { res = SPACE; } FMT_CONSTEXPR void on_hash() { res = HASH; } FMT_CONSTEXPR void on_zero() { res = ZERO; } + FMT_CONSTEXPR void on_localized() { res = LOC; } FMT_CONSTEXPR void on_width(int w) { width = w; } FMT_CONSTEXPR void on_dynamic_width(fmt::detail::auto_id) {} @@ -2204,6 +2205,7 @@ TEST(FormatTest, ConstexprParseFormatSpecs) { static_assert(parse_test_specs(" ").res == handler::SPACE, ""); static_assert(parse_test_specs("#").res == handler::HASH, ""); static_assert(parse_test_specs("0").res == handler::ZERO, ""); + static_assert(parse_test_specs("L").res == handler::LOC, ""); static_assert(parse_test_specs("42").width == 42, ""); static_assert(parse_test_specs("{42}").width_ref.val.index == 42, ""); static_assert(parse_test_specs(".42").precision == 42, ""); diff --git a/test/locale-test.cc b/test/locale-test.cc index 143348d1..aa8b6009 100644 --- a/test/locale-test.cc +++ b/test/locale-test.cc @@ -45,6 +45,7 @@ template struct small_grouping : std::numpunct { TEST(LocaleTest, DoubleDecimalPoint) { std::locale loc(std::locale(), new numpunct()); EXPECT_EQ("1?23", fmt::format(loc, "{:L}", 1.23)); + EXPECT_EQ("1?230000", fmt::format(loc, "{:Lf}", 1.23)); } TEST(LocaleTest, Format) {