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