Skip to content

Commit

Permalink
Fix wchar_t corner cases
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Aug 24, 2022
1 parent 665d977 commit e724bbe
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 13 deletions.
2 changes: 1 addition & 1 deletion include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -3167,7 +3167,7 @@ template <typename Char, typename... Args> class basic_format_string {
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround broken conversion on older gcc.
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
template <typename... Args>
using format_string = basic_format_string<char, type_identity_t<Args>...>;
Expand Down
12 changes: 5 additions & 7 deletions include/fmt/xchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ using wmemory_buffer = basic_memory_buffer<wchar_t>;
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround broken conversion on older gcc.
template <typename... Args> using wformat_string = wstring_view;
inline auto runtime(wstring_view s) -> wstring_view { return s; }
#else
template <typename... 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

template <> struct is_char<wchar_t> : std::true_type {};
Expand Down Expand Up @@ -81,20 +83,16 @@ auto vformat(basic_string_view<Char> format_str,
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>
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
// std::basic_string<char_t<S>> to reduce the symbol size.
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> {
return vformat(detail::to_string_view(format_str),
fmt::make_format_args<buffer_context<Char>>(args...));
Expand Down
11 changes: 6 additions & 5 deletions test/xchar-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ TEST(xchar_test, format) {
EXPECT_EQ(L"4.2", fmt::format(L"{}", 4.2));
EXPECT_EQ(L"abc", fmt::format(L"{}", L"abc"));
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"a", fmt::format(L"{0}", 'a'));
EXPECT_EQ(L"a", fmt::format(L"{0}", L'a'));
Expand All @@ -98,8 +98,9 @@ TEST(xchar_test, is_formattable) {
}

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
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
}

Expand Down Expand Up @@ -246,7 +247,7 @@ TEST(xchar_test, sign_not_truncated) {
wchar_t format_str[] = {
L'{', L':',
'+' | 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) {
Expand Down Expand Up @@ -311,8 +312,8 @@ TEST(chrono_test_wchar, time_point) {
auto sys_output = system_wcsftime(spec, &tm);

auto fmt_spec = fmt::format(L"{{:{}}}", spec);
EXPECT_EQ(sys_output, fmt::format(fmt_spec, t1));
EXPECT_EQ(sys_output, fmt::format(fmt_spec, tm));
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), t1));
EXPECT_EQ(sys_output, fmt::format(fmt::runtime(fmt_spec), tm));
}
}

Expand Down

0 comments on commit e724bbe

Please sign in to comment.