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 28 static const int __limit = 8; 29 30 // __stdinbuf 31 32 template <class _CharT> 33 class _LIBCPP_HIDDEN __stdinbuf 34 : public basic_streambuf<_CharT, char_traits<_CharT> > 35 { 36 public: 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 46 protected: 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 52 private: 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 66 template <class _CharT> 67 __stdinbuf<_CharT>::__stdinbuf(FILE* __fp) 68 : __file_(__fp), 69 __st_() 70 { 71 imbue(this->getloc()); 72 } 73 74 template <class _CharT> 75 void 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 85 template <class _CharT> 86 typename __stdinbuf<_CharT>::int_type 87 __stdinbuf<_CharT>::underflow() 88 { 89 return __getchar(false); 90 } 91 92 template <class _CharT> 93 typename __stdinbuf<_CharT>::int_type 94 __stdinbuf<_CharT>::uflow() 95 { 96 return __getchar(true); 97 } 98 99 template <class _CharT> 100 typename __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 160 template <class _CharT> 161 typename __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 191 template <class _CharT> 192 class _LIBCPP_HIDDEN __stdoutbuf 193 : public basic_streambuf<_CharT, char_traits<_CharT> > 194 { 195 public: 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 205 protected: 206 virtual int_type overflow (int_type __c = traits_type::eof()); 207 virtual int sync(); 208 virtual void imbue(const locale& __loc); 209 210 private: 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 220 template <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 229 template <class _CharT> 230 typename __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 283 template <class _CharT> 284 int 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 306 template <class _CharT> 307 void 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