140a187bbSMartin Storsjö // -*- C++ -*- 240a187bbSMartin Storsjö //===----------------------------------------------------------------------===// 340a187bbSMartin Storsjö // 440a187bbSMartin Storsjö // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 540a187bbSMartin Storsjö // See https://llvm.org/LICENSE.txt for license information. 640a187bbSMartin Storsjö // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 740a187bbSMartin Storsjö // 840a187bbSMartin Storsjö //===----------------------------------------------------------------------===// 940a187bbSMartin Storsjö 1040a187bbSMartin Storsjö #ifndef _LIBCPP_STD_STREAM_H 1140a187bbSMartin Storsjö #define _LIBCPP_STD_STREAM_H 1240a187bbSMartin Storsjö 1340a187bbSMartin Storsjö #include <__config> 1440a187bbSMartin Storsjö #include <__locale> 1540a187bbSMartin Storsjö #include <cstdio> 1640a187bbSMartin Storsjö #include <istream> 1740a187bbSMartin Storsjö #include <ostream> 1840a187bbSMartin Storsjö 1940a187bbSMartin Storsjö #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2040a187bbSMartin Storsjö # pragma GCC system_header 2140a187bbSMartin Storsjö #endif 2240a187bbSMartin Storsjö 2340a187bbSMartin Storsjö _LIBCPP_PUSH_MACROS 2440a187bbSMartin Storsjö #include <__undef_macros> 2540a187bbSMartin Storsjö 2640a187bbSMartin Storsjö _LIBCPP_BEGIN_NAMESPACE_STD 2740a187bbSMartin Storsjö 2840a187bbSMartin Storsjö static const int __limit = 8; 2940a187bbSMartin Storsjö 3040a187bbSMartin Storsjö // __stdinbuf 3140a187bbSMartin Storsjö 3240a187bbSMartin Storsjö template <class _CharT> 339783f28cSLouis Dionne class _LIBCPP_HIDDEN __stdinbuf : public basic_streambuf<_CharT, char_traits<_CharT> > { 3440a187bbSMartin Storsjö public: 3540a187bbSMartin Storsjö typedef _CharT char_type; 3640a187bbSMartin Storsjö typedef char_traits<char_type> traits_type; 3740a187bbSMartin Storsjö typedef typename traits_type::int_type int_type; 3840a187bbSMartin Storsjö typedef typename traits_type::pos_type pos_type; 3940a187bbSMartin Storsjö typedef typename traits_type::off_type off_type; 4040a187bbSMartin Storsjö typedef typename traits_type::state_type state_type; 4140a187bbSMartin Storsjö 4240a187bbSMartin Storsjö __stdinbuf(FILE* __fp, state_type* __st); 4340a187bbSMartin Storsjö 4440a187bbSMartin Storsjö protected: 4540a187bbSMartin Storsjö virtual int_type underflow(); 4640a187bbSMartin Storsjö virtual int_type uflow(); 4740a187bbSMartin Storsjö virtual int_type pbackfail(int_type __c = traits_type::eof()); 4840a187bbSMartin Storsjö virtual void imbue(const locale& __loc); 4940a187bbSMartin Storsjö 5040a187bbSMartin Storsjö private: 5140a187bbSMartin Storsjö FILE* __file_; 5240a187bbSMartin Storsjö const codecvt<char_type, char, state_type>* __cv_; 5340a187bbSMartin Storsjö state_type* __st_; 5440a187bbSMartin Storsjö int __encoding_; 5540a187bbSMartin Storsjö int_type __last_consumed_; 5640a187bbSMartin Storsjö bool __last_consumed_is_next_; 5740a187bbSMartin Storsjö bool __always_noconv_; 5840a187bbSMartin Storsjö 59fcbbd964SMartin Storsjö #if defined(_LIBCPP_WIN32API) 60fcbbd964SMartin Storsjö static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; 61fcbbd964SMartin Storsjö #else 62fcbbd964SMartin Storsjö static constexpr bool __is_win32api_wide_char = false; 63fcbbd964SMartin Storsjö #endif 64fcbbd964SMartin Storsjö 6540a187bbSMartin Storsjö __stdinbuf(const __stdinbuf&); 6640a187bbSMartin Storsjö __stdinbuf& operator=(const __stdinbuf&); 6740a187bbSMartin Storsjö 6840a187bbSMartin Storsjö int_type __getchar(bool __consume); 6940a187bbSMartin Storsjö }; 7040a187bbSMartin Storsjö 7140a187bbSMartin Storsjö template <class _CharT> 7240a187bbSMartin Storsjö __stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) 739783f28cSLouis Dionne : __file_(__fp), __st_(__st), __last_consumed_(traits_type::eof()), __last_consumed_is_next_(false) { 7440a187bbSMartin Storsjö imbue(this->getloc()); 75fcbbd964SMartin Storsjö // On Windows, in wchar_t mode, ignore the codecvt from the locale by 76fcbbd964SMartin Storsjö // default and assume noconv; this passes wchar_t through unmodified from 77fcbbd964SMartin Storsjö // getwc. If the user sets a custom locale with imbue(), that gets honored, 78fcbbd964SMartin Storsjö // the IO is done with getc() and converted with the provided codecvt. 79fcbbd964SMartin Storsjö if constexpr (__is_win32api_wide_char) 80fcbbd964SMartin Storsjö __always_noconv_ = true; 8140a187bbSMartin Storsjö } 8240a187bbSMartin Storsjö 8340a187bbSMartin Storsjö template <class _CharT> 849783f28cSLouis Dionne void __stdinbuf<_CharT>::imbue(const locale& __loc) { 8540a187bbSMartin Storsjö __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 8640a187bbSMartin Storsjö __encoding_ = __cv_->encoding(); 8740a187bbSMartin Storsjö __always_noconv_ = __cv_->always_noconv(); 8840a187bbSMartin Storsjö if (__encoding_ > __limit) 8940a187bbSMartin Storsjö __throw_runtime_error("unsupported locale for standard input"); 9040a187bbSMartin Storsjö } 9140a187bbSMartin Storsjö 9240a187bbSMartin Storsjö template <class _CharT> 939783f28cSLouis Dionne typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::underflow() { 9440a187bbSMartin Storsjö return __getchar(false); 9540a187bbSMartin Storsjö } 9640a187bbSMartin Storsjö 9740a187bbSMartin Storsjö template <class _CharT> 989783f28cSLouis Dionne typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::uflow() { 9940a187bbSMartin Storsjö return __getchar(true); 10040a187bbSMartin Storsjö } 10140a187bbSMartin Storsjö 1022a0f2fa9SMark de Wever inline bool __do_getc(FILE* __fp, char* __pbuf) { 103fcbbd964SMartin Storsjö int __c = getc(__fp); 104fcbbd964SMartin Storsjö if (__c == EOF) 105fcbbd964SMartin Storsjö return false; 106fcbbd964SMartin Storsjö *__pbuf = static_cast<char>(__c); 107fcbbd964SMartin Storsjö return true; 108fcbbd964SMartin Storsjö } 109*c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_WIDE_CHARACTERS 1102a0f2fa9SMark de Wever inline bool __do_getc(FILE* __fp, wchar_t* __pbuf) { 111fcbbd964SMartin Storsjö wint_t __c = getwc(__fp); 112fcbbd964SMartin Storsjö if (__c == WEOF) 113fcbbd964SMartin Storsjö return false; 114fcbbd964SMartin Storsjö *__pbuf = static_cast<wchar_t>(__c); 115fcbbd964SMartin Storsjö return true; 116fcbbd964SMartin Storsjö } 117fcbbd964SMartin Storsjö #endif 118fcbbd964SMartin Storsjö 1192a0f2fa9SMark de Wever inline bool __do_ungetc(int __c, FILE* __fp, char __dummy) { 120fcbbd964SMartin Storsjö if (ungetc(__c, __fp) == EOF) 121fcbbd964SMartin Storsjö return false; 122fcbbd964SMartin Storsjö return true; 123fcbbd964SMartin Storsjö } 124*c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_WIDE_CHARACTERS 1252a0f2fa9SMark de Wever inline bool __do_ungetc(std::wint_t __c, FILE* __fp, wchar_t __dummy) { 126fcbbd964SMartin Storsjö if (ungetwc(__c, __fp) == WEOF) 127fcbbd964SMartin Storsjö return false; 128fcbbd964SMartin Storsjö return true; 129fcbbd964SMartin Storsjö } 130fcbbd964SMartin Storsjö #endif 131fcbbd964SMartin Storsjö 13240a187bbSMartin Storsjö template <class _CharT> 1339783f28cSLouis Dionne typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::__getchar(bool __consume) { 1349783f28cSLouis Dionne if (__last_consumed_is_next_) { 13540a187bbSMartin Storsjö int_type __result = __last_consumed_; 1369783f28cSLouis Dionne if (__consume) { 13740a187bbSMartin Storsjö __last_consumed_ = traits_type::eof(); 13840a187bbSMartin Storsjö __last_consumed_is_next_ = false; 13940a187bbSMartin Storsjö } 14040a187bbSMartin Storsjö return __result; 14140a187bbSMartin Storsjö } 142fcbbd964SMartin Storsjö if (__always_noconv_) { 143fcbbd964SMartin Storsjö char_type __1buf; 144fcbbd964SMartin Storsjö if (!__do_getc(__file_, &__1buf)) 145fcbbd964SMartin Storsjö return traits_type::eof(); 1469783f28cSLouis Dionne if (!__consume) { 147fcbbd964SMartin Storsjö if (!__do_ungetc(traits_type::to_int_type(__1buf), __file_, __1buf)) 148fcbbd964SMartin Storsjö return traits_type::eof(); 1499783f28cSLouis Dionne } else 150fcbbd964SMartin Storsjö __last_consumed_ = traits_type::to_int_type(__1buf); 151fcbbd964SMartin Storsjö return traits_type::to_int_type(__1buf); 152fcbbd964SMartin Storsjö } 153fcbbd964SMartin Storsjö 15440a187bbSMartin Storsjö char __extbuf[__limit]; 15577a00c0dSLouis Dionne int __nread = std::max(1, __encoding_); 1569783f28cSLouis Dionne for (int __i = 0; __i < __nread; ++__i) { 15740a187bbSMartin Storsjö int __c = getc(__file_); 15840a187bbSMartin Storsjö if (__c == EOF) 15940a187bbSMartin Storsjö return traits_type::eof(); 16040a187bbSMartin Storsjö __extbuf[__i] = static_cast<char>(__c); 16140a187bbSMartin Storsjö } 16240a187bbSMartin Storsjö char_type __1buf; 16340a187bbSMartin Storsjö const char* __enxt; 16440a187bbSMartin Storsjö char_type* __inxt; 16540a187bbSMartin Storsjö codecvt_base::result __r; 1669783f28cSLouis Dionne do { 16740a187bbSMartin Storsjö state_type __sv_st = *__st_; 1689783f28cSLouis Dionne __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, &__1buf, &__1buf + 1, __inxt); 1699783f28cSLouis Dionne switch (__r) { 17077a00c0dSLouis Dionne case std::codecvt_base::ok: 17140a187bbSMartin Storsjö break; 17240a187bbSMartin Storsjö case codecvt_base::partial: 17340a187bbSMartin Storsjö *__st_ = __sv_st; 17440a187bbSMartin Storsjö if (__nread == sizeof(__extbuf)) 17540a187bbSMartin Storsjö return traits_type::eof(); 17640a187bbSMartin Storsjö { 17740a187bbSMartin Storsjö int __c = getc(__file_); 17840a187bbSMartin Storsjö if (__c == EOF) 17940a187bbSMartin Storsjö return traits_type::eof(); 18040a187bbSMartin Storsjö __extbuf[__nread] = static_cast<char>(__c); 18140a187bbSMartin Storsjö } 18240a187bbSMartin Storsjö ++__nread; 18340a187bbSMartin Storsjö break; 18440a187bbSMartin Storsjö case codecvt_base::error: 18540a187bbSMartin Storsjö return traits_type::eof(); 18677a00c0dSLouis Dionne case std::codecvt_base::noconv: 18740a187bbSMartin Storsjö __1buf = static_cast<char_type>(__extbuf[0]); 18840a187bbSMartin Storsjö break; 18940a187bbSMartin Storsjö } 19077a00c0dSLouis Dionne } while (__r == std::codecvt_base::partial); 1919783f28cSLouis Dionne if (!__consume) { 1929783f28cSLouis Dionne for (int __i = __nread; __i > 0;) { 19340a187bbSMartin Storsjö if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) 19440a187bbSMartin Storsjö return traits_type::eof(); 19540a187bbSMartin Storsjö } 1969783f28cSLouis Dionne } else 19740a187bbSMartin Storsjö __last_consumed_ = traits_type::to_int_type(__1buf); 19840a187bbSMartin Storsjö return traits_type::to_int_type(__1buf); 19940a187bbSMartin Storsjö } 20040a187bbSMartin Storsjö 20140a187bbSMartin Storsjö template <class _CharT> 2029783f28cSLouis Dionne typename __stdinbuf<_CharT>::int_type __stdinbuf<_CharT>::pbackfail(int_type __c) { 2039783f28cSLouis Dionne if (traits_type::eq_int_type(__c, traits_type::eof())) { 2049783f28cSLouis Dionne if (!__last_consumed_is_next_) { 20540a187bbSMartin Storsjö __c = __last_consumed_; 2069783f28cSLouis Dionne __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, traits_type::eof()); 20740a187bbSMartin Storsjö } 20840a187bbSMartin Storsjö return __c; 20940a187bbSMartin Storsjö } 210fcbbd964SMartin Storsjö if (__always_noconv_ && __last_consumed_is_next_) { 2119783f28cSLouis Dionne if (!__do_ungetc(__last_consumed_, __file_, traits_type::to_char_type(__last_consumed_))) 212fcbbd964SMartin Storsjö return traits_type::eof(); 213fcbbd964SMartin Storsjö } else if (__last_consumed_is_next_) { 21440a187bbSMartin Storsjö char __extbuf[__limit]; 21540a187bbSMartin Storsjö char* __enxt; 21640a187bbSMartin Storsjö const char_type __ci = traits_type::to_char_type(__last_consumed_); 21740a187bbSMartin Storsjö const char_type* __inxt; 2189783f28cSLouis Dionne switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, __extbuf, __extbuf + sizeof(__extbuf), __enxt)) { 21977a00c0dSLouis Dionne case std::codecvt_base::ok: 22040a187bbSMartin Storsjö break; 22177a00c0dSLouis Dionne case std::codecvt_base::noconv: 22240a187bbSMartin Storsjö __extbuf[0] = static_cast<char>(__last_consumed_); 22340a187bbSMartin Storsjö __enxt = __extbuf + 1; 22440a187bbSMartin Storsjö break; 22540a187bbSMartin Storsjö case codecvt_base::partial: 22640a187bbSMartin Storsjö case codecvt_base::error: 22740a187bbSMartin Storsjö return traits_type::eof(); 22840a187bbSMartin Storsjö } 22940a187bbSMartin Storsjö while (__enxt > __extbuf) 23040a187bbSMartin Storsjö if (ungetc(*--__enxt, __file_) == EOF) 23140a187bbSMartin Storsjö return traits_type::eof(); 23240a187bbSMartin Storsjö } 23340a187bbSMartin Storsjö __last_consumed_ = __c; 23440a187bbSMartin Storsjö __last_consumed_is_next_ = true; 23540a187bbSMartin Storsjö return __c; 23640a187bbSMartin Storsjö } 23740a187bbSMartin Storsjö 23840a187bbSMartin Storsjö // __stdoutbuf 23940a187bbSMartin Storsjö 24040a187bbSMartin Storsjö template <class _CharT> 2419783f28cSLouis Dionne class _LIBCPP_HIDDEN __stdoutbuf : public basic_streambuf<_CharT, char_traits<_CharT> > { 24240a187bbSMartin Storsjö public: 24340a187bbSMartin Storsjö typedef _CharT char_type; 24440a187bbSMartin Storsjö typedef char_traits<char_type> traits_type; 24540a187bbSMartin Storsjö typedef typename traits_type::int_type int_type; 24640a187bbSMartin Storsjö typedef typename traits_type::pos_type pos_type; 24740a187bbSMartin Storsjö typedef typename traits_type::off_type off_type; 24840a187bbSMartin Storsjö typedef typename traits_type::state_type state_type; 24940a187bbSMartin Storsjö 25040a187bbSMartin Storsjö __stdoutbuf(FILE* __fp, state_type* __st); 25140a187bbSMartin Storsjö 25240a187bbSMartin Storsjö protected: 25340a187bbSMartin Storsjö virtual int_type overflow(int_type __c = traits_type::eof()); 25440a187bbSMartin Storsjö virtual streamsize xsputn(const char_type* __s, streamsize __n); 25540a187bbSMartin Storsjö virtual int sync(); 25640a187bbSMartin Storsjö virtual void imbue(const locale& __loc); 25740a187bbSMartin Storsjö 25840a187bbSMartin Storsjö private: 25940a187bbSMartin Storsjö FILE* __file_; 26040a187bbSMartin Storsjö const codecvt<char_type, char, state_type>* __cv_; 26140a187bbSMartin Storsjö state_type* __st_; 26240a187bbSMartin Storsjö bool __always_noconv_; 26340a187bbSMartin Storsjö 264fcbbd964SMartin Storsjö #if defined(_LIBCPP_WIN32API) 265fcbbd964SMartin Storsjö static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; 266fcbbd964SMartin Storsjö #else 267fcbbd964SMartin Storsjö static constexpr bool __is_win32api_wide_char = false; 268fcbbd964SMartin Storsjö #endif 269fcbbd964SMartin Storsjö 27040a187bbSMartin Storsjö __stdoutbuf(const __stdoutbuf&); 27140a187bbSMartin Storsjö __stdoutbuf& operator=(const __stdoutbuf&); 2722fd4084fSMark de Wever 2732fd4084fSMark de Wever _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&); 27440a187bbSMartin Storsjö }; 27540a187bbSMartin Storsjö 27640a187bbSMartin Storsjö template <class _CharT> 27740a187bbSMartin Storsjö __stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) 27840a187bbSMartin Storsjö : __file_(__fp), 27940a187bbSMartin Storsjö __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), 28040a187bbSMartin Storsjö __st_(__st), 2819783f28cSLouis Dionne __always_noconv_(__cv_->always_noconv()) { 282fcbbd964SMartin Storsjö // On Windows, in wchar_t mode, ignore the codecvt from the locale by 283fcbbd964SMartin Storsjö // default and assume noconv; this passes wchar_t through unmodified to 284fcbbd964SMartin Storsjö // fputwc, which handles it correctly depending on the actual mode of the 285fcbbd964SMartin Storsjö // output stream. If the user sets a custom locale with imbue(), that 286fcbbd964SMartin Storsjö // gets honored. 287fcbbd964SMartin Storsjö if constexpr (__is_win32api_wide_char) 288fcbbd964SMartin Storsjö __always_noconv_ = true; 28940a187bbSMartin Storsjö } 29040a187bbSMartin Storsjö 2912a0f2fa9SMark de Wever inline bool __do_fputc(char __c, FILE* __fp) { 292fcbbd964SMartin Storsjö if (fwrite(&__c, sizeof(__c), 1, __fp) != 1) 293fcbbd964SMartin Storsjö return false; 294fcbbd964SMartin Storsjö return true; 295fcbbd964SMartin Storsjö } 296*c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_WIDE_CHARACTERS 2972a0f2fa9SMark de Wever inline bool __do_fputc(wchar_t __c, FILE* __fp) { 298fcbbd964SMartin Storsjö // fputwc works regardless of wide/narrow mode of stdout, while 299fcbbd964SMartin Storsjö // fwrite of wchar_t only works if the stream actually has been set 300fcbbd964SMartin Storsjö // into wide mode. 301fcbbd964SMartin Storsjö if (fputwc(__c, __fp) == WEOF) 302fcbbd964SMartin Storsjö return false; 303fcbbd964SMartin Storsjö return true; 304fcbbd964SMartin Storsjö } 305fcbbd964SMartin Storsjö #endif 306fcbbd964SMartin Storsjö 30740a187bbSMartin Storsjö template <class _CharT> 3089783f28cSLouis Dionne typename __stdoutbuf<_CharT>::int_type __stdoutbuf<_CharT>::overflow(int_type __c) { 30940a187bbSMartin Storsjö char __extbuf[__limit]; 31040a187bbSMartin Storsjö char_type __1buf; 3119783f28cSLouis Dionne if (!traits_type::eq_int_type(__c, traits_type::eof())) { 31240a187bbSMartin Storsjö __1buf = traits_type::to_char_type(__c); 3139783f28cSLouis Dionne if (__always_noconv_) { 314fcbbd964SMartin Storsjö if (!__do_fputc(__1buf, __file_)) 31540a187bbSMartin Storsjö return traits_type::eof(); 3169783f28cSLouis Dionne } else { 31740a187bbSMartin Storsjö char* __extbe = __extbuf; 31840a187bbSMartin Storsjö codecvt_base::result __r; 31940a187bbSMartin Storsjö char_type* pbase = &__1buf; 32040a187bbSMartin Storsjö char_type* pptr = pbase + 1; 3219783f28cSLouis Dionne do { 32240a187bbSMartin Storsjö const char_type* __e; 3239783f28cSLouis Dionne __r = __cv_->out(*__st_, pbase, pptr, __e, __extbuf, __extbuf + sizeof(__extbuf), __extbe); 32440a187bbSMartin Storsjö if (__e == pbase) 32540a187bbSMartin Storsjö return traits_type::eof(); 3269783f28cSLouis Dionne if (__r == codecvt_base::noconv) { 32740a187bbSMartin Storsjö if (fwrite(pbase, 1, 1, __file_) != 1) 32840a187bbSMartin Storsjö return traits_type::eof(); 3299783f28cSLouis Dionne } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { 33040a187bbSMartin Storsjö size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 33140a187bbSMartin Storsjö if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 33240a187bbSMartin Storsjö return traits_type::eof(); 3339783f28cSLouis Dionne if (__r == codecvt_base::partial) { 33440a187bbSMartin Storsjö pbase = const_cast<char_type*>(__e); 33540a187bbSMartin Storsjö } 3369783f28cSLouis Dionne } else 33740a187bbSMartin Storsjö return traits_type::eof(); 33840a187bbSMartin Storsjö } while (__r == codecvt_base::partial); 33940a187bbSMartin Storsjö } 34040a187bbSMartin Storsjö } 34140a187bbSMartin Storsjö return traits_type::not_eof(__c); 34240a187bbSMartin Storsjö } 34340a187bbSMartin Storsjö 34440a187bbSMartin Storsjö template <class _CharT> 3459783f28cSLouis Dionne streamsize __stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) { 346fcbbd964SMartin Storsjö // For wchar_t on Windows, don't call fwrite(), but write characters one 347fcbbd964SMartin Storsjö // at a time with fputwc(); that works both when stdout is in the default 348fcbbd964SMartin Storsjö // mode and when it is set to Unicode mode. 349fcbbd964SMartin Storsjö if (__always_noconv_ && !__is_win32api_wide_char) 35040a187bbSMartin Storsjö return fwrite(__s, sizeof(char_type), __n, __file_); 35140a187bbSMartin Storsjö streamsize __i = 0; 35240a187bbSMartin Storsjö for (; __i < __n; ++__i, ++__s) 35340a187bbSMartin Storsjö if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) 35440a187bbSMartin Storsjö break; 35540a187bbSMartin Storsjö return __i; 35640a187bbSMartin Storsjö } 35740a187bbSMartin Storsjö 35840a187bbSMartin Storsjö template <class _CharT> 3599783f28cSLouis Dionne int __stdoutbuf<_CharT>::sync() { 36040a187bbSMartin Storsjö char __extbuf[__limit]; 36140a187bbSMartin Storsjö codecvt_base::result __r; 3629783f28cSLouis Dionne do { 36340a187bbSMartin Storsjö char* __extbe; 3649783f28cSLouis Dionne __r = __cv_->unshift(*__st_, __extbuf, __extbuf + sizeof(__extbuf), __extbe); 36540a187bbSMartin Storsjö size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 36640a187bbSMartin Storsjö if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 36740a187bbSMartin Storsjö return -1; 36840a187bbSMartin Storsjö } while (__r == codecvt_base::partial); 36940a187bbSMartin Storsjö if (__r == codecvt_base::error) 37040a187bbSMartin Storsjö return -1; 37140a187bbSMartin Storsjö if (fflush(__file_)) 37240a187bbSMartin Storsjö return -1; 37340a187bbSMartin Storsjö return 0; 37440a187bbSMartin Storsjö } 37540a187bbSMartin Storsjö 37640a187bbSMartin Storsjö template <class _CharT> 3779783f28cSLouis Dionne void __stdoutbuf<_CharT>::imbue(const locale& __loc) { 37840a187bbSMartin Storsjö sync(); 37940a187bbSMartin Storsjö __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 38040a187bbSMartin Storsjö __always_noconv_ = __cv_->always_noconv(); 38140a187bbSMartin Storsjö } 38240a187bbSMartin Storsjö 38340a187bbSMartin Storsjö _LIBCPP_END_NAMESPACE_STD 38440a187bbSMartin Storsjö 38540a187bbSMartin Storsjö _LIBCPP_POP_MACROS 38640a187bbSMartin Storsjö 38740a187bbSMartin Storsjö #endif // _LIBCPP_STD_STREAM_H 388