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