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
51template <class _Traits>
52struct _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
63template <class _Traits>
64struct _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
77template <class _Traits>
78struct _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
93template <class _Traits>
94struct _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
111template <class _Traits>
112struct _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
127template <class _Traits>
128struct _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
144template <class _Traits>
145struct _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
166template <class _CharT, class _Traits>
167bool _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.
184template <class _CharT, class _Traits, class _Number>
185ios_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      // 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
208template <class _CharT, class _Traits>
209basic_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
233template <class _CharT, class _Traits>
234basic_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
258template <class _CharT, class _Traits>
259basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned short& __val) {
260  _STLP_PRIV __get_num(*this, __val);
261  return *this;
262}
263
264template <class _CharT, class _Traits>
265basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned int& __val) {
266  _STLP_PRIV __get_num(*this, __val);
267  return *this;
268}
269
270template <class _CharT, class _Traits>
271basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (long& __val) {
272  _STLP_PRIV __get_num(*this, __val);
273  return *this;
274}
275
276template <class _CharT, class _Traits>
277basic_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)
283template <class _CharT, class _Traits>
284basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (_STLP_LONG_LONG& __val) {
285  _STLP_PRIV __get_num(*this, __val);
286  return *this;
287}
288
289template <class _CharT, class _Traits>
290basic_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
295template <class _CharT, class _Traits>
296basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (float& __val) {
297  _STLP_PRIV __get_num(*this, __val);
298  return *this;
299}
300template <class _CharT, class _Traits>
301basic_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)
306template <class _CharT, class _Traits>
307basic_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)
313template <class _CharT, class _Traits>
314basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (bool& __val) {
315  _STLP_PRIV __get_num(*this, __val);
316  return *this;
317}
318#endif
319
320template <class _CharT, class _Traits>
321basic_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
328template <class _CharT, class _Traits>
329__BIS_int_type__
330basic_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
351template <class _CharT, class _Traits>
352__BIS_int_type__
353basic_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
376template <class _CharT, class _Traits>
377basic_istream<_CharT, _Traits>&
378basic_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.
408template <class _CharT, class _Traits>
409basic_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
434template <class _CharT, class _Traits>
435basic_istream<_CharT, _Traits>&
436basic_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
461template <class _CharT, class _Traits>
462basic_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
489template <class _CharT, class _Traits>
490int 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
506template <class _CharT, class _Traits>
507__BIS_pos_type__
508basic_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
516template <class _CharT, class _Traits>
517basic_istream<_CharT, _Traits>&
518basic_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
530template <class _CharT, class _Traits>
531basic_istream<_CharT, _Traits>&
532basic_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
543template <class _CharT, class _Traits>
544void 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
591template < class _CharT, class _Traits, class _Is_Delim>
592streamsize _STLP_CALL
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
647template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim>
648streamsize _STLP_CALL
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
733template <class _CharT, class _Traits>
734basic_istream<_CharT, _Traits>&
735basic_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.
766template <class _CharT, class _Traits>
767basic_istream<_CharT, _Traits>&
768basic_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.
795template <class _CharT, class _Traits>
796basic_istream<_CharT, _Traits>&
797basic_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.
827template <class _CharT, class _Traits>
828streamsize
829basic_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
871template <class _CharT, class _Traits>
872void 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
900template < class _CharT, class _Traits, class _Is_Delim>
901void _STLP_CALL
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
940template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim>
941void _STLP_CALL
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
995template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim>
996streamsize _STLP_CALL
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
1037template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim, class _Scan_Delim>
1038streamsize _STLP_CALL
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
1114template <class _CharT, class _Traits>
1115basic_istream<_CharT, _Traits>&
1116basic_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
1154template <class _CharT, class _Traits>
1155basic_istream<_CharT, _Traits>&
1156basic_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.
1198template <class _CharT, class _Traits>
1199void 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
1224template < class _CharT, class _Traits, class _Is_Delim>
1225streamsize _STLP_CALL
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
1293template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim>
1294streamsize _STLP_CALL
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
1361template <class _CharT, class _Traits>
1362basic_istream<_CharT, _Traits>&
1363basic_istream<_CharT, _Traits>
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.
1389template <class _CharT, class _Traits>
1390basic_istream<_CharT, _Traits>&
1391basic_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
1419template <class _CharT, class _Traits>
1420basic_iostream<_CharT, _Traits>
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
1428template <class _CharT, class _Traits>
1429basic_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