Index: libcxx/include/__std_stream =================================================================== --- libcxx/include/__std_stream +++ libcxx/include/__std_stream @@ -83,6 +83,12 @@ __cv_ = &use_facet >(__loc); __encoding_ = __cv_->encoding(); __always_noconv_ = __cv_->always_noconv(); +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) { + __encoding_ = 1; + __always_noconv_ = true; + } +#endif if (__encoding_ > __limit) __throw_runtime_error("unsupported locale for standard input"); } @@ -115,19 +121,39 @@ } return __result; } +#ifdef _WIN32 + char_type __extbuf[__limit]; +#else char __extbuf[__limit]; +#endif int __nread = _VSTD::max(1, __encoding_); for (int __i = 0; __i < __nread; ++__i) { - int __c = getc(__file_); - if (__c == EOF) - return traits_type::eof(); - __extbuf[__i] = static_cast(__c); +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) { + int __c = getwc(__file_); + if (__c == WEOF) + return traits_type::eof(); + __extbuf[__i] = static_cast(__c); + } else +#endif + { + int __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__i] = static_cast(__c); + } } char_type __1buf; if (__always_noconv_) __1buf = static_cast(__extbuf[0]); else +#ifdef _WIN32 + // In wchar_t mode, __extbuf is the wrong type for __cv_->in below. + // In this mode, __always_noconv_ is true (but the compiler doesn't + // know), let it know that it doesn't need to instantiate this below. + if constexpr (sizeof(char_type) == sizeof(char)) +#endif { const char* __enxt; char_type* __inxt; @@ -165,6 +191,12 @@ { for (int __i = __nread; __i > 0;) { +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) { + if (ungetwc(traits_type::to_int_type(__extbuf[--__i]), __file_) == WEOF) + return traits_type::eof(); + } else +#endif if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) return traits_type::eof(); } @@ -188,6 +220,13 @@ } return __c; } +#ifdef _WIN32 + if (sizeof(char_type) == sizeof(wchar_t) && __last_consumed_is_next_) { + const char_type __ci = traits_type::to_char_type(__last_consumed_); + if (ungetwc(__ci, __file_) == WEOF) + return traits_type::eof(); + } else +#endif if (__last_consumed_is_next_) { char __extbuf[__limit]; @@ -255,6 +294,10 @@ __st_(__st), __always_noconv_(__cv_->always_noconv()) { +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) + __always_noconv_ = true; +#endif } template @@ -268,6 +311,13 @@ __1buf = traits_type::to_char_type(__c); if (__always_noconv_) { +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) { + // fputwc works regardless of wide/narrow mode of stdout. + if (fputwc(__1buf, __file_) == WEOF) + return traits_type::eof(); + } else +#endif if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1) return traits_type::eof(); } @@ -313,7 +363,13 @@ streamsize __stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) { - if (__always_noconv_) + if (__always_noconv_ +#ifdef _WIN32 + // for wchar_t, prefer writing it element by element with fputwc, + // since that works when stdout is in narrow mode too. + && sizeof(char_type) != sizeof(wchar_t) +#endif + ) return fwrite(__s, sizeof(char_type), __n, __file_); streamsize __i = 0; for (; __i < __n; ++__i, ++__s) @@ -352,6 +408,10 @@ sync(); __cv_ = &use_facet >(__loc); __always_noconv_ = __cv_->always_noconv(); +#ifdef _WIN32 + if constexpr (sizeof(char_type) == sizeof(wchar_t)) + __always_noconv_ = true; +#endif } _LIBCPP_END_NAMESPACE_STD