1*06c3fb27SDimitry Andric // -*- C++ -*- 2*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 3*06c3fb27SDimitry Andric // 4*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*06c3fb27SDimitry Andric // 8*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 9*06c3fb27SDimitry Andric 10*06c3fb27SDimitry Andric #ifndef _LIBCPP_STD_STREAM_H 11*06c3fb27SDimitry Andric #define _LIBCPP_STD_STREAM_H 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #include <__config> 14*06c3fb27SDimitry Andric #include <__locale> 15*06c3fb27SDimitry Andric #include <cstdio> 16*06c3fb27SDimitry Andric #include <istream> 17*06c3fb27SDimitry Andric #include <ostream> 18*06c3fb27SDimitry Andric 19*06c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20*06c3fb27SDimitry Andric # pragma GCC system_header 21*06c3fb27SDimitry Andric #endif 22*06c3fb27SDimitry Andric 23*06c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 24*06c3fb27SDimitry Andric #include <__undef_macros> 25*06c3fb27SDimitry Andric 26*06c3fb27SDimitry Andric 27*06c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 28*06c3fb27SDimitry Andric 29*06c3fb27SDimitry Andric static const int __limit = 8; 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric // __stdinbuf 32*06c3fb27SDimitry Andric 33*06c3fb27SDimitry Andric template <class _CharT> 34*06c3fb27SDimitry Andric class _LIBCPP_HIDDEN __stdinbuf 35*06c3fb27SDimitry Andric : public basic_streambuf<_CharT, char_traits<_CharT> > 36*06c3fb27SDimitry Andric { 37*06c3fb27SDimitry Andric public: 38*06c3fb27SDimitry Andric typedef _CharT char_type; 39*06c3fb27SDimitry Andric typedef char_traits<char_type> traits_type; 40*06c3fb27SDimitry Andric typedef typename traits_type::int_type int_type; 41*06c3fb27SDimitry Andric typedef typename traits_type::pos_type pos_type; 42*06c3fb27SDimitry Andric typedef typename traits_type::off_type off_type; 43*06c3fb27SDimitry Andric typedef typename traits_type::state_type state_type; 44*06c3fb27SDimitry Andric 45*06c3fb27SDimitry Andric __stdinbuf(FILE* __fp, state_type* __st); 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric protected: 48*06c3fb27SDimitry Andric virtual int_type underflow(); 49*06c3fb27SDimitry Andric virtual int_type uflow(); 50*06c3fb27SDimitry Andric virtual int_type pbackfail(int_type __c = traits_type::eof()); 51*06c3fb27SDimitry Andric virtual void imbue(const locale& __loc); 52*06c3fb27SDimitry Andric 53*06c3fb27SDimitry Andric private: 54*06c3fb27SDimitry Andric 55*06c3fb27SDimitry Andric FILE* __file_; 56*06c3fb27SDimitry Andric const codecvt<char_type, char, state_type>* __cv_; 57*06c3fb27SDimitry Andric state_type* __st_; 58*06c3fb27SDimitry Andric int __encoding_; 59*06c3fb27SDimitry Andric int_type __last_consumed_; 60*06c3fb27SDimitry Andric bool __last_consumed_is_next_; 61*06c3fb27SDimitry Andric bool __always_noconv_; 62*06c3fb27SDimitry Andric 63*06c3fb27SDimitry Andric #if defined(_LIBCPP_WIN32API) 64*06c3fb27SDimitry Andric static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; 65*06c3fb27SDimitry Andric #else 66*06c3fb27SDimitry Andric static constexpr bool __is_win32api_wide_char = false; 67*06c3fb27SDimitry Andric #endif 68*06c3fb27SDimitry Andric 69*06c3fb27SDimitry Andric __stdinbuf(const __stdinbuf&); 70*06c3fb27SDimitry Andric __stdinbuf& operator=(const __stdinbuf&); 71*06c3fb27SDimitry Andric 72*06c3fb27SDimitry Andric int_type __getchar(bool __consume); 73*06c3fb27SDimitry Andric }; 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric template <class _CharT> 76*06c3fb27SDimitry Andric __stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) 77*06c3fb27SDimitry Andric : __file_(__fp), 78*06c3fb27SDimitry Andric __st_(__st), 79*06c3fb27SDimitry Andric __last_consumed_(traits_type::eof()), 80*06c3fb27SDimitry Andric __last_consumed_is_next_(false) 81*06c3fb27SDimitry Andric { 82*06c3fb27SDimitry Andric imbue(this->getloc()); 83*06c3fb27SDimitry Andric // On Windows, in wchar_t mode, ignore the codecvt from the locale by 84*06c3fb27SDimitry Andric // default and assume noconv; this passes wchar_t through unmodified from 85*06c3fb27SDimitry Andric // getwc. If the user sets a custom locale with imbue(), that gets honored, 86*06c3fb27SDimitry Andric // the IO is done with getc() and converted with the provided codecvt. 87*06c3fb27SDimitry Andric if constexpr (__is_win32api_wide_char) 88*06c3fb27SDimitry Andric __always_noconv_ = true; 89*06c3fb27SDimitry Andric } 90*06c3fb27SDimitry Andric 91*06c3fb27SDimitry Andric template <class _CharT> 92*06c3fb27SDimitry Andric void 93*06c3fb27SDimitry Andric __stdinbuf<_CharT>::imbue(const locale& __loc) 94*06c3fb27SDimitry Andric { 95*06c3fb27SDimitry Andric __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 96*06c3fb27SDimitry Andric __encoding_ = __cv_->encoding(); 97*06c3fb27SDimitry Andric __always_noconv_ = __cv_->always_noconv(); 98*06c3fb27SDimitry Andric if (__encoding_ > __limit) 99*06c3fb27SDimitry Andric __throw_runtime_error("unsupported locale for standard input"); 100*06c3fb27SDimitry Andric } 101*06c3fb27SDimitry Andric 102*06c3fb27SDimitry Andric template <class _CharT> 103*06c3fb27SDimitry Andric typename __stdinbuf<_CharT>::int_type 104*06c3fb27SDimitry Andric __stdinbuf<_CharT>::underflow() 105*06c3fb27SDimitry Andric { 106*06c3fb27SDimitry Andric return __getchar(false); 107*06c3fb27SDimitry Andric } 108*06c3fb27SDimitry Andric 109*06c3fb27SDimitry Andric template <class _CharT> 110*06c3fb27SDimitry Andric typename __stdinbuf<_CharT>::int_type 111*06c3fb27SDimitry Andric __stdinbuf<_CharT>::uflow() 112*06c3fb27SDimitry Andric { 113*06c3fb27SDimitry Andric return __getchar(true); 114*06c3fb27SDimitry Andric } 115*06c3fb27SDimitry Andric 116*06c3fb27SDimitry Andric static bool __do_getc(FILE *__fp, char *__pbuf) { 117*06c3fb27SDimitry Andric int __c = getc(__fp); 118*06c3fb27SDimitry Andric if (__c == EOF) 119*06c3fb27SDimitry Andric return false; 120*06c3fb27SDimitry Andric *__pbuf = static_cast<char>(__c); 121*06c3fb27SDimitry Andric return true; 122*06c3fb27SDimitry Andric } 123*06c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 124*06c3fb27SDimitry Andric static bool __do_getc(FILE *__fp, wchar_t *__pbuf) { 125*06c3fb27SDimitry Andric wint_t __c = getwc(__fp); 126*06c3fb27SDimitry Andric if (__c == WEOF) 127*06c3fb27SDimitry Andric return false; 128*06c3fb27SDimitry Andric *__pbuf = static_cast<wchar_t>(__c); 129*06c3fb27SDimitry Andric return true; 130*06c3fb27SDimitry Andric } 131*06c3fb27SDimitry Andric #endif 132*06c3fb27SDimitry Andric 133*06c3fb27SDimitry Andric static bool __do_ungetc(int __c, FILE *__fp, char __dummy) { 134*06c3fb27SDimitry Andric if (ungetc(__c, __fp) == EOF) 135*06c3fb27SDimitry Andric return false; 136*06c3fb27SDimitry Andric return true; 137*06c3fb27SDimitry Andric } 138*06c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 139*06c3fb27SDimitry Andric static bool __do_ungetc(std::wint_t __c, FILE *__fp, wchar_t __dummy) { 140*06c3fb27SDimitry Andric if (ungetwc(__c, __fp) == WEOF) 141*06c3fb27SDimitry Andric return false; 142*06c3fb27SDimitry Andric return true; 143*06c3fb27SDimitry Andric } 144*06c3fb27SDimitry Andric #endif 145*06c3fb27SDimitry Andric 146*06c3fb27SDimitry Andric template <class _CharT> 147*06c3fb27SDimitry Andric typename __stdinbuf<_CharT>::int_type 148*06c3fb27SDimitry Andric __stdinbuf<_CharT>::__getchar(bool __consume) 149*06c3fb27SDimitry Andric { 150*06c3fb27SDimitry Andric if (__last_consumed_is_next_) 151*06c3fb27SDimitry Andric { 152*06c3fb27SDimitry Andric int_type __result = __last_consumed_; 153*06c3fb27SDimitry Andric if (__consume) 154*06c3fb27SDimitry Andric { 155*06c3fb27SDimitry Andric __last_consumed_ = traits_type::eof(); 156*06c3fb27SDimitry Andric __last_consumed_is_next_ = false; 157*06c3fb27SDimitry Andric } 158*06c3fb27SDimitry Andric return __result; 159*06c3fb27SDimitry Andric } 160*06c3fb27SDimitry Andric if (__always_noconv_) { 161*06c3fb27SDimitry Andric char_type __1buf; 162*06c3fb27SDimitry Andric if (!__do_getc(__file_, &__1buf)) 163*06c3fb27SDimitry Andric return traits_type::eof(); 164*06c3fb27SDimitry Andric if (!__consume) 165*06c3fb27SDimitry Andric { 166*06c3fb27SDimitry Andric if (!__do_ungetc(traits_type::to_int_type(__1buf), __file_, __1buf)) 167*06c3fb27SDimitry Andric return traits_type::eof(); 168*06c3fb27SDimitry Andric } 169*06c3fb27SDimitry Andric else 170*06c3fb27SDimitry Andric __last_consumed_ = traits_type::to_int_type(__1buf); 171*06c3fb27SDimitry Andric return traits_type::to_int_type(__1buf); 172*06c3fb27SDimitry Andric } 173*06c3fb27SDimitry Andric 174*06c3fb27SDimitry Andric char __extbuf[__limit]; 175*06c3fb27SDimitry Andric int __nread = _VSTD::max(1, __encoding_); 176*06c3fb27SDimitry Andric for (int __i = 0; __i < __nread; ++__i) 177*06c3fb27SDimitry Andric { 178*06c3fb27SDimitry Andric int __c = getc(__file_); 179*06c3fb27SDimitry Andric if (__c == EOF) 180*06c3fb27SDimitry Andric return traits_type::eof(); 181*06c3fb27SDimitry Andric __extbuf[__i] = static_cast<char>(__c); 182*06c3fb27SDimitry Andric } 183*06c3fb27SDimitry Andric char_type __1buf; 184*06c3fb27SDimitry Andric const char* __enxt; 185*06c3fb27SDimitry Andric char_type* __inxt; 186*06c3fb27SDimitry Andric codecvt_base::result __r; 187*06c3fb27SDimitry Andric do 188*06c3fb27SDimitry Andric { 189*06c3fb27SDimitry Andric state_type __sv_st = *__st_; 190*06c3fb27SDimitry Andric __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, 191*06c3fb27SDimitry Andric &__1buf, &__1buf + 1, __inxt); 192*06c3fb27SDimitry Andric switch (__r) 193*06c3fb27SDimitry Andric { 194*06c3fb27SDimitry Andric case _VSTD::codecvt_base::ok: 195*06c3fb27SDimitry Andric break; 196*06c3fb27SDimitry Andric case codecvt_base::partial: 197*06c3fb27SDimitry Andric *__st_ = __sv_st; 198*06c3fb27SDimitry Andric if (__nread == sizeof(__extbuf)) 199*06c3fb27SDimitry Andric return traits_type::eof(); 200*06c3fb27SDimitry Andric { 201*06c3fb27SDimitry Andric int __c = getc(__file_); 202*06c3fb27SDimitry Andric if (__c == EOF) 203*06c3fb27SDimitry Andric return traits_type::eof(); 204*06c3fb27SDimitry Andric __extbuf[__nread] = static_cast<char>(__c); 205*06c3fb27SDimitry Andric } 206*06c3fb27SDimitry Andric ++__nread; 207*06c3fb27SDimitry Andric break; 208*06c3fb27SDimitry Andric case codecvt_base::error: 209*06c3fb27SDimitry Andric return traits_type::eof(); 210*06c3fb27SDimitry Andric case _VSTD::codecvt_base::noconv: 211*06c3fb27SDimitry Andric __1buf = static_cast<char_type>(__extbuf[0]); 212*06c3fb27SDimitry Andric break; 213*06c3fb27SDimitry Andric } 214*06c3fb27SDimitry Andric } while (__r == _VSTD::codecvt_base::partial); 215*06c3fb27SDimitry Andric if (!__consume) 216*06c3fb27SDimitry Andric { 217*06c3fb27SDimitry Andric for (int __i = __nread; __i > 0;) 218*06c3fb27SDimitry Andric { 219*06c3fb27SDimitry Andric if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) 220*06c3fb27SDimitry Andric return traits_type::eof(); 221*06c3fb27SDimitry Andric } 222*06c3fb27SDimitry Andric } 223*06c3fb27SDimitry Andric else 224*06c3fb27SDimitry Andric __last_consumed_ = traits_type::to_int_type(__1buf); 225*06c3fb27SDimitry Andric return traits_type::to_int_type(__1buf); 226*06c3fb27SDimitry Andric } 227*06c3fb27SDimitry Andric 228*06c3fb27SDimitry Andric template <class _CharT> 229*06c3fb27SDimitry Andric typename __stdinbuf<_CharT>::int_type 230*06c3fb27SDimitry Andric __stdinbuf<_CharT>::pbackfail(int_type __c) 231*06c3fb27SDimitry Andric { 232*06c3fb27SDimitry Andric if (traits_type::eq_int_type(__c, traits_type::eof())) 233*06c3fb27SDimitry Andric { 234*06c3fb27SDimitry Andric if (!__last_consumed_is_next_) 235*06c3fb27SDimitry Andric { 236*06c3fb27SDimitry Andric __c = __last_consumed_; 237*06c3fb27SDimitry Andric __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, 238*06c3fb27SDimitry Andric traits_type::eof()); 239*06c3fb27SDimitry Andric } 240*06c3fb27SDimitry Andric return __c; 241*06c3fb27SDimitry Andric } 242*06c3fb27SDimitry Andric if (__always_noconv_ && __last_consumed_is_next_) { 243*06c3fb27SDimitry Andric if (!__do_ungetc(__last_consumed_, __file_, 244*06c3fb27SDimitry Andric traits_type::to_char_type(__last_consumed_))) 245*06c3fb27SDimitry Andric return traits_type::eof(); 246*06c3fb27SDimitry Andric } else if (__last_consumed_is_next_) { 247*06c3fb27SDimitry Andric char __extbuf[__limit]; 248*06c3fb27SDimitry Andric char* __enxt; 249*06c3fb27SDimitry Andric const char_type __ci = traits_type::to_char_type(__last_consumed_); 250*06c3fb27SDimitry Andric const char_type* __inxt; 251*06c3fb27SDimitry Andric switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, 252*06c3fb27SDimitry Andric __extbuf, __extbuf + sizeof(__extbuf), __enxt)) 253*06c3fb27SDimitry Andric { 254*06c3fb27SDimitry Andric case _VSTD::codecvt_base::ok: 255*06c3fb27SDimitry Andric break; 256*06c3fb27SDimitry Andric case _VSTD::codecvt_base::noconv: 257*06c3fb27SDimitry Andric __extbuf[0] = static_cast<char>(__last_consumed_); 258*06c3fb27SDimitry Andric __enxt = __extbuf + 1; 259*06c3fb27SDimitry Andric break; 260*06c3fb27SDimitry Andric case codecvt_base::partial: 261*06c3fb27SDimitry Andric case codecvt_base::error: 262*06c3fb27SDimitry Andric return traits_type::eof(); 263*06c3fb27SDimitry Andric } 264*06c3fb27SDimitry Andric while (__enxt > __extbuf) 265*06c3fb27SDimitry Andric if (ungetc(*--__enxt, __file_) == EOF) 266*06c3fb27SDimitry Andric return traits_type::eof(); 267*06c3fb27SDimitry Andric } 268*06c3fb27SDimitry Andric __last_consumed_ = __c; 269*06c3fb27SDimitry Andric __last_consumed_is_next_ = true; 270*06c3fb27SDimitry Andric return __c; 271*06c3fb27SDimitry Andric } 272*06c3fb27SDimitry Andric 273*06c3fb27SDimitry Andric // __stdoutbuf 274*06c3fb27SDimitry Andric 275*06c3fb27SDimitry Andric template <class _CharT> 276*06c3fb27SDimitry Andric class _LIBCPP_HIDDEN __stdoutbuf 277*06c3fb27SDimitry Andric : public basic_streambuf<_CharT, char_traits<_CharT> > 278*06c3fb27SDimitry Andric { 279*06c3fb27SDimitry Andric public: 280*06c3fb27SDimitry Andric typedef _CharT char_type; 281*06c3fb27SDimitry Andric typedef char_traits<char_type> traits_type; 282*06c3fb27SDimitry Andric typedef typename traits_type::int_type int_type; 283*06c3fb27SDimitry Andric typedef typename traits_type::pos_type pos_type; 284*06c3fb27SDimitry Andric typedef typename traits_type::off_type off_type; 285*06c3fb27SDimitry Andric typedef typename traits_type::state_type state_type; 286*06c3fb27SDimitry Andric 287*06c3fb27SDimitry Andric __stdoutbuf(FILE* __fp, state_type* __st); 288*06c3fb27SDimitry Andric 289*06c3fb27SDimitry Andric protected: 290*06c3fb27SDimitry Andric virtual int_type overflow (int_type __c = traits_type::eof()); 291*06c3fb27SDimitry Andric virtual streamsize xsputn(const char_type* __s, streamsize __n); 292*06c3fb27SDimitry Andric virtual int sync(); 293*06c3fb27SDimitry Andric virtual void imbue(const locale& __loc); 294*06c3fb27SDimitry Andric 295*06c3fb27SDimitry Andric private: 296*06c3fb27SDimitry Andric FILE* __file_; 297*06c3fb27SDimitry Andric const codecvt<char_type, char, state_type>* __cv_; 298*06c3fb27SDimitry Andric state_type* __st_; 299*06c3fb27SDimitry Andric bool __always_noconv_; 300*06c3fb27SDimitry Andric 301*06c3fb27SDimitry Andric #if defined(_LIBCPP_WIN32API) 302*06c3fb27SDimitry Andric static constexpr bool __is_win32api_wide_char = !is_same_v<_CharT, char>; 303*06c3fb27SDimitry Andric #else 304*06c3fb27SDimitry Andric static constexpr bool __is_win32api_wide_char = false; 305*06c3fb27SDimitry Andric #endif 306*06c3fb27SDimitry Andric 307*06c3fb27SDimitry Andric __stdoutbuf(const __stdoutbuf&); 308*06c3fb27SDimitry Andric __stdoutbuf& operator=(const __stdoutbuf&); 309*06c3fb27SDimitry Andric }; 310*06c3fb27SDimitry Andric 311*06c3fb27SDimitry Andric template <class _CharT> 312*06c3fb27SDimitry Andric __stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) 313*06c3fb27SDimitry Andric : __file_(__fp), 314*06c3fb27SDimitry Andric __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), 315*06c3fb27SDimitry Andric __st_(__st), 316*06c3fb27SDimitry Andric __always_noconv_(__cv_->always_noconv()) 317*06c3fb27SDimitry Andric { 318*06c3fb27SDimitry Andric // On Windows, in wchar_t mode, ignore the codecvt from the locale by 319*06c3fb27SDimitry Andric // default and assume noconv; this passes wchar_t through unmodified to 320*06c3fb27SDimitry Andric // fputwc, which handles it correctly depending on the actual mode of the 321*06c3fb27SDimitry Andric // output stream. If the user sets a custom locale with imbue(), that 322*06c3fb27SDimitry Andric // gets honored. 323*06c3fb27SDimitry Andric if constexpr (__is_win32api_wide_char) 324*06c3fb27SDimitry Andric __always_noconv_ = true; 325*06c3fb27SDimitry Andric } 326*06c3fb27SDimitry Andric 327*06c3fb27SDimitry Andric static bool __do_fputc(char __c, FILE* __fp) { 328*06c3fb27SDimitry Andric if (fwrite(&__c, sizeof(__c), 1, __fp) != 1) 329*06c3fb27SDimitry Andric return false; 330*06c3fb27SDimitry Andric return true; 331*06c3fb27SDimitry Andric } 332*06c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 333*06c3fb27SDimitry Andric static bool __do_fputc(wchar_t __c, FILE* __fp) { 334*06c3fb27SDimitry Andric // fputwc works regardless of wide/narrow mode of stdout, while 335*06c3fb27SDimitry Andric // fwrite of wchar_t only works if the stream actually has been set 336*06c3fb27SDimitry Andric // into wide mode. 337*06c3fb27SDimitry Andric if (fputwc(__c, __fp) == WEOF) 338*06c3fb27SDimitry Andric return false; 339*06c3fb27SDimitry Andric return true; 340*06c3fb27SDimitry Andric } 341*06c3fb27SDimitry Andric #endif 342*06c3fb27SDimitry Andric 343*06c3fb27SDimitry Andric template <class _CharT> 344*06c3fb27SDimitry Andric typename __stdoutbuf<_CharT>::int_type 345*06c3fb27SDimitry Andric __stdoutbuf<_CharT>::overflow(int_type __c) 346*06c3fb27SDimitry Andric { 347*06c3fb27SDimitry Andric char __extbuf[__limit]; 348*06c3fb27SDimitry Andric char_type __1buf; 349*06c3fb27SDimitry Andric if (!traits_type::eq_int_type(__c, traits_type::eof())) 350*06c3fb27SDimitry Andric { 351*06c3fb27SDimitry Andric __1buf = traits_type::to_char_type(__c); 352*06c3fb27SDimitry Andric if (__always_noconv_) 353*06c3fb27SDimitry Andric { 354*06c3fb27SDimitry Andric if (!__do_fputc(__1buf, __file_)) 355*06c3fb27SDimitry Andric return traits_type::eof(); 356*06c3fb27SDimitry Andric } 357*06c3fb27SDimitry Andric else 358*06c3fb27SDimitry Andric { 359*06c3fb27SDimitry Andric char* __extbe = __extbuf; 360*06c3fb27SDimitry Andric codecvt_base::result __r; 361*06c3fb27SDimitry Andric char_type* pbase = &__1buf; 362*06c3fb27SDimitry Andric char_type* pptr = pbase + 1; 363*06c3fb27SDimitry Andric do 364*06c3fb27SDimitry Andric { 365*06c3fb27SDimitry Andric const char_type* __e; 366*06c3fb27SDimitry Andric __r = __cv_->out(*__st_, pbase, pptr, __e, 367*06c3fb27SDimitry Andric __extbuf, 368*06c3fb27SDimitry Andric __extbuf + sizeof(__extbuf), 369*06c3fb27SDimitry Andric __extbe); 370*06c3fb27SDimitry Andric if (__e == pbase) 371*06c3fb27SDimitry Andric return traits_type::eof(); 372*06c3fb27SDimitry Andric if (__r == codecvt_base::noconv) 373*06c3fb27SDimitry Andric { 374*06c3fb27SDimitry Andric if (fwrite(pbase, 1, 1, __file_) != 1) 375*06c3fb27SDimitry Andric return traits_type::eof(); 376*06c3fb27SDimitry Andric } 377*06c3fb27SDimitry Andric else if (__r == codecvt_base::ok || __r == codecvt_base::partial) 378*06c3fb27SDimitry Andric { 379*06c3fb27SDimitry Andric size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 380*06c3fb27SDimitry Andric if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 381*06c3fb27SDimitry Andric return traits_type::eof(); 382*06c3fb27SDimitry Andric if (__r == codecvt_base::partial) 383*06c3fb27SDimitry Andric { 384*06c3fb27SDimitry Andric pbase = const_cast<char_type*>(__e); 385*06c3fb27SDimitry Andric } 386*06c3fb27SDimitry Andric } 387*06c3fb27SDimitry Andric else 388*06c3fb27SDimitry Andric return traits_type::eof(); 389*06c3fb27SDimitry Andric } while (__r == codecvt_base::partial); 390*06c3fb27SDimitry Andric } 391*06c3fb27SDimitry Andric } 392*06c3fb27SDimitry Andric return traits_type::not_eof(__c); 393*06c3fb27SDimitry Andric } 394*06c3fb27SDimitry Andric 395*06c3fb27SDimitry Andric template <class _CharT> 396*06c3fb27SDimitry Andric streamsize 397*06c3fb27SDimitry Andric __stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) 398*06c3fb27SDimitry Andric { 399*06c3fb27SDimitry Andric // For wchar_t on Windows, don't call fwrite(), but write characters one 400*06c3fb27SDimitry Andric // at a time with fputwc(); that works both when stdout is in the default 401*06c3fb27SDimitry Andric // mode and when it is set to Unicode mode. 402*06c3fb27SDimitry Andric if (__always_noconv_ && !__is_win32api_wide_char) 403*06c3fb27SDimitry Andric return fwrite(__s, sizeof(char_type), __n, __file_); 404*06c3fb27SDimitry Andric streamsize __i = 0; 405*06c3fb27SDimitry Andric for (; __i < __n; ++__i, ++__s) 406*06c3fb27SDimitry Andric if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) 407*06c3fb27SDimitry Andric break; 408*06c3fb27SDimitry Andric return __i; 409*06c3fb27SDimitry Andric } 410*06c3fb27SDimitry Andric 411*06c3fb27SDimitry Andric template <class _CharT> 412*06c3fb27SDimitry Andric int 413*06c3fb27SDimitry Andric __stdoutbuf<_CharT>::sync() 414*06c3fb27SDimitry Andric { 415*06c3fb27SDimitry Andric char __extbuf[__limit]; 416*06c3fb27SDimitry Andric codecvt_base::result __r; 417*06c3fb27SDimitry Andric do 418*06c3fb27SDimitry Andric { 419*06c3fb27SDimitry Andric char* __extbe; 420*06c3fb27SDimitry Andric __r = __cv_->unshift(*__st_, __extbuf, 421*06c3fb27SDimitry Andric __extbuf + sizeof(__extbuf), 422*06c3fb27SDimitry Andric __extbe); 423*06c3fb27SDimitry Andric size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 424*06c3fb27SDimitry Andric if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 425*06c3fb27SDimitry Andric return -1; 426*06c3fb27SDimitry Andric } while (__r == codecvt_base::partial); 427*06c3fb27SDimitry Andric if (__r == codecvt_base::error) 428*06c3fb27SDimitry Andric return -1; 429*06c3fb27SDimitry Andric if (fflush(__file_)) 430*06c3fb27SDimitry Andric return -1; 431*06c3fb27SDimitry Andric return 0; 432*06c3fb27SDimitry Andric } 433*06c3fb27SDimitry Andric 434*06c3fb27SDimitry Andric template <class _CharT> 435*06c3fb27SDimitry Andric void 436*06c3fb27SDimitry Andric __stdoutbuf<_CharT>::imbue(const locale& __loc) 437*06c3fb27SDimitry Andric { 438*06c3fb27SDimitry Andric sync(); 439*06c3fb27SDimitry Andric __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 440*06c3fb27SDimitry Andric __always_noconv_ = __cv_->always_noconv(); 441*06c3fb27SDimitry Andric } 442*06c3fb27SDimitry Andric 443*06c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 444*06c3fb27SDimitry Andric 445*06c3fb27SDimitry Andric _LIBCPP_POP_MACROS 446*06c3fb27SDimitry Andric 447*06c3fb27SDimitry Andric #endif // _LIBCPP_STD_STREAM_H 448