Fix wchar_t corner cases

This commit is contained in:
Victor Zverovich 2022-08-24 10:00:12 -07:00
parent 665d9779ec
commit e724bbea16
3 changed files with 12 additions and 13 deletions

View File

@ -3167,7 +3167,7 @@ template <typename Char, typename... Args> class basic_format_string {
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround broken conversion on older gcc. // Workaround broken conversion on older gcc.
template <typename...> using format_string = string_view; template <typename...> using format_string = string_view;
inline auto runtime(string_view s) -> basic_string_view<char> { return s; } inline auto runtime(string_view s) -> string_view { return s; }
#else #else
template <typename... Args> template <typename... Args>
using format_string = basic_format_string<char, type_identity_t<Args>...>; using format_string = basic_format_string<char, type_identity_t<Args>...>;

View File

@ -29,9 +29,11 @@ using wmemory_buffer = basic_memory_buffer<wchar_t>;
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround broken conversion on older gcc. // Workaround broken conversion on older gcc.
template <typename... Args> using wformat_string = wstring_view; template <typename... Args> using wformat_string = wstring_view;
inline auto runtime(wstring_view s) -> wstring_view { return s; }
#else #else
template <typename... Args> template <typename... Args>
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>; using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
inline auto runtime(wstring_view s) -> basic_runtime<wchar_t> { return {{s}}; }
#endif #endif
template <> struct is_char<wchar_t> : std::true_type {}; template <> struct is_char<wchar_t> : std::true_type {};
@ -81,20 +83,16 @@ auto vformat(basic_string_view<Char> format_str,
return to_string(buffer); return to_string(buffer);
} }
#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 409
template <typename... Args>
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
#endif
template <typename... T> template <typename... T>
auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring { auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
return vformat(fmt, fmt::make_wformat_args(args...)); return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
} }
// Pass char_t as a default template parameter instead of using // Pass char_t as a default template parameter instead of using
// std::basic_string<char_t<S>> to reduce the symbol size. // std::basic_string<char_t<S>> to reduce the symbol size.
template <typename S, typename... Args, typename Char = char_t<S>, template <typename S, typename... Args, typename Char = char_t<S>,
FMT_ENABLE_IF(!std::is_same<Char, char>::value)> FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
!std::is_same<Char, wchar_t>::value)>
auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> { auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
return vformat(detail::to_string_view(format_str), return vformat(detail::to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...)); fmt::make_format_args<buffer_context<Char>>(args...));

View File

@ -84,7 +84,7 @@ TEST(xchar_test, format) {
EXPECT_EQ(L"4.2", fmt::format(L"{}", 4.2)); EXPECT_EQ(L"4.2", fmt::format(L"{}", 4.2));
EXPECT_EQ(L"abc", fmt::format(L"{}", L"abc")); EXPECT_EQ(L"abc", fmt::format(L"{}", L"abc"));
EXPECT_EQ(L"z", fmt::format(L"{}", L'z')); EXPECT_EQ(L"z", fmt::format(L"{}", L'z'));
EXPECT_THROW(fmt::format(L"{:*\x343E}", 42), fmt::format_error); EXPECT_THROW(fmt::format(fmt::runtime(L"{:*\x343E}"), 42), fmt::format_error);
EXPECT_EQ(L"true", fmt::format(L"{}", true)); EXPECT_EQ(L"true", fmt::format(L"{}", true));
EXPECT_EQ(L"a", fmt::format(L"{0}", 'a')); EXPECT_EQ(L"a", fmt::format(L"{0}", 'a'));
EXPECT_EQ(L"a", fmt::format(L"{0}", L'a')); EXPECT_EQ(L"a", fmt::format(L"{0}", L'a'));
@ -98,8 +98,9 @@ TEST(xchar_test, is_formattable) {
} }
TEST(xchar_test, compile_time_string) { TEST(xchar_test, compile_time_string) {
EXPECT_EQ(fmt::format(fmt::wformat_string<int>(L"{}"), 42), L"42");
#if defined(FMT_USE_STRING_VIEW) && FMT_CPLUSPLUS >= 201703L #if defined(FMT_USE_STRING_VIEW) && FMT_CPLUSPLUS >= 201703L
EXPECT_EQ(L"42", fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42)); EXPECT_EQ(fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42), L"42");
#endif #endif
} }
@ -246,7 +247,7 @@ TEST(xchar_test, sign_not_truncated) {
wchar_t format_str[] = { wchar_t format_str[] = {
L'{', L':', L'{', L':',
'+' | static_cast<wchar_t>(1 << fmt::detail::num_bits<char>()), L'}', 0}; '+' | static_cast<wchar_t>(1 << fmt::detail::num_bits<char>()), L'}', 0};
EXPECT_THROW(fmt::format(format_str, 42), fmt::format_error); EXPECT_THROW(fmt::format(fmt::runtime(format_str), 42), fmt::format_error);
} }
TEST(xchar_test, chrono) { TEST(xchar_test, chrono) {
@ -311,8 +312,8 @@ TEST(chrono_test_wchar, time_point) {
auto sys_output = system_wcsftime(spec, &tm); auto sys_output = system_wcsftime(spec, &tm);
auto fmt_spec = fmt::format(L"{{:{}}}", spec); auto fmt_spec = fmt::format(L"{{:{}}}", spec);
EXPECT_EQ(sys_output, fmt::format(fmt_spec, t1)); EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
EXPECT_EQ(sys_output, fmt::format(fmt_spec, tm)); EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
} }
} }