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