Make Unicode handing when writing to std::ostream more robust.

Calls to print(ostream&) in the special Unicode case on Windows fallback
to writing via ostream::write instead of fwrite().
This commit is contained in:
Dimitrij Mijoski 2022-07-18 15:58:17 +02:00
parent 0cbc004949
commit e17de67514

View File

@ -81,13 +81,14 @@ template class filebuf_access<filebuf_access_tag,
decltype(&filebuf_type::_Myfile), decltype(&filebuf_type::_Myfile),
&filebuf_type::_Myfile>; &filebuf_type::_Myfile>;
inline bool write(std::filebuf& buf, fmt::string_view data) { inline bool write_ostream_msvc_unicode(std::ostream& os,
FILE* f = get_file(buf); fmt::string_view data) {
if (!f) return false; if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
print(f, data); if (FILE* f = get_file(*buf)) return write_console_on_windows(f, data);
return true; return false;
} }
inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) { inline bool write_ostream_msvc_unicode(std::wostream&,
fmt::basic_string_view<wchar_t>) {
return false; return false;
} }
@ -95,10 +96,8 @@ inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) {
// It is a separate function rather than a part of vprint to simplify testing. // It is a separate function rather than a part of vprint to simplify testing.
template <typename Char> template <typename Char>
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) { void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
if (const_check(FMT_MSC_VERSION)) { if (const_check(FMT_MSC_VERSION))
auto filebuf = dynamic_cast<std::basic_filebuf<Char>*>(os.rdbuf()); if (write_ostream_msvc_unicode(os, {buf.data(), buf.size()})) return;
if (filebuf && write(*filebuf, {buf.data(), buf.size()})) return;
}
const Char* buf_data = buf.data(); const Char* buf_data = buf.data();
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type; using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
unsigned_streamsize size = buf.size(); unsigned_streamsize size = buf.size();