xref: /openbsd/gnu/gcc/libstdc++-v3/src/istream.cc (revision 898184e3)
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 _GLIBCXX_BEGIN_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, int_type __delim)
112     {
113       if (traits_type::eq_int_type(__delim, traits_type::eof()))
114 	return ignore(__n);
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 char_type __cdelim = traits_type::to_char_type(__delim);
124 	      const int_type __eof = traits_type::eof();
125 	      __streambuf_type* __sb = this->rdbuf();
126 	      int_type __c = __sb->sgetc();
127 
128 	      bool __large_ignore = false;
129 	      while (true)
130 		{
131 		  while (_M_gcount < __n
132 			 && !traits_type::eq_int_type(__c, __eof)
133 			 && !traits_type::eq_int_type(__c, __delim))
134 		    {
135 		      streamsize __size = std::min(streamsize(__sb->egptr()
136 							      - __sb->gptr()),
137 						   streamsize(__n - _M_gcount));
138 		      if (__size > 1)
139 			{
140 			  const char_type* __p = traits_type::find(__sb->gptr(),
141 								   __size,
142 								   __cdelim);
143 			  if (__p)
144 			    __size = __p - __sb->gptr();
145 			  __sb->gbump(__size);
146 			  _M_gcount += __size;
147 			  __c = __sb->sgetc();
148 			}
149 		      else
150 			{
151 			  ++_M_gcount;
152 			  __c = __sb->snextc();
153 			}
154 		    }
155 		  if (__n == numeric_limits<streamsize>::max()
156 		      && !traits_type::eq_int_type(__c, __eof)
157 		      && !traits_type::eq_int_type(__c, __delim))
158 		    {
159 		      _M_gcount = numeric_limits<streamsize>::min();
160 		      __large_ignore = true;
161 		    }
162 		  else
163 		    break;
164 		}
165 
166 	      if (__large_ignore)
167 		_M_gcount = numeric_limits<streamsize>::max();
168 
169 	      if (traits_type::eq_int_type(__c, __eof))
170 		__err |= ios_base::eofbit;
171 	      else if (traits_type::eq_int_type(__c, __delim))
172 		{
173 		  if (_M_gcount < numeric_limits<streamsize>::max())
174 		    ++_M_gcount;
175 		  __sb->sbumpc();
176 		}
177 	    }
178 	  catch(...)
179 	    { this->_M_setstate(ios_base::badbit); }
180 	  if (__err)
181 	    this->setstate(__err);
182 	}
183       return *this;
184     }
185 
186   template<>
187     basic_istream<char>&
188     operator>>(basic_istream<char>& __in, char* __s)
189     {
190       typedef basic_istream<char>       	__istream_type;
191       typedef __istream_type::int_type		__int_type;
192       typedef __istream_type::char_type		__char_type;
193       typedef __istream_type::traits_type	__traits_type;
194       typedef __istream_type::__streambuf_type  __streambuf_type;
195       typedef __istream_type::__ctype_type	__ctype_type;
196 
197       streamsize __extracted = 0;
198       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
199       __istream_type::sentry __cerb(__in, false);
200       if (__cerb)
201 	{
202 	  try
203 	    {
204 	      // Figure out how many characters to extract.
205 	      streamsize __num = __in.width();
206 	      if (__num <= 0)
207 		__num = numeric_limits<streamsize>::max();
208 
209 	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
210 
211 	      const __int_type __eof = __traits_type::eof();
212 	      __streambuf_type* __sb = __in.rdbuf();
213 	      __int_type __c = __sb->sgetc();
214 
215 	      while (__extracted < __num - 1
216 		     && !__traits_type::eq_int_type(__c, __eof)
217 		     && !__ct.is(ctype_base::space,
218 				 __traits_type::to_char_type(__c)))
219 		{
220 		  streamsize __size = std::min(streamsize(__sb->egptr()
221 							  - __sb->gptr()),
222 					       streamsize(__num - __extracted
223 							  - 1));
224 		  if (__size > 1)
225 		    {
226 		      __size = (__ct.scan_is(ctype_base::space,
227 					     __sb->gptr() + 1,
228 					     __sb->gptr() + __size)
229 				- __sb->gptr());
230 		      __traits_type::copy(__s, __sb->gptr(), __size);
231 		      __s += __size;
232 		      __sb->gbump(__size);
233 		      __extracted += __size;
234 		      __c = __sb->sgetc();
235 		    }
236 		  else
237 		    {
238 		      *__s++ = __traits_type::to_char_type(__c);
239 		      ++__extracted;
240 		      __c = __sb->snextc();
241 		    }
242 		}
243 
244 	      if (__traits_type::eq_int_type(__c, __eof))
245 		__err |= ios_base::eofbit;
246 
247 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
248 	      // 68.  Extractors for char* should store null at end
249 	      *__s = __char_type();
250 	      __in.width(0);
251 	    }
252 	  catch(...)
253 	    { __in._M_setstate(ios_base::badbit); }
254 	}
255       if (!__extracted)
256 	__err |= ios_base::failbit;
257       if (__err)
258 	__in.setstate(__err);
259       return __in;
260     }
261 
262   template<>
263     basic_istream<char>&
264     operator>>(basic_istream<char>& __in, basic_string<char>& __str)
265     {
266       typedef basic_istream<char>       	__istream_type;
267       typedef __istream_type::int_type		__int_type;
268       typedef __istream_type::char_type		__char_type;
269       typedef __istream_type::traits_type	__traits_type;
270       typedef __istream_type::__streambuf_type  __streambuf_type;
271       typedef __istream_type::__ctype_type	__ctype_type;
272       typedef basic_string<char>        	__string_type;
273       typedef __string_type::size_type		__size_type;
274 
275       __size_type __extracted = 0;
276       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
277       __istream_type::sentry __cerb(__in, false);
278       if (__cerb)
279 	{
280 	  try
281 	    {
282 	      __str.erase();
283 	      const streamsize __w = __in.width();
284 	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
285 		                              : __str.max_size();
286 	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
287 	      const __int_type __eof = __traits_type::eof();
288 	      __streambuf_type* __sb = __in.rdbuf();
289 	      __int_type __c = __sb->sgetc();
290 
291 	      while (__extracted < __n
292 		     && !__traits_type::eq_int_type(__c, __eof)
293 		     && !__ct.is(ctype_base::space,
294 				 __traits_type::to_char_type(__c)))
295 		{
296 		  streamsize __size = std::min(streamsize(__sb->egptr()
297 							  - __sb->gptr()),
298 					       streamsize(__n - __extracted));
299 		  if (__size > 1)
300 		    {
301 		      __size = (__ct.scan_is(ctype_base::space,
302 					     __sb->gptr() + 1,
303 					     __sb->gptr() + __size)
304 				- __sb->gptr());
305 		      __str.append(__sb->gptr(), __size);
306 		      __sb->gbump(__size);
307 		      __extracted += __size;
308 		      __c = __sb->sgetc();
309 		    }
310 		  else
311 		    {
312 		      __str += __traits_type::to_char_type(__c);
313 		      ++__extracted;
314 		      __c = __sb->snextc();
315 		    }
316 		}
317 
318 	      if (__traits_type::eq_int_type(__c, __eof))
319 		__err |= ios_base::eofbit;
320 	      __in.width(0);
321 	    }
322 	  catch(...)
323 	    {
324 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
325 	      // 91. Description of operator>> and getline() for string<>
326 	      // might cause endless loop
327 	      __in._M_setstate(ios_base::badbit);
328 	    }
329 	}
330       if (!__extracted)
331 	__err |= ios_base::failbit;
332       if (__err)
333 	__in.setstate(__err);
334       return __in;
335     }
336 
337   template<>
338     basic_istream<char>&
339     getline(basic_istream<char>& __in, basic_string<char>& __str,
340 	    char __delim)
341     {
342       typedef basic_istream<char>       	__istream_type;
343       typedef __istream_type::int_type		__int_type;
344       typedef __istream_type::char_type		__char_type;
345       typedef __istream_type::traits_type	__traits_type;
346       typedef __istream_type::__streambuf_type  __streambuf_type;
347       typedef __istream_type::__ctype_type	__ctype_type;
348       typedef basic_string<char>        	__string_type;
349       typedef __string_type::size_type		__size_type;
350 
351       __size_type __extracted = 0;
352       const __size_type __n = __str.max_size();
353       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
354       __istream_type::sentry __cerb(__in, true);
355       if (__cerb)
356 	{
357 	  try
358 	    {
359 	      __str.erase();
360 	      const __int_type __idelim = __traits_type::to_int_type(__delim);
361 	      const __int_type __eof = __traits_type::eof();
362 	      __streambuf_type* __sb = __in.rdbuf();
363 	      __int_type __c = __sb->sgetc();
364 
365 	      while (__extracted < __n
366 		     && !__traits_type::eq_int_type(__c, __eof)
367 		     && !__traits_type::eq_int_type(__c, __idelim))
368 		{
369 		  streamsize __size = std::min(streamsize(__sb->egptr()
370 							  - __sb->gptr()),
371 					       streamsize(__n - __extracted));
372 		  if (__size > 1)
373 		    {
374 		      const __char_type* __p = __traits_type::find(__sb->gptr(),
375 								   __size,
376 								   __delim);
377 		      if (__p)
378 			__size = __p - __sb->gptr();
379 		      __str.append(__sb->gptr(), __size);
380 		      __sb->gbump(__size);
381 		      __extracted += __size;
382 		      __c = __sb->sgetc();
383 		    }
384 		  else
385 		    {
386 		      __str += __traits_type::to_char_type(__c);
387 		      ++__extracted;
388 		      __c = __sb->snextc();
389 		    }
390 		}
391 
392 	      if (__traits_type::eq_int_type(__c, __eof))
393 		__err |= ios_base::eofbit;
394 	      else if (__traits_type::eq_int_type(__c, __idelim))
395 		{
396 		  ++__extracted;
397 		  __sb->sbumpc();
398 		}
399 	      else
400 		__err |= ios_base::failbit;
401 	    }
402 	  catch(...)
403 	    {
404 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
405 	      // 91. Description of operator>> and getline() for string<>
406 	      // might cause endless loop
407 	      __in._M_setstate(ios_base::badbit);
408 	    }
409 	}
410       if (!__extracted)
411 	__err |= ios_base::failbit;
412       if (__err)
413 	__in.setstate(__err);
414       return __in;
415     }
416 
417 #ifdef _GLIBCXX_USE_WCHAR_T
418   template<>
419     basic_istream<wchar_t>&
420     basic_istream<wchar_t>::
421     getline(char_type* __s, streamsize __n, char_type __delim)
422     {
423       _M_gcount = 0;
424       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
425       sentry __cerb(*this, true);
426       if (__cerb)
427 	{
428           try
429 	    {
430 	      const int_type __idelim = traits_type::to_int_type(__delim);
431 	      const int_type __eof = traits_type::eof();
432 	      __streambuf_type* __sb = this->rdbuf();
433 	      int_type __c = __sb->sgetc();
434 
435 	      while (_M_gcount + 1 < __n
436 		     && !traits_type::eq_int_type(__c, __eof)
437 		     && !traits_type::eq_int_type(__c, __idelim))
438 		{
439 		  streamsize __size = std::min(streamsize(__sb->egptr()
440 							  - __sb->gptr()),
441 					       streamsize(__n - _M_gcount
442 							  - 1));
443 		  if (__size > 1)
444 		    {
445 		      const char_type* __p = traits_type::find(__sb->gptr(),
446 							       __size,
447 							       __delim);
448 		      if (__p)
449 			__size = __p - __sb->gptr();
450 		      traits_type::copy(__s, __sb->gptr(), __size);
451 		      __s += __size;
452 		      __sb->gbump(__size);
453 		      _M_gcount += __size;
454 		      __c = __sb->sgetc();
455 		    }
456 		  else
457 		    {
458 		      *__s++ = traits_type::to_char_type(__c);
459 		      ++_M_gcount;
460 		      __c = __sb->snextc();
461 		    }
462 		}
463 
464 	      if (traits_type::eq_int_type(__c, __eof))
465 		__err |= ios_base::eofbit;
466 	      else if (traits_type::eq_int_type(__c, __idelim))
467 		{
468 		  ++_M_gcount;
469 		  __sb->sbumpc();
470 		}
471 	      else
472 		__err |= ios_base::failbit;
473 	    }
474 	  catch(...)
475 	    { this->_M_setstate(ios_base::badbit); }
476 	}
477       // _GLIBCXX_RESOLVE_LIB_DEFECTS
478       // 243. get and getline when sentry reports failure.
479       if (__n > 0)
480 	*__s = char_type();
481       if (!_M_gcount)
482 	__err |= ios_base::failbit;
483       if (__err)
484 	this->setstate(__err);
485       return *this;
486     }
487 
488   template<>
489     basic_istream<wchar_t>&
490     basic_istream<wchar_t>::
491     ignore(streamsize __n, int_type __delim)
492     {
493       if (traits_type::eq_int_type(__delim, traits_type::eof()))
494 	return ignore(__n);
495 
496       _M_gcount = 0;
497       sentry __cerb(*this, true);
498       if (__cerb && __n > 0)
499 	{
500 	  ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
501 	  try
502 	    {
503 	      const char_type __cdelim = traits_type::to_char_type(__delim);
504 	      const int_type __eof = traits_type::eof();
505 	      __streambuf_type* __sb = this->rdbuf();
506 	      int_type __c = __sb->sgetc();
507 
508 	      bool __large_ignore = false;
509 	      while (true)
510 		{
511 		  while (_M_gcount < __n
512 			 && !traits_type::eq_int_type(__c, __eof)
513 			 && !traits_type::eq_int_type(__c, __delim))
514 		    {
515 		      streamsize __size = std::min(streamsize(__sb->egptr()
516 							      - __sb->gptr()),
517 						   streamsize(__n - _M_gcount));
518 		      if (__size > 1)
519 			{
520 			  const char_type* __p = traits_type::find(__sb->gptr(),
521 								   __size,
522 								   __cdelim);
523 			  if (__p)
524 			    __size = __p - __sb->gptr();
525 			  __sb->gbump(__size);
526 			  _M_gcount += __size;
527 			  __c = __sb->sgetc();
528 			}
529 		      else
530 			{
531 			  ++_M_gcount;
532 			  __c = __sb->snextc();
533 			}
534 		    }
535 		  if (__n == numeric_limits<streamsize>::max()
536 		      && !traits_type::eq_int_type(__c, __eof)
537 		      && !traits_type::eq_int_type(__c, __delim))
538 		    {
539 		      _M_gcount = numeric_limits<streamsize>::min();
540 		      __large_ignore = true;
541 		    }
542 		  else
543 		    break;
544 		}
545 
546 	      if (__large_ignore)
547 		_M_gcount = numeric_limits<streamsize>::max();
548 
549 	      if (traits_type::eq_int_type(__c, __eof))
550 		__err |= ios_base::eofbit;
551 	      else if (traits_type::eq_int_type(__c, __delim))
552 		{
553 		  if (_M_gcount < numeric_limits<streamsize>::max())
554 		    ++_M_gcount;
555 		  __sb->sbumpc();
556 		}
557 	    }
558 	  catch(...)
559 	    { this->_M_setstate(ios_base::badbit); }
560 	  if (__err)
561 	    this->setstate(__err);
562 	}
563       return *this;
564     }
565 
566   template<>
567     basic_istream<wchar_t>&
568     getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
569 	    wchar_t __delim)
570     {
571       typedef basic_istream<wchar_t>       	__istream_type;
572       typedef __istream_type::int_type		__int_type;
573       typedef __istream_type::char_type		__char_type;
574       typedef __istream_type::traits_type	__traits_type;
575       typedef __istream_type::__streambuf_type  __streambuf_type;
576       typedef __istream_type::__ctype_type	__ctype_type;
577       typedef basic_string<wchar_t>        	__string_type;
578       typedef __string_type::size_type		__size_type;
579 
580       __size_type __extracted = 0;
581       const __size_type __n = __str.max_size();
582       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
583       __istream_type::sentry __cerb(__in, true);
584       if (__cerb)
585 	{
586 	  try
587 	    {
588 	      __str.erase();
589 	      const __int_type __idelim = __traits_type::to_int_type(__delim);
590 	      const __int_type __eof = __traits_type::eof();
591 	      __streambuf_type* __sb = __in.rdbuf();
592 	      __int_type __c = __sb->sgetc();
593 
594 	      while (__extracted < __n
595 		     && !__traits_type::eq_int_type(__c, __eof)
596 		     && !__traits_type::eq_int_type(__c, __idelim))
597 		{
598 		  streamsize __size = std::min(streamsize(__sb->egptr()
599 							  - __sb->gptr()),
600 					       streamsize(__n - __extracted));
601 		  if (__size > 1)
602 		    {
603 		      const __char_type* __p = __traits_type::find(__sb->gptr(),
604 								   __size,
605 								   __delim);
606 		      if (__p)
607 			__size = __p - __sb->gptr();
608 		      __str.append(__sb->gptr(), __size);
609 		      __sb->gbump(__size);
610 		      __extracted += __size;
611 		      __c = __sb->sgetc();
612 		    }
613 		  else
614 		    {
615 		      __str += __traits_type::to_char_type(__c);
616 		      ++__extracted;
617 		      __c = __sb->snextc();
618 		    }
619 		}
620 
621 	      if (__traits_type::eq_int_type(__c, __eof))
622 		__err |= ios_base::eofbit;
623 	      else if (__traits_type::eq_int_type(__c, __idelim))
624 		{
625 		  ++__extracted;
626 		  __sb->sbumpc();
627 		}
628 	      else
629 		__err |= ios_base::failbit;
630 	    }
631 	  catch(...)
632 	    {
633 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
634 	      // 91. Description of operator>> and getline() for string<>
635 	      // might cause endless loop
636 	      __in._M_setstate(ios_base::badbit);
637 	    }
638 	}
639       if (!__extracted)
640 	__err |= ios_base::failbit;
641       if (__err)
642 	__in.setstate(__err);
643       return __in;
644     }
645 #endif
646 
647 _GLIBCXX_END_NAMESPACE
648