num_format_facet -> format_facet

This commit is contained in:
Victor Zverovich
2022-09-02 17:27:19 -07:00
parent f187274d36
commit fec5515c55
4 changed files with 40 additions and 38 deletions

View File

@ -332,7 +332,7 @@ struct monostate {
#ifdef FMT_DOC #ifdef FMT_DOC
# define FMT_ENABLE_IF(...) # define FMT_ENABLE_IF(...)
#else #else
# define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 # define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
#endif #endif
FMT_BEGIN_DETAIL_NAMESPACE FMT_BEGIN_DETAIL_NAMESPACE

View File

@ -29,7 +29,7 @@
#include "format.h" #include "format.h"
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
template <typename Locale> typename Locale::id num_format_facet<Locale>::id; template <typename Locale> typename Locale::id format_facet<Locale>::id;
namespace detail { namespace detail {
@ -118,14 +118,14 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
} }
#endif #endif
FMT_FUNC auto write_int(appender out, loc_value value, FMT_FUNC auto write_int(appender out, basic_format_arg<format_context> value,
const format_specs& specs, locale_ref loc) -> bool { const format_specs& specs, locale_ref loc) -> bool {
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
auto locale = loc.get<std::locale>(); auto locale = loc.get<std::locale>();
// We cannot use the num_put<char> facet because it may produce output in // We cannot use the num_put<char> facet because it may produce output in
// a wrong encoding. // a wrong encoding.
if (!std::has_facet<num_format_facet<std::locale>>(locale)) return {}; if (!std::has_facet<format_facet<std::locale>>(locale)) return {};
std::use_facet<num_format_facet<std::locale>>(locale).put(out, value, specs, std::use_facet<format_facet<std::locale>>(locale).put(out, value, specs,
locale); locale);
return true; return true;
#endif #endif

View File

@ -985,27 +985,20 @@ constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
} }
} // namespace detail_exported } // namespace detail_exported
// A value to localize. // A locale facet that formats values in UTF-8.
struct loc_value { // It is parameterized on the locale to avoid the heavy <locale> include.
union { template <typename Locale> class format_facet : public Locale::facet {
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 <locale> include.
template <typename Locale> class num_format_facet : public Locale::facet {
public: public:
static FMT_API typename Locale::id id; static FMT_API typename Locale::id id;
void put(appender out, loc_value val, const format_specs& specs, void put(appender out, basic_format_arg<format_context> val,
Locale& loc) const { const format_specs& specs, Locale& loc) const {
do_put(out, val, specs, loc); do_put(out, val, specs, loc);
} }
protected: protected:
virtual void do_put(appender out, loc_value val, const format_specs& specs, virtual void do_put(appender out, basic_format_arg<format_context> val,
Locale& loc) const = 0; const format_specs& specs, Locale& loc) const = 0;
}; };
FMT_BEGIN_DETAIL_NAMESPACE FMT_BEGIN_DETAIL_NAMESPACE
@ -2037,23 +2030,21 @@ auto write_int(OutputIt out, UInt value, unsigned prefix,
}); });
} }
FMT_API auto write_int(appender out, loc_value value, const format_specs& specs, FMT_API auto write_int(appender out, basic_format_arg<format_context> value,
locale_ref loc) -> bool; const format_specs& specs, locale_ref loc) -> bool;
template <typename OutputIt, typename Char> template <typename OutputIt, typename Char>
inline auto write_int(OutputIt, loc_value, const basic_format_specs<Char>&, inline auto write_int(OutputIt, basic_format_arg<buffer_context<Char>>,
locale_ref) -> bool { const basic_format_specs<Char>&, locale_ref) -> bool {
return false; return false;
} }
template <typename OutputIt, typename UInt, typename Char> template <typename OutputIt, typename UInt, typename Char>
auto write_int(OutputIt& out, UInt value, unsigned prefix, auto write_int(OutputIt& out, UInt value, unsigned prefix,
const basic_format_specs<Char>& specs, locale_ref loc) -> bool { const basic_format_specs<Char>& specs, locale_ref loc) -> bool {
auto result = false;
auto buf = memory_buffer(); auto buf = memory_buffer();
if (sizeof(value) <= sizeof(unsigned long long)) auto written = write_int(appender(buf), make_arg<buffer_context<Char>>(value),
result = write_int(appender(buf), {static_cast<unsigned long long>(value)},
specs, loc); specs, loc);
if (!result) { if (!written) {
auto grouping = digit_grouping<Char>(loc); auto grouping = digit_grouping<Char>(loc);
out = write_int(out, value, prefix, specs, grouping); out = write_int(out, value, prefix, specs, grouping);
return true; return true;

View File

@ -2312,25 +2312,36 @@ TEST(format_int_test, format_int) {
EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str()); EXPECT_EQ(os.str(), fmt::format_int(max_value<int64_t>()).str());
} }
#ifdef FMT_STATIC_THOUSANDS_SEPARATOR #ifndef FMT_STATIC_THOUSANDS_SEPARATOR
# include <locale> # include <locale>
class num_format : public fmt::num_format_facet<std::locale> { class format_facet : public fmt::format_facet<std::locale> {
protected: protected:
void do_put(fmt::appender out, fmt::loc_value, const fmt::format_specs&, struct int_formatter {
std::locale&) const override; fmt::appender out;
template <typename T, FMT_ENABLE_IF(fmt::detail::is_integer<T>::value)>
void operator()(T value) {
fmt::format_to(out, "[{}]", value);
}
template <typename T, FMT_ENABLE_IF(!fmt::detail::is_integer<T>::value)>
void operator()(T) {}
};
void do_put(fmt::appender out, fmt::basic_format_arg<fmt::format_context> arg,
const fmt::format_specs&, std::locale&) const override;
}; };
void num_format::do_put(fmt::appender out, fmt::loc_value value, void format_facet::do_put(fmt::appender out,
fmt::basic_format_arg<fmt::format_context> arg,
const fmt::format_specs&, std::locale&) const { const fmt::format_specs&, std::locale&) const {
fmt::format_to(out, "[{}]", value.ulong_long_value); visit_format_arg(int_formatter{out}, arg);
} }
TEST(format_test, num_format) { TEST(format_test, format_facet) {
auto loc = std::locale(std::locale(), new num_format()); auto loc = std::locale(std::locale(), new format_facet());
EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]"); EXPECT_EQ(fmt::format(loc, "{:L}", 42), "[42]");
EXPECT_EQ(fmt::format(loc, "{:L}", -42), "[-42]");
} }
#endif // FMT_STATIC_THOUSANDS_SEPARATOR #endif // FMT_STATIC_THOUSANDS_SEPARATOR