mirror of
https://github.com/fmtlib/fmt.git
synced 2026-06-15 00:16:15 +08:00
fix: convert std::error_code messages to UTF-8 on Windows
When formatting with {:s}, system error messages may use the active
code page instead of UTF-8. Convert from ACP via UTF-16 before writing.
Fixes #4436.
This commit is contained in:
parent
2f18a88e68
commit
4292bb8499
@ -117,6 +117,8 @@ FMT_API const std::error_category& system_category() noexcept;
|
||||
namespace detail {
|
||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
||||
const char* message) noexcept;
|
||||
FMT_API bool append_system_error_message_as_utf8(buffer<char>& buf,
|
||||
string_view message) noexcept;
|
||||
}
|
||||
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
|
||||
|
||||
@ -546,6 +546,13 @@ struct formatter<Variant, Char,
|
||||
|
||||
#endif // FMT_CPP_LIB_VARIANT
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace detail {
|
||||
FMT_API bool append_system_error_message_as_utf8(buffer<char>& buf,
|
||||
string_view message) noexcept;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <> struct formatter<std::error_code> {
|
||||
private:
|
||||
format_specs specs_;
|
||||
@ -584,7 +591,12 @@ template <> struct formatter<std::error_code> {
|
||||
ctx);
|
||||
auto buf = memory_buffer();
|
||||
if (specs_.type() == presentation_type::string) {
|
||||
#ifdef _WIN32
|
||||
if (!detail::append_system_error_message_as_utf8(buf, ec.message()))
|
||||
buf.append(ec.message());
|
||||
#else
|
||||
buf.append(ec.message());
|
||||
#endif
|
||||
} else {
|
||||
buf.append(string_view(ec.category().name()));
|
||||
buf.push_back(':');
|
||||
|
||||
23
src/os.cc
23
src/os.cc
@ -165,6 +165,29 @@ void report_windows_error(int error_code, const char* message) noexcept {
|
||||
do_report_error(detail::format_windows_error, error_code, message);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
bool append_system_error_message_as_utf8(buffer<char>& buf,
|
||||
string_view message) noexcept {
|
||||
FMT_TRY {
|
||||
if (message.empty()) return true;
|
||||
const int size = static_cast<int>(message.size());
|
||||
const int wide_size =
|
||||
MultiByteToWideChar(CP_ACP, 0, message.data(), size, nullptr, 0);
|
||||
if (wide_size == 0) return false;
|
||||
std::wstring wide(static_cast<size_t>(wide_size), L'\0');
|
||||
if (MultiByteToWideChar(CP_ACP, 0, message.data(), size, wide.data(),
|
||||
wide_size) == 0)
|
||||
return false;
|
||||
auto utf8_message = to_utf8<wchar_t>();
|
||||
if (!utf8_message.convert(wide)) return false;
|
||||
buf.append(string_view(utf8_message.c_str(), utf8_message.size()));
|
||||
return true;
|
||||
}
|
||||
FMT_CATCH(...) {}
|
||||
return false;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
buffered_file::~buffered_file() noexcept {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user