Import of virgin gcc 4.0.0 distribution.
[dragonfly.git] / contrib / gcc-4.0 / libstdc++-v3 / src / istream.cc
1 // Input streams -*- C++ -*-
2
3 // Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 //
31 // ISO C++ 14882: 27.6.1  Input streams
32 //
33
34 #include <istream>
35
36 namespace std
37 {
38   template<>
39     basic_istream<char>&
40     basic_istream<char>::
41     getline(char_type* __s, streamsize __n, char_type __delim)
42     {
43       _M_gcount = 0;
44       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
45       sentry __cerb(*this, true);
46       if (__cerb)
47         {
48           try
49             {
50               const int_type __idelim = traits_type::to_int_type(__delim);
51               const int_type __eof = traits_type::eof();
52               __streambuf_type* __sb = this->rdbuf();
53               int_type __c = __sb->sgetc();
54               
55               while (_M_gcount + 1 < __n
56                      && !traits_type::eq_int_type(__c, __eof)
57                      && !traits_type::eq_int_type(__c, __idelim))
58                 {
59                   streamsize __size = std::min(streamsize(__sb->egptr()
60                                                           - __sb->gptr()),
61                                                streamsize(__n - _M_gcount
62                                                           - 1));
63                   if (__size > 1)
64                     {
65                       const char_type* __p = traits_type::find(__sb->gptr(),
66                                                                __size,
67                                                                __delim);
68                       if (__p)
69                         __size = __p - __sb->gptr();
70                       traits_type::copy(__s, __sb->gptr(), __size);
71                       __s += __size;
72                       __sb->gbump(__size);
73                       _M_gcount += __size;
74                       __c = __sb->sgetc();
75                     }
76                   else
77                     {
78                       *__s++ = traits_type::to_char_type(__c);
79                       ++_M_gcount;
80                       __c = __sb->snextc();
81                     }
82                 }
83
84               if (traits_type::eq_int_type(__c, __eof))
85                 __err |= ios_base::eofbit;
86               else if (traits_type::eq_int_type(__c, __idelim))
87                 {
88                   ++_M_gcount;            
89                   __sb->sbumpc();
90                 }
91               else
92                 __err |= ios_base::failbit;
93             }
94           catch(...)
95             { this->_M_setstate(ios_base::badbit); }
96         }
97       // _GLIBCXX_RESOLVE_LIB_DEFECTS
98       // 243. get and getline when sentry reports failure.
99       if (__n > 0)
100         *__s = char_type();
101       if (!_M_gcount)
102         __err |= ios_base::failbit;
103       if (__err)
104         this->setstate(__err);
105       return *this;
106     }
107
108   template<>
109     basic_istream<char>&
110     basic_istream<char>::
111     ignore(streamsize __n)
112     {
113       if (__n == 1)
114         return ignore();
115       
116       _M_gcount = 0;
117       sentry __cerb(*this, true);
118       if (__cerb && __n > 0)
119         {
120           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
121           try
122             {
123               const int_type __eof = traits_type::eof();
124               __streambuf_type* __sb = this->rdbuf();
125               int_type __c = __sb->sgetc();
126
127               // See comment in istream.tcc.
128               bool __large_ignore = false;
129               while (true)
130                 {
131                   while (_M_gcount < __n
132                          && !traits_type::eq_int_type(__c, __eof))
133                     {
134                       streamsize __size = std::min(streamsize(__sb->egptr()
135                                                               - __sb->gptr()),
136                                                    streamsize(__n - _M_gcount));
137                       if (__size > 1)
138                         {
139                           __sb->gbump(__size);
140                           _M_gcount += __size;
141                           __c = __sb->sgetc();
142                         }
143                       else
144                         {
145                           ++_M_gcount;
146                           __c = __sb->snextc();
147                         } 
148                     }
149                   if (__n == numeric_limits<streamsize>::max()
150                       && !traits_type::eq_int_type(__c, __eof))
151                     {
152                       _M_gcount = numeric_limits<streamsize>::min();
153                       __large_ignore = true;
154                     }
155                   else
156                     break;
157                 }
158
159               if (__large_ignore)
160                 _M_gcount = numeric_limits<streamsize>::max();
161
162               if (traits_type::eq_int_type(__c, __eof))
163                 __err |= ios_base::eofbit;
164             }
165           catch(...)
166             { this->_M_setstate(ios_base::badbit); }
167           if (__err)
168             this->setstate(__err);
169         }
170       return *this;
171     }
172
173   template<>
174     basic_istream<char>&
175     basic_istream<char>::
176     ignore(streamsize __n, int_type __delim)
177     {
178       if (traits_type::eq_int_type(__delim, traits_type::eof()))
179         return ignore(__n);
180
181       _M_gcount = 0;
182       sentry __cerb(*this, true);
183       if (__cerb && __n > 0)
184         {
185           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
186           try
187             {
188               const char_type __cdelim = traits_type::to_char_type(__delim);          
189               const int_type __eof = traits_type::eof();
190               __streambuf_type* __sb = this->rdbuf();
191               int_type __c = __sb->sgetc();
192
193               bool __large_ignore = false;
194               while (true)
195                 {
196                   while (_M_gcount < __n
197                          && !traits_type::eq_int_type(__c, __eof)
198                          && !traits_type::eq_int_type(__c, __delim))
199                     {
200                       streamsize __size = std::min(streamsize(__sb->egptr()
201                                                               - __sb->gptr()),
202                                                    streamsize(__n - _M_gcount));
203                       if (__size > 1)
204                         {
205                           const char_type* __p = traits_type::find(__sb->gptr(),
206                                                                    __size,
207                                                                    __cdelim);
208                           if (__p)
209                             __size = __p - __sb->gptr();
210                           __sb->gbump(__size);
211                           _M_gcount += __size;
212                           __c = __sb->sgetc();
213                         }
214                       else
215                         {
216                           ++_M_gcount;
217                           __c = __sb->snextc();
218                         }
219                     }
220                   if (__n == numeric_limits<streamsize>::max()
221                       && !traits_type::eq_int_type(__c, __eof)
222                       && !traits_type::eq_int_type(__c, __delim))
223                     {
224                       _M_gcount = numeric_limits<streamsize>::min();
225                       __large_ignore = true;
226                     }
227                   else
228                     break;
229                 }
230
231               if (__large_ignore)
232                 _M_gcount = numeric_limits<streamsize>::max();
233
234               if (traits_type::eq_int_type(__c, __eof))
235                 __err |= ios_base::eofbit;
236               else if (traits_type::eq_int_type(__c, __delim))
237                 {
238                   if (_M_gcount < numeric_limits<streamsize>::max())
239                     ++_M_gcount;
240                   __sb->sbumpc();
241                 }
242             }
243           catch(...)
244             { this->_M_setstate(ios_base::badbit); }
245           if (__err)
246             this->setstate(__err);
247         }
248       return *this;
249     }
250
251   template<>
252     basic_istream<char>&
253     getline(basic_istream<char>& __in, basic_string<char>& __str,
254             char __delim)
255     {
256       typedef basic_istream<char>               __istream_type;
257       typedef __istream_type::int_type          __int_type;
258       typedef __istream_type::char_type         __char_type;
259       typedef __istream_type::traits_type       __traits_type;
260       typedef __istream_type::__streambuf_type  __streambuf_type;
261       typedef __istream_type::__ctype_type      __ctype_type;
262       typedef basic_string<char>                __string_type;
263       typedef __string_type::size_type          __size_type;
264
265       __size_type __extracted = 0;
266       const __size_type __n = __str.max_size();
267       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
268       __istream_type::sentry __cerb(__in, true);
269       if (__cerb)
270         {
271           try
272             {
273               __str.erase();
274               const __int_type __idelim = __traits_type::to_int_type(__delim);
275               const __int_type __eof = __traits_type::eof();
276               __streambuf_type* __sb = __in.rdbuf();
277               __int_type __c = __sb->sgetc();
278
279               while (__extracted < __n
280                      && !__traits_type::eq_int_type(__c, __eof)
281                      && !__traits_type::eq_int_type(__c, __idelim))
282                 {
283                   streamsize __size = std::min(streamsize(__sb->egptr()
284                                                           - __sb->gptr()),
285                                                streamsize(__n - __extracted));
286                   if (__size > 1)
287                     {
288                       const __char_type* __p = __traits_type::find(__sb->gptr(),
289                                                                    __size,
290                                                                    __delim);
291                       if (__p)
292                         __size = __p - __sb->gptr();
293                       __str.append(__sb->gptr(), __size);
294                       __sb->gbump(__size);
295                       __extracted += __size;
296                       __c = __sb->sgetc();
297                     }
298                   else
299                     {
300                       __str += __traits_type::to_char_type(__c);
301                       ++__extracted;
302                       __c = __sb->snextc();
303                     }             
304                 }
305
306               if (__traits_type::eq_int_type(__c, __eof))
307                 __err |= ios_base::eofbit;
308               else if (__traits_type::eq_int_type(__c, __idelim))
309                 {
310                   ++__extracted;
311                   __sb->sbumpc();
312                 }
313               else
314                 __err |= ios_base::failbit;
315             }
316           catch(...)
317             {
318               // _GLIBCXX_RESOLVE_LIB_DEFECTS
319               // 91. Description of operator>> and getline() for string<>
320               // might cause endless loop
321               __in._M_setstate(ios_base::badbit);
322             }
323         }
324       if (!__extracted)
325         __err |= ios_base::failbit;
326       if (__err)
327         __in.setstate(__err);
328       return __in;
329     }
330
331 #ifdef _GLIBCXX_USE_WCHAR_T
332   template<>
333     basic_istream<wchar_t>&
334     basic_istream<wchar_t>::
335     getline(char_type* __s, streamsize __n, char_type __delim)
336     {
337       _M_gcount = 0;
338       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
339       sentry __cerb(*this, true);
340       if (__cerb)
341         {
342           try
343             {
344               const int_type __idelim = traits_type::to_int_type(__delim);
345               const int_type __eof = traits_type::eof();
346               __streambuf_type* __sb = this->rdbuf();
347               int_type __c = __sb->sgetc();
348               
349               while (_M_gcount + 1 < __n
350                      && !traits_type::eq_int_type(__c, __eof)
351                      && !traits_type::eq_int_type(__c, __idelim))
352                 {
353                   streamsize __size = std::min(streamsize(__sb->egptr()
354                                                           - __sb->gptr()),
355                                                streamsize(__n - _M_gcount
356                                                           - 1));
357                   if (__size > 1)
358                     {
359                       const char_type* __p = traits_type::find(__sb->gptr(),
360                                                                __size,
361                                                                __delim);
362                       if (__p)
363                         __size = __p - __sb->gptr();
364                       traits_type::copy(__s, __sb->gptr(), __size);
365                       __s += __size;
366                       __sb->gbump(__size);
367                       _M_gcount += __size;
368                       __c = __sb->sgetc();
369                     }
370                   else
371                     {
372                       *__s++ = traits_type::to_char_type(__c);
373                       ++_M_gcount;
374                       __c = __sb->snextc();
375                     }
376                 }
377
378               if (traits_type::eq_int_type(__c, __eof))
379                 __err |= ios_base::eofbit;
380               else if (traits_type::eq_int_type(__c, __idelim))
381                 {
382                   ++_M_gcount;            
383                   __sb->sbumpc();
384                 }
385               else
386                 __err |= ios_base::failbit;
387             }
388           catch(...)
389             { this->_M_setstate(ios_base::badbit); }
390         }
391       // _GLIBCXX_RESOLVE_LIB_DEFECTS
392       // 243. get and getline when sentry reports failure.
393       if (__n > 0)
394         *__s = char_type();
395       if (!_M_gcount)
396         __err |= ios_base::failbit;
397       if (__err)
398         this->setstate(__err);
399       return *this;
400     }
401
402   template<>
403     basic_istream<wchar_t>&
404     basic_istream<wchar_t>::
405     ignore(streamsize __n)
406     {
407       if (__n == 1)
408         return ignore();
409       
410       _M_gcount = 0;
411       sentry __cerb(*this, true);
412       if (__cerb && __n > 0)
413         {
414           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
415           try
416             {
417               const int_type __eof = traits_type::eof();
418               __streambuf_type* __sb = this->rdbuf();
419               int_type __c = __sb->sgetc();
420
421               bool __large_ignore = false;
422               while (true)
423                 {
424                   while (_M_gcount < __n
425                          && !traits_type::eq_int_type(__c, __eof))
426                     {
427                       streamsize __size = std::min(streamsize(__sb->egptr()
428                                                               - __sb->gptr()),
429                                                    streamsize(__n - _M_gcount));
430                       if (__size > 1)
431                         {
432                           __sb->gbump(__size);
433                           _M_gcount += __size;
434                           __c = __sb->sgetc();
435                         }
436                       else
437                         {
438                           ++_M_gcount;
439                           __c = __sb->snextc();
440                         }
441                     }
442                   if (__n == numeric_limits<streamsize>::max()
443                       && !traits_type::eq_int_type(__c, __eof))
444                     {
445                       _M_gcount = numeric_limits<streamsize>::min();
446                       __large_ignore = true;
447                     }
448                   else
449                     break;
450                 }
451
452               if (__large_ignore)
453                 _M_gcount = numeric_limits<streamsize>::max();
454
455               if (traits_type::eq_int_type(__c, __eof))
456                 __err |= ios_base::eofbit;
457             }
458           catch(...)
459             { this->_M_setstate(ios_base::badbit); }
460           if (__err)
461             this->setstate(__err);
462         }
463       return *this;
464     }
465
466   template<>
467     basic_istream<wchar_t>&
468     basic_istream<wchar_t>::
469     ignore(streamsize __n, int_type __delim)
470     {
471       if (traits_type::eq_int_type(__delim, traits_type::eof()))
472         return ignore(__n);
473
474       _M_gcount = 0;
475       sentry __cerb(*this, true);
476       if (__cerb && __n > 0)
477         {
478           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
479           try
480             {
481               const char_type __cdelim = traits_type::to_char_type(__delim);          
482               const int_type __eof = traits_type::eof();
483               __streambuf_type* __sb = this->rdbuf();
484               int_type __c = __sb->sgetc();
485
486               bool __large_ignore = false;
487               while (true)
488                 {
489                   while (_M_gcount < __n
490                          && !traits_type::eq_int_type(__c, __eof)
491                          && !traits_type::eq_int_type(__c, __delim))
492                     {
493                       streamsize __size = std::min(streamsize(__sb->egptr()
494                                                               - __sb->gptr()),
495                                                    streamsize(__n - _M_gcount));
496                       if (__size > 1)
497                         {
498                           const char_type* __p = traits_type::find(__sb->gptr(),
499                                                                    __size,
500                                                                    __cdelim);
501                           if (__p)
502                             __size = __p - __sb->gptr();
503                           __sb->gbump(__size);
504                           _M_gcount += __size;
505                           __c = __sb->sgetc();
506                         }
507                       else
508                         {
509                           ++_M_gcount;
510                           __c = __sb->snextc();
511                         }
512                     }
513                   if (__n == numeric_limits<streamsize>::max()
514                       && !traits_type::eq_int_type(__c, __eof)
515                       && !traits_type::eq_int_type(__c, __delim))
516                     {
517                       _M_gcount = numeric_limits<streamsize>::min();
518                       __large_ignore = true;
519                     }
520                   else
521                     break;
522                 }
523
524               if (__large_ignore)
525                 _M_gcount = numeric_limits<streamsize>::max();
526
527               if (traits_type::eq_int_type(__c, __eof))
528                 __err |= ios_base::eofbit;
529               else if (traits_type::eq_int_type(__c, __delim))
530                 {
531                   if (_M_gcount < numeric_limits<streamsize>::max())
532                     ++_M_gcount;
533                   __sb->sbumpc();
534                 }
535             }
536           catch(...)
537             { this->_M_setstate(ios_base::badbit); }
538           if (__err)
539             this->setstate(__err);
540         }
541       return *this;
542     }
543
544   template<>
545     basic_istream<wchar_t>&
546     getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
547             wchar_t __delim)
548     {
549       typedef basic_istream<wchar_t>            __istream_type;
550       typedef __istream_type::int_type          __int_type;
551       typedef __istream_type::char_type         __char_type;
552       typedef __istream_type::traits_type       __traits_type;
553       typedef __istream_type::__streambuf_type  __streambuf_type;
554       typedef __istream_type::__ctype_type      __ctype_type;
555       typedef basic_string<wchar_t>             __string_type;
556       typedef __string_type::size_type          __size_type;
557
558       __size_type __extracted = 0;
559       const __size_type __n = __str.max_size();
560       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
561       __istream_type::sentry __cerb(__in, true);
562       if (__cerb)
563         {
564           try
565             {
566               __str.erase();
567               const __int_type __idelim = __traits_type::to_int_type(__delim);
568               const __int_type __eof = __traits_type::eof();
569               __streambuf_type* __sb = __in.rdbuf();
570               __int_type __c = __sb->sgetc();
571
572               while (__extracted < __n
573                      && !__traits_type::eq_int_type(__c, __eof)
574                      && !__traits_type::eq_int_type(__c, __idelim))
575                 {
576                   streamsize __size = std::min(streamsize(__sb->egptr()
577                                                           - __sb->gptr()),
578                                                streamsize(__n - __extracted));
579                   if (__size > 1)
580                     {
581                       const __char_type* __p = __traits_type::find(__sb->gptr(),
582                                                                    __size,
583                                                                    __delim);
584                       if (__p)
585                         __size = __p - __sb->gptr();
586                       __str.append(__sb->gptr(), __size);
587                       __sb->gbump(__size);
588                       __extracted += __size;
589                       __c = __sb->sgetc();
590                     }
591                   else
592                     {
593                       __str += __traits_type::to_char_type(__c);
594                       ++__extracted;
595                       __c = __sb->snextc();
596                     }             
597                 }
598
599               if (__traits_type::eq_int_type(__c, __eof))
600                 __err |= ios_base::eofbit;
601               else if (__traits_type::eq_int_type(__c, __idelim))
602                 {
603                   ++__extracted;
604                   __sb->sbumpc();
605                 }
606               else
607                 __err |= ios_base::failbit;
608             }
609           catch(...)
610             {
611               // _GLIBCXX_RESOLVE_LIB_DEFECTS
612               // 91. Description of operator>> and getline() for string<>
613               // might cause endless loop
614               __in._M_setstate(ios_base::badbit);
615             }
616         }
617       if (!__extracted)
618         __err |= ios_base::failbit;
619       if (__err)
620         __in.setstate(__err);
621       return __in;
622     }
623 #endif
624 } // namespace std