]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/__std_stream
Merge bmake-20130123
[FreeBSD/FreeBSD.git] / contrib / libc++ / include / __std_stream
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