mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-19 11:14:41 +00:00
Simplify locale handling
This commit is contained in:
parent
cd8d01d8cd
commit
e582d377c2
@ -14,10 +14,6 @@
|
|||||||
# include <climits>
|
# include <climits>
|
||||||
# include <cmath>
|
# include <cmath>
|
||||||
# include <exception>
|
# include <exception>
|
||||||
|
|
||||||
# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
|
||||||
# include <locale>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE)
|
#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE)
|
||||||
@ -26,6 +22,19 @@
|
|||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
|
#ifdef FMT_USE_LOCALE
|
||||||
|
// Use the provided definition.
|
||||||
|
#elif defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
|
# define FMT_USE_LOCALE 0
|
||||||
|
#else
|
||||||
|
# define FMT_USE_LOCALE 1
|
||||||
|
#endif
|
||||||
|
#if FMT_USE_LOCALE
|
||||||
|
# include <locale>
|
||||||
|
#elif !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
|
# define FMT_STATIC_THOUSANDS_SEPARATOR ','
|
||||||
|
#endif
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
FMT_BEGIN_NAMESPACE
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@ -77,53 +86,56 @@ inline void fwrite_fully(const void* ptr, size_t count, FILE* stream) {
|
|||||||
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
#if FMT_USE_LOCALE
|
||||||
|
using std::locale;
|
||||||
|
using std::numpunct;
|
||||||
|
using std::use_facet;
|
||||||
|
#else
|
||||||
|
struct locale {};
|
||||||
|
template <typename Char> struct numpunct {
|
||||||
|
auto grouping() const -> std::string { return "\03"; }
|
||||||
|
auto thousands_sep() const -> Char { return FMT_STATIC_THOUSANDS_SEPARATOR; }
|
||||||
|
auto decimal_point() const -> Char { return '.'; }
|
||||||
|
};
|
||||||
|
template <typename Facet> Facet use_facet(locale) { return {}; }
|
||||||
|
#endif // FMT_USE_LOCALE
|
||||||
|
|
||||||
template <typename Locale>
|
template <typename Locale>
|
||||||
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
||||||
static_assert(std::is_same<Locale, std::locale>::value, "");
|
static_assert(std::is_same<Locale, locale>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Locale> auto locale_ref::get() const -> Locale {
|
template <typename Locale> auto locale_ref::get() const -> Locale {
|
||||||
static_assert(std::is_same<Locale, std::locale>::value, "");
|
static_assert(std::is_same<Locale, locale>::value, "");
|
||||||
return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
|
return locale_ ? *static_cast<const locale*>(locale_) : locale();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
|
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
|
||||||
auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
|
auto&& facet = use_facet<numpunct<Char>>(loc.get<locale>());
|
||||||
auto grouping = facet.grouping();
|
auto grouping = facet.grouping();
|
||||||
auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
|
auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
|
||||||
return {std::move(grouping), thousands_sep};
|
return {std::move(grouping), thousands_sep};
|
||||||
}
|
}
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char {
|
FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char {
|
||||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
return use_facet<numpunct<Char>>(loc.get<locale>()).decimal_point();
|
||||||
.decimal_point();
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
template <typename Char>
|
|
||||||
FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
|
|
||||||
return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
|
|
||||||
}
|
|
||||||
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
|
|
||||||
return '.';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FMT_FUNC auto write_loc(appender out, loc_value value,
|
FMT_FUNC auto write_loc(appender out, loc_value value,
|
||||||
const format_specs& specs, locale_ref loc) -> bool {
|
const format_specs& specs, locale_ref loc) -> bool {
|
||||||
#ifdef FMT_STATIC_THOUSANDS_SEPARATOR
|
#if FMT_USE_LOCALE
|
||||||
value.visit(loc_writer<>{
|
|
||||||
out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."});
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
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.
|
||||||
using facet = format_facet<std::locale>;
|
using facet = format_facet<std::locale>;
|
||||||
if (std::has_facet<facet>(locale))
|
if (std::has_facet<facet>(locale))
|
||||||
return std::use_facet<facet>(locale).put(out, value, specs);
|
return use_facet<facet>(locale).put(out, value, specs);
|
||||||
return facet(locale).put(out, value, specs);
|
return facet(locale).put(out, value, specs);
|
||||||
|
#else
|
||||||
|
value.visit(loc_writer<>{
|
||||||
|
out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."});
|
||||||
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -134,13 +146,13 @@ FMT_FUNC void report_error(const char* message) {
|
|||||||
|
|
||||||
template <typename Locale> typename Locale::id format_facet<Locale>::id;
|
template <typename Locale> typename Locale::id format_facet<Locale>::id;
|
||||||
|
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
|
||||||
template <typename Locale> format_facet<Locale>::format_facet(Locale& loc) {
|
template <typename Locale> format_facet<Locale>::format_facet(Locale& loc) {
|
||||||
auto& numpunct = std::use_facet<std::numpunct<char>>(loc);
|
auto& np = detail::use_facet<detail::numpunct<char>>(loc);
|
||||||
grouping_ = numpunct.grouping();
|
grouping_ = np.grouping();
|
||||||
if (!grouping_.empty()) separator_ = std::string(1, numpunct.thousands_sep());
|
if (!grouping_.empty()) separator_ = std::string(1, np.thousands_sep());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FMT_USE_LOCALE
|
||||||
template <>
|
template <>
|
||||||
FMT_API FMT_FUNC auto format_facet<std::locale>::do_put(
|
FMT_API FMT_FUNC auto format_facet<std::locale>::do_put(
|
||||||
appender out, loc_value val, const format_specs& specs) const -> bool {
|
appender out, loc_value val, const format_specs& specs) const -> bool {
|
||||||
@ -1019,7 +1031,8 @@ template <> struct cache_accessor<double> {
|
|||||||
{0xe4d5e82392a40515, 0x0fabaf3feaa5334b},
|
{0xe4d5e82392a40515, 0x0fabaf3feaa5334b},
|
||||||
{0xb8da1662e7b00a17, 0x3d6a751f3b936244},
|
{0xb8da1662e7b00a17, 0x3d6a751f3b936244},
|
||||||
{0x95527a5202df0ccb, 0x0f37801e0c43ebc9},
|
{0x95527a5202df0ccb, 0x0f37801e0c43ebc9},
|
||||||
{0xf13e34aabb430a15, 0x647726b9e7c68ff0}
|
{ 0xf13e34aabb430a15,
|
||||||
|
0x647726b9e7c68ff0 }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -765,16 +765,6 @@ using is_integer =
|
|||||||
!std::is_same<T, char>::value &&
|
!std::is_same<T, char>::value &&
|
||||||
!std::is_same<T, wchar_t>::value>;
|
!std::is_same<T, wchar_t>::value>;
|
||||||
|
|
||||||
#ifndef FMT_USE_FLOAT
|
|
||||||
# define FMT_USE_FLOAT 1
|
|
||||||
#endif
|
|
||||||
#ifndef FMT_USE_DOUBLE
|
|
||||||
# define FMT_USE_DOUBLE 1
|
|
||||||
#endif
|
|
||||||
#ifndef FMT_USE_LONG_DOUBLE
|
|
||||||
# define FMT_USE_LONG_DOUBLE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(FMT_USE_FLOAT128)
|
#if defined(FMT_USE_FLOAT128)
|
||||||
// Use the provided definition.
|
// Use the provided definition.
|
||||||
#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>)
|
#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>)
|
||||||
@ -1132,14 +1122,6 @@ constexpr auto is_negative(T) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool {
|
|
||||||
if (std::is_same<T, float>()) return FMT_USE_FLOAT;
|
|
||||||
if (std::is_same<T, double>()) return FMT_USE_DOUBLE;
|
|
||||||
if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
|
// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
|
||||||
// represent all values of an integral type T.
|
// represent all values of an integral type T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -3556,7 +3538,6 @@ template <typename Char, typename OutputIt, typename T,
|
|||||||
FMT_ENABLE_IF(is_floating_point<T>::value)>
|
FMT_ENABLE_IF(is_floating_point<T>::value)>
|
||||||
FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs,
|
FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs,
|
||||||
locale_ref loc = {}) -> OutputIt {
|
locale_ref loc = {}) -> OutputIt {
|
||||||
if (const_check(!is_supported_floating_point(value))) return out;
|
|
||||||
return specs.localized() && write_loc(out, value, specs, loc)
|
return specs.localized() && write_loc(out, value, specs, loc)
|
||||||
? out
|
? out
|
||||||
: write_float<Char>(out, value, specs, loc);
|
: write_float<Char>(out, value, specs, loc);
|
||||||
@ -3566,7 +3547,6 @@ template <typename Char, typename OutputIt, typename T,
|
|||||||
FMT_ENABLE_IF(is_fast_float<T>::value)>
|
FMT_ENABLE_IF(is_fast_float<T>::value)>
|
||||||
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
|
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
|
||||||
if (is_constant_evaluated()) return write<Char>(out, value, format_specs());
|
if (is_constant_evaluated()) return write<Char>(out, value, format_specs());
|
||||||
if (const_check(!is_supported_floating_point(value))) return out;
|
|
||||||
|
|
||||||
auto s = detail::signbit(value) ? sign::minus : sign::none;
|
auto s = detail::signbit(value) ? sign::minus : sign::none;
|
||||||
|
|
||||||
@ -3708,28 +3688,23 @@ template <typename Char> struct default_arg_formatter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Char> struct arg_formatter {
|
template <typename Char> struct arg_formatter {
|
||||||
using iterator = basic_appender<Char>;
|
basic_appender<Char> out;
|
||||||
using context = buffered_context<Char>;
|
|
||||||
|
|
||||||
iterator out;
|
|
||||||
const format_specs& specs;
|
const format_specs& specs;
|
||||||
locale_ref locale;
|
locale_ref locale;
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(is_builtin<T>::value)>
|
template <typename T, FMT_ENABLE_IF(is_builtin<T>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {
|
FMT_CONSTEXPR FMT_INLINE void operator()(T value) {
|
||||||
return detail::write<Char>(out, value, specs, locale);
|
detail::write<Char>(out, value, specs, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(!is_builtin<T>::value)>
|
template <typename T, FMT_ENABLE_IF(!is_builtin<T>::value)>
|
||||||
auto operator()(T) -> iterator {
|
void operator()(T) {
|
||||||
FMT_ASSERT(false, "");
|
FMT_ASSERT(false, "");
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator()(typename basic_format_arg<context>::handle) -> iterator {
|
void operator()(typename basic_format_arg<buffered_context<Char>>::handle) {
|
||||||
// User-defined types are handled separately because they require access
|
// User-defined types are handled separately because they require access
|
||||||
// to the parse context.
|
// to the parse context.
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user