OSDN Git Service

2005-06-17 Jakub Jelinek <jakub@redhat.com>
[pf3gnuchains/gcc-fork.git] / 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, 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     getline(basic_istream<char>& __in, basic_string<char>& __str,
189             char __delim)
190     {
191       typedef basic_istream<char>               __istream_type;
192       typedef __istream_type::int_type          __int_type;
193       typedef __istream_type::char_type         __char_type;
194       typedef __istream_type::traits_type       __traits_type;
195       typedef __istream_type::__streambuf_type  __streambuf_type;
196       typedef __istream_type::__ctype_type      __ctype_type;
197       typedef basic_string<char>                __string_type;
198       typedef __string_type::size_type          __size_type;
199
200       __size_type __extracted = 0;
201       const __size_type __n = __str.max_size();
202       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
203       __istream_type::sentry __cerb(__in, true);
204       if (__cerb)
205         {
206           try
207             {
208               __str.erase();
209               const __int_type __idelim = __traits_type::to_int_type(__delim);
210               const __int_type __eof = __traits_type::eof();
211               __streambuf_type* __sb = __in.rdbuf();
212               __int_type __c = __sb->sgetc();
213
214               while (__extracted < __n
215                      && !__traits_type::eq_int_type(__c, __eof)
216                      && !__traits_type::eq_int_type(__c, __idelim))
217                 {
218                   streamsize __size = std::min(streamsize(__sb->egptr()
219                                                           - __sb->gptr()),
220                                                streamsize(__n - __extracted));
221                   if (__size > 1)
222                     {
223                       const __char_type* __p = __traits_type::find(__sb->gptr(),
224                                                                    __size,
225                                                                    __delim);
226                       if (__p)
227                         __size = __p - __sb->gptr();
228                       __str.append(__sb->gptr(), __size);
229                       __sb->gbump(__size);
230                       __extracted += __size;
231                       __c = __sb->sgetc();
232                     }
233                   else
234                     {
235                       __str += __traits_type::to_char_type(__c);
236                       ++__extracted;
237                       __c = __sb->snextc();
238                     }             
239                 }
240
241               if (__traits_type::eq_int_type(__c, __eof))
242                 __err |= ios_base::eofbit;
243               else if (__traits_type::eq_int_type(__c, __idelim))
244                 {
245                   ++__extracted;
246                   __sb->sbumpc();
247                 }
248               else
249                 __err |= ios_base::failbit;
250             }
251           catch(...)
252             {
253               // _GLIBCXX_RESOLVE_LIB_DEFECTS
254               // 91. Description of operator>> and getline() for string<>
255               // might cause endless loop
256               __in._M_setstate(ios_base::badbit);
257             }
258         }
259       if (!__extracted)
260         __err |= ios_base::failbit;
261       if (__err)
262         __in.setstate(__err);
263       return __in;
264     }
265
266 #ifdef _GLIBCXX_USE_WCHAR_T
267   template<>
268     basic_istream<wchar_t>&
269     basic_istream<wchar_t>::
270     getline(char_type* __s, streamsize __n, char_type __delim)
271     {
272       _M_gcount = 0;
273       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
274       sentry __cerb(*this, true);
275       if (__cerb)
276         {
277           try
278             {
279               const int_type __idelim = traits_type::to_int_type(__delim);
280               const int_type __eof = traits_type::eof();
281               __streambuf_type* __sb = this->rdbuf();
282               int_type __c = __sb->sgetc();
283               
284               while (_M_gcount + 1 < __n
285                      && !traits_type::eq_int_type(__c, __eof)
286                      && !traits_type::eq_int_type(__c, __idelim))
287                 {
288                   streamsize __size = std::min(streamsize(__sb->egptr()
289                                                           - __sb->gptr()),
290                                                streamsize(__n - _M_gcount
291                                                           - 1));
292                   if (__size > 1)
293                     {
294                       const char_type* __p = traits_type::find(__sb->gptr(),
295                                                                __size,
296                                                                __delim);
297                       if (__p)
298                         __size = __p - __sb->gptr();
299                       traits_type::copy(__s, __sb->gptr(), __size);
300                       __s += __size;
301                       __sb->gbump(__size);
302                       _M_gcount += __size;
303                       __c = __sb->sgetc();
304                     }
305                   else
306                     {
307                       *__s++ = traits_type::to_char_type(__c);
308                       ++_M_gcount;
309                       __c = __sb->snextc();
310                     }
311                 }
312
313               if (traits_type::eq_int_type(__c, __eof))
314                 __err |= ios_base::eofbit;
315               else if (traits_type::eq_int_type(__c, __idelim))
316                 {
317                   ++_M_gcount;            
318                   __sb->sbumpc();
319                 }
320               else
321                 __err |= ios_base::failbit;
322             }
323           catch(...)
324             { this->_M_setstate(ios_base::badbit); }
325         }
326       // _GLIBCXX_RESOLVE_LIB_DEFECTS
327       // 243. get and getline when sentry reports failure.
328       if (__n > 0)
329         *__s = char_type();
330       if (!_M_gcount)
331         __err |= ios_base::failbit;
332       if (__err)
333         this->setstate(__err);
334       return *this;
335     }
336
337   template<>
338     basic_istream<wchar_t>&
339     basic_istream<wchar_t>::
340     ignore(streamsize __n, int_type __delim)
341     {
342       if (traits_type::eq_int_type(__delim, traits_type::eof()))
343         return ignore(__n);
344
345       _M_gcount = 0;
346       sentry __cerb(*this, true);
347       if (__cerb && __n > 0)
348         {
349           ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
350           try
351             {
352               const char_type __cdelim = traits_type::to_char_type(__delim);          
353               const int_type __eof = traits_type::eof();
354               __streambuf_type* __sb = this->rdbuf();
355               int_type __c = __sb->sgetc();
356
357               bool __large_ignore = false;
358               while (true)
359                 {
360                   while (_M_gcount < __n
361                          && !traits_type::eq_int_type(__c, __eof)
362                          && !traits_type::eq_int_type(__c, __delim))
363                     {
364                       streamsize __size = std::min(streamsize(__sb->egptr()
365                                                               - __sb->gptr()),
366                                                    streamsize(__n - _M_gcount));
367                       if (__size > 1)
368                         {
369                           const char_type* __p = traits_type::find(__sb->gptr(),
370                                                                    __size,
371                                                                    __cdelim);
372                           if (__p)
373                             __size = __p - __sb->gptr();
374                           __sb->gbump(__size);
375                           _M_gcount += __size;
376                           __c = __sb->sgetc();
377                         }
378                       else
379                         {
380                           ++_M_gcount;
381                           __c = __sb->snextc();
382                         }
383                     }
384                   if (__n == numeric_limits<streamsize>::max()
385                       && !traits_type::eq_int_type(__c, __eof)
386                       && !traits_type::eq_int_type(__c, __delim))
387                     {
388                       _M_gcount = numeric_limits<streamsize>::min();
389                       __large_ignore = true;
390                     }
391                   else
392                     break;
393                 }
394
395               if (__large_ignore)
396                 _M_gcount = numeric_limits<streamsize>::max();
397
398               if (traits_type::eq_int_type(__c, __eof))
399                 __err |= ios_base::eofbit;
400               else if (traits_type::eq_int_type(__c, __delim))
401                 {
402                   if (_M_gcount < numeric_limits<streamsize>::max())
403                     ++_M_gcount;
404                   __sb->sbumpc();
405                 }
406             }
407           catch(...)
408             { this->_M_setstate(ios_base::badbit); }
409           if (__err)
410             this->setstate(__err);
411         }
412       return *this;
413     }
414
415   template<>
416     basic_istream<wchar_t>&
417     getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
418             wchar_t __delim)
419     {
420       typedef basic_istream<wchar_t>            __istream_type;
421       typedef __istream_type::int_type          __int_type;
422       typedef __istream_type::char_type         __char_type;
423       typedef __istream_type::traits_type       __traits_type;
424       typedef __istream_type::__streambuf_type  __streambuf_type;
425       typedef __istream_type::__ctype_type      __ctype_type;
426       typedef basic_string<wchar_t>             __string_type;
427       typedef __string_type::size_type          __size_type;
428
429       __size_type __extracted = 0;
430       const __size_type __n = __str.max_size();
431       ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
432       __istream_type::sentry __cerb(__in, true);
433       if (__cerb)
434         {
435           try
436             {
437               __str.erase();
438               const __int_type __idelim = __traits_type::to_int_type(__delim);
439               const __int_type __eof = __traits_type::eof();
440               __streambuf_type* __sb = __in.rdbuf();
441               __int_type __c = __sb->sgetc();
442
443               while (__extracted < __n
444                      && !__traits_type::eq_int_type(__c, __eof)
445                      && !__traits_type::eq_int_type(__c, __idelim))
446                 {
447                   streamsize __size = std::min(streamsize(__sb->egptr()
448                                                           - __sb->gptr()),
449                                                streamsize(__n - __extracted));
450                   if (__size > 1)
451                     {
452                       const __char_type* __p = __traits_type::find(__sb->gptr(),
453                                                                    __size,
454                                                                    __delim);
455                       if (__p)
456                         __size = __p - __sb->gptr();
457                       __str.append(__sb->gptr(), __size);
458                       __sb->gbump(__size);
459                       __extracted += __size;
460                       __c = __sb->sgetc();
461                     }
462                   else
463                     {
464                       __str += __traits_type::to_char_type(__c);
465                       ++__extracted;
466                       __c = __sb->snextc();
467                     }             
468                 }
469
470               if (__traits_type::eq_int_type(__c, __eof))
471                 __err |= ios_base::eofbit;
472               else if (__traits_type::eq_int_type(__c, __idelim))
473                 {
474                   ++__extracted;
475                   __sb->sbumpc();
476                 }
477               else
478                 __err |= ios_base::failbit;
479             }
480           catch(...)
481             {
482               // _GLIBCXX_RESOLVE_LIB_DEFECTS
483               // 91. Description of operator>> and getline() for string<>
484               // might cause endless loop
485               __in._M_setstate(ios_base::badbit);
486             }
487         }
488       if (!__extracted)
489         __err |= ios_base::failbit;
490       if (__err)
491         __in.setstate(__err);
492       return __in;
493     }
494 #endif
495 } // namespace std