OSDN Git Service

2004-11-26 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / istream.cc
1 // Input streams -*- C++ -*-
2
3 // Copyright (C) 2004 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               const bool __bound = __n != numeric_limits<streamsize>::max();
128               if (__bound)
129                 --__n;
130               while (_M_gcount <= __n
131                      && !traits_type::eq_int_type(__c, __eof))
132                 {
133                   streamsize __size = __sb->egptr() - __sb->gptr();
134                   if (__bound)
135                     __size = std::min(__size, streamsize(__n - _M_gcount + 1));
136
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 (traits_type::eq_int_type(__c, __eof))
150                 __err |= ios_base::eofbit;
151             }
152           catch(...)
153             { this->_M_setstate(ios_base::badbit); }
154           if (__err)
155             this->setstate(__err);
156         }
157       return *this;
158     }
159
160   template<>
161     basic_istream<char>&
162     basic_istream<char>::
163     ignore(streamsize __n, int_type __delim)
164     {
165       if (traits_type::eq_int_type(__delim, traits_type::eof()))
166         return ignore(__n);
167
168       _M_gcount = 0;
169       sentry __cerb(*this, true);
170       if (__cerb && __n > 0)
171         {
172           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
173           try
174             {
175               const char_type __cdelim = traits_type::to_char_type(__delim);          
176               const int_type __eof = traits_type::eof();
177               __streambuf_type* __sb = this->rdbuf();
178               int_type __c = __sb->sgetc();
179
180               const bool __bound = __n != numeric_limits<streamsize>::max();
181               if (__bound)
182                 --__n;
183               while (_M_gcount <= __n
184                      && !traits_type::eq_int_type(__c, __eof)
185                      && !traits_type::eq_int_type(__c, __delim))
186                 {
187                   streamsize __size = __sb->egptr() - __sb->gptr();
188                   if (__bound)
189                     __size = std::min(__size, streamsize(__n - _M_gcount + 1));
190
191                   if (__size > 1)
192                     {
193                       const char_type* __p = traits_type::find(__sb->gptr(),
194                                                                __size,
195                                                                __cdelim);
196                       if (__p)
197                         __size = __p - __sb->gptr();
198                       __sb->gbump(__size);
199                       _M_gcount += __size;
200                       __c = __sb->sgetc();
201                     }
202                   else
203                     {
204                       ++_M_gcount;
205                       __c = __sb->snextc();
206                     }             
207                 }
208               if (traits_type::eq_int_type(__c, __eof))
209                 __err |= ios_base::eofbit;
210               else if (traits_type::eq_int_type(__c, __delim))
211                 {
212                   ++_M_gcount;
213                   __sb->sbumpc();
214                 }
215             }
216           catch(...)
217             { this->_M_setstate(ios_base::badbit); }
218           if (__err)
219             this->setstate(__err);
220         }
221       return *this;
222     }
223
224   template<>
225     basic_istream<char>&
226     getline(basic_istream<char>& __in, basic_string<char>& __str,
227             char __delim)
228     {
229       typedef basic_istream<char>               __istream_type;
230       typedef __istream_type::int_type          __int_type;
231       typedef __istream_type::char_type         __char_type;
232       typedef __istream_type::traits_type       __traits_type;
233       typedef __istream_type::__streambuf_type  __streambuf_type;
234       typedef __istream_type::__ctype_type      __ctype_type;
235       typedef basic_string<char>                __string_type;
236       typedef __string_type::size_type          __size_type;
237
238       __size_type __extracted = 0;
239       const __size_type __n = __str.max_size();
240       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
241       __istream_type::sentry __cerb(__in, true);
242       if (__cerb)
243         {
244           try
245             {
246               __str.erase();
247               const __int_type __idelim = __traits_type::to_int_type(__delim);
248               const __int_type __eof = __traits_type::eof();
249               __streambuf_type* __sb = __in.rdbuf();
250               __int_type __c = __sb->sgetc();
251
252               while (__extracted < __n
253                      && !__traits_type::eq_int_type(__c, __eof)
254                      && !__traits_type::eq_int_type(__c, __idelim))
255                 {
256                   streamsize __size = std::min(streamsize(__sb->egptr()
257                                                           - __sb->gptr()),
258                                                streamsize(__n - __extracted));
259                   if (__size > 1)
260                     {
261                       const __char_type* __p = __traits_type::find(__sb->gptr(),
262                                                                    __size,
263                                                                    __delim);
264                       if (__p)
265                         __size = __p - __sb->gptr();
266                       __str.append(__sb->gptr(), __size);
267                       __sb->gbump(__size);
268                       __extracted += __size;
269                       __c = __sb->sgetc();
270                     }
271                   else
272                     {
273                       __str += __traits_type::to_char_type(__c);
274                       ++__extracted;
275                       __c = __sb->snextc();
276                     }             
277                 }
278
279               if (__traits_type::eq_int_type(__c, __eof))
280                 __err |= ios_base::eofbit;
281               else if (__traits_type::eq_int_type(__c, __idelim))
282                 {
283                   ++__extracted;
284                   __sb->sbumpc();
285                 }
286               else
287                 __err |= ios_base::failbit;
288             }
289           catch(...)
290             {
291               // _GLIBCXX_RESOLVE_LIB_DEFECTS
292               // 91. Description of operator>> and getline() for string<>
293               // might cause endless loop
294               __in._M_setstate(ios_base::badbit);
295             }
296         }
297       if (!__extracted)
298         __err |= ios_base::failbit;
299       if (__err)
300         __in.setstate(__err);
301       return __in;
302     }
303
304 #ifdef _GLIBCXX_USE_WCHAR_T
305   template<>
306     basic_istream<wchar_t>&
307     basic_istream<wchar_t>::
308     getline(char_type* __s, streamsize __n, char_type __delim)
309     {
310       _M_gcount = 0;
311       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
312       sentry __cerb(*this, true);
313       if (__cerb)
314         {
315           try
316             {
317               const int_type __idelim = traits_type::to_int_type(__delim);
318               const int_type __eof = traits_type::eof();
319               __streambuf_type* __sb = this->rdbuf();
320               int_type __c = __sb->sgetc();
321               
322               while (_M_gcount + 1 < __n
323                      && !traits_type::eq_int_type(__c, __eof)
324                      && !traits_type::eq_int_type(__c, __idelim))
325                 {
326                   streamsize __size = std::min(streamsize(__sb->egptr()
327                                                           - __sb->gptr()),
328                                                streamsize(__n - _M_gcount
329                                                           - 1));
330                   if (__size > 1)
331                     {
332                       const char_type* __p = traits_type::find(__sb->gptr(),
333                                                                __size,
334                                                                __delim);
335                       if (__p)
336                         __size = __p - __sb->gptr();
337                       traits_type::copy(__s, __sb->gptr(), __size);
338                       __s += __size;
339                       __sb->gbump(__size);
340                       _M_gcount += __size;
341                       __c = __sb->sgetc();
342                     }
343                   else
344                     {
345                       *__s++ = traits_type::to_char_type(__c);
346                       ++_M_gcount;
347                       __c = __sb->snextc();
348                     }
349                 }
350
351               if (traits_type::eq_int_type(__c, __eof))
352                 __err |= ios_base::eofbit;
353               else if (traits_type::eq_int_type(__c, __idelim))
354                 {
355                   ++_M_gcount;            
356                   __sb->sbumpc();
357                 }
358               else
359                 __err |= ios_base::failbit;
360             }
361           catch(...)
362             { this->_M_setstate(ios_base::badbit); }
363         }
364       // _GLIBCXX_RESOLVE_LIB_DEFECTS
365       // 243. get and getline when sentry reports failure.
366       if (__n > 0)
367         *__s = char_type();
368       if (!_M_gcount)
369         __err |= ios_base::failbit;
370       if (__err)
371         this->setstate(__err);
372       return *this;
373     }
374
375   template<>
376     basic_istream<wchar_t>&
377     basic_istream<wchar_t>::
378     ignore(streamsize __n)
379     {
380       if (__n == 1)
381         return ignore();
382       
383       _M_gcount = 0;
384       sentry __cerb(*this, true);
385       if (__cerb && __n > 0)
386         {
387           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
388           try
389             {
390               const int_type __eof = traits_type::eof();
391               __streambuf_type* __sb = this->rdbuf();
392               int_type __c = __sb->sgetc();
393               
394               const bool __bound = __n != numeric_limits<streamsize>::max();
395               if (__bound)
396                 --__n;
397               while (_M_gcount <= __n
398                      && !traits_type::eq_int_type(__c, __eof))
399                 {
400                   streamsize __size = __sb->egptr() - __sb->gptr();
401                   if (__bound)
402                     __size = std::min(__size, streamsize(__n - _M_gcount + 1));
403
404                   if (__size > 1)
405                     {
406                       __sb->gbump(__size);
407                       _M_gcount += __size;
408                       __c = __sb->sgetc();
409                     }
410                   else
411                     {
412                       ++_M_gcount;
413                       __c = __sb->snextc();
414                     }             
415                 }
416               if (traits_type::eq_int_type(__c, __eof))
417                 __err |= ios_base::eofbit;
418             }
419           catch(...)
420             { this->_M_setstate(ios_base::badbit); }
421           if (__err)
422             this->setstate(__err);
423         }
424       return *this;
425     }
426
427   template<>
428     basic_istream<wchar_t>&
429     basic_istream<wchar_t>::
430     ignore(streamsize __n, int_type __delim)
431     {
432       if (traits_type::eq_int_type(__delim, traits_type::eof()))
433         return ignore(__n);
434
435       _M_gcount = 0;
436       sentry __cerb(*this, true);
437       if (__cerb && __n > 0)
438         {
439           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
440           try
441             {
442               const char_type __cdelim = traits_type::to_char_type(__delim);          
443               const int_type __eof = traits_type::eof();
444               __streambuf_type* __sb = this->rdbuf();
445               int_type __c = __sb->sgetc();
446
447               const bool __bound = __n != numeric_limits<streamsize>::max();
448               if (__bound)
449                 --__n;
450               while (_M_gcount <= __n
451                      && !traits_type::eq_int_type(__c, __eof)
452                      && !traits_type::eq_int_type(__c, __delim))
453                 {
454                   streamsize __size = __sb->egptr() - __sb->gptr();
455                   if (__bound)
456                     __size = std::min(__size, streamsize(__n - _M_gcount + 1));
457
458                   if (__size > 1)
459                     {
460                       const char_type* __p = traits_type::find(__sb->gptr(),
461                                                                __size,
462                                                                __cdelim);
463                       if (__p)
464                         __size = __p - __sb->gptr();
465                       __sb->gbump(__size);
466                       _M_gcount += __size;
467                       __c = __sb->sgetc();
468                     }
469                   else
470                     {
471                       ++_M_gcount;
472                       __c = __sb->snextc();
473                     }             
474                 }
475               if (traits_type::eq_int_type(__c, __eof))
476                 __err |= ios_base::eofbit;
477               else if (traits_type::eq_int_type(__c, __delim))
478                 {
479                   ++_M_gcount;
480                   __sb->sbumpc();
481                 }
482             }
483           catch(...)
484             { this->_M_setstate(ios_base::badbit); }
485           if (__err)
486             this->setstate(__err);
487         }
488       return *this;
489     }
490
491   template<>
492     basic_istream<wchar_t>&
493     getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
494             wchar_t __delim)
495     {
496       typedef basic_istream<wchar_t>            __istream_type;
497       typedef __istream_type::int_type          __int_type;
498       typedef __istream_type::char_type         __char_type;
499       typedef __istream_type::traits_type       __traits_type;
500       typedef __istream_type::__streambuf_type  __streambuf_type;
501       typedef __istream_type::__ctype_type      __ctype_type;
502       typedef basic_string<wchar_t>             __string_type;
503       typedef __string_type::size_type          __size_type;
504
505       __size_type __extracted = 0;
506       const __size_type __n = __str.max_size();
507       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
508       __istream_type::sentry __cerb(__in, true);
509       if (__cerb)
510         {
511           try
512             {
513               __str.erase();
514               const __int_type __idelim = __traits_type::to_int_type(__delim);
515               const __int_type __eof = __traits_type::eof();
516               __streambuf_type* __sb = __in.rdbuf();
517               __int_type __c = __sb->sgetc();
518
519               while (__extracted < __n
520                      && !__traits_type::eq_int_type(__c, __eof)
521                      && !__traits_type::eq_int_type(__c, __idelim))
522                 {
523                   streamsize __size = std::min(streamsize(__sb->egptr()
524                                                           - __sb->gptr()),
525                                                streamsize(__n - __extracted));
526                   if (__size > 1)
527                     {
528                       const __char_type* __p = __traits_type::find(__sb->gptr(),
529                                                                    __size,
530                                                                    __delim);
531                       if (__p)
532                         __size = __p - __sb->gptr();
533                       __str.append(__sb->gptr(), __size);
534                       __sb->gbump(__size);
535                       __extracted += __size;
536                       __c = __sb->sgetc();
537                     }
538                   else
539                     {
540                       __str += __traits_type::to_char_type(__c);
541                       ++__extracted;
542                       __c = __sb->snextc();
543                     }             
544                 }
545
546               if (__traits_type::eq_int_type(__c, __eof))
547                 __err |= ios_base::eofbit;
548               else if (__traits_type::eq_int_type(__c, __idelim))
549                 {
550                   ++__extracted;
551                   __sb->sbumpc();
552                 }
553               else
554                 __err |= ios_base::failbit;
555             }
556           catch(...)
557             {
558               // _GLIBCXX_RESOLVE_LIB_DEFECTS
559               // 91. Description of operator>> and getline() for string<>
560               // might cause endless loop
561               __in._M_setstate(ios_base::badbit);
562             }
563         }
564       if (!__extracted)
565         __err |= ios_base::failbit;
566       if (__err)
567         __in.setstate(__err);
568       return __in;
569     }
570 #endif
571 } // namespace std