__std_stream revision 232950
1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP___STD_STREAM 12#define _LIBCPP___STD_STREAM 13 14#include <__config> 15#include <ostream> 16#include <istream> 17#include <__locale> 18#include <cstdio> 19 20#include <__undef_min_max> 21 22#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23#pragma GCC system_header 24#endif 25 26_LIBCPP_BEGIN_NAMESPACE_STD 27 28static const int __limit = 8; 29 30// __stdinbuf 31 32template <class _CharT> 33class _LIBCPP_HIDDEN __stdinbuf 34 : public basic_streambuf<_CharT, char_traits<_CharT> > 35{ 36public: 37 typedef _CharT char_type; 38 typedef char_traits<char_type> traits_type; 39 typedef typename traits_type::int_type int_type; 40 typedef typename traits_type::pos_type pos_type; 41 typedef typename traits_type::off_type off_type; 42 typedef typename traits_type::state_type state_type; 43 44 explicit __stdinbuf(FILE* __fp); 45 46protected: 47 virtual int_type underflow(); 48 virtual int_type uflow(); 49 virtual int_type pbackfail(int_type __c = traits_type::eof()); 50 virtual void imbue(const locale& __loc); 51 52private: 53 54 FILE* __file_; 55 const codecvt<char_type, char, state_type>* __cv_; 56 state_type __st_; 57 int __encoding_; 58 bool __always_noconv_; 59 60 __stdinbuf(const __stdinbuf&); 61 __stdinbuf& operator=(const __stdinbuf&); 62 63 int_type __getchar(bool __consume); 64}; 65 66template <class _CharT> 67__stdinbuf<_CharT>::__stdinbuf(FILE* __fp) 68 : __file_(__fp), 69 __st_() 70{ 71 imbue(this->getloc()); 72} 73 74template <class _CharT> 75void 76__stdinbuf<_CharT>::imbue(const locale& __loc) 77{ 78 __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 79 __encoding_ = __cv_->encoding(); 80 __always_noconv_ = __cv_->always_noconv(); 81 if (__encoding_ > __limit) 82 __throw_runtime_error("unsupported locale for standard input"); 83} 84 85template <class _CharT> 86typename __stdinbuf<_CharT>::int_type 87__stdinbuf<_CharT>::underflow() 88{ 89 return __getchar(false); 90} 91 92template <class _CharT> 93typename __stdinbuf<_CharT>::int_type 94__stdinbuf<_CharT>::uflow() 95{ 96 return __getchar(true); 97} 98 99template <class _CharT> 100typename __stdinbuf<_CharT>::int_type 101__stdinbuf<_CharT>::__getchar(bool __consume) 102{ 103 char __extbuf[__limit]; 104 int __nread = _VSTD::max(1, __encoding_); 105 for (int __i = 0; __i < __nread; ++__i) 106 { 107 int __c = getc(__file_); 108 if (__c == EOF) 109 return traits_type::eof(); 110 __extbuf[__i] = static_cast<char>(__c); 111 } 112 char_type __1buf; 113 if (__always_noconv_) 114 __1buf = static_cast<char_type>(__extbuf[0]); 115 else 116 { 117 const char* __enxt; 118 char_type* __inxt; 119 codecvt_base::result __r; 120 do 121 { 122 state_type __sv_st = __st_; 123 __r = __cv_->in(__st_, __extbuf, __extbuf + __nread, __enxt, 124 &__1buf, &__1buf + 1, __inxt); 125 switch (__r) 126 { 127 case _VSTD::codecvt_base::ok: 128 break; 129 case codecvt_base::partial: 130 __st_ = __sv_st; 131 if (__nread == sizeof(__extbuf)) 132 return traits_type::eof(); 133 { 134 int __c = getc(__file_); 135 if (__c == EOF) 136 return traits_type::eof(); 137 __extbuf[__nread] = static_cast<char>(__c); 138 } 139 ++__nread; 140 break; 141 case codecvt_base::error: 142 return traits_type::eof(); 143 case _VSTD::codecvt_base::noconv: 144 __1buf = static_cast<char_type>(__extbuf[0]); 145 break; 146 } 147 } while (__r == _VSTD::codecvt_base::partial); 148 } 149 if (!__consume) 150 { 151 for (int __i = __nread; __i > 0;) 152 { 153 if (ungetc(__extbuf[--__i], __file_) == EOF) 154 return traits_type::eof(); 155 } 156 } 157 return traits_type::to_int_type(__1buf); 158} 159 160template <class _CharT> 161typename __stdinbuf<_CharT>::int_type 162__stdinbuf<_CharT>::pbackfail(int_type __c) 163{ 164 if (traits_type::eq_int_type(__c, traits_type::eof())) 165 return __c; 166 char __extbuf[__limit]; 167 char* __enxt; 168 const char_type __ci = traits_type::to_char_type(__c); 169 const char_type* __inxt; 170 switch (__cv_->out(__st_, &__ci, &__ci + 1, __inxt, 171 __extbuf, __extbuf + sizeof(__extbuf), __enxt)) 172 { 173 case _VSTD::codecvt_base::ok: 174 break; 175 case _VSTD::codecvt_base::noconv: 176 __extbuf[0] = static_cast<char>(__c); 177 __enxt = __extbuf + 1; 178 break; 179 case codecvt_base::partial: 180 case codecvt_base::error: 181 return traits_type::eof(); 182 } 183 while (__enxt > __extbuf) 184 if (ungetc(*--__enxt, __file_) == EOF) 185 return traits_type::eof(); 186 return traits_type::not_eof(__c); 187} 188 189// __stdoutbuf 190 191template <class _CharT> 192class _LIBCPP_HIDDEN __stdoutbuf 193 : public basic_streambuf<_CharT, char_traits<_CharT> > 194{ 195public: 196 typedef _CharT char_type; 197 typedef char_traits<char_type> traits_type; 198 typedef typename traits_type::int_type int_type; 199 typedef typename traits_type::pos_type pos_type; 200 typedef typename traits_type::off_type off_type; 201 typedef typename traits_type::state_type state_type; 202 203 explicit __stdoutbuf(FILE* __fp); 204 205protected: 206 virtual int_type overflow (int_type __c = traits_type::eof()); 207 virtual int sync(); 208 virtual void imbue(const locale& __loc); 209 210private: 211 FILE* __file_; 212 const codecvt<char_type, char, state_type>* __cv_; 213 state_type __st_; 214 bool __always_noconv_; 215 216 __stdoutbuf(const __stdoutbuf&); 217 __stdoutbuf& operator=(const __stdoutbuf&); 218}; 219 220template <class _CharT> 221__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp) 222 : __file_(__fp), 223 __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), 224 __st_(), 225 __always_noconv_(__cv_->always_noconv()) 226{ 227} 228 229template <class _CharT> 230typename __stdoutbuf<_CharT>::int_type 231__stdoutbuf<_CharT>::overflow(int_type __c) 232{ 233 char __extbuf[__limit]; 234 char_type __1buf; 235 if (!traits_type::eq_int_type(__c, traits_type::eof())) 236 { 237 this->setp(&__1buf, &__1buf+1); 238 *this->pptr() = traits_type::to_char_type(__c); 239 this->pbump(1); 240 if (__always_noconv_) 241 { 242 if (fwrite(this->pbase(), sizeof(char_type), 1, __file_) != 1) 243 return traits_type::eof(); 244 } 245 else 246 { 247 char* __extbe = __extbuf; 248 codecvt_base::result __r; 249 do 250 { 251 const char_type* __e; 252 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, 253 __extbuf, 254 __extbuf + sizeof(__extbuf), 255 __extbe); 256 if (__e == this->pbase()) 257 return traits_type::eof(); 258 if (__r == codecvt_base::noconv) 259 { 260 if (fwrite(this->pbase(), 1, 1, __file_) != 1) 261 return traits_type::eof(); 262 } 263 else if (__r == codecvt_base::ok || __r == codecvt_base::partial) 264 { 265 size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 266 if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 267 return traits_type::eof(); 268 if (__r == codecvt_base::partial) 269 { 270 this->setp((char_type*)__e, this->pptr()); 271 this->pbump(static_cast<int>(this->epptr() - this->pbase())); 272 } 273 } 274 else 275 return traits_type::eof(); 276 } while (__r == codecvt_base::partial); 277 } 278 this->setp(0, 0); 279 } 280 return traits_type::not_eof(__c); 281} 282 283template <class _CharT> 284int 285__stdoutbuf<_CharT>::sync() 286{ 287 char __extbuf[__limit]; 288 codecvt_base::result __r; 289 do 290 { 291 char* __extbe; 292 __r = __cv_->unshift(__st_, __extbuf, 293 __extbuf + sizeof(__extbuf), 294 __extbe); 295 size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); 296 if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) 297 return -1; 298 } while (__r == codecvt_base::partial); 299 if (__r == codecvt_base::error) 300 return -1; 301 if (fflush(__file_)) 302 return -1; 303 return 0; 304} 305 306template <class _CharT> 307void 308__stdoutbuf<_CharT>::imbue(const locale& __loc) 309{ 310 sync(); 311 __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); 312 __always_noconv_ = __cv_->always_noconv(); 313} 314 315_LIBCPP_END_NAMESPACE_STD 316 317#endif // _LIBCPP___STD_STREAM 318