|
1 /* |
|
2 * Copyright (c) 1999 |
|
3 * Silicon Graphics Computer Systems, Inc. |
|
4 * |
|
5 * Copyright (c) 1999 |
|
6 * Boris Fomitchev |
|
7 * |
|
8 * This material is provided "as is", with absolutely no warranty expressed |
|
9 * or implied. Any use is at your own risk. |
|
10 * |
|
11 * Permission to use or copy this software for any purpose is hereby granted |
|
12 * without fee, provided the above notices are retained on all copies. |
|
13 * Permission to modify the code and to distribute modified code is granted, |
|
14 * provided the above notices are retained, and a notice that the code was |
|
15 * modified is included with the above copyright notice. |
|
16 * |
|
17 */ |
|
18 #ifndef _STLP_ISTREAM_C |
|
19 #define _STLP_ISTREAM_C |
|
20 |
|
21 #ifndef _STLP_INTERNAL_ISTREAM |
|
22 # include <stl/_istream.h> |
|
23 #endif |
|
24 |
|
25 #ifndef _STLP_INTERNAL_LIMITS |
|
26 # include <stl/_limits.h> |
|
27 #endif |
|
28 |
|
29 #ifndef _STLP_INTERNAL_NUM_GET_H |
|
30 # include <stl/_num_get.h> |
|
31 #endif |
|
32 |
|
33 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) |
|
34 // no wchar_t is supported for this mode |
|
35 # define __BIS_int_type__ int |
|
36 # define __BIS_pos_type__ streampos |
|
37 # define __BIS_off_type__ streamoff |
|
38 #else |
|
39 # define __BIS_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::int_type |
|
40 # define __BIS_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::pos_type |
|
41 # define __BIS_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::off_type |
|
42 #endif |
|
43 |
|
44 _STLP_BEGIN_NAMESPACE |
|
45 |
|
46 //---------------------------------------------------------------------- |
|
47 // Function object structs used by some member functions. |
|
48 |
|
49 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
50 |
|
51 template <class _Traits> |
|
52 struct _Is_not_wspace { |
|
53 typedef typename _Traits::char_type argument_type; |
|
54 typedef bool result_type; |
|
55 |
|
56 const ctype<argument_type>* _M_ctype; |
|
57 |
|
58 _Is_not_wspace(const ctype<argument_type>* __c_type) : _M_ctype(__c_type) {} |
|
59 bool operator()(argument_type __c) const |
|
60 { return !_M_ctype->is(ctype_base::space, __c); } |
|
61 }; |
|
62 |
|
63 template <class _Traits> |
|
64 struct _Is_wspace_null { |
|
65 typedef typename _Traits::char_type argument_type; |
|
66 typedef bool result_type; |
|
67 |
|
68 const ctype<argument_type>* _M_ctype; |
|
69 |
|
70 _Is_wspace_null(const ctype<argument_type>* __c_type) : _M_ctype(__c_type) {} |
|
71 bool operator()(argument_type __c) const { |
|
72 return _Traits::eq(__c, argument_type()) || |
|
73 _M_ctype->is(ctype_base::space, __c); |
|
74 } |
|
75 }; |
|
76 |
|
77 template <class _Traits> |
|
78 struct _Scan_for_wspace { |
|
79 typedef typename _Traits::char_type char_type; |
|
80 typedef char_type* first_argument_type; |
|
81 typedef char_type* second_argument_type; |
|
82 typedef char_type* result_type; |
|
83 |
|
84 const ctype<char_type>* _M_ctype; |
|
85 |
|
86 _Scan_for_wspace(const ctype<char_type>* __ctype) : _M_ctype(__ctype) {} |
|
87 const char_type* |
|
88 operator()(const char_type* __first, const char_type* __last) const { |
|
89 return _M_ctype->scan_is(ctype_base::space, __first, __last); |
|
90 } |
|
91 }; |
|
92 |
|
93 template <class _Traits> |
|
94 struct _Scan_wspace_null { |
|
95 typedef typename _Traits::char_type char_type; |
|
96 typedef char_type* first_argument_type; |
|
97 typedef char_type* second_argument_type; |
|
98 typedef char_type* result_type; |
|
99 |
|
100 const ctype<char_type>* _M_ctype; |
|
101 |
|
102 _Scan_wspace_null(const ctype<char_type>* __c_type) : _M_ctype(__c_type) {} |
|
103 const char_type* |
|
104 operator()(const char_type* __first, const char_type* __last) const { |
|
105 __last = find_if(__first, __last, |
|
106 _Eq_char_bound<_Traits>(char_type())); |
|
107 return _M_ctype->scan_is(ctype_base::space, __first, __last); |
|
108 } |
|
109 }; |
|
110 |
|
111 template <class _Traits> |
|
112 struct _Scan_for_not_wspace { |
|
113 typedef typename _Traits::char_type char_type; |
|
114 typedef char_type* first_argument_type; |
|
115 typedef char_type* second_argument_type; |
|
116 typedef char_type* result_type; |
|
117 |
|
118 const ctype<char_type>* _M_ctype; |
|
119 |
|
120 _Scan_for_not_wspace(const ctype<char_type>* __c_type) : _M_ctype(__c_type) {} |
|
121 const char_type* |
|
122 operator()(const char_type* __first, const char_type* __last) const { |
|
123 return _M_ctype->scan_not(ctype_base::space, __first, __last); |
|
124 } |
|
125 }; |
|
126 |
|
127 template <class _Traits> |
|
128 struct _Scan_for_char_val { |
|
129 typedef typename _Traits::char_type char_type; |
|
130 typedef char_type* first_argument_type; |
|
131 typedef char_type* second_argument_type; |
|
132 typedef char_type* result_type; |
|
133 |
|
134 char_type _M_val; |
|
135 |
|
136 _Scan_for_char_val(char_type __val) : _M_val(__val) {} |
|
137 |
|
138 const char_type* |
|
139 operator()(const char_type* __first, const char_type* __last) const { |
|
140 return find_if(__first, __last, _Eq_char_bound<_Traits>(_M_val)); |
|
141 } |
|
142 }; |
|
143 |
|
144 template <class _Traits> |
|
145 struct _Scan_for_int_val { |
|
146 typedef typename _Traits::char_type char_type; |
|
147 typedef typename _Traits::int_type int_type; |
|
148 typedef char_type* first_argument_type; |
|
149 typedef char_type* second_argument_type; |
|
150 typedef char_type* result_type; |
|
151 |
|
152 int_type _M_val; |
|
153 |
|
154 _Scan_for_int_val(int_type __val) : _M_val(__val) {} |
|
155 |
|
156 const char_type* |
|
157 operator()(const char_type* __first, const char_type* __last) const { |
|
158 return find_if(__first, __last, |
|
159 _Eq_int_bound<_Traits>(_M_val)); |
|
160 } |
|
161 }; |
|
162 |
|
163 // Helper function: try to push back a character to a streambuf, |
|
164 // return true if the pushback succeeded. Does not throw. |
|
165 |
|
166 template <class _CharT, class _Traits> |
|
167 bool _STLP_CALL |
|
168 __pushback(basic_streambuf<_CharT, _Traits>* __buf, _CharT __c) { |
|
169 bool ret; |
|
170 _STLP_TRY { |
|
171 const typename _Traits::int_type __eof = _Traits::eof(); |
|
172 ret = !_Traits::eq_int_type(__buf->sputbackc(__c), __eof); |
|
173 } |
|
174 _STLP_CATCH_ALL { |
|
175 ret = false; |
|
176 } |
|
177 return ret; |
|
178 } |
|
179 |
|
180 //---------------------------------------------------------------------- |
|
181 // Definitions of basic_istream<>'s noninline member functions. |
|
182 |
|
183 // Helper function for formatted input of numbers. |
|
184 template <class _CharT, class _Traits, class _Number> |
|
185 ios_base::iostate _STLP_CALL |
|
186 __get_num(basic_istream<_CharT, _Traits>& __that, _Number& __val) { |
|
187 typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; |
|
188 ios_base::iostate __err = 0; |
|
189 _Sentry __sentry( __that ); // Skip whitespace. |
|
190 if (__sentry) { |
|
191 typedef num_get<_CharT, istreambuf_iterator<_CharT, _Traits> > _Num_get; |
|
192 _STLP_TRY { |
|
193 ((const _Num_get&)use_facet<_Num_get>(__that.getloc())).get(istreambuf_iterator<_CharT, _Traits>(__that.rdbuf()), |
|
194 0, __that, __err, __val); |
|
195 } |
|
196 _STLP_CATCH_ALL { |
|
197 __that._M_handle_exception(ios_base::badbit); |
|
198 } |
|
199 if (__err) __that.setstate(__err); |
|
200 } |
|
201 return __err; |
|
202 } |
|
203 |
|
204 _STLP_MOVE_TO_STD_NAMESPACE |
|
205 |
|
206 template <class _CharT, class _Traits> |
|
207 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (short& __val) { |
|
208 long __lval; |
|
209 _STLP_PRIV __get_num(*this, __lval); |
|
210 if ( this->fail() ) { |
|
211 return *this; |
|
212 } |
|
213 short __tmp = __STATIC_CAST(short, __lval); |
|
214 unsigned short __uval = __STATIC_CAST(unsigned short, __lval); |
|
215 // check if we lose digits |
|
216 // if ((__val != __lval) && ((unsigned short)__val != __lval)) |
|
217 if ((__tmp != __lval) && ((long)__uval != __lval)) |
|
218 this->setstate(ios_base::failbit); |
|
219 else |
|
220 __val = __tmp; |
|
221 return *this; |
|
222 } |
|
223 |
|
224 template <class _CharT, class _Traits> |
|
225 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (int& __val) { |
|
226 long __lval; |
|
227 _STLP_PRIV __get_num(*this, __lval); |
|
228 if ( this->fail() ) { |
|
229 return *this; |
|
230 } |
|
231 int __tmp = __lval; |
|
232 unsigned int __uval = __lval; |
|
233 // check if we lose digits |
|
234 // if ((__val != __lval) && ((unsigned int)__val != __lval)) |
|
235 if ((__tmp != __lval) && ((long)__uval != __lval)) |
|
236 this->setstate(ios_base::failbit); |
|
237 else |
|
238 __val = __tmp; |
|
239 return *this; |
|
240 } |
|
241 |
|
242 template <class _CharT, class _Traits> |
|
243 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned short& __val) { |
|
244 _STLP_PRIV __get_num(*this, __val); |
|
245 return *this; |
|
246 } |
|
247 |
|
248 template <class _CharT, class _Traits> |
|
249 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned int& __val) { |
|
250 _STLP_PRIV __get_num(*this, __val); |
|
251 return *this; |
|
252 } |
|
253 |
|
254 template <class _CharT, class _Traits> |
|
255 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (long& __val) { |
|
256 _STLP_PRIV __get_num(*this, __val); |
|
257 return *this; |
|
258 } |
|
259 |
|
260 template <class _CharT, class _Traits> |
|
261 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned long& __val) { |
|
262 _STLP_PRIV __get_num(*this, __val); |
|
263 return *this; |
|
264 } |
|
265 |
|
266 #if defined (_STLP_LONG_LONG) |
|
267 template <class _CharT, class _Traits> |
|
268 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (_STLP_LONG_LONG& __val) { |
|
269 _STLP_PRIV __get_num(*this, __val); |
|
270 return *this; |
|
271 } |
|
272 |
|
273 template <class _CharT, class _Traits> |
|
274 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned _STLP_LONG_LONG& __val) { |
|
275 _STLP_PRIV __get_num(*this, __val); |
|
276 return *this; |
|
277 } |
|
278 #endif |
|
279 template <class _CharT, class _Traits> |
|
280 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (float& __val) { |
|
281 _STLP_PRIV __get_num(*this, __val); |
|
282 return *this; |
|
283 } |
|
284 template <class _CharT, class _Traits> |
|
285 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (double& __val) { |
|
286 _STLP_PRIV __get_num(*this, __val); |
|
287 return *this; |
|
288 } |
|
289 #if !defined (_STLP_NO_LONG_DOUBLE) |
|
290 template <class _CharT, class _Traits> |
|
291 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (long double& __val) { |
|
292 _STLP_PRIV __get_num(*this, __val); |
|
293 return *this; |
|
294 } |
|
295 #endif |
|
296 #if !defined (_STLP_NO_BOOL) |
|
297 template <class _CharT, class _Traits> |
|
298 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (bool& __val) { |
|
299 _STLP_PRIV __get_num(*this, __val); |
|
300 return *this; |
|
301 } |
|
302 #endif |
|
303 |
|
304 template <class _CharT, class _Traits> |
|
305 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (void*& __val) { |
|
306 _STLP_PRIV __get_num(*this, __val); |
|
307 return *this; |
|
308 } |
|
309 |
|
310 // Unformatted input |
|
311 |
|
312 template <class _CharT, class _Traits> |
|
313 __BIS_int_type__ |
|
314 basic_istream<_CharT, _Traits>::peek() { |
|
315 typename _Traits::int_type __tmp = _Traits::eof(); |
|
316 |
|
317 this->_M_gcount = 0; |
|
318 sentry __sentry(*this, _No_Skip_WS()); |
|
319 |
|
320 if (__sentry) { |
|
321 _STLP_TRY { |
|
322 __tmp = this->rdbuf()->sgetc(); |
|
323 } |
|
324 _STLP_CATCH_ALL { |
|
325 this->_M_handle_exception(ios_base::badbit); |
|
326 } |
|
327 if (this->_S_eof(__tmp)) |
|
328 this->setstate(ios_base::eofbit); |
|
329 } |
|
330 |
|
331 return __tmp; |
|
332 } |
|
333 |
|
334 |
|
335 template <class _CharT, class _Traits> |
|
336 __BIS_int_type__ |
|
337 basic_istream<_CharT, _Traits>::get() { |
|
338 typename _Traits::int_type __tmp = _Traits::eof(); |
|
339 sentry __sentry(*this, _No_Skip_WS()); |
|
340 this->_M_gcount = 0; |
|
341 |
|
342 if (__sentry) { |
|
343 _STLP_TRY { |
|
344 __tmp = this->rdbuf()->sbumpc(); |
|
345 } |
|
346 _STLP_CATCH_ALL { |
|
347 this->_M_handle_exception(ios_base::badbit); |
|
348 } |
|
349 |
|
350 if (!this->_S_eof(__tmp)) |
|
351 this->_M_gcount = 1; |
|
352 } |
|
353 |
|
354 if (_M_gcount == 0) |
|
355 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
356 |
|
357 return __tmp; |
|
358 } |
|
359 |
|
360 template <class _CharT, class _Traits> |
|
361 basic_istream<_CharT, _Traits>& |
|
362 basic_istream<_CharT, _Traits>::get(_CharT& __c) { |
|
363 sentry __sentry(*this, _No_Skip_WS()); |
|
364 this->_M_gcount = 0; |
|
365 |
|
366 if (__sentry) { |
|
367 typename _Traits::int_type __tmp = _Traits::eof(); |
|
368 _STLP_TRY { |
|
369 __tmp = this->rdbuf()->sbumpc(); |
|
370 } |
|
371 _STLP_CATCH_ALL { |
|
372 this->_M_handle_exception(ios_base::badbit); |
|
373 } |
|
374 |
|
375 if (!this->_S_eof(__tmp)) { |
|
376 this->_M_gcount = 1; |
|
377 __c = _Traits::to_char_type(__tmp); |
|
378 } |
|
379 } |
|
380 |
|
381 if (this->_M_gcount == 0) |
|
382 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
383 |
|
384 return *this; |
|
385 } |
|
386 |
|
387 |
|
388 // Read characters and discard them. The standard specifies a single |
|
389 // function with two arguments, each with a default. We instead use |
|
390 // three overloded functions, because it's possible to implement the |
|
391 // first two more efficiently than the fully general third version. |
|
392 template <class _CharT, class _Traits> |
|
393 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::ignore() { |
|
394 sentry __sentry(*this, _No_Skip_WS()); |
|
395 this->_M_gcount = 0; |
|
396 |
|
397 if (__sentry) { |
|
398 int_type __c; |
|
399 _STLP_TRY { |
|
400 __c = this->rdbuf()->sbumpc(); |
|
401 } |
|
402 _STLP_CATCH_ALL { |
|
403 this->_M_handle_exception(ios_base::badbit); |
|
404 return *this; |
|
405 } |
|
406 |
|
407 if (!this->_S_eof(__c)) |
|
408 this->_M_gcount = 1; |
|
409 else |
|
410 this->setstate(ios_base::eofbit); |
|
411 } |
|
412 |
|
413 return *this; |
|
414 } |
|
415 |
|
416 // Putback |
|
417 |
|
418 template <class _CharT, class _Traits> |
|
419 basic_istream<_CharT, _Traits>& |
|
420 basic_istream<_CharT, _Traits>::putback(_CharT __c) { |
|
421 this->_M_gcount = 0; |
|
422 sentry __sentry(*this, _No_Skip_WS()); |
|
423 |
|
424 if (__sentry) { |
|
425 typename _Traits::int_type __tmp = _Traits::eof(); |
|
426 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
427 // if (!__buf || this->_S_eof(__buf->sputbackc(__c))) |
|
428 if (__buf) { |
|
429 _STLP_TRY { |
|
430 __tmp = __buf->sputbackc(__c); |
|
431 } |
|
432 _STLP_CATCH_ALL { |
|
433 this->_M_handle_exception(ios_base::badbit); |
|
434 } |
|
435 } |
|
436 if (this->_S_eof(__tmp)) |
|
437 this->setstate(ios_base::badbit); |
|
438 } |
|
439 else |
|
440 this->setstate(ios_base::failbit); |
|
441 |
|
442 return *this; |
|
443 } |
|
444 |
|
445 template <class _CharT, class _Traits> |
|
446 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::unget() { |
|
447 this->_M_gcount = 0; |
|
448 |
|
449 sentry __sentry(*this, _No_Skip_WS()); |
|
450 |
|
451 if (__sentry) { |
|
452 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
453 // if (!__buf || _Traits::eq_int_type(__buf->sungetc(), _Traits::eof())) |
|
454 if (__buf) { |
|
455 _STLP_TRY { |
|
456 if (this->_S_eof(__buf->sungetc())) |
|
457 this->setstate(ios_base::badbit); |
|
458 } |
|
459 _STLP_CATCH_ALL { |
|
460 this->_M_handle_exception(ios_base::badbit); |
|
461 } |
|
462 } else |
|
463 this->setstate(ios_base::badbit); |
|
464 } |
|
465 else |
|
466 this->setstate(ios_base::failbit); |
|
467 |
|
468 return *this; |
|
469 } |
|
470 |
|
471 // Positioning and buffer control. |
|
472 |
|
473 template <class _CharT, class _Traits> |
|
474 int basic_istream<_CharT, _Traits>::sync() { |
|
475 sentry __sentry(*this, _No_Skip_WS()); |
|
476 |
|
477 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
478 if (__buf) { |
|
479 if (__buf->pubsync() == -1) { |
|
480 this->setstate(ios_base::badbit); |
|
481 return -1; |
|
482 } |
|
483 else |
|
484 return 0; |
|
485 } |
|
486 else |
|
487 return -1; |
|
488 } |
|
489 |
|
490 template <class _CharT, class _Traits> |
|
491 __BIS_pos_type__ |
|
492 basic_istream<_CharT, _Traits>::tellg() { |
|
493 sentry __sentry(*this, _No_Skip_WS()); |
|
494 |
|
495 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
496 return (__buf && !this->fail()) ? __buf->pubseekoff(0, ios_base::cur, ios_base::in) |
|
497 : pos_type(-1); |
|
498 } |
|
499 |
|
500 template <class _CharT, class _Traits> |
|
501 basic_istream<_CharT, _Traits>& |
|
502 basic_istream<_CharT, _Traits>::seekg(pos_type __pos) { |
|
503 sentry __sentry(*this, _No_Skip_WS()); |
|
504 |
|
505 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
506 if (!this->fail() && __buf) { |
|
507 if (__buf->pubseekpos(__pos) == pos_type(-1)) { |
|
508 this->setstate(ios_base::failbit); |
|
509 } |
|
510 } |
|
511 return *this; |
|
512 } |
|
513 |
|
514 template <class _CharT, class _Traits> |
|
515 basic_istream<_CharT, _Traits>& |
|
516 basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) { |
|
517 sentry __sentry(*this, _No_Skip_WS()); |
|
518 |
|
519 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
520 if (!this->fail() && __buf) |
|
521 __buf->pubseekoff(__off, __dir); |
|
522 return *this; |
|
523 } |
|
524 |
|
525 // Formatted input of characters and character arrays. |
|
526 |
|
527 template <class _CharT, class _Traits> |
|
528 void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT& __c) { |
|
529 // typename _Traits::int_type __tmp = _Traits::eof(); |
|
530 |
|
531 sentry __sentry(*this); // Skip whitespace. |
|
532 |
|
533 if (__sentry) { |
|
534 typename _Traits::int_type __tmp;// = _Traits::eof(); |
|
535 |
|
536 _STLP_TRY { |
|
537 __tmp = this->rdbuf()->sbumpc(); |
|
538 } |
|
539 _STLP_CATCH_ALL { |
|
540 this->_M_handle_exception(ios_base::badbit); |
|
541 return; |
|
542 } |
|
543 |
|
544 if (!this->_S_eof(__tmp)) |
|
545 __c = _Traits::to_char_type(__tmp); |
|
546 else |
|
547 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
548 } |
|
549 } |
|
550 |
|
551 |
|
552 //--------------------------------------------------------------------------- |
|
553 // istream's helper functions. |
|
554 |
|
555 // A generic function for unbuffered input. We stop when we reach EOF, |
|
556 // or when we have extracted _Num characters, or when the function object |
|
557 // __is_delim return true. In the last case, it extracts the character |
|
558 // for which __is_delim is true, if and only if __extract_delim is true. |
|
559 // It appends a null character to the end of the string; this means that |
|
560 // it may store up to _Num + 1 characters. |
|
561 // |
|
562 // __is_getline governs two corner cases: reading _Num characters without |
|
563 // encountering delim or eof (in which case failbit is set if __is_getline |
|
564 // is true); and reading _Num characters where the _Num+1'st character is |
|
565 // eof (in which case eofbit is set if __is_getline is true). |
|
566 // |
|
567 // It is assumed that __is_delim never throws. |
|
568 // |
|
569 // Return value is the number of characters extracted, including the |
|
570 // delimiter if it is extracted. Note that the number of characaters |
|
571 // extracted isn't necessarily the same as the number stored. |
|
572 |
|
573 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
574 |
|
575 template < class _CharT, class _Traits, class _Is_Delim> |
|
576 streamsize _STLP_CALL |
|
577 __read_unbuffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, |
|
578 streamsize _Num, _CharT* __s, |
|
579 _Is_Delim __is_delim, |
|
580 bool __extract_delim, bool __append_null, |
|
581 bool __is_getline) { |
|
582 streamsize __n = 0; |
|
583 ios_base::iostate __status = 0; |
|
584 |
|
585 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
586 // The operations that can potentially throw are sbumpc, snextc, and sgetc. |
|
587 _STLP_TRY { |
|
588 for (;;) { |
|
589 int_type __c = __buf->sbumpc(); // sschwarz |
|
590 |
|
591 if (__that->_S_eof(__c)) { |
|
592 if (__n < _Num || __is_getline) |
|
593 __status |= ios_base::eofbit; |
|
594 break; |
|
595 } |
|
596 else if (__is_delim(_Traits::to_char_type(__c))) { |
|
597 if (__extract_delim) { // Extract and discard current character. |
|
598 ++__n; |
|
599 } else if ( !__pushback(__buf, _Traits::to_char_type(__c)) ) { // leave delimiter |
|
600 __status |= ios_base::failbit; |
|
601 } |
|
602 break; |
|
603 } |
|
604 else { // regular character |
|
605 *__s++ = _Traits::to_char_type(__c); |
|
606 ++__n; |
|
607 } |
|
608 |
|
609 if (__n == _Num) { |
|
610 if (__is_getline) // didn't find delimiter as one of the _Num chars |
|
611 __status |= ios_base::failbit; |
|
612 break; |
|
613 } |
|
614 } |
|
615 } |
|
616 _STLP_CATCH_ALL { |
|
617 __that->_M_handle_exception(ios_base::badbit); |
|
618 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
619 return __n; |
|
620 } |
|
621 |
|
622 if (__append_null) |
|
623 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
624 if (__status) |
|
625 __that->setstate(__status); // This might throw. |
|
626 return __n; |
|
627 } |
|
628 |
|
629 // Much like __read_unbuffered, but with one additional function object: |
|
630 // __scan_delim(first, last) returns the first pointer p in [first, last) |
|
631 // such that __is_delim(p) is true. |
|
632 |
|
633 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
634 streamsize _STLP_CALL |
|
635 __read_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, |
|
636 streamsize _Num, _CharT* __s, |
|
637 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
638 bool __extract_delim, bool __append_null, |
|
639 bool __is_getline) { |
|
640 streamsize __n = 0; |
|
641 ios_base::iostate __status = 0; |
|
642 bool __done = false; |
|
643 |
|
644 _STLP_TRY { |
|
645 while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { |
|
646 const _CharT* __first = __buf->_M_gptr(); |
|
647 const _CharT* __last = __buf->_M_egptr(); |
|
648 //casting numeric_limits<ptrdiff_t>::max to streamsize only works is ptrdiff_t is signed or streamsize representation |
|
649 //is larger than ptrdiff_t one. |
|
650 _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) || |
|
651 (sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits<ptrdiff_t>::is_signed) |
|
652 ptrdiff_t __request = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits<ptrdiff_t>::max)()), _Num - __n)); |
|
653 |
|
654 const _CharT* __p = __scan_delim(__first, __last); |
|
655 ptrdiff_t __chunk = (min) (ptrdiff_t(__p - __first), __request); |
|
656 _Traits::copy(__s, __first, __chunk); |
|
657 __s += __chunk; |
|
658 __n += __chunk; |
|
659 __buf->_M_gbump((int)__chunk); |
|
660 |
|
661 // We terminated by finding delim. |
|
662 if (__p != __last && __p - __first <= __request) { |
|
663 if (__extract_delim) { |
|
664 __n += 1; |
|
665 __buf->_M_gbump(1); |
|
666 } |
|
667 __done = true; |
|
668 } |
|
669 |
|
670 // We terminated by reading all the characters we were asked for. |
|
671 else if (__n == _Num) { |
|
672 |
|
673 // Find out if we have reached eof. This matters for getline. |
|
674 if (__is_getline) { |
|
675 if (__chunk == __last - __first) { |
|
676 if (__that->_S_eof(__buf->sgetc())) |
|
677 __status |= ios_base::eofbit; |
|
678 } |
|
679 else |
|
680 __status |= ios_base::failbit; |
|
681 } |
|
682 __done = true; |
|
683 } |
|
684 |
|
685 // The buffer contained fewer than _Num - __n characters. Either we're |
|
686 // at eof, or we should refill the buffer and try again. |
|
687 else { |
|
688 if (__that->_S_eof(__buf->sgetc())) { |
|
689 __status |= ios_base::eofbit; |
|
690 __done = true; |
|
691 } |
|
692 } |
|
693 } // Close the while loop. |
|
694 } |
|
695 _STLP_CATCH_ALL { |
|
696 __that->_M_handle_exception(ios_base::badbit); |
|
697 __done = true; |
|
698 } |
|
699 |
|
700 if (__done) { |
|
701 if (__append_null) |
|
702 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
703 if (__status != 0) |
|
704 __that->setstate(__status); // This might throw. |
|
705 return __n; |
|
706 } |
|
707 |
|
708 // If execution has reached this point, then we have an empty buffer but |
|
709 // we have not reached eof. What that means is that the streambuf has |
|
710 // decided to switch from buffered to unbuffered input. We switch to |
|
711 // to __read_unbuffered. |
|
712 |
|
713 return __n + __read_unbuffered(__that, __buf, _Num - __n, __s, __is_delim, |
|
714 __extract_delim,__append_null,__is_getline); |
|
715 } |
|
716 |
|
717 _STLP_MOVE_TO_STD_NAMESPACE |
|
718 |
|
719 template <class _CharT, class _Traits> |
|
720 basic_istream<_CharT, _Traits>& |
|
721 basic_istream<_CharT, _Traits>::get(_CharT* __s, streamsize __n, |
|
722 _CharT __delim) { |
|
723 sentry __sentry(*this, _No_Skip_WS()); |
|
724 this->_M_gcount = 0; |
|
725 |
|
726 if (__sentry) { |
|
727 if (__n > 0) { |
|
728 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
729 |
|
730 if (__buf->egptr() != __buf->gptr()) |
|
731 this->_M_gcount = |
|
732 _STLP_PRIV __read_buffered(this, __buf, __n - 1, __s, |
|
733 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
734 _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), |
|
735 false, true, false); |
|
736 else |
|
737 this->_M_gcount = |
|
738 _STLP_PRIV __read_unbuffered(this, __buf, __n - 1, __s, |
|
739 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
740 false, true, false); |
|
741 } |
|
742 } |
|
743 |
|
744 if (this->_M_gcount == 0) |
|
745 this->setstate(ios_base::failbit); |
|
746 |
|
747 return *this; |
|
748 } |
|
749 |
|
750 // Getline is essentially identical to get, except that it extracts |
|
751 // the delimiter. |
|
752 template <class _CharT, class _Traits> |
|
753 basic_istream<_CharT, _Traits>& |
|
754 basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, |
|
755 _CharT __delim) { |
|
756 sentry __sentry(*this, _No_Skip_WS()); |
|
757 this->_M_gcount = 0; |
|
758 |
|
759 if (__sentry) { |
|
760 if (__n > 0) { |
|
761 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
762 this->_M_gcount = __buf->egptr() != __buf->gptr() |
|
763 ? _STLP_PRIV __read_buffered(this, __buf, __n - 1, __s, |
|
764 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
765 _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), |
|
766 true, true, true) |
|
767 : _STLP_PRIV __read_unbuffered(this, __buf, __n - 1, __s, |
|
768 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
769 true, true, true); |
|
770 } |
|
771 } |
|
772 |
|
773 if (this->_M_gcount == 0) |
|
774 this->setstate(ios_base::failbit); |
|
775 |
|
776 return *this; |
|
777 } |
|
778 |
|
779 // Read n characters. We don't look for any delimiter, and we don't |
|
780 // put in a terminating null character. |
|
781 template <class _CharT, class _Traits> |
|
782 basic_istream<_CharT, _Traits>& |
|
783 basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) { |
|
784 sentry __sentry(*this, _No_Skip_WS()); |
|
785 this->_M_gcount = 0; |
|
786 |
|
787 if (__sentry && !this->eof()) { |
|
788 basic_streambuf<_CharT, _Traits>*__buf = this->rdbuf(); |
|
789 if (__buf->gptr() != __buf->egptr()) |
|
790 _M_gcount |
|
791 = _STLP_PRIV __read_buffered(this, __buf, __n, __s, |
|
792 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
793 _STLP_PRIV _Project2nd<const _CharT*, const _CharT*>(), |
|
794 false, false, false); |
|
795 else |
|
796 _M_gcount |
|
797 = _STLP_PRIV __read_unbuffered(this, __buf, __n, __s, |
|
798 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
799 false, false, false); |
|
800 } |
|
801 else |
|
802 this->setstate(ios_base::failbit); |
|
803 |
|
804 if (this->eof()) |
|
805 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
806 |
|
807 return *this; |
|
808 } |
|
809 |
|
810 |
|
811 // Read n or fewer characters. We don't look for any delimiter, and |
|
812 // we don't put in a terminating null character. |
|
813 template <class _CharT, class _Traits> |
|
814 streamsize |
|
815 basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __nmax) { |
|
816 sentry __sentry(*this, _No_Skip_WS()); |
|
817 this->_M_gcount = 0; |
|
818 |
|
819 if (__sentry && !this->eof() && __nmax >= 0) { |
|
820 |
|
821 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
822 streamsize __avail = __buf->in_avail(); |
|
823 |
|
824 // fbp : isn't full-blown setstate required here ? |
|
825 if (__avail == -1) |
|
826 this->_M_setstate_nothrow(ios_base::eofbit); |
|
827 |
|
828 else if (__avail != 0) { |
|
829 |
|
830 if (__buf->gptr() != __buf->egptr()) |
|
831 _M_gcount |
|
832 = _STLP_PRIV __read_buffered(this, __buf, (min) (__avail, __nmax), __s, |
|
833 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
834 _STLP_PRIV _Project2nd<const _CharT*, const _CharT*>(), |
|
835 false, false, false); |
|
836 else |
|
837 _M_gcount |
|
838 = _STLP_PRIV __read_unbuffered(this, __buf, (min) (__avail, __nmax), __s, |
|
839 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
840 false, false, false); |
|
841 } |
|
842 } |
|
843 else { |
|
844 // fbp : changed so that failbit is set only there, to pass Dietmar's test |
|
845 if (this->eof()) |
|
846 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
847 else |
|
848 this->setstate(ios_base::failbit); |
|
849 } |
|
850 |
|
851 // if (this->eof()) |
|
852 // this->setstate(ios_base::eofbit | ios_base::failbit); |
|
853 |
|
854 return _M_gcount; |
|
855 } |
|
856 |
|
857 template <class _CharT, class _Traits> |
|
858 void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT* __s) { |
|
859 sentry __sentry(*this); // Skip whitespace. |
|
860 |
|
861 if (__sentry) { |
|
862 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
863 streamsize __nmax = this->width() > 0 |
|
864 ? this->width() - 1 |
|
865 : ((numeric_limits<streamsize>::max)() / sizeof(_CharT)) - 1; |
|
866 |
|
867 streamsize __n = __buf->gptr() != __buf->egptr() |
|
868 ? _STLP_PRIV __read_buffered(this, __buf, __nmax, __s, |
|
869 _STLP_PRIV _Is_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
870 _STLP_PRIV _Scan_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
871 false, true, false) |
|
872 : _STLP_PRIV __read_unbuffered(this, __buf, __nmax, __s, |
|
873 _STLP_PRIV _Is_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
874 false, true, false); |
|
875 if (__n == 0) |
|
876 this->setstate(ios_base::failbit); |
|
877 } |
|
878 this->width(0); |
|
879 } |
|
880 |
|
881 // A generic unbuffered function for ignoring characters. We stop |
|
882 // when we reach EOF, or when the function object __is_delim returns |
|
883 // true. In the last case, it extracts the character for which |
|
884 // __is_delim is true, if and only if __extract_delim is true. |
|
885 |
|
886 template < class _CharT, class _Traits, class _Is_Delim> |
|
887 void _STLP_CALL |
|
888 _M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, |
|
889 basic_streambuf<_CharT, _Traits>* __buf, |
|
890 _Is_Delim __is_delim, |
|
891 bool __extract_delim, bool __set_failbit) { |
|
892 bool __done = false; |
|
893 ios_base::iostate __status = 0; |
|
894 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
895 |
|
896 _STLP_TRY { |
|
897 while (!__done) { |
|
898 int_type __c = __buf->sbumpc(); |
|
899 |
|
900 if (__that->_S_eof(__c)) { |
|
901 __done = true; |
|
902 __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit |
|
903 : ios_base::eofbit; |
|
904 } |
|
905 |
|
906 else if (__is_delim(_Traits::to_char_type(__c))) { |
|
907 __done = true; |
|
908 if (!__extract_delim) |
|
909 if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) |
|
910 __status |= ios_base::failbit; |
|
911 } |
|
912 } |
|
913 } |
|
914 _STLP_CATCH_ALL { |
|
915 __that->_M_handle_exception(ios_base::badbit); |
|
916 } |
|
917 |
|
918 __that->setstate(__status); |
|
919 } |
|
920 |
|
921 // A generic buffered function for ignoring characters. Much like |
|
922 // _M_ignore_unbuffered, but with one additional function object: |
|
923 // __scan_delim(first, last) returns the first pointer p in [first, |
|
924 // last) such that __is_delim(p) is true. |
|
925 |
|
926 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
927 void _STLP_CALL |
|
928 _M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, |
|
929 basic_streambuf<_CharT, _Traits>* __buf, |
|
930 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
931 bool __extract_delim, bool __set_failbit) { |
|
932 bool __at_eof = false; |
|
933 bool __found_delim = false; |
|
934 |
|
935 _STLP_TRY { |
|
936 while (__buf->_M_egptr() != __buf->_M_gptr() && !__at_eof && !__found_delim) { |
|
937 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); |
|
938 __buf->_M_gbump((int)(__p - __buf->_M_gptr())); |
|
939 |
|
940 if (__p != __buf->_M_egptr()) { // We found delim, so we're done. |
|
941 if (__extract_delim) |
|
942 __buf->_M_gbump(1); |
|
943 __found_delim = true; |
|
944 } |
|
945 |
|
946 else // No delim. Try to refil the buffer. |
|
947 __at_eof = __that->_S_eof(__buf->sgetc()); |
|
948 } // Close the while loop. |
|
949 } |
|
950 _STLP_CATCH_ALL { |
|
951 __that->_M_handle_exception(ios_base::badbit); |
|
952 return; |
|
953 } |
|
954 |
|
955 if (__at_eof) { |
|
956 __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit |
|
957 : ios_base::eofbit); |
|
958 return; |
|
959 } |
|
960 if (__found_delim) |
|
961 return; |
|
962 |
|
963 // If execution has reached this point, then we have an empty buffer but |
|
964 // we have not reached eof. What that means is that the streambuf has |
|
965 // decided to switch from a buffered to an unbuffered mode. We switch |
|
966 // to _M_ignore_unbuffered. |
|
967 _M_ignore_unbuffered(__that, __buf, __is_delim, __extract_delim, __set_failbit); |
|
968 } |
|
969 |
|
970 // Overloaded versions of _M_ignore_unbuffered and _M_ignore_unbuffered |
|
971 // with an explicit count _Num. Return value is the number of |
|
972 // characters extracted. |
|
973 // |
|
974 // The function object __max_chars takes two arguments, _Num and __n |
|
975 // (the latter being the number of characters we have already read), |
|
976 // and returns the maximum number of characters to read from the buffer. |
|
977 // We parameterize _M_ignore_buffered so that we can use it for both |
|
978 // bounded and unbounded input; for the former the function object should |
|
979 // be minus<>, and for the latter it should return a constant maximum value. |
|
980 |
|
981 template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim> |
|
982 streamsize _STLP_CALL |
|
983 _M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, |
|
984 basic_streambuf<_CharT, _Traits>* __buf, |
|
985 streamsize _Num, _Max_Chars __max_chars, |
|
986 _Is_Delim __is_delim, |
|
987 bool __extract_delim, bool __set_failbit) { |
|
988 streamsize __n = 0; |
|
989 ios_base::iostate __status = 0; |
|
990 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
991 |
|
992 _STLP_TRY { |
|
993 while (__max_chars(_Num, __n) > 0) { |
|
994 int_type __c = __buf->sbumpc(); |
|
995 |
|
996 if (__that->_S_eof(__c)) { |
|
997 __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit |
|
998 : ios_base::eofbit; |
|
999 break; |
|
1000 } |
|
1001 |
|
1002 else if (__is_delim(_Traits::to_char_type(__c))) { |
|
1003 if (__extract_delim) |
|
1004 ++__n; |
|
1005 else if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) |
|
1006 __status |= ios_base::failbit; |
|
1007 |
|
1008 break; |
|
1009 } |
|
1010 // fbp : added counter increment to pass Dietmar's test |
|
1011 ++__n; |
|
1012 } |
|
1013 } |
|
1014 _STLP_CATCH_ALL { |
|
1015 __that->_M_handle_exception(ios_base::badbit); |
|
1016 } |
|
1017 |
|
1018 if (__status) |
|
1019 __that->setstate(__status); // This might throw. |
|
1020 return __n; |
|
1021 } |
|
1022 |
|
1023 template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim, class _Scan_Delim> |
|
1024 streamsize _STLP_CALL |
|
1025 _M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, |
|
1026 basic_streambuf<_CharT, _Traits>* __buf, |
|
1027 streamsize _Num, |
|
1028 _Max_Chars __max_chars, |
|
1029 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
1030 bool __extract_delim, bool __set_failbit) { |
|
1031 streamsize __n = 0; |
|
1032 bool __at_eof = false; |
|
1033 bool __done = false; |
|
1034 |
|
1035 _STLP_TRY { |
|
1036 while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { |
|
1037 ptrdiff_t __avail = __buf->_M_egptr() - __buf->_M_gptr(); |
|
1038 streamsize __m = __max_chars(_Num, __n); |
|
1039 |
|
1040 if (__avail >= __m) { // We have more characters than we need. |
|
1041 const _CharT* __last = __buf->_M_gptr() + __STATIC_CAST(ptrdiff_t, __m); |
|
1042 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __last); |
|
1043 ptrdiff_t __chunk = __p - __buf->_M_gptr(); |
|
1044 __n += __chunk; |
|
1045 __buf->_M_gbump((int)__chunk); |
|
1046 |
|
1047 if (__extract_delim && __p != __last) { |
|
1048 __n += 1; |
|
1049 __buf->_M_gbump(1); |
|
1050 } |
|
1051 |
|
1052 __done = true; |
|
1053 } |
|
1054 |
|
1055 else { |
|
1056 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); |
|
1057 ptrdiff_t __chunk = __p - __buf->_M_gptr(); |
|
1058 __n += __chunk; |
|
1059 __buf->_M_gbump((int)__chunk); |
|
1060 |
|
1061 if (__p != __buf->_M_egptr()) { // We found delim. |
|
1062 if (__extract_delim) { |
|
1063 __n += 1; |
|
1064 __buf->_M_gbump(1); |
|
1065 } |
|
1066 |
|
1067 __done = true; |
|
1068 } |
|
1069 |
|
1070 // We didn't find delim. Try to refill the buffer. |
|
1071 else if (__that->_S_eof(__buf->sgetc())) { |
|
1072 __done = true; |
|
1073 __at_eof = true; |
|
1074 } |
|
1075 } |
|
1076 } // Close the while loop. |
|
1077 } |
|
1078 _STLP_CATCH_ALL { |
|
1079 __that->_M_handle_exception(ios_base::badbit); |
|
1080 return __n; |
|
1081 } |
|
1082 |
|
1083 if (__at_eof) |
|
1084 __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit |
|
1085 : ios_base::eofbit); |
|
1086 |
|
1087 if (__done) |
|
1088 return __n; |
|
1089 |
|
1090 // If execution has reached this point, then we have an empty buffer but |
|
1091 // we have not reached eof. What that means is that the streambuf has |
|
1092 // decided to switch from buffered to unbuffered input. We switch to |
|
1093 // to _M_ignore_unbuffered. |
|
1094 |
|
1095 return __n + _M_ignore_unbuffered(__that, __buf, _Num, __max_chars, |
|
1096 __is_delim, __extract_delim, __set_failbit); |
|
1097 } |
|
1098 |
|
1099 |
|
1100 template <class _CharT, class _Traits> |
|
1101 basic_istream<_CharT, _Traits>& |
|
1102 basic_istream<_CharT, _Traits>::ignore(streamsize __n) { |
|
1103 sentry __sentry(*this, _No_Skip_WS()); |
|
1104 this->_M_gcount = 0; |
|
1105 |
|
1106 if (__sentry) { |
|
1107 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1108 typedef _STLP_PRIV _Constant_unary_fun<bool, int_type> _Const_bool; |
|
1109 typedef _STLP_PRIV _Constant_binary_fun<streamsize, streamsize, streamsize> _Const_streamsize; |
|
1110 const streamsize __maxss = (numeric_limits<streamsize>::max)(); |
|
1111 |
|
1112 if (__n == (numeric_limits<int>::max)()) { |
|
1113 if (__buf->gptr() != __buf->egptr()) |
|
1114 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1115 __maxss, _Const_streamsize(__maxss), |
|
1116 _Const_bool(false), |
|
1117 _STLP_PRIV _Project2nd<const _CharT*, const _CharT*>(), |
|
1118 false, false); |
|
1119 else |
|
1120 _M_gcount = _M_ignore_unbuffered(this, __buf, |
|
1121 __maxss, _Const_streamsize(__maxss), |
|
1122 _Const_bool(false), false, false); |
|
1123 } |
|
1124 else { |
|
1125 if (__buf->gptr() != __buf->egptr()) |
|
1126 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1127 __n, minus<streamsize>(), |
|
1128 _Const_bool(false), |
|
1129 _STLP_PRIV _Project2nd<const _CharT*, const _CharT*>(), |
|
1130 false, false); |
|
1131 else |
|
1132 _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus<streamsize>(), |
|
1133 _Const_bool(false), false, false); |
|
1134 } |
|
1135 } |
|
1136 |
|
1137 return *this; |
|
1138 } |
|
1139 |
|
1140 template <class _CharT, class _Traits> |
|
1141 basic_istream<_CharT, _Traits>& |
|
1142 basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __delim) { |
|
1143 sentry __sentry(*this, _No_Skip_WS()); |
|
1144 this->_M_gcount = 0; |
|
1145 |
|
1146 if (__sentry) { |
|
1147 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1148 typedef _STLP_PRIV _Constant_unary_fun<bool, int_type> _Const_bool; |
|
1149 typedef _STLP_PRIV _Constant_binary_fun<streamsize, streamsize, streamsize> |
|
1150 _Const_streamsize; |
|
1151 const streamsize __maxss = (numeric_limits<streamsize>::max)(); |
|
1152 |
|
1153 if (__n == (numeric_limits<int>::max)()) { |
|
1154 if (__buf->gptr() != __buf->egptr()) |
|
1155 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1156 __maxss, _Const_streamsize(__maxss), |
|
1157 _STLP_PRIV _Eq_int_bound<_Traits>(__delim), |
|
1158 _STLP_PRIV _Scan_for_int_val<_Traits>(__delim), |
|
1159 true, false); |
|
1160 else |
|
1161 _M_gcount = _M_ignore_unbuffered(this, __buf, |
|
1162 __maxss, _Const_streamsize(__maxss), |
|
1163 _STLP_PRIV _Eq_int_bound<_Traits>(__delim), |
|
1164 true, false); |
|
1165 } |
|
1166 else { |
|
1167 if (__buf->gptr() != __buf->egptr()) |
|
1168 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1169 __n, minus<streamsize>(), |
|
1170 _STLP_PRIV _Eq_int_bound<_Traits>(__delim), |
|
1171 _STLP_PRIV _Scan_for_int_val<_Traits>(__delim), |
|
1172 true, false); |
|
1173 else |
|
1174 _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus<streamsize>(), |
|
1175 _STLP_PRIV _Eq_int_bound<_Traits>(__delim), |
|
1176 true, false); |
|
1177 } |
|
1178 } |
|
1179 |
|
1180 return *this; |
|
1181 } |
|
1182 |
|
1183 // This member function does not construct a sentry object, because |
|
1184 // it is called from sentry's constructor. |
|
1185 template <class _CharT, class _Traits> |
|
1186 void basic_istream<_CharT, _Traits>::_M_skip_whitespace(bool __set_failbit) { |
|
1187 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1188 if (!__buf) |
|
1189 this->setstate(ios_base::badbit); |
|
1190 else if (__buf->gptr() != __buf->egptr()) |
|
1191 _M_ignore_buffered(this, __buf, |
|
1192 _STLP_PRIV _Is_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
1193 _STLP_PRIV _Scan_for_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
1194 false, __set_failbit); |
|
1195 else |
|
1196 _M_ignore_unbuffered(this, __buf, |
|
1197 _STLP_PRIV _Is_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), |
|
1198 false, __set_failbit); |
|
1199 } |
|
1200 |
|
1201 |
|
1202 // This is a very simple loop that reads characters from __src and puts |
|
1203 // them into __dest. It looks complicated because of the (standard- |
|
1204 // mandated) exception handling policy. |
|
1205 // |
|
1206 // We stop when we get an exception, when we fail to insert into the |
|
1207 // output streambuf, or when __is_delim is true. |
|
1208 |
|
1209 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
1210 |
|
1211 template < class _CharT, class _Traits, class _Is_Delim> |
|
1212 streamsize _STLP_CALL |
|
1213 __copy_unbuffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, |
|
1214 basic_streambuf<_CharT, _Traits>* __dest, |
|
1215 _Is_Delim __is_delim, |
|
1216 bool __extract_delim, bool __rethrow) { |
|
1217 streamsize __extracted = 0; |
|
1218 ios_base::iostate __status = 0; |
|
1219 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
1220 int_type __c; |
|
1221 |
|
1222 _STLP_TRY { |
|
1223 for (;;) { |
|
1224 // Get a character. If there's an exception, catch and (maybe) rethrow it. |
|
1225 __c = __src->sbumpc(); |
|
1226 |
|
1227 // If we failed to get a character, then quit. |
|
1228 if (__that->_S_eof(__c)) { |
|
1229 __status |= ios_base::eofbit; |
|
1230 break; |
|
1231 } |
|
1232 // If it's the delimiter, then quit. |
|
1233 else if (__is_delim(_Traits::to_char_type(__c))) { |
|
1234 if (!__extract_delim && !__pushback(__src, _Traits::to_char_type(__c))) |
|
1235 __status |= ios_base::failbit; |
|
1236 break; |
|
1237 } |
|
1238 else { |
|
1239 // Try to put the character in the output streambuf. |
|
1240 bool __failed = false; |
|
1241 _STLP_TRY { |
|
1242 if (!__that->_S_eof(__dest->sputc(_Traits::to_char_type(__c)))) |
|
1243 ++__extracted; |
|
1244 else |
|
1245 __failed = true; |
|
1246 } |
|
1247 _STLP_CATCH_ALL { |
|
1248 __failed = true; |
|
1249 } |
|
1250 |
|
1251 // If we failed to put the character in the output streambuf, then |
|
1252 // try to push it back to the input streambuf. |
|
1253 if (__failed && !__pushback(__src, _Traits::to_char_type(__c))) |
|
1254 __status |= ios_base::failbit; |
|
1255 |
|
1256 // fbp : avoiding infinite loop in io-27-6-1-2-3.exp |
|
1257 if (__failed) |
|
1258 break; |
|
1259 } |
|
1260 |
|
1261 } /* for (;;) */ |
|
1262 |
|
1263 } |
|
1264 // fbp : this try/catch moved here in reasonable assumption |
|
1265 // __is_delim never throw (__pushback is guaranteed not to) |
|
1266 _STLP_CATCH_ALL { |
|
1267 // See 27.6.1.2.3, paragraph 13. |
|
1268 if (__rethrow && __extracted == 0) |
|
1269 __that->_M_handle_exception(ios_base::failbit); |
|
1270 } |
|
1271 __that->setstate(__status); |
|
1272 return __extracted; |
|
1273 } |
|
1274 |
|
1275 // Buffered copying from one streambuf to another. We copy the characters |
|
1276 // in chunks, rather than one at a time. We still have to worry about all |
|
1277 // of the error conditions we checked in __copy_unbuffered, plus one more: |
|
1278 // the streambuf might decide to switch from a buffered to an unbuffered mode. |
|
1279 |
|
1280 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
1281 streamsize _STLP_CALL |
|
1282 __copy_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, |
|
1283 basic_streambuf<_CharT, _Traits>* __dest, |
|
1284 _Scan_Delim __scan_delim, _Is_Delim __is_delim, |
|
1285 bool __extract_delim, bool __rethrow) { |
|
1286 streamsize __extracted = 0; |
|
1287 ios_base::iostate __status = 0; |
|
1288 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
1289 //Borland compiler generates a warning if assignment because value is never used: |
|
1290 int_type __c /*= _Traits::eof()*/; |
|
1291 _CharT* __first = __src->_M_gptr(); |
|
1292 ptrdiff_t __avail = __src->_M_egptr() - __first; |
|
1293 // fbp : introduced to move catch/try blocks out of the loop |
|
1294 bool __do_handle_exceptions = false; |
|
1295 |
|
1296 _STLP_TRY { |
|
1297 for (;;) { |
|
1298 const _CharT* __last = __scan_delim(__first, __src->_M_egptr()); |
|
1299 |
|
1300 // Try to copy the entire input buffer to the output buffer. |
|
1301 streamsize __n = __dest->sputn(__first, __extract_delim && __last != __src->_M_egptr() |
|
1302 ? (__last - __first) + 1 |
|
1303 : (__last - __first)); |
|
1304 __src->_M_gbump((int)__n); |
|
1305 __extracted += __n; |
|
1306 |
|
1307 // from this on, catch() will call _M_handle_exceptions() |
|
1308 __do_handle_exceptions = true; |
|
1309 |
|
1310 if (__n < __avail) // We found the delimiter, or else failed to |
|
1311 break; // copy some characters. |
|
1312 |
|
1313 __c = __src->sgetc(); |
|
1314 |
|
1315 // Three possibilities: we succeeded in refilling the buffer, or |
|
1316 // we got EOF, or the streambuf has switched to unbuffered mode. |
|
1317 __first = __src->_M_gptr(); |
|
1318 __avail = __src->_M_egptr() - __first; |
|
1319 |
|
1320 if (__avail > 0) |
|
1321 {} // dwa 1/16/00 -- suppress a Metrowerks warning |
|
1322 else if (__that->_S_eof(__c)) { |
|
1323 __status |= ios_base::eofbit; |
|
1324 break; |
|
1325 } |
|
1326 else { |
|
1327 return __extracted + __copy_unbuffered(__that, __src, __dest, __is_delim, |
|
1328 __extract_delim, __rethrow); |
|
1329 } |
|
1330 |
|
1331 __do_handle_exceptions = false; |
|
1332 } |
|
1333 } |
|
1334 |
|
1335 _STLP_CATCH_ALL { |
|
1336 // See 27.6.1.2.3, paragraph 13. |
|
1337 if (__rethrow && __do_handle_exceptions && __extracted == 0) |
|
1338 __that->_M_handle_exception(ios_base::failbit); |
|
1339 } |
|
1340 |
|
1341 if (__status) |
|
1342 __that->setstate(__status); // This might throw. |
|
1343 return __extracted; |
|
1344 } |
|
1345 |
|
1346 _STLP_MOVE_TO_STD_NAMESPACE |
|
1347 |
|
1348 template <class _CharT, class _Traits> |
|
1349 basic_istream<_CharT, _Traits>& |
|
1350 basic_istream<_CharT, _Traits> |
|
1351 ::get(basic_streambuf<_CharT, _Traits>& __dest, _CharT __delim) { |
|
1352 sentry __sentry(*this, _No_Skip_WS()); |
|
1353 this->_M_gcount = 0; |
|
1354 |
|
1355 if (__sentry) { |
|
1356 basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); |
|
1357 |
|
1358 if (__src) |
|
1359 this->_M_gcount = __src->egptr() != __src->gptr() |
|
1360 ? _STLP_PRIV __copy_buffered(this, __src, &__dest, |
|
1361 _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), |
|
1362 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
1363 false, false) |
|
1364 : _STLP_PRIV __copy_unbuffered(this, __src, &__dest, |
|
1365 _STLP_PRIV _Eq_char_bound<_Traits>(__delim), |
|
1366 false, false); |
|
1367 } |
|
1368 |
|
1369 if (this->_M_gcount == 0) |
|
1370 this->setstate(ios_base::failbit); |
|
1371 |
|
1372 return *this; |
|
1373 } |
|
1374 |
|
1375 // Copying characters into a streambuf. |
|
1376 template <class _CharT, class _Traits> |
|
1377 basic_istream<_CharT, _Traits>& |
|
1378 basic_istream<_CharT, _Traits> |
|
1379 ::operator>>(basic_streambuf<_CharT, _Traits>* __dest) { |
|
1380 streamsize __n = 0; |
|
1381 typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; |
|
1382 _Sentry __sentry(*this); |
|
1383 if (__sentry) { |
|
1384 basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); |
|
1385 if (__src && __dest) |
|
1386 __n = __src->egptr() != __src->gptr() |
|
1387 ? _STLP_PRIV __copy_buffered(this, __src, __dest, |
|
1388 _STLP_PRIV _Project2nd<const _CharT*, const _CharT*>(), |
|
1389 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
1390 false, true) |
|
1391 : _STLP_PRIV __copy_unbuffered(this, __src, __dest, |
|
1392 _STLP_PRIV _Constant_unary_fun<bool, int_type>(false), |
|
1393 false, true); |
|
1394 } |
|
1395 |
|
1396 if (__n == 0) |
|
1397 this->setstate(ios_base::failbit); |
|
1398 |
|
1399 return *this; |
|
1400 } |
|
1401 |
|
1402 // ---------------------------------------------------------------- |
|
1403 // basic_iostream<> class |
|
1404 // ---------------------------------------------------------------- |
|
1405 |
|
1406 |
|
1407 template <class _CharT, class _Traits> |
|
1408 basic_iostream<_CharT, _Traits> |
|
1409 ::basic_iostream(basic_streambuf<_CharT, _Traits>* __buf) |
|
1410 : basic_ios<_CharT, _Traits>(), |
|
1411 basic_istream<_CharT, _Traits>(__buf), |
|
1412 basic_ostream<_CharT, _Traits>(__buf) { |
|
1413 this->init(__buf); |
|
1414 } |
|
1415 |
|
1416 |
|
1417 _STLP_END_NAMESPACE |
|
1418 |
|
1419 #undef __BIS_int_type__ |
|
1420 #undef __BIS_pos_type__ |
|
1421 #undef __BIS_off_type__ |
|
1422 |
|
1423 #endif /* _STLP_ISTREAM_C */ |
|
1424 |
|
1425 // Local Variables: |
|
1426 // mode:C++ |
|
1427 // End: |