From f187274d3637403e1391deb69233b34b5e345d37 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 2 Sep 2022 13:45:23 -0700 Subject: [PATCH] Add loc_value --- include/fmt/format-inl.h | 2 +- include/fmt/format.h | 49 +++++++++++++++++++++++----------------- test/format-test.cc | 23 +++++++++++++++++++ test/xchar-test.cc | 16 ------------- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 80b44a42..6fbdb52a 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -118,7 +118,7 @@ template FMT_FUNC Char decimal_point_impl(locale_ref) { } #endif -FMT_FUNC auto write_int(appender out, unsigned long long value, +FMT_FUNC auto write_int(appender out, loc_value value, const format_specs& specs, locale_ref loc) -> bool { #ifndef FMT_STATIC_THOUSANDS_SEPARATOR auto locale = loc.get(); diff --git a/include/fmt/format.h b/include/fmt/format.h index a792f31d..a1b98c7f 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -985,6 +985,29 @@ constexpr auto compile_string_to_view(detail::std_string_view s) } } // namespace detail_exported +// A value to localize. +struct loc_value { + union { + unsigned long long ulong_long_value; + }; +}; + +// A locale facet that formats numeric values in UTF-8. +// It is parameterized on the locale to avoid heavy include. +template class num_format_facet : public Locale::facet { + public: + static FMT_API typename Locale::id id; + + void put(appender out, loc_value val, const format_specs& specs, + Locale& loc) const { + do_put(out, val, specs, loc); + } + + protected: + virtual void do_put(appender out, loc_value val, const format_specs& specs, + Locale& loc) const = 0; +}; + FMT_BEGIN_DETAIL_NAMESPACE template struct is_integral : std::is_integral {}; @@ -2014,11 +2037,11 @@ auto write_int(OutputIt out, UInt value, unsigned prefix, }); } -FMT_API auto write_int(appender out, unsigned long long value, - const format_specs& specs, locale_ref loc) -> bool; +FMT_API auto write_int(appender out, loc_value value, const format_specs& specs, + locale_ref loc) -> bool; template -inline auto write_int(OutputIt, unsigned long long, - const basic_format_specs&, locale_ref) -> bool { +inline auto write_int(OutputIt, loc_value, const basic_format_specs&, + locale_ref) -> bool { return false; } @@ -2028,7 +2051,7 @@ auto write_int(OutputIt& out, UInt value, unsigned prefix, auto result = false; auto buf = memory_buffer(); if (sizeof(value) <= sizeof(unsigned long long)) - result = write_int(appender(buf), static_cast(value), + result = write_int(appender(buf), {static_cast(value)}, specs, loc); if (!result) { auto grouping = digit_grouping(loc); @@ -4176,22 +4199,6 @@ extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; FMT_END_DETAIL_NAMESPACE -// A locale facet that formats numeric values in UTF-8. -// It is parameterized on the locale to avoid heavy include. -template class num_format_facet : public Locale::facet { - public: - static FMT_API typename Locale::id id; - - void put(appender out, unsigned long long val, const format_specs& specs, - Locale& loc) const { - do_put(out, val, specs, loc); - } - - protected: - virtual void do_put(appender out, unsigned long long val, - const format_specs& specs, Locale& loc) const = 0; -}; - #if FMT_USE_USER_DEFINED_LITERALS inline namespace literals { /** diff --git a/test/format-test.cc b/test/format-test.cc index 9d318470..b028aefd 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2311,3 +2311,26 @@ TEST(format_int_test, format_int) { os << max_value(); EXPECT_EQ(os.str(), fmt::format_int(max_value()).str()); } + +#ifdef FMT_STATIC_THOUSANDS_SEPARATOR + +# include + +class num_format : public fmt::num_format_facet { + protected: + void do_put(fmt::appender out, fmt::loc_value, const fmt::format_specs&, + std::locale&) const override; +}; + +void num_format::do_put(fmt::appender out, fmt::loc_value value, + const fmt::format_specs&, std::locale&) const { + fmt::format_to(out, "[{}]", value.ulong_long_value); +} + +TEST(format_test, num_format) { + auto loc = std::locale(std::locale(), new num_format()); + EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]"); + EXPECT_EQ(fmt::format(loc, "{:L}", -42), "[-42]"); +} + +#endif // FMT_STATIC_THOUSANDS_SEPARATOR diff --git a/test/xchar-test.cc b/test/xchar-test.cc index 91300da1..3eec7384 100644 --- a/test/xchar-test.cc +++ b/test/xchar-test.cc @@ -520,20 +520,4 @@ TEST(locale_test, sign) { EXPECT_EQ(fmt::format(std::locale(), L"{:L}", -50), L"-50"); } -class num_format : public fmt::num_format_facet { - protected: - void do_put(fmt::appender out, unsigned long long, const fmt::format_specs&, - std::locale&) const override; -}; - -void num_format::do_put(fmt::appender out, unsigned long long value, - const fmt::format_specs&, std::locale&) const { - fmt::format_to(out, "[{}]", value); -} - -TEST(locale_test, num_format) { - auto loc = std::locale(std::locale(), new num_format()); - EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]"); -} - #endif // FMT_STATIC_THOUSANDS_SEPARATOR