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