mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-27 15:35:18 +00:00
Add support for UTF-8 digit separators
This commit is contained in:
parent
768d79a839
commit
1b94271ff6
@ -123,8 +123,7 @@ FMT_FUNC auto write_int(appender out, basic_format_arg<format_context> value,
|
|||||||
// 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<format_facet<std::locale>>(locale)) return {};
|
if (!std::has_facet<format_facet<std::locale>>(locale)) return {};
|
||||||
std::use_facet<format_facet<std::locale>>(locale).put(out, value, specs,
|
std::use_facet<format_facet<std::locale>>(locale).put(out, value, specs);
|
||||||
locale);
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@ -133,13 +132,13 @@ FMT_FUNC auto write_int(appender out, basic_format_arg<format_context> value,
|
|||||||
struct localize_int {
|
struct localize_int {
|
||||||
appender out;
|
appender out;
|
||||||
const format_specs& specs;
|
const format_specs& specs;
|
||||||
locale_ref loc;
|
std::string sep;
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(detail::is_integer<T>::value)>
|
template <typename T, FMT_ENABLE_IF(detail::is_integer<T>::value)>
|
||||||
void operator()(T value) {
|
void operator()(T value) {
|
||||||
auto arg = make_write_int_arg(value, specs.sign);
|
auto arg = make_write_int_arg(value, specs.sign);
|
||||||
write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix,
|
write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix,
|
||||||
specs, digit_grouping<char>(loc));
|
specs, digit_grouping<char>("\3", sep));
|
||||||
}
|
}
|
||||||
template <typename T, FMT_ENABLE_IF(!detail::is_integer<T>::value)>
|
template <typename T, FMT_ENABLE_IF(!detail::is_integer<T>::value)>
|
||||||
void operator()(T) {}
|
void operator()(T) {}
|
||||||
@ -152,9 +151,8 @@ template <typename Locale> typename Locale::id format_facet<Locale>::id;
|
|||||||
template <>
|
template <>
|
||||||
FMT_API FMT_FUNC void format_facet<std::locale>::do_put(
|
FMT_API FMT_FUNC void format_facet<std::locale>::do_put(
|
||||||
appender out, basic_format_arg<format_context> val,
|
appender out, basic_format_arg<format_context> val,
|
||||||
const format_specs& specs, std::locale& loc) const {
|
const format_specs& specs) const {
|
||||||
visit_format_arg(detail::localize_int{out, specs, detail::locale_ref(loc)},
|
visit_format_arg(detail::localize_int{out, specs, separator_}, val);
|
||||||
val);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -993,7 +993,7 @@ template <typename Locale> class format_facet : public Locale::facet {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void do_put(appender out, basic_format_arg<format_context> val,
|
virtual void do_put(appender out, basic_format_arg<format_context> val,
|
||||||
const format_specs& specs, Locale& loc) const;
|
const format_specs& specs) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static FMT_API typename Locale::id id;
|
static FMT_API typename Locale::id id;
|
||||||
@ -1002,8 +1002,8 @@ template <typename Locale> class format_facet : public Locale::facet {
|
|||||||
: separator_(sep.data(), sep.size()) {}
|
: separator_(sep.data(), sep.size()) {}
|
||||||
|
|
||||||
void put(appender out, basic_format_arg<format_context> val,
|
void put(appender out, basic_format_arg<format_context> val,
|
||||||
const format_specs& specs, Locale& loc) const {
|
const format_specs& specs) const {
|
||||||
do_put(out, val, specs, loc);
|
do_put(out, val, specs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1981,9 +1981,8 @@ template <typename Char> class digit_grouping {
|
|||||||
grouping_ = sep.grouping;
|
grouping_ = sep.grouping;
|
||||||
if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
|
if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
|
||||||
}
|
}
|
||||||
explicit digit_grouping(thousands_sep_result<Char> sep)
|
digit_grouping(std::string grouping, std::string sep)
|
||||||
: grouping_(sep.grouping),
|
: grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {}
|
||||||
thousands_sep_(sep.thousands_sep ? 1 : 0, sep.thousands_sep) {}
|
|
||||||
|
|
||||||
bool has_separator() const { return !thousands_sep_.empty(); }
|
bool has_separator() const { return !thousands_sep_.empty(); }
|
||||||
|
|
||||||
@ -3950,7 +3949,7 @@ template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
|
|||||||
specs_.precision, specs_.precision_ref, ctx);
|
specs_.precision, specs_.precision_ref, ctx);
|
||||||
return detail::write_int(
|
return detail::write_int(
|
||||||
ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
|
ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
|
||||||
detail::digit_grouping<char>({"\3", ','}));
|
detail::digit_grouping<char>("\3", ","));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2330,12 +2330,12 @@ class format_facet : public fmt::format_facet<std::locale> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void do_put(fmt::appender out, fmt::basic_format_arg<fmt::format_context> arg,
|
void do_put(fmt::appender out, fmt::basic_format_arg<fmt::format_context> arg,
|
||||||
const fmt::format_specs&, std::locale&) const override;
|
const fmt::format_specs&) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
void format_facet::do_put(fmt::appender out,
|
void format_facet::do_put(fmt::appender out,
|
||||||
fmt::basic_format_arg<fmt::format_context> arg,
|
fmt::basic_format_arg<fmt::format_context> arg,
|
||||||
const fmt::format_specs&, std::locale&) const {
|
const fmt::format_specs&) const {
|
||||||
visit_format_arg(int_formatter{out}, arg);
|
visit_format_arg(int_formatter{out}, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2345,4 +2345,14 @@ TEST(format_test, format_facet) {
|
|||||||
EXPECT_EQ(fmt::format(loc, "{:L}", -42), "[-42]");
|
EXPECT_EQ(fmt::format(loc, "{:L}", -42), "[-42]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(format_test, format_facet_separator) {
|
||||||
|
// U+2019 RIGHT SINGLE QUOTATION MARK is a digit separator in the de_CH
|
||||||
|
// locale.
|
||||||
|
auto loc = std::locale(std::locale(),
|
||||||
|
new fmt::format_facet<std::locale>("\xe2\x80\x99"));
|
||||||
|
EXPECT_EQ(fmt::format(loc, "{:L}", 1000),
|
||||||
|
"1\xe2\x80\x99"
|
||||||
|
"000");
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
#endif // FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
|
Loading…
x
Reference in New Issue
Block a user