1 _istream.c |
1 /* |
|
2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. |
|
3 * Copyright (c) 1999 |
|
4 * Silicon Graphics Computer Systems, Inc. |
|
5 * |
|
6 * Copyright (c) 1999 |
|
7 * Boris Fomitchev |
|
8 * |
|
9 * This material is provided "as is", with absolutely no warranty expressed |
|
10 * or implied. Any use is at your own risk. |
|
11 * |
|
12 * Permission to use or copy this software for any purpose is hereby granted |
|
13 * without fee, provided the above notices are retained on all copies. |
|
14 * Permission to modify the code and to distribute modified code is granted, |
|
15 * provided the above notices are retained, and a notice that the code was |
|
16 * modified is included with the above copyright notice. |
|
17 * |
|
18 */ |
|
19 #ifndef _STLP_ISTREAM_C |
|
20 #define _STLP_ISTREAM_C |
|
21 |
|
22 #ifndef _STLP_INTERNAL_ISTREAM_H |
|
23 # include <stl/_istream.h> |
|
24 #endif |
|
25 |
|
26 # if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) |
|
27 |
|
28 #ifndef _STLP_LIMITS_H |
|
29 # include <stl/_limits.h> |
|
30 #endif |
|
31 |
|
32 #ifndef _STLP_INTERNAL_NUM_GET_H |
|
33 # include <stl/_num_get.h> |
|
34 #endif |
|
35 |
|
36 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) |
|
37 // no wchar_t is supported for this mode |
|
38 # define __BIS_int_type__ int |
|
39 # define __BIS_pos_type__ streampos |
|
40 # define __BIS_off_type__ streamoff |
|
41 # else |
|
42 # define __BIS_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::int_type |
|
43 # define __BIS_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::pos_type |
|
44 # define __BIS_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::off_type |
|
45 # endif |
|
46 |
|
47 _STLP_BEGIN_NAMESPACE |
|
48 |
|
49 //---------------------------------------------------------------------- |
|
50 // Function object structs used by some member functions. |
|
51 |
|
52 template <class _Traits> |
|
53 struct _Is_not_wspace { |
|
54 typedef typename _Traits::char_type argument_type; |
|
55 typedef bool result_type; |
|
56 |
|
57 const ctype<argument_type>* _M_ctype; |
|
58 |
|
59 _Is_not_wspace(const ctype<argument_type>* __c_type) : _M_ctype(__c_type) {} |
|
60 bool operator()(argument_type __c) const |
|
61 { return !_M_ctype->is(ctype_base::space, __c); } |
|
62 }; |
|
63 |
|
64 template <class _Traits> |
|
65 struct _Is_wspace_null { |
|
66 typedef typename _Traits::char_type argument_type; |
|
67 typedef bool result_type; |
|
68 |
|
69 const ctype<argument_type>* _M_ctype; |
|
70 |
|
71 _Is_wspace_null(const ctype<argument_type>* __c_type) : _M_ctype(__c_type) {} |
|
72 bool operator()(argument_type __c) const { |
|
73 return _Traits::eq(__c, argument_type()) || |
|
74 _M_ctype->is(ctype_base::space, __c); |
|
75 } |
|
76 }; |
|
77 |
|
78 template <class _Traits> |
|
79 struct _Scan_for_wspace { |
|
80 typedef typename _Traits::char_type char_type; |
|
81 typedef char_type* first_argument_type; |
|
82 typedef char_type* second_argument_type; |
|
83 typedef char_type* result_type; |
|
84 |
|
85 const ctype<char_type>* _M_ctype; |
|
86 |
|
87 _Scan_for_wspace(const ctype<char_type>* __ctype) : _M_ctype(__ctype) {} |
|
88 const char_type* |
|
89 operator()(const char_type* __first, const char_type* __last) const { |
|
90 return _M_ctype->scan_is(ctype_base::space, __first, __last); |
|
91 } |
|
92 }; |
|
93 |
|
94 template <class _Traits> |
|
95 struct _Scan_wspace_null { |
|
96 typedef typename _Traits::char_type char_type; |
|
97 typedef char_type* first_argument_type; |
|
98 typedef char_type* second_argument_type; |
|
99 typedef char_type* result_type; |
|
100 |
|
101 const ctype<char_type>* _M_ctype; |
|
102 |
|
103 _Scan_wspace_null(const ctype<char_type>* __c_type) : _M_ctype(__c_type) {} |
|
104 const char_type* |
|
105 operator()(const char_type* __first, const char_type* __last) const { |
|
106 __last = find_if(__first, __last, |
|
107 _Eq_char_bound<_Traits>(char_type())); |
|
108 return _M_ctype->scan_is(ctype_base::space, __first, __last); |
|
109 } |
|
110 }; |
|
111 |
|
112 template <class _Traits> |
|
113 struct _Scan_for_not_wspace { |
|
114 typedef typename _Traits::char_type char_type; |
|
115 typedef char_type* first_argument_type; |
|
116 typedef char_type* second_argument_type; |
|
117 typedef char_type* result_type; |
|
118 |
|
119 const ctype<char_type>* _M_ctype; |
|
120 |
|
121 _Scan_for_not_wspace(const ctype<char_type>* __c_type) : _M_ctype(__c_type) {} |
|
122 const char_type* |
|
123 operator()(const char_type* __first, const char_type* __last) const { |
|
124 return _M_ctype->scan_not(ctype_base::space, __first, __last); |
|
125 } |
|
126 }; |
|
127 |
|
128 template <class _Traits> |
|
129 struct _Scan_for_char_val |
|
130 { |
|
131 typedef typename _Traits::char_type char_type; |
|
132 typedef char_type* first_argument_type; |
|
133 typedef char_type* second_argument_type; |
|
134 typedef char_type* result_type; |
|
135 |
|
136 char_type _M_val; |
|
137 |
|
138 _Scan_for_char_val(char_type __val) : _M_val(__val) {} |
|
139 |
|
140 const char_type* |
|
141 operator()(const char_type* __first, const char_type* __last) const { |
|
142 return find_if(__first, __last, _Eq_char_bound<_Traits>(_M_val)); |
|
143 } |
|
144 }; |
|
145 |
|
146 template <class _Traits> |
|
147 struct _Scan_for_int_val |
|
148 { |
|
149 typedef typename _Traits::char_type char_type; |
|
150 typedef typename _Traits::int_type int_type; |
|
151 typedef char_type* first_argument_type; |
|
152 typedef char_type* second_argument_type; |
|
153 typedef char_type* result_type; |
|
154 |
|
155 int_type _M_val; |
|
156 |
|
157 _Scan_for_int_val(int_type __val) : _M_val(__val) {} |
|
158 |
|
159 const char_type* |
|
160 operator()(const char_type* __first, const char_type* __last) const { |
|
161 return find_if(__first, __last, |
|
162 _Eq_int_bound<_Traits>(_M_val)); |
|
163 } |
|
164 }; |
|
165 |
|
166 // Helper function: try to push back a character to a streambuf, |
|
167 // return true if the pushback succeeded. Does not throw. |
|
168 |
|
169 template <class _CharT, class _Traits> |
|
170 bool _STLP_CALL |
|
171 __pushback(basic_streambuf<_CharT, _Traits>* __buf, _CharT __c) |
|
172 { |
|
173 bool ret; |
|
174 _STLP_TRY { |
|
175 const typename _Traits::int_type __eof = _Traits::eof(); |
|
176 ret = !_Traits::eq_int_type(__buf->sputbackc(__c), __eof); |
|
177 } |
|
178 _STLP_CATCH_ALL { |
|
179 ret = false; |
|
180 } |
|
181 return ret; |
|
182 } |
|
183 |
|
184 template <class _CharT, class _Traits> |
|
185 basic_istream<_CharT, _Traits>& _STLP_CALL |
|
186 ws(basic_istream<_CharT, _Traits>& __is) |
|
187 { |
|
188 typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; |
|
189 _Sentry __sentry(__is, _No_Skip_WS()); // Don't skip whitespace. |
|
190 if (__sentry) |
|
191 __is._M_skip_whitespace(false); |
|
192 return __is; |
|
193 } |
|
194 |
|
195 // Helper functions for istream<>::sentry constructor. |
|
196 template <class _CharT, class _Traits> |
|
197 bool |
|
198 _M_init_skip(basic_istream<_CharT, _Traits>& __is) { |
|
199 if (__is.good()) { |
|
200 if (__is.tie()) |
|
201 __is.tie()->flush(); |
|
202 |
|
203 __is._M_skip_whitespace(true); |
|
204 } |
|
205 |
|
206 if (!__is.good()) { |
|
207 __is.setstate(ios_base::failbit); |
|
208 return false; |
|
209 } else |
|
210 return true; |
|
211 } |
|
212 |
|
213 template <class _CharT, class _Traits> |
|
214 bool |
|
215 _M_init_noskip(basic_istream<_CharT, _Traits>& __is){ |
|
216 if (__is.good()) { |
|
217 if (__is.tie()) |
|
218 __is.tie()->flush(); |
|
219 |
|
220 if (!__is.rdbuf()) |
|
221 __is.setstate(ios_base::badbit); |
|
222 } |
|
223 else |
|
224 __is.setstate(ios_base::failbit); |
|
225 return __is.good(); |
|
226 } |
|
227 |
|
228 //---------------------------------------------------------------------- |
|
229 // Definitions of basic_istream<>'s noninline member functions. |
|
230 |
|
231 // Helper function for formatted input of numbers. |
|
232 template <class _CharT, class _Traits, class _Number> |
|
233 ios_base::iostate _STLP_CALL |
|
234 _M_get_num(basic_istream<_CharT, _Traits>& __that, _Number& __val) |
|
235 { |
|
236 typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; |
|
237 ios_base::iostate __err = 0; |
|
238 _Sentry __sentry( __that ); // Skip whitespace. |
|
239 if (__sentry) { |
|
240 typedef num_get<_CharT, istreambuf_iterator<_CharT, _Traits> > _Num_get; |
|
241 _STLP_TRY { |
|
242 ((const _Num_get&)use_facet<_Num_get>(__that.getloc())).get(istreambuf_iterator<_CharT, _Traits>(__that.rdbuf()), |
|
243 0, __that, __err, __val); |
|
244 } |
|
245 _STLP_CATCH_ALL { |
|
246 __that._M_handle_exception(ios_base::badbit); |
|
247 } |
|
248 if (__err) __that.setstate(__err); |
|
249 } |
|
250 return __err; |
|
251 } |
|
252 |
|
253 |
|
254 // Unformatted input |
|
255 |
|
256 template <class _CharT, class _Traits> |
|
257 __BIS_int_type__ |
|
258 basic_istream<_CharT, _Traits>::peek() |
|
259 { |
|
260 typename _Traits::int_type __tmp = _Traits::eof(); |
|
261 |
|
262 this->_M_gcount = 0; |
|
263 sentry __sentry(*this, _No_Skip_WS()); |
|
264 |
|
265 if (__sentry) { |
|
266 _STLP_TRY { |
|
267 __tmp = this->rdbuf()->sgetc(); |
|
268 } |
|
269 _STLP_CATCH_ALL { |
|
270 this->_M_handle_exception(ios_base::badbit); |
|
271 } |
|
272 } |
|
273 else |
|
274 { |
|
275 if (this->_S_eof(__tmp)) |
|
276 { |
|
277 this->clear(); |
|
278 this->setstate(ios_base::eofbit); |
|
279 } |
|
280 } |
|
281 return __tmp; |
|
282 } |
|
283 |
|
284 |
|
285 template <class _CharT, class _Traits> |
|
286 __BIS_int_type__ |
|
287 basic_istream<_CharT, _Traits>::get() |
|
288 { |
|
289 typename _Traits::int_type __tmp = _Traits::eof(); |
|
290 sentry __sentry(*this, _No_Skip_WS()); |
|
291 this->_M_gcount = 0; |
|
292 |
|
293 if (__sentry) { |
|
294 _STLP_TRY { |
|
295 __tmp = this->rdbuf()->sbumpc(); |
|
296 } |
|
297 _STLP_CATCH_ALL { |
|
298 this->_M_handle_exception(ios_base::badbit); |
|
299 } |
|
300 |
|
301 if (!this->_S_eof(__tmp)) |
|
302 this->_M_gcount = 1; |
|
303 } |
|
304 |
|
305 if (_M_gcount == 0) |
|
306 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
307 |
|
308 return __tmp; |
|
309 } |
|
310 |
|
311 template <class _CharT, class _Traits> |
|
312 basic_istream<_CharT, _Traits>& |
|
313 basic_istream<_CharT, _Traits>::get(_CharT& __c) |
|
314 { |
|
315 sentry __sentry(*this, _No_Skip_WS()); |
|
316 this->_M_gcount = 0; |
|
317 |
|
318 if (__sentry) { |
|
319 typename _Traits::int_type __tmp = _Traits::eof(); |
|
320 _STLP_TRY { |
|
321 __tmp = this->rdbuf()->sbumpc(); |
|
322 } |
|
323 _STLP_CATCH_ALL { |
|
324 this->_M_handle_exception(ios_base::badbit); |
|
325 } |
|
326 |
|
327 if (!this->_S_eof(__tmp)) { |
|
328 this->_M_gcount = 1; |
|
329 __c = _Traits::to_char_type(__tmp); |
|
330 } |
|
331 } |
|
332 |
|
333 if (this->_M_gcount == 0) |
|
334 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
335 |
|
336 return *this; |
|
337 } |
|
338 |
|
339 |
|
340 |
|
341 // Read characters and discard them. The standard specifies a single |
|
342 // function with two arguments, each with a default. We instead use |
|
343 // three overloded functions, because it's possible to implement the |
|
344 // first two more efficiently than the fully general third version. |
|
345 template <class _CharT, class _Traits> |
|
346 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::ignore() |
|
347 { |
|
348 sentry __sentry(*this, _No_Skip_WS()); |
|
349 this->_M_gcount = 0; |
|
350 |
|
351 if (__sentry) { |
|
352 int_type __c; |
|
353 _STLP_TRY { |
|
354 __c = this->rdbuf()->sbumpc(); |
|
355 } |
|
356 _STLP_CATCH_ALL { |
|
357 this->_M_handle_exception(ios_base::badbit); |
|
358 return *this; |
|
359 } |
|
360 |
|
361 if (!this->_S_eof(__c)) |
|
362 this->_M_gcount = 1; |
|
363 else |
|
364 this->setstate(ios_base::eofbit); |
|
365 } |
|
366 |
|
367 return *this; |
|
368 } |
|
369 |
|
370 // Putback |
|
371 |
|
372 template <class _CharT, class _Traits> |
|
373 basic_istream<_CharT, _Traits>& |
|
374 basic_istream<_CharT, _Traits>::putback(_CharT __c) { |
|
375 this->_M_gcount = 0; |
|
376 sentry __sentry(*this, _No_Skip_WS()); |
|
377 |
|
378 if (__sentry) { |
|
379 typename _Traits::int_type __tmp = _Traits::eof(); |
|
380 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
381 // if (!__buf || this->_S_eof(__buf->sputbackc(__c))) |
|
382 if (__buf) { |
|
383 _STLP_TRY { |
|
384 __tmp = __buf->sputbackc(__c); |
|
385 } |
|
386 _STLP_CATCH_ALL { |
|
387 this->_M_handle_exception(ios_base::badbit); |
|
388 } |
|
389 } |
|
390 if (this->_S_eof(__tmp)) |
|
391 this->setstate(ios_base::badbit); |
|
392 } |
|
393 else |
|
394 this->setstate(ios_base::failbit); |
|
395 |
|
396 return *this; |
|
397 } |
|
398 |
|
399 template <class _CharT, class _Traits> |
|
400 basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::unget() { |
|
401 this->_M_gcount = 0; |
|
402 |
|
403 sentry __sentry(*this, _No_Skip_WS()); |
|
404 |
|
405 if (__sentry) { |
|
406 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
407 // if (!__buf || _Traits::eq_int_type(__buf->sungetc(), _Traits::eof())) |
|
408 if (__buf) { |
|
409 _STLP_TRY { |
|
410 _CharT __tmp; |
|
411 __tmp = __buf->sungetc(); |
|
412 #ifdef __SYMBIAN32__ |
|
413 if (__tmp == (_CharT)-1) //chek for eof |
|
414 #else |
|
415 if (this->_S_eof(__tmp)) |
|
416 #endif |
|
417 this->setstate(ios_base::badbit); |
|
418 } |
|
419 _STLP_CATCH_ALL { |
|
420 this->_M_handle_exception(ios_base::badbit); |
|
421 } |
|
422 } else |
|
423 this->setstate(ios_base::badbit); |
|
424 } |
|
425 else |
|
426 this->setstate(ios_base::failbit); |
|
427 |
|
428 return *this; |
|
429 } |
|
430 |
|
431 // Positioning and buffer control. |
|
432 |
|
433 template <class _CharT, class _Traits> |
|
434 int basic_istream<_CharT, _Traits>::sync() { |
|
435 sentry __sentry(*this, _No_Skip_WS()); |
|
436 |
|
437 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
438 if (__buf) { |
|
439 if (__buf->pubsync() == -1) { |
|
440 this->setstate(ios_base::badbit); |
|
441 return -1; |
|
442 } |
|
443 else |
|
444 return 0; |
|
445 } |
|
446 else |
|
447 return -1; |
|
448 } |
|
449 |
|
450 template <class _CharT, class _Traits> |
|
451 __BIS_pos_type__ |
|
452 basic_istream<_CharT, _Traits>::tellg() { |
|
453 #ifndef __SYMBIAN32__ |
|
454 sentry __sentry(*this, _No_Skip_WS()); |
|
455 #endif |
|
456 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
457 return (__buf && !this->fail()) ? __buf->pubseekoff(0, ios_base::cur, ios_base::in) |
|
458 : pos_type(-1); |
|
459 } |
|
460 |
|
461 template <class _CharT, class _Traits> |
|
462 basic_istream<_CharT, _Traits>& |
|
463 basic_istream<_CharT, _Traits>::seekg(pos_type __pos) { |
|
464 #ifndef __SYMBIAN32__ |
|
465 sentry __sentry(*this, _No_Skip_WS()); |
|
466 #endif |
|
467 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
468 if (!this->fail() && __buf) |
|
469 { |
|
470 pos_type pos = __buf->pubseekpos(__pos, ios_base::in); |
|
471 if(pos == pos_type(off_type(-1))) |
|
472 this->setstate(ios_base::failbit); |
|
473 } |
|
474 return *this; |
|
475 } |
|
476 |
|
477 template <class _CharT, class _Traits> |
|
478 basic_istream<_CharT, _Traits>& |
|
479 basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) |
|
480 { |
|
481 #ifndef __SYMBIAN32__ |
|
482 sentry __sentry(*this, _No_Skip_WS()); |
|
483 #endif |
|
484 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
485 if (!this->fail() && __buf) |
|
486 { |
|
487 |
|
488 pos_type pos = __buf->pubseekoff(__off, __dir, ios_base::in); |
|
489 if(pos == pos_type(off_type(-1))) |
|
490 this->setstate(ios_base::failbit); |
|
491 } |
|
492 return *this; |
|
493 } |
|
494 |
|
495 // Formatted input of characters and character arrays. |
|
496 |
|
497 template <class _CharT, class _Traits> |
|
498 void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT& __c) |
|
499 { |
|
500 // typename _Traits::int_type __tmp = _Traits::eof(); |
|
501 |
|
502 sentry __sentry(*this); // Skip whitespace. |
|
503 |
|
504 if (__sentry) { |
|
505 typename _Traits::int_type __tmp = _Traits::eof(); |
|
506 |
|
507 _STLP_TRY { |
|
508 __tmp = this->rdbuf()->sbumpc(); |
|
509 } |
|
510 _STLP_CATCH_ALL { |
|
511 this->_M_handle_exception(ios_base::badbit); |
|
512 return; |
|
513 } |
|
514 |
|
515 if (!this->_S_eof(__tmp)) |
|
516 __c = _Traits::to_char_type(__tmp); |
|
517 else |
|
518 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
519 } |
|
520 } |
|
521 |
|
522 |
|
523 //--------------------------------------------------------------------------- |
|
524 // istream's helper functions. |
|
525 |
|
526 // A generic function for unbuffered input. We stop when we reach EOF, |
|
527 // or when we have extracted _Num characters, or when the function object |
|
528 // __is_delim return true. In the last case, it extracts the character |
|
529 // for which __is_delim is true, if and only if __extract_delim is true. |
|
530 // It appends a null character to the end of the string; this means that |
|
531 // it may store up to _Num + 1 characters. |
|
532 // |
|
533 // __is_getline governs two corner cases: reading _Num characters without |
|
534 // encountering delim or eof (in which case failbit is set if __is_getline |
|
535 // is true); and reading _Num characters where the _Num+1'st character is |
|
536 // eof (in which case eofbit is set if __is_getline is true). |
|
537 // |
|
538 // It is assumed that __is_delim never throws. |
|
539 // |
|
540 // Return value is the number of characters extracted, including the |
|
541 // delimiter if it is extracted. Note that the number of characaters |
|
542 // extracted isn't necessarily the same as the number stored. |
|
543 |
|
544 template < class _CharT, class _Traits, class _Is_Delim> |
|
545 streamsize _STLP_CALL |
|
546 _M_read_unbuffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, |
|
547 streamsize _Num, _CharT* __s, |
|
548 _Is_Delim __is_delim, |
|
549 bool __extract_delim, bool __append_null, |
|
550 bool __is_getline) |
|
551 { |
|
552 streamsize __n = 0; |
|
553 ios_base::iostate __status = 0; |
|
554 |
|
555 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
556 // The operations that can potentially throw are sbumpc, snextc, and sgetc. |
|
557 _STLP_TRY { |
|
558 # if 0 |
|
559 int_type __c = __buf->sgetc(); |
|
560 while (true) { |
|
561 if (__that->_S_eof(__c)) { |
|
562 if (__n < _Num || __is_getline) |
|
563 __status |= ios_base::eofbit; |
|
564 break; |
|
565 } |
|
566 |
|
567 else if (__is_delim(__c)) { |
|
568 if (__extract_delim) { // Extract and discard current character. |
|
569 __buf->sbumpc(); |
|
570 ++__n; |
|
571 } |
|
572 break; |
|
573 } |
|
574 |
|
575 else if (__n == _Num) { |
|
576 if (__is_getline) |
|
577 __status |= ios_base::failbit; |
|
578 break; |
|
579 } |
|
580 |
|
581 *__s++ = _Traits::to_char_type(__c); |
|
582 ++__n; |
|
583 __c = __buf->snextc(); |
|
584 } |
|
585 # else |
|
586 // int_type __c = __buf->sbumpc(); // __buf->sgetc(); |
|
587 while (true) { |
|
588 |
|
589 int_type __c = __buf->sbumpc(); // sschwarz |
|
590 |
|
591 if (__that->_S_eof(__c)) { |
|
592 if (__n < _Num || __is_getline) |
|
593 __status |= ios_base::eofbit; |
|
594 break; |
|
595 } |
|
596 |
|
597 else if (__is_delim(__c)) { |
|
598 if (__extract_delim) { // Extract and discard current character. |
|
599 // __buf->sbumpc(); |
|
600 ++__n; |
|
601 } |
|
602 break; |
|
603 } |
|
604 |
|
605 else { // regular character |
|
606 |
|
607 *__s++ = _Traits::to_char_type(__c); |
|
608 ++__n; |
|
609 |
|
610 } |
|
611 |
|
612 if (__n == _Num) { |
|
613 if (__is_getline) // didn't find delimiter as one of the _Num chars |
|
614 __status |= ios_base::failbit; |
|
615 break; |
|
616 } |
|
617 |
|
618 // *__s++ = _Traits::to_char_type(__c); |
|
619 // ++__n; |
|
620 |
|
621 } |
|
622 |
|
623 # endif |
|
624 |
|
625 } |
|
626 _STLP_CATCH_ALL { |
|
627 __that->_M_handle_exception(ios_base::badbit); |
|
628 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
629 return __n; |
|
630 } |
|
631 |
|
632 if (__append_null) |
|
633 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
634 if (__status) |
|
635 __that->setstate(__status); // This might throw. |
|
636 return __n; |
|
637 } |
|
638 |
|
639 // Much like _M_read_unbuffered, but with one additional function object: |
|
640 // __scan_delim(first, last) returns the first pointer p in [first, last) |
|
641 // such that __is_delim(p) is true. |
|
642 |
|
643 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
644 streamsize _STLP_CALL |
|
645 _M_read_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, |
|
646 streamsize _Num, _CharT* __s, |
|
647 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
648 bool __extract_delim, bool __append_null, |
|
649 bool __is_getline) |
|
650 { |
|
651 streamsize __n = 0; |
|
652 ios_base::iostate __status = 0; |
|
653 bool __done = false; |
|
654 |
|
655 _STLP_TRY { |
|
656 while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { |
|
657 const _CharT* __first = __buf->_M_gptr(); |
|
658 const _CharT* __last = __buf->_M_egptr(); |
|
659 ptrdiff_t __request = _Num - __n; |
|
660 |
|
661 const _CharT* __p = __scan_delim(__first, __last); |
|
662 ptrdiff_t __chunk = (min) (ptrdiff_t(__p - __first), __request); |
|
663 _Traits::copy(__s, __first, __chunk); |
|
664 __s += __chunk; |
|
665 __n += __chunk; |
|
666 __buf->_M_gbump((int)__chunk); |
|
667 |
|
668 // We terminated by finding delim. |
|
669 if (__p != __last && __p - __first <= __request) { |
|
670 if (__extract_delim) { |
|
671 __n += 1; |
|
672 __buf->_M_gbump(1); |
|
673 } |
|
674 __done = true; |
|
675 } |
|
676 |
|
677 // We terminated by reading all the characters we were asked for. |
|
678 else if(__n == _Num) { |
|
679 |
|
680 // Find out if we have reached eof. This matters for getline. |
|
681 if (__is_getline) { |
|
682 if (__chunk == __last - __first) { |
|
683 if (__that->_S_eof(__buf->sgetc())) |
|
684 __status |= ios_base::eofbit; |
|
685 } |
|
686 else |
|
687 __status |= ios_base::failbit; |
|
688 } |
|
689 __done = true; |
|
690 } |
|
691 |
|
692 // The buffer contained fewer than _Num - __n characters. Either we're |
|
693 // at eof, or we should refill the buffer and try again. |
|
694 else { |
|
695 if (__that->_S_eof(__buf->sgetc())) { |
|
696 __status |= ios_base::eofbit; |
|
697 __done = true; |
|
698 } |
|
699 } |
|
700 } // Close the while loop. |
|
701 } |
|
702 _STLP_CATCH_ALL { |
|
703 __that->_M_handle_exception(ios_base::badbit); |
|
704 __done = true; |
|
705 } |
|
706 |
|
707 if (__done) { |
|
708 if (__append_null) |
|
709 *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
710 if (__status != 0) |
|
711 __that->setstate(__status); // This might throw. |
|
712 return __n; |
|
713 } |
|
714 |
|
715 // If execution has reached this point, then we have an empty buffer but |
|
716 // we have not reached eof. What that means is that the streambuf has |
|
717 // decided to switch from buffered to unbuffered input. We switch to |
|
718 // to _M_read_unbuffered. |
|
719 |
|
720 return __n + _M_read_unbuffered(__that, __buf, _Num - __n, __s, __is_delim, |
|
721 __extract_delim,__append_null,__is_getline); |
|
722 } |
|
723 |
|
724 |
|
725 |
|
726 |
|
727 template <class _CharT, class _Traits> |
|
728 basic_istream<_CharT, _Traits>& |
|
729 basic_istream<_CharT, _Traits>::get(_CharT* __s, streamsize __n, |
|
730 _CharT __delim) { |
|
731 sentry __sentry(*this, _No_Skip_WS()); |
|
732 this->_M_gcount = 0; |
|
733 |
|
734 if (__sentry) { |
|
735 if (__n > 0) { |
|
736 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
737 |
|
738 if (__buf->egptr() != __buf->gptr()) |
|
739 this->_M_gcount = |
|
740 _M_read_buffered(this, __buf, __n - 1, __s, |
|
741 _Eq_char_bound<_Traits>(__delim), |
|
742 _Scan_for_char_val<_Traits>(__delim), |
|
743 false, true, false); |
|
744 else |
|
745 this->_M_gcount = |
|
746 _M_read_unbuffered(this, __buf, __n - 1, __s, |
|
747 _Eq_char_bound<_Traits>(__delim), |
|
748 false, true, false); |
|
749 } |
|
750 } |
|
751 #ifdef __SYMBIAN32__ |
|
752 *(__s + this->_M_gcount) = _STLP_DEFAULT_CONSTRUCTED(_CharT); |
|
753 #endif //__SYMBIAN32__ |
|
754 if (this->_M_gcount == 0) |
|
755 this->setstate(ios_base::failbit); |
|
756 |
|
757 return *this; |
|
758 } |
|
759 |
|
760 // Getline is essentially identical to get, except that it extracts |
|
761 // the delimiter. |
|
762 template <class _CharT, class _Traits> |
|
763 basic_istream<_CharT, _Traits>& |
|
764 basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, |
|
765 _CharT __delim) { |
|
766 sentry __sentry(*this, _No_Skip_WS()); |
|
767 this->_M_gcount = 0; |
|
768 |
|
769 if (__sentry) { |
|
770 if (__n > 0) { |
|
771 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
772 this->_M_gcount = __buf->egptr() != __buf->gptr() |
|
773 ? _M_read_buffered(this, __buf, __n - 1, __s, |
|
774 _Eq_char_bound<_Traits>(__delim), |
|
775 _Scan_for_char_val<_Traits>(__delim), |
|
776 true, true, true) |
|
777 : _M_read_unbuffered(this, __buf, __n - 1, __s, |
|
778 _Eq_char_bound<_Traits>(__delim), |
|
779 true, true, true); |
|
780 } |
|
781 } |
|
782 |
|
783 if (this->_M_gcount == 0) |
|
784 this->setstate(ios_base::failbit); |
|
785 |
|
786 return *this; |
|
787 } |
|
788 |
|
789 // Read n characters. We don't look for any delimiter, and we don't |
|
790 // put in a terminating null character. |
|
791 template <class _CharT, class _Traits> |
|
792 basic_istream<_CharT, _Traits>& |
|
793 basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) |
|
794 { |
|
795 sentry __sentry(*this, _No_Skip_WS()); |
|
796 this->_M_gcount = 0; |
|
797 |
|
798 if (__sentry && !this->eof()) { |
|
799 basic_streambuf<_CharT, _Traits>*__buf = this->rdbuf(); |
|
800 if (__buf->gptr() != __buf->egptr()) |
|
801 _M_gcount |
|
802 = _M_read_buffered(this, __buf, __n, __s, |
|
803 _Constant_unary_fun<bool, int_type>(false), |
|
804 _Project2nd<const _CharT*, const _CharT*>(), |
|
805 false, false, false); |
|
806 else |
|
807 _M_gcount |
|
808 = _M_read_unbuffered(this, __buf, __n, __s, |
|
809 _Constant_unary_fun<bool, int_type>(false), |
|
810 false, false, false); |
|
811 } |
|
812 else |
|
813 this->setstate(ios_base::failbit); |
|
814 |
|
815 if (this->eof()) |
|
816 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
817 |
|
818 return *this; |
|
819 } |
|
820 |
|
821 |
|
822 // Read n or fewer characters. We don't look for any delimiter, and |
|
823 // we don't put in a terminating null character. |
|
824 template <class _CharT, class _Traits> |
|
825 streamsize |
|
826 basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __nmax) |
|
827 { |
|
828 sentry __sentry(*this, _No_Skip_WS()); |
|
829 this->_M_gcount = 0; |
|
830 |
|
831 if (__sentry && !this->eof() && __nmax >= 0) { |
|
832 |
|
833 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
834 streamsize __avail = __buf->in_avail(); |
|
835 |
|
836 // fbp : isn't full-blown setstate required here ? |
|
837 if (__avail == -1) |
|
838 this->_M_setstate_nothrow(ios_base::eofbit); |
|
839 |
|
840 else if (__avail != 0) { |
|
841 |
|
842 if (__buf->gptr() != __buf->egptr()) |
|
843 _M_gcount |
|
844 = _M_read_buffered(this, __buf, (min) (__avail, __nmax), __s, |
|
845 _Constant_unary_fun<bool, int_type>(false), |
|
846 _Project2nd<const _CharT*, const _CharT*>(), |
|
847 false, false, false); |
|
848 else |
|
849 _M_gcount |
|
850 = _M_read_unbuffered(this, __buf, (min) (__avail, __nmax), __s, |
|
851 _Constant_unary_fun<bool, int_type>(false), |
|
852 false, false, false); |
|
853 } |
|
854 } |
|
855 else { |
|
856 // fbp : changed so that failbit is set only there, to pass Dietmar's test |
|
857 if (this->eof()) |
|
858 this->setstate(ios_base::eofbit | ios_base::failbit); |
|
859 else |
|
860 { |
|
861 if (__nmax < 0) |
|
862 { |
|
863 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
864 streamsize __avail = __buf->in_avail(); |
|
865 if(__avail == -1) |
|
866 this->setstate(ios_base::eofbit); |
|
867 } |
|
868 else |
|
869 this->setstate(ios_base::failbit); |
|
870 } |
|
871 } |
|
872 |
|
873 // if (this->eof()) |
|
874 // this->setstate(ios_base::eofbit | ios_base::failbit); |
|
875 |
|
876 return _M_gcount; |
|
877 } |
|
878 |
|
879 template <class _CharT, class _Traits> |
|
880 void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT* __s) |
|
881 { |
|
882 sentry __sentry(*this); // Skip whitespace. |
|
883 |
|
884 if (__sentry) { |
|
885 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
886 streamsize __nmax = this->width() > 0 |
|
887 ? this->width() - 1 |
|
888 : (numeric_limits<streamsize>::max)() / sizeof(_CharT) - 1; |
|
889 |
|
890 streamsize __n = __buf->gptr() != __buf->egptr() |
|
891 ? _M_read_buffered(this, __buf, __nmax, __s, |
|
892 _Is_wspace_null<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
893 _Scan_wspace_null<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
894 false, true, false) |
|
895 : _M_read_unbuffered(this, __buf, __nmax, __s, |
|
896 _Is_wspace_null<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
897 false, true, false); |
|
898 if (__n == 0) |
|
899 this->setstate(ios_base::failbit); |
|
900 } |
|
901 this->width(0); |
|
902 } |
|
903 |
|
904 // A generic unbuffered function for ignoring characters. We stop |
|
905 // when we reach EOF, or when the function object __is_delim returns |
|
906 // true. In the last case, it extracts the character for which |
|
907 // __is_delim is true, if and only if __extract_delim is true. |
|
908 |
|
909 template < class _CharT, class _Traits, class _Is_Delim> |
|
910 void _STLP_CALL |
|
911 _M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, |
|
912 basic_streambuf<_CharT, _Traits>* __buf, |
|
913 _Is_Delim __is_delim, |
|
914 bool __extract_delim, bool __set_failbit) |
|
915 { |
|
916 bool __done = false; |
|
917 ios_base::iostate __status = 0; |
|
918 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
919 |
|
920 _STLP_TRY { |
|
921 #ifdef __SYMBIAN32__ |
|
922 int_type __c = __buf->sgetc(); |
|
923 do { |
|
924 |
|
925 if (__that->_S_eof(__c)) { |
|
926 __done = true; |
|
927 __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit |
|
928 : ios_base::eofbit; |
|
929 break; |
|
930 } |
|
931 |
|
932 else if (__is_delim(__c)) { |
|
933 __done = true; |
|
934 if (__extract_delim) |
|
935 __buf->snextc(); |
|
936 break; |
|
937 |
|
938 } |
|
939 __c = __buf->snextc(); |
|
940 } while(!__done); |
|
941 #else |
|
942 while (!__done) { |
|
943 int_type __c = __buf->sbumpc(); |
|
944 |
|
945 if (__that->_S_eof(__c)) { |
|
946 __done = true; |
|
947 __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit |
|
948 : ios_base::eofbit; |
|
949 } |
|
950 |
|
951 else if (__is_delim(__c)) { |
|
952 __done = true; |
|
953 if (!__extract_delim) |
|
954 if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) |
|
955 __status |= ios_base::failbit; |
|
956 } |
|
957 } |
|
958 #endif |
|
959 } |
|
960 _STLP_CATCH_ALL { |
|
961 __that->_M_handle_exception(ios_base::badbit); |
|
962 } |
|
963 |
|
964 __that->setstate(__status); |
|
965 } |
|
966 |
|
967 // A generic buffered function for ignoring characters. Much like |
|
968 // _M_ignore_unbuffered, but with one additional function object: |
|
969 // __scan_delim(first, last) returns the first pointer p in [first, |
|
970 // last) such that __is_delim(p) is true. |
|
971 |
|
972 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
973 void _STLP_CALL |
|
974 _M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, |
|
975 basic_streambuf<_CharT, _Traits>* __buf, |
|
976 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
977 bool __extract_delim, bool __set_failbit) |
|
978 { |
|
979 bool __at_eof = false; |
|
980 bool __found_delim = false; |
|
981 |
|
982 _STLP_TRY { |
|
983 while (__buf->_M_egptr() != __buf->_M_gptr() && !__at_eof && !__found_delim) { |
|
984 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); |
|
985 __buf->_M_gbump((int)(__p - __buf->_M_gptr())); |
|
986 |
|
987 if (__p != __buf->_M_egptr()) { // We found delim, so we're done. |
|
988 if (__extract_delim) |
|
989 __buf->_M_gbump(1); |
|
990 __found_delim = true; |
|
991 } |
|
992 |
|
993 else // No delim. Try to refil the buffer. |
|
994 __at_eof = __that->_S_eof(__buf->sgetc()); |
|
995 } // Close the while loop. |
|
996 } |
|
997 _STLP_CATCH_ALL { |
|
998 __that->_M_handle_exception(ios_base::badbit); |
|
999 return; |
|
1000 } |
|
1001 |
|
1002 if (__at_eof) { |
|
1003 __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit |
|
1004 : ios_base::eofbit); |
|
1005 return; |
|
1006 } |
|
1007 if (__found_delim) |
|
1008 return; |
|
1009 |
|
1010 // If execution has reached this point, then we have an empty buffer but |
|
1011 // we have not reached eof. What that means is that the streambuf has |
|
1012 // decided to switch from a buffered to an unbuffered mode. We switch |
|
1013 // to _M_ignore_unbuffered. |
|
1014 _M_ignore_unbuffered(__that, __buf, __is_delim, __extract_delim, __set_failbit); |
|
1015 } |
|
1016 |
|
1017 // Overloaded versions of _M_ignore_unbuffered and _M_ignore_unbuffered |
|
1018 // with an explicit count _Num. Return value is the number of |
|
1019 // characters extracted. |
|
1020 // |
|
1021 // The function object __max_chars takes two arguments, _Num and __n |
|
1022 // (the latter being the number of characters we have already read), |
|
1023 // and returns the maximum number of characters to read from the buffer. |
|
1024 // We parameterize _M_ignore_buffered so that we can use it for both |
|
1025 // bounded and unbounded input; for the former the function object should |
|
1026 // be minus<>, and for the latter it should return a constant maximum value. |
|
1027 |
|
1028 template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim> |
|
1029 streamsize _STLP_CALL |
|
1030 _M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, |
|
1031 basic_streambuf<_CharT, _Traits>* __buf, |
|
1032 streamsize _Num, _Max_Chars __max_chars, |
|
1033 _Is_Delim __is_delim, |
|
1034 bool __extract_delim, bool __set_failbit) |
|
1035 { |
|
1036 streamsize __n = 0; |
|
1037 ios_base::iostate __status = 0; |
|
1038 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
1039 |
|
1040 _STLP_TRY { |
|
1041 while (__max_chars(_Num, __n) > 0) { |
|
1042 int_type __c = __buf->sbumpc(); |
|
1043 |
|
1044 if (__that->_S_eof(__c)) { |
|
1045 __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit |
|
1046 : ios_base::eofbit; |
|
1047 break; |
|
1048 } |
|
1049 |
|
1050 else if (__is_delim(__c)) { |
|
1051 if (__extract_delim) |
|
1052 ++__n; |
|
1053 else if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) |
|
1054 __status |= ios_base::failbit; |
|
1055 |
|
1056 break; |
|
1057 } |
|
1058 // fbp : added counter increment to pass Dietmar's test |
|
1059 ++__n; |
|
1060 } |
|
1061 } |
|
1062 _STLP_CATCH_ALL { |
|
1063 __that->_M_handle_exception(ios_base::badbit); |
|
1064 } |
|
1065 |
|
1066 if (__status) |
|
1067 __that->setstate(__status); // This might throw. |
|
1068 return __n; |
|
1069 } |
|
1070 |
|
1071 template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim, class _Scan_Delim> |
|
1072 streamsize _STLP_CALL |
|
1073 _M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, |
|
1074 basic_streambuf<_CharT, _Traits>* __buf, |
|
1075 streamsize _Num, |
|
1076 _Max_Chars __max_chars, |
|
1077 _Is_Delim __is_delim, _Scan_Delim __scan_delim, |
|
1078 bool __extract_delim, bool __set_failbit) |
|
1079 { |
|
1080 streamsize __n = 0; |
|
1081 bool __at_eof = false; |
|
1082 bool __done = false; |
|
1083 |
|
1084 _STLP_TRY { |
|
1085 while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { |
|
1086 ptrdiff_t __avail = __buf->_M_egptr() - __buf->_M_gptr(); |
|
1087 streamsize __m = __max_chars(_Num, __n); |
|
1088 |
|
1089 if (__avail >= __m) { // We have more characters than we need. |
|
1090 const _CharT* __last = __buf->_M_gptr() + __m; |
|
1091 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __last); |
|
1092 ptrdiff_t __chunk = __p - __buf->_M_gptr(); |
|
1093 __n += __chunk; |
|
1094 __buf->_M_gbump((int)__chunk); |
|
1095 |
|
1096 if (__extract_delim && __p != __last) { |
|
1097 __n += 1; |
|
1098 __buf->_M_gbump(1); |
|
1099 } |
|
1100 |
|
1101 __done = true; |
|
1102 } |
|
1103 |
|
1104 else { |
|
1105 const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); |
|
1106 ptrdiff_t __chunk = __p - __buf->_M_gptr(); |
|
1107 __n += __chunk; |
|
1108 __buf->_M_gbump((int)__chunk); |
|
1109 |
|
1110 if (__p != __buf->_M_egptr()) { // We found delim. |
|
1111 if (__extract_delim) { |
|
1112 __n += 1; |
|
1113 __buf->_M_gbump(1); |
|
1114 } |
|
1115 |
|
1116 __done = true; |
|
1117 } |
|
1118 |
|
1119 // We didn't find delim. Try to refill the buffer. |
|
1120 else if (__that->_S_eof(__buf->sgetc())) { |
|
1121 __done = true; |
|
1122 __at_eof = true; |
|
1123 } |
|
1124 } |
|
1125 } // Close the while loop. |
|
1126 } |
|
1127 _STLP_CATCH_ALL { |
|
1128 __that->_M_handle_exception(ios_base::badbit); |
|
1129 return __n; |
|
1130 } |
|
1131 |
|
1132 if (__at_eof) |
|
1133 __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit |
|
1134 : ios_base::eofbit); |
|
1135 |
|
1136 if (__done) |
|
1137 return __n; |
|
1138 |
|
1139 // If execution has reached this point, then we have an empty buffer but |
|
1140 // we have not reached eof. What that means is that the streambuf has |
|
1141 // decided to switch from buffered to unbuffered input. We switch to |
|
1142 // to _M_ignore_unbuffered. |
|
1143 |
|
1144 return __n + _M_ignore_unbuffered( __that, __buf, _Num, __max_chars, |
|
1145 __is_delim, __extract_delim, __set_failbit); |
|
1146 } |
|
1147 |
|
1148 |
|
1149 template <class _CharT, class _Traits> |
|
1150 basic_istream<_CharT, _Traits>& |
|
1151 basic_istream<_CharT, _Traits>::ignore(streamsize __n) |
|
1152 { |
|
1153 sentry __sentry(*this, _No_Skip_WS()); |
|
1154 this->_M_gcount = 0; |
|
1155 |
|
1156 if (__sentry) { |
|
1157 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1158 typedef _Constant_unary_fun<bool, int_type> _Const_bool; |
|
1159 typedef _Constant_binary_fun<streamsize, streamsize, streamsize> |
|
1160 _Const_streamsize; |
|
1161 const streamsize __maxss = (numeric_limits<streamsize>::max)(); |
|
1162 |
|
1163 if (__n == (numeric_limits<int>::max)()) { |
|
1164 if (__buf->gptr() != __buf->egptr()) |
|
1165 _M_gcount |
|
1166 = _M_ignore_buffered(this, __buf, |
|
1167 __maxss, _Const_streamsize(__maxss), |
|
1168 _Const_bool(false), |
|
1169 _Project2nd<const _CharT*, const _CharT*>(), |
|
1170 false, false); |
|
1171 else |
|
1172 _M_gcount = _M_ignore_unbuffered(this, __buf, |
|
1173 __maxss, _Const_streamsize(__maxss), |
|
1174 _Const_bool(false), false, false); |
|
1175 } |
|
1176 else { |
|
1177 if (__buf->gptr() != __buf->egptr()) |
|
1178 _M_gcount |
|
1179 = _M_ignore_buffered(this, __buf, |
|
1180 __n, minus<streamsize>(), |
|
1181 _Const_bool(false), |
|
1182 _Project2nd<const _CharT*, const _CharT*>(), |
|
1183 false, false); |
|
1184 else |
|
1185 _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus<streamsize>(), |
|
1186 _Const_bool(false), false, false); |
|
1187 } |
|
1188 } |
|
1189 |
|
1190 return *this; |
|
1191 } |
|
1192 |
|
1193 template <class _CharT, class _Traits> |
|
1194 basic_istream<_CharT, _Traits>& |
|
1195 basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __delim) |
|
1196 { |
|
1197 sentry __sentry(*this, _No_Skip_WS()); |
|
1198 this->_M_gcount = 0; |
|
1199 |
|
1200 if (__sentry) { |
|
1201 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1202 typedef _Constant_unary_fun<bool, int_type> _Const_bool; |
|
1203 typedef _Constant_binary_fun<streamsize, streamsize, streamsize> |
|
1204 _Const_streamsize; |
|
1205 const streamsize __maxss = (numeric_limits<streamsize>::max)(); |
|
1206 |
|
1207 if (__n == (numeric_limits<int>::max)()) { |
|
1208 if (__buf->gptr() != __buf->egptr()) |
|
1209 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1210 __maxss, _Const_streamsize(__maxss), |
|
1211 _Eq_int_bound<_Traits>(__delim), |
|
1212 _Scan_for_int_val<_Traits>(__delim), |
|
1213 true, false); |
|
1214 else |
|
1215 _M_gcount = _M_ignore_unbuffered(this, __buf, |
|
1216 __maxss, _Const_streamsize(__maxss), |
|
1217 _Eq_int_bound<_Traits>(__delim), |
|
1218 true, false); |
|
1219 } |
|
1220 else { |
|
1221 if (__buf->gptr() != __buf->egptr()) |
|
1222 _M_gcount = _M_ignore_buffered(this, __buf, |
|
1223 __n, minus<streamsize>(), |
|
1224 _Eq_int_bound<_Traits>( |
|
1225 __delim), |
|
1226 _Scan_for_int_val<_Traits>(__delim), |
|
1227 true, false); |
|
1228 else |
|
1229 _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus<streamsize>(), |
|
1230 _Eq_int_bound<_Traits>(__delim), |
|
1231 true, false); |
|
1232 } |
|
1233 } |
|
1234 |
|
1235 return *this; |
|
1236 } |
|
1237 |
|
1238 // This member function does not construct a sentry object, because |
|
1239 // it is called from sentry's constructor. |
|
1240 template <class _CharT, class _Traits> |
|
1241 void basic_istream<_CharT, _Traits>::_M_skip_whitespace(bool __set_failbit) |
|
1242 { |
|
1243 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
1244 if (!__buf) |
|
1245 this->setstate(ios_base::badbit); |
|
1246 else if (__buf->gptr() != __buf->egptr()) |
|
1247 _M_ignore_buffered(this, __buf, |
|
1248 _Is_not_wspace<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
1249 _Scan_for_not_wspace<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
1250 false, __set_failbit); |
|
1251 else |
|
1252 _M_ignore_unbuffered(this, __buf, |
|
1253 _Is_not_wspace<_Traits>((const ctype<_CharT>*)this->_M_ctype_facet()), |
|
1254 false, __set_failbit); |
|
1255 } |
|
1256 |
|
1257 |
|
1258 // This is a very simple loop that reads characters from __src and puts |
|
1259 // them into __dest. It looks complicated because of the (standard- |
|
1260 // mandated) exception handling policy. |
|
1261 // |
|
1262 // We stop when we get an exception, when we fail to insert into the |
|
1263 // output streambuf, or when __is_delim is true. |
|
1264 |
|
1265 template < class _CharT, class _Traits, class _Is_Delim> |
|
1266 streamsize _STLP_CALL |
|
1267 _M_copy_unbuffered( basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, |
|
1268 basic_streambuf<_CharT, _Traits>* __dest, |
|
1269 _Is_Delim __is_delim, |
|
1270 bool __extract_delim, bool __rethrow) |
|
1271 { |
|
1272 streamsize __extracted = 0; |
|
1273 ios_base::iostate __status = 0; |
|
1274 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
1275 int_type __c; |
|
1276 |
|
1277 _STLP_TRY { |
|
1278 #ifdef __SYMBIAN32__ |
|
1279 __c = __src->sgetc(); |
|
1280 for(;; __c = __src->snextc()){ |
|
1281 |
|
1282 // If we failed to get a character, then quit. |
|
1283 if (__that->_S_eof(__c)) { |
|
1284 __status |= ios_base::eofbit; |
|
1285 break; |
|
1286 } |
|
1287 // If it's the delimiter, then quit. |
|
1288 else if (__is_delim(__c)) { |
|
1289 if (!__extract_delim) |
|
1290 __status |= ios_base::failbit; |
|
1291 break; |
|
1292 } |
|
1293 |
|
1294 else { |
|
1295 |
|
1296 // Try to put the character in the output streambuf. |
|
1297 _STLP_TRY { |
|
1298 if (!__that->_S_eof(__dest->sputc(__c))) |
|
1299 ++__extracted; |
|
1300 else |
|
1301 break; |
|
1302 } |
|
1303 _STLP_CATCH_ALL { |
|
1304 __status |= ios_base::failbit; |
|
1305 break; |
|
1306 } |
|
1307 |
|
1308 } |
|
1309 |
|
1310 } /* while (true) */ |
|
1311 #else |
|
1312 while (true) { |
|
1313 |
|
1314 // Get a character. If there's an exception, catch and (maybe) rethrow it. |
|
1315 __c = __src->sbumpc(); |
|
1316 |
|
1317 // If we failed to get a character, then quit. |
|
1318 if (__that->_S_eof(__c)) { |
|
1319 __status |= ios_base::eofbit; |
|
1320 break; |
|
1321 } |
|
1322 // If it's the delimiter, then quit. |
|
1323 else if (__is_delim(__c)) { |
|
1324 if (!__extract_delim && !__pushback(__src, _Traits::to_char_type(__c))) |
|
1325 __status |= ios_base::failbit; |
|
1326 break; |
|
1327 } |
|
1328 |
|
1329 else { |
|
1330 |
|
1331 // Try to put the character in the output streambuf. |
|
1332 bool __failed = false; |
|
1333 _STLP_TRY { |
|
1334 if (!__that->_S_eof(__dest->sputc(__c))) |
|
1335 ++__extracted; |
|
1336 else |
|
1337 __failed = true; |
|
1338 } |
|
1339 _STLP_CATCH_ALL { |
|
1340 __failed = true; |
|
1341 } |
|
1342 |
|
1343 // If we failed to put the character in the output streambuf, then |
|
1344 // try to push it back to the input streambuf. |
|
1345 if (__failed && !__pushback(__src, _Traits::to_char_type(__c))) |
|
1346 __status |= ios_base::failbit; |
|
1347 |
|
1348 // fbp : avoiding infinite loop in io-27-6-1-2-3.exp |
|
1349 if (__failed) |
|
1350 break; |
|
1351 } |
|
1352 |
|
1353 } /* while (true) */ |
|
1354 #endif |
|
1355 } |
|
1356 // fbp : this try/catch moved here in reasonable assumption |
|
1357 // __is_delim never throw (__pushback is guaranteed not to) |
|
1358 _STLP_CATCH_ALL { |
|
1359 // See 27.6.1.2.3, paragraph 13. |
|
1360 if (__rethrow && __extracted == 0) |
|
1361 __that->_M_handle_exception(ios_base::failbit); |
|
1362 } |
|
1363 __that->setstate(__status); |
|
1364 return __extracted; |
|
1365 } |
|
1366 |
|
1367 // Buffered copying from one streambuf to another. We copy the characters |
|
1368 // in chunks, rather than one at a time. We still have to worry about all |
|
1369 // of the error conditions we checked in _M_copy_unbuffered, plus one more: |
|
1370 // the streambuf might decide to switch from a buffered to an unbuffered mode. |
|
1371 |
|
1372 template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> |
|
1373 streamsize _STLP_CALL |
|
1374 _M_copy_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, |
|
1375 basic_streambuf<_CharT, _Traits>* __dest, |
|
1376 _Scan_Delim __scan_delim, _Is_Delim __is_delim, |
|
1377 bool __extract_delim, bool __rethrow) |
|
1378 { |
|
1379 streamsize __extracted = 0; |
|
1380 ios_base::iostate __status = 0; |
|
1381 typedef typename basic_istream<_CharT, _Traits>::int_type int_type; |
|
1382 int_type __c = _Traits::eof(); |
|
1383 _CharT* __first = __src->_M_gptr(); |
|
1384 ptrdiff_t __avail = __src->_M_egptr() - __first; |
|
1385 // fbp : introduced to move catch/try blocks out of the loop |
|
1386 bool __do_handle_exceptions; |
|
1387 |
|
1388 _STLP_TRY { |
|
1389 while (true) { |
|
1390 __do_handle_exceptions = false ; |
|
1391 const _CharT* __last = __scan_delim(__first, __src->_M_egptr()); |
|
1392 |
|
1393 // Try to copy the entire input buffer to the output buffer. |
|
1394 streamsize __n = __dest->sputn(__first, __extract_delim && __last != __src->_M_egptr() |
|
1395 ? (__last - __first) + 1 |
|
1396 : (__last - __first)); |
|
1397 __src->_M_gbump((int)__n); |
|
1398 __extracted += __n; |
|
1399 |
|
1400 // from this on, catch() will call _M_handle_exceptions() |
|
1401 __do_handle_exceptions = true; |
|
1402 |
|
1403 if (__n < __avail) // We found the delimiter, or else failed to |
|
1404 break; // copy some characters. |
|
1405 |
|
1406 __c = __src->sgetc(); |
|
1407 |
|
1408 // Three possibilities: we succeeded in refilling the buffer, or |
|
1409 // we got EOF, or the streambuf has switched to unbuffered mode. |
|
1410 __first = __src->_M_gptr(); |
|
1411 __avail = __src->_M_egptr() - __first; |
|
1412 |
|
1413 if (__avail > 0) |
|
1414 {} // dwa 1/16/00 -- suppress a Metrowerks warning |
|
1415 else if (__that->_S_eof(__c)) { |
|
1416 __status |= ios_base::eofbit; |
|
1417 break; |
|
1418 } |
|
1419 else |
|
1420 return __extracted + _M_copy_unbuffered(__that, __src, __dest, __is_delim, |
|
1421 __extract_delim, __rethrow); |
|
1422 } /* while */ |
|
1423 } |
|
1424 |
|
1425 _STLP_CATCH_ALL { |
|
1426 // See 27.6.1.2.3, paragraph 13. |
|
1427 if (__rethrow && __do_handle_exceptions && __extracted == 0) |
|
1428 __that->_M_handle_exception(ios_base::failbit); |
|
1429 } |
|
1430 |
|
1431 if (__status) |
|
1432 __that->setstate(__status); // This might throw. |
|
1433 return __extracted; |
|
1434 } |
|
1435 |
|
1436 |
|
1437 |
|
1438 template <class _CharT, class _Traits> |
|
1439 basic_istream<_CharT, _Traits>& |
|
1440 basic_istream<_CharT, _Traits> |
|
1441 ::get(basic_streambuf<_CharT, _Traits>& __dest, _CharT __delim) |
|
1442 { |
|
1443 sentry __sentry(*this, _No_Skip_WS()); |
|
1444 this->_M_gcount = 0; |
|
1445 |
|
1446 if (__sentry) { |
|
1447 basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); |
|
1448 |
|
1449 if (__src) |
|
1450 this->_M_gcount = __src->egptr() != __src->gptr() |
|
1451 ? _M_copy_buffered(this, __src, &__dest, |
|
1452 _Scan_for_char_val<_Traits>(__delim), |
|
1453 _Eq_char_bound<_Traits>(__delim), |
|
1454 false, false) |
|
1455 : _M_copy_unbuffered(this, __src, &__dest, |
|
1456 _Eq_char_bound<_Traits>(__delim), |
|
1457 false, false); |
|
1458 } |
|
1459 |
|
1460 if (this->_M_gcount == 0) |
|
1461 this->setstate(ios_base::failbit); |
|
1462 |
|
1463 return *this; |
|
1464 } |
|
1465 |
|
1466 // Copying characters into a streambuf. |
|
1467 template <class _CharT, class _Traits> |
|
1468 basic_istream<_CharT, _Traits>& |
|
1469 basic_istream<_CharT, _Traits> |
|
1470 ::operator>>(basic_streambuf<_CharT, _Traits>* __dest) |
|
1471 { |
|
1472 streamsize __n = 0; |
|
1473 typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; |
|
1474 _Sentry __sentry(*this); |
|
1475 if (__sentry) { |
|
1476 basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); |
|
1477 if (__src && __dest) |
|
1478 __n = __src->egptr() != __src->gptr() |
|
1479 ? _M_copy_buffered(this, __src, __dest, |
|
1480 _Project2nd<const _CharT*, const _CharT*>(), |
|
1481 _Constant_unary_fun<bool, int_type>(false), |
|
1482 false, true) |
|
1483 : _M_copy_unbuffered(this, __src, __dest, |
|
1484 _Constant_unary_fun<bool, int_type>(false), |
|
1485 false, true); |
|
1486 } |
|
1487 |
|
1488 if (__n == 0) |
|
1489 this->setstate(ios_base::failbit); |
|
1490 |
|
1491 return *this; |
|
1492 } |
|
1493 |
|
1494 // ---------------------------------------------------------------- |
|
1495 // basic_iostream<> class |
|
1496 // ---------------------------------------------------------------- |
|
1497 |
|
1498 template <class _CharT, class _Traits> |
|
1499 _STLP_EXP_DECLSPEC basic_iostream<_CharT, _Traits> |
|
1500 ::basic_iostream(basic_streambuf<_CharT, _Traits>* __buf) |
|
1501 : basic_ios<_CharT, _Traits>(), |
|
1502 basic_istream<_CharT, _Traits>(__buf), |
|
1503 basic_ostream<_CharT, _Traits>(__buf) |
|
1504 { |
|
1505 this->init(__buf); |
|
1506 } |
|
1507 |
|
1508 template <class _CharT, class _Traits> |
|
1509 _STLP_EXP_DECLSPEC basic_iostream<_CharT, _Traits>::~basic_iostream() |
|
1510 {} |
|
1511 |
|
1512 |
|
1513 template <class _CharT, class _Traits> |
|
1514 _STLP_EXP_DECLSPEC basic_istream<_CharT, _Traits> |
|
1515 ::basic_istream(basic_streambuf<_CharT, _Traits>* __buf) : |
|
1516 basic_ios<_CharT, _Traits>(), _M_gcount(0) { |
|
1517 this->init(__buf); |
|
1518 } |
|
1519 |
|
1520 template <class _CharT, class _Traits> |
|
1521 _STLP_EXP_DECLSPEC basic_istream<_CharT, _Traits> |
|
1522 ::~basic_istream() {} |
|
1523 |
|
1524 |
|
1525 |
|
1526 _STLP_END_NAMESPACE |
|
1527 |
|
1528 # undef __BIS_int_type__ |
|
1529 # undef __BIS_pos_type__ |
|
1530 # undef __BIS_off_type__ |
|
1531 |
|
1532 # endif /* defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) */ |
|
1533 |
|
1534 #endif /* _STLP_ISTREAM_C */ |