Skip to content

Commit e582d37

Browse files
committed
Simplify locale handling
1 parent cd8d01d commit e582d37

File tree

2 files changed

+49
-61
lines changed

2 files changed

+49
-61
lines changed

include/fmt/format-inl.h

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
# include <climits>
1515
# include <cmath>
1616
# include <exception>
17-
18-
# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
19-
# include <locale>
20-
# endif
2117
#endif
2218

2319
#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE)
@@ -26,6 +22,19 @@
2622

2723
#include "format.h"
2824

25+
#ifdef FMT_USE_LOCALE
26+
// Use the provided definition.
27+
#elif defined(FMT_STATIC_THOUSANDS_SEPARATOR)
28+
# define FMT_USE_LOCALE 0
29+
#else
30+
# define FMT_USE_LOCALE 1
31+
#endif
32+
#if FMT_USE_LOCALE
33+
# include <locale>
34+
#elif !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
35+
# define FMT_STATIC_THOUSANDS_SEPARATOR ','
36+
#endif
37+
2938
FMT_BEGIN_NAMESPACE
3039
namespace detail {
3140

@@ -77,53 +86,56 @@ inline void fwrite_fully(const void* ptr, size_t count, FILE* stream) {
7786
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
7887
}
7988

80-
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
89+
#if FMT_USE_LOCALE
90+
using std::locale;
91+
using std::numpunct;
92+
using std::use_facet;
93+
#else
94+
struct locale {};
95+
template <typename Char> struct numpunct {
96+
auto grouping() const -> std::string { return "\03"; }
97+
auto thousands_sep() const -> Char { return FMT_STATIC_THOUSANDS_SEPARATOR; }
98+
auto decimal_point() const -> Char { return '.'; }
99+
};
100+
template <typename Facet> Facet use_facet(locale) { return {}; }
101+
#endif // FMT_USE_LOCALE
102+
81103
template <typename Locale>
82104
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
83-
static_assert(std::is_same<Locale, std::locale>::value, "");
105+
static_assert(std::is_same<Locale, locale>::value, "");
84106
}
85107

86108
template <typename Locale> auto locale_ref::get() const -> Locale {
87-
static_assert(std::is_same<Locale, std::locale>::value, "");
88-
return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
109+
static_assert(std::is_same<Locale, locale>::value, "");
110+
return locale_ ? *static_cast<const locale*>(locale_) : locale();
89111
}
90112

91113
template <typename Char>
92114
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
93-
auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
115+
auto&& facet = use_facet<numpunct<Char>>(loc.get<locale>());
94116
auto grouping = facet.grouping();
95117
auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
96118
return {std::move(grouping), thousands_sep};
97119
}
98120
template <typename Char>
99121
FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char {
100-
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
101-
.decimal_point();
102-
}
103-
#else
104-
template <typename Char>
105-
FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
106-
return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
122+
return use_facet<numpunct<Char>>(loc.get<locale>()).decimal_point();
107123
}
108-
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
109-
return '.';
110-
}
111-
#endif
112124

113125
FMT_FUNC auto write_loc(appender out, loc_value value,
114126
const format_specs& specs, locale_ref loc) -> bool {
115-
#ifdef FMT_STATIC_THOUSANDS_SEPARATOR
116-
value.visit(loc_writer<>{
117-
out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."});
118-
return true;
119-
#else
127+
#if FMT_USE_LOCALE
120128
auto locale = loc.get<std::locale>();
121129
// We cannot use the num_put<char> facet because it may produce output in
122130
// a wrong encoding.
123131
using facet = format_facet<std::locale>;
124132
if (std::has_facet<facet>(locale))
125-
return std::use_facet<facet>(locale).put(out, value, specs);
133+
return use_facet<facet>(locale).put(out, value, specs);
126134
return facet(locale).put(out, value, specs);
135+
#else
136+
value.visit(loc_writer<>{
137+
out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."});
138+
return true;
127139
#endif
128140
}
129141
} // namespace detail
@@ -134,13 +146,13 @@ FMT_FUNC void report_error(const char* message) {
134146

135147
template <typename Locale> typename Locale::id format_facet<Locale>::id;
136148

137-
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
138149
template <typename Locale> format_facet<Locale>::format_facet(Locale& loc) {
139-
auto& numpunct = std::use_facet<std::numpunct<char>>(loc);
140-
grouping_ = numpunct.grouping();
141-
if (!grouping_.empty()) separator_ = std::string(1, numpunct.thousands_sep());
150+
auto& np = detail::use_facet<detail::numpunct<char>>(loc);
151+
grouping_ = np.grouping();
152+
if (!grouping_.empty()) separator_ = std::string(1, np.thousands_sep());
142153
}
143154

155+
#if FMT_USE_LOCALE
144156
template <>
145157
FMT_API FMT_FUNC auto format_facet<std::locale>::do_put(
146158
appender out, loc_value val, const format_specs& specs) const -> bool {
@@ -1019,7 +1031,8 @@ template <> struct cache_accessor<double> {
10191031
{0xe4d5e82392a40515, 0x0fabaf3feaa5334b},
10201032
{0xb8da1662e7b00a17, 0x3d6a751f3b936244},
10211033
{0x95527a5202df0ccb, 0x0f37801e0c43ebc9},
1022-
{0xf13e34aabb430a15, 0x647726b9e7c68ff0}
1034+
{ 0xf13e34aabb430a15,
1035+
0x647726b9e7c68ff0 }
10231036
#endif
10241037
};
10251038

include/fmt/format.h

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -765,16 +765,6 @@ using is_integer =
765765
!std::is_same<T, char>::value &&
766766
!std::is_same<T, wchar_t>::value>;
767767

768-
#ifndef FMT_USE_FLOAT
769-
# define FMT_USE_FLOAT 1
770-
#endif
771-
#ifndef FMT_USE_DOUBLE
772-
# define FMT_USE_DOUBLE 1
773-
#endif
774-
#ifndef FMT_USE_LONG_DOUBLE
775-
# define FMT_USE_LONG_DOUBLE 1
776-
#endif
777-
778768
#if defined(FMT_USE_FLOAT128)
779769
// Use the provided definition.
780770
#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>)
@@ -1132,14 +1122,6 @@ constexpr auto is_negative(T) -> bool {
11321122
return false;
11331123
}
11341124

1135-
template <typename T>
1136-
FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool {
1137-
if (std::is_same<T, float>()) return FMT_USE_FLOAT;
1138-
if (std::is_same<T, double>()) return FMT_USE_DOUBLE;
1139-
if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE;
1140-
return true;
1141-
}
1142-
11431125
// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
11441126
// represent all values of an integral type T.
11451127
template <typename T>
@@ -3556,7 +3538,6 @@ template <typename Char, typename OutputIt, typename T,
35563538
FMT_ENABLE_IF(is_floating_point<T>::value)>
35573539
FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs,
35583540
locale_ref loc = {}) -> OutputIt {
3559-
if (const_check(!is_supported_floating_point(value))) return out;
35603541
return specs.localized() && write_loc(out, value, specs, loc)
35613542
? out
35623543
: write_float<Char>(out, value, specs, loc);
@@ -3566,7 +3547,6 @@ template <typename Char, typename OutputIt, typename T,
35663547
FMT_ENABLE_IF(is_fast_float<T>::value)>
35673548
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
35683549
if (is_constant_evaluated()) return write<Char>(out, value, format_specs());
3569-
if (const_check(!is_supported_floating_point(value))) return out;
35703550

35713551
auto s = detail::signbit(value) ? sign::minus : sign::none;
35723552

@@ -3708,28 +3688,23 @@ template <typename Char> struct default_arg_formatter {
37083688
};
37093689

37103690
template <typename Char> struct arg_formatter {
3711-
using iterator = basic_appender<Char>;
3712-
using context = buffered_context<Char>;
3713-
3714-
iterator out;
3691+
basic_appender<Char> out;
37153692
const format_specs& specs;
37163693
locale_ref locale;
37173694

37183695
template <typename T, FMT_ENABLE_IF(is_builtin<T>::value)>
3719-
FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {
3720-
return detail::write<Char>(out, value, specs, locale);
3696+
FMT_CONSTEXPR FMT_INLINE void operator()(T value) {
3697+
detail::write<Char>(out, value, specs, locale);
37213698
}
37223699

37233700
template <typename T, FMT_ENABLE_IF(!is_builtin<T>::value)>
3724-
auto operator()(T) -> iterator {
3701+
void operator()(T) {
37253702
FMT_ASSERT(false, "");
3726-
return out;
37273703
}
37283704

3729-
auto operator()(typename basic_format_arg<context>::handle) -> iterator {
3705+
void operator()(typename basic_format_arg<buffered_context<Char>>::handle) {
37303706
// User-defined types are handled separately because they require access
37313707
// to the parse context.
3732-
return out;
37333708
}
37343709
};
37353710

0 commit comments

Comments
 (0)