root / lab4 / .minix-src / include / c++ / __std_stream
History | View | Annotate | Download (10.3 KB)
1 | 13 | up20180614 | // -*- 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 | __stdinbuf(FILE* __fp, state_type* __st); |
||
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 | int_type __last_consumed_; |
||
59 | bool __last_consumed_is_next_; |
||
60 | bool __always_noconv_; |
||
61 | |||
62 | __stdinbuf(const __stdinbuf&); |
||
63 | __stdinbuf& operator=(const __stdinbuf&); |
||
64 | |||
65 | int_type __getchar(bool __consume); |
||
66 | }; |
||
67 | |||
68 | template <class _CharT> |
||
69 | __stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) |
||
70 | : __file_(__fp), |
||
71 | __st_(__st), |
||
72 | __last_consumed_(traits_type::eof()), |
||
73 | __last_consumed_is_next_(false) |
||
74 | { |
||
75 | imbue(this->getloc()); |
||
76 | } |
||
77 | |||
78 | template <class _CharT> |
||
79 | void |
||
80 | __stdinbuf<_CharT>::imbue(const locale& __loc) |
||
81 | { |
||
82 | __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); |
||
83 | __encoding_ = __cv_->encoding(); |
||
84 | __always_noconv_ = __cv_->always_noconv(); |
||
85 | if (__encoding_ > __limit) |
||
86 | __throw_runtime_error("unsupported locale for standard input"); |
||
87 | } |
||
88 | |||
89 | template <class _CharT> |
||
90 | typename __stdinbuf<_CharT>::int_type |
||
91 | __stdinbuf<_CharT>::underflow() |
||
92 | { |
||
93 | return __getchar(false); |
||
94 | } |
||
95 | |||
96 | template <class _CharT> |
||
97 | typename __stdinbuf<_CharT>::int_type |
||
98 | __stdinbuf<_CharT>::uflow() |
||
99 | { |
||
100 | return __getchar(true); |
||
101 | } |
||
102 | |||
103 | template <class _CharT> |
||
104 | typename __stdinbuf<_CharT>::int_type |
||
105 | __stdinbuf<_CharT>::__getchar(bool __consume) |
||
106 | { |
||
107 | if (__last_consumed_is_next_) |
||
108 | { |
||
109 | int_type __result = __last_consumed_; |
||
110 | if (__consume) |
||
111 | { |
||
112 | __last_consumed_ = traits_type::eof(); |
||
113 | __last_consumed_is_next_ = false; |
||
114 | } |
||
115 | return __result; |
||
116 | } |
||
117 | char __extbuf[__limit]; |
||
118 | int __nread = _VSTD::max(1, __encoding_); |
||
119 | for (int __i = 0; __i < __nread; ++__i) |
||
120 | { |
||
121 | int __c = getc(__file_); |
||
122 | if (__c == EOF) |
||
123 | return traits_type::eof(); |
||
124 | __extbuf[__i] = static_cast<char>(__c); |
||
125 | } |
||
126 | char_type __1buf; |
||
127 | if (__always_noconv_) |
||
128 | __1buf = static_cast<char_type>(__extbuf[0]); |
||
129 | else |
||
130 | { |
||
131 | const char* __enxt; |
||
132 | char_type* __inxt; |
||
133 | codecvt_base::result __r; |
||
134 | do |
||
135 | { |
||
136 | state_type __sv_st = *__st_; |
||
137 | __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, |
||
138 | &__1buf, &__1buf + 1, __inxt); |
||
139 | switch (__r) |
||
140 | { |
||
141 | case _VSTD::codecvt_base::ok: |
||
142 | break; |
||
143 | case codecvt_base::partial: |
||
144 | *__st_ = __sv_st; |
||
145 | if (__nread == sizeof(__extbuf)) |
||
146 | return traits_type::eof(); |
||
147 | { |
||
148 | int __c = getc(__file_); |
||
149 | if (__c == EOF) |
||
150 | return traits_type::eof(); |
||
151 | __extbuf[__nread] = static_cast<char>(__c); |
||
152 | } |
||
153 | ++__nread; |
||
154 | break; |
||
155 | case codecvt_base::error: |
||
156 | return traits_type::eof(); |
||
157 | case _VSTD::codecvt_base::noconv: |
||
158 | __1buf = static_cast<char_type>(__extbuf[0]); |
||
159 | break; |
||
160 | } |
||
161 | } while (__r == _VSTD::codecvt_base::partial); |
||
162 | } |
||
163 | if (!__consume) |
||
164 | { |
||
165 | for (int __i = __nread; __i > 0;) |
||
166 | { |
||
167 | if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) |
||
168 | return traits_type::eof(); |
||
169 | } |
||
170 | } |
||
171 | else |
||
172 | __last_consumed_ = traits_type::to_int_type(__1buf); |
||
173 | return traits_type::to_int_type(__1buf); |
||
174 | } |
||
175 | |||
176 | template <class _CharT> |
||
177 | typename __stdinbuf<_CharT>::int_type |
||
178 | __stdinbuf<_CharT>::pbackfail(int_type __c) |
||
179 | { |
||
180 | if (traits_type::eq_int_type(__c, traits_type::eof())) |
||
181 | { |
||
182 | if (!__last_consumed_is_next_) |
||
183 | { |
||
184 | __c = __last_consumed_; |
||
185 | __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, |
||
186 | traits_type::eof()); |
||
187 | } |
||
188 | return __c; |
||
189 | } |
||
190 | if (__last_consumed_is_next_) |
||
191 | { |
||
192 | char __extbuf[__limit]; |
||
193 | char* __enxt; |
||
194 | const char_type __ci = traits_type::to_char_type(__last_consumed_); |
||
195 | const char_type* __inxt; |
||
196 | switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, |
||
197 | __extbuf, __extbuf + sizeof(__extbuf), __enxt)) |
||
198 | { |
||
199 | case _VSTD::codecvt_base::ok: |
||
200 | break; |
||
201 | case _VSTD::codecvt_base::noconv: |
||
202 | __extbuf[0] = static_cast<char>(__last_consumed_); |
||
203 | __enxt = __extbuf + 1; |
||
204 | break; |
||
205 | case codecvt_base::partial: |
||
206 | case codecvt_base::error: |
||
207 | return traits_type::eof(); |
||
208 | } |
||
209 | while (__enxt > __extbuf) |
||
210 | if (ungetc(*--__enxt, __file_) == EOF) |
||
211 | return traits_type::eof(); |
||
212 | } |
||
213 | __last_consumed_ = __c; |
||
214 | __last_consumed_is_next_ = true; |
||
215 | return __c; |
||
216 | } |
||
217 | |||
218 | // __stdoutbuf |
||
219 | |||
220 | template <class _CharT> |
||
221 | class _LIBCPP_HIDDEN __stdoutbuf |
||
222 | : public basic_streambuf<_CharT, char_traits<_CharT> > |
||
223 | { |
||
224 | public: |
||
225 | typedef _CharT char_type; |
||
226 | typedef char_traits<char_type> traits_type; |
||
227 | typedef typename traits_type::int_type int_type; |
||
228 | typedef typename traits_type::pos_type pos_type; |
||
229 | typedef typename traits_type::off_type off_type; |
||
230 | typedef typename traits_type::state_type state_type; |
||
231 | |||
232 | __stdoutbuf(FILE* __fp, state_type* __st); |
||
233 | |||
234 | protected: |
||
235 | virtual int_type overflow (int_type __c = traits_type::eof()); |
||
236 | virtual streamsize xsputn(const char_type* __s, streamsize __n); |
||
237 | virtual int sync(); |
||
238 | virtual void imbue(const locale& __loc); |
||
239 | |||
240 | private: |
||
241 | FILE* __file_; |
||
242 | const codecvt<char_type, char, state_type>* __cv_; |
||
243 | state_type* __st_; |
||
244 | bool __always_noconv_; |
||
245 | |||
246 | __stdoutbuf(const __stdoutbuf&); |
||
247 | __stdoutbuf& operator=(const __stdoutbuf&); |
||
248 | }; |
||
249 | |||
250 | template <class _CharT> |
||
251 | __stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) |
||
252 | : __file_(__fp), |
||
253 | __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), |
||
254 | __st_(__st), |
||
255 | __always_noconv_(__cv_->always_noconv()) |
||
256 | { |
||
257 | } |
||
258 | |||
259 | template <class _CharT> |
||
260 | typename __stdoutbuf<_CharT>::int_type |
||
261 | __stdoutbuf<_CharT>::overflow(int_type __c) |
||
262 | { |
||
263 | char __extbuf[__limit]; |
||
264 | char_type __1buf; |
||
265 | if (!traits_type::eq_int_type(__c, traits_type::eof())) |
||
266 | { |
||
267 | __1buf = traits_type::to_char_type(__c); |
||
268 | if (__always_noconv_) |
||
269 | { |
||
270 | if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1) |
||
271 | return traits_type::eof(); |
||
272 | } |
||
273 | else |
||
274 | { |
||
275 | char* __extbe = __extbuf; |
||
276 | codecvt_base::result __r; |
||
277 | char_type* pbase = &__1buf; |
||
278 | char_type* pptr = pbase + 1; |
||
279 | do |
||
280 | { |
||
281 | const char_type* __e; |
||
282 | __r = __cv_->out(*__st_, pbase, pptr, __e, |
||
283 | __extbuf, |
||
284 | __extbuf + sizeof(__extbuf), |
||
285 | __extbe); |
||
286 | if (__e == pbase) |
||
287 | return traits_type::eof(); |
||
288 | if (__r == codecvt_base::noconv) |
||
289 | { |
||
290 | if (fwrite(pbase, 1, 1, __file_) != 1) |
||
291 | return traits_type::eof(); |
||
292 | } |
||
293 | else if (__r == codecvt_base::ok || __r == codecvt_base::partial) |
||
294 | { |
||
295 | size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); |
||
296 | if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) |
||
297 | return traits_type::eof(); |
||
298 | if (__r == codecvt_base::partial) |
||
299 | { |
||
300 | pbase = (char_type*)__e; |
||
301 | } |
||
302 | } |
||
303 | else |
||
304 | return traits_type::eof(); |
||
305 | } while (__r == codecvt_base::partial); |
||
306 | } |
||
307 | } |
||
308 | return traits_type::not_eof(__c); |
||
309 | } |
||
310 | |||
311 | template <class _CharT> |
||
312 | streamsize |
||
313 | __stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) |
||
314 | { |
||
315 | if (__always_noconv_) |
||
316 | return fwrite(__s, sizeof(char_type), __n, __file_); |
||
317 | streamsize __i = 0; |
||
318 | for (; __i < __n; ++__i, ++__s) |
||
319 | if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) |
||
320 | break; |
||
321 | return __i; |
||
322 | } |
||
323 | |||
324 | template <class _CharT> |
||
325 | int |
||
326 | __stdoutbuf<_CharT>::sync() |
||
327 | { |
||
328 | char __extbuf[__limit]; |
||
329 | codecvt_base::result __r; |
||
330 | do |
||
331 | { |
||
332 | char* __extbe; |
||
333 | __r = __cv_->unshift(*__st_, __extbuf, |
||
334 | __extbuf + sizeof(__extbuf), |
||
335 | __extbe); |
||
336 | size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); |
||
337 | if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) |
||
338 | return -1; |
||
339 | } while (__r == codecvt_base::partial); |
||
340 | if (__r == codecvt_base::error) |
||
341 | return -1; |
||
342 | if (fflush(__file_)) |
||
343 | return -1; |
||
344 | return 0; |
||
345 | } |
||
346 | |||
347 | template <class _CharT> |
||
348 | void |
||
349 | __stdoutbuf<_CharT>::imbue(const locale& __loc) |
||
350 | { |
||
351 | sync(); |
||
352 | __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); |
||
353 | __always_noconv_ = __cv_->always_noconv(); |
||
354 | } |
||
355 | |||
356 | _LIBCPP_END_NAMESPACE_STD |
||
357 | |||
358 | #endif // _LIBCPP___STD_STREAM |