1 // Input streams -*- C++ -*- 2 3 // Copyright (C) 2004-2021 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 // 26 // ISO C++ 14882: 27.6.1 Input streams 27 // 28 29 #include <istream> 30 31 namespace std _GLIBCXX_VISIBILITY(default) 32 { 33 _GLIBCXX_BEGIN_NAMESPACE_VERSION 34 35 template<> 36 basic_istream<char>& 37 basic_istream<char>:: getline(char_type * __s,streamsize __n,char_type __delim)38 getline(char_type* __s, streamsize __n, char_type __delim) 39 { 40 _M_gcount = 0; 41 ios_base::iostate __err = ios_base::goodbit; 42 sentry __cerb(*this, true); 43 if (__cerb) 44 { 45 __try 46 { 47 const int_type __idelim = traits_type::to_int_type(__delim); 48 const int_type __eof = traits_type::eof(); 49 __streambuf_type* __sb = this->rdbuf(); 50 int_type __c = __sb->sgetc(); 51 52 while (_M_gcount + 1 < __n 53 && !traits_type::eq_int_type(__c, __eof) 54 && !traits_type::eq_int_type(__c, __idelim)) 55 { 56 streamsize __size = std::min(streamsize(__sb->egptr() 57 - __sb->gptr()), 58 streamsize(__n - _M_gcount 59 - 1)); 60 if (__size > 1) 61 { 62 const char_type* __p = traits_type::find(__sb->gptr(), 63 __size, 64 __delim); 65 if (__p) 66 __size = __p - __sb->gptr(); 67 traits_type::copy(__s, __sb->gptr(), __size); 68 __s += __size; 69 __sb->__safe_gbump(__size); 70 _M_gcount += __size; 71 __c = __sb->sgetc(); 72 } 73 else 74 { 75 *__s++ = traits_type::to_char_type(__c); 76 ++_M_gcount; 77 __c = __sb->snextc(); 78 } 79 } 80 81 if (traits_type::eq_int_type(__c, __eof)) 82 __err |= ios_base::eofbit; 83 else if (traits_type::eq_int_type(__c, __idelim)) 84 { 85 ++_M_gcount; 86 __sb->sbumpc(); 87 } 88 else 89 __err |= ios_base::failbit; 90 } 91 __catch(__cxxabiv1::__forced_unwind&) 92 { 93 this->_M_setstate(ios_base::badbit); 94 __throw_exception_again; 95 } 96 __catch(...) 97 { this->_M_setstate(ios_base::badbit); } 98 } 99 // _GLIBCXX_RESOLVE_LIB_DEFECTS 100 // 243. get and getline when sentry reports failure. 101 if (__n > 0) 102 *__s = char_type(); 103 if (!_M_gcount) 104 __err |= ios_base::failbit; 105 if (__err) 106 this->setstate(__err); 107 return *this; 108 } 109 110 template<> 111 basic_istream<char>& 112 basic_istream<char>:: ignore(streamsize __n,int_type __delim)113 ignore(streamsize __n, int_type __delim) 114 { 115 if (traits_type::eq_int_type(__delim, traits_type::eof())) 116 return ignore(__n); 117 118 _M_gcount = 0; 119 sentry __cerb(*this, true); 120 if (__n > 0 && __cerb) 121 { 122 ios_base::iostate __err = ios_base::goodbit; 123 __try 124 { 125 const char_type __cdelim = traits_type::to_char_type(__delim); 126 const int_type __eof = traits_type::eof(); 127 __streambuf_type* __sb = this->rdbuf(); 128 int_type __c = __sb->sgetc(); 129 130 bool __large_ignore = false; 131 while (true) 132 { 133 while (_M_gcount < __n 134 && !traits_type::eq_int_type(__c, __eof) 135 && !traits_type::eq_int_type(__c, __delim)) 136 { 137 streamsize __size = std::min(streamsize(__sb->egptr() 138 - __sb->gptr()), 139 streamsize(__n - _M_gcount)); 140 if (__size > 1) 141 { 142 const char_type* __p = traits_type::find(__sb->gptr(), 143 __size, 144 __cdelim); 145 if (__p) 146 __size = __p - __sb->gptr(); 147 __sb->__safe_gbump(__size); 148 _M_gcount += __size; 149 __c = __sb->sgetc(); 150 } 151 else 152 { 153 ++_M_gcount; 154 __c = __sb->snextc(); 155 } 156 } 157 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max 158 && !traits_type::eq_int_type(__c, __eof) 159 && !traits_type::eq_int_type(__c, __delim)) 160 { 161 _M_gcount = 162 __gnu_cxx::__numeric_traits<streamsize>::__min; 163 __large_ignore = true; 164 } 165 else 166 break; 167 } 168 169 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max) 170 { 171 if (__large_ignore) 172 _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max; 173 174 if (traits_type::eq_int_type(__c, __eof)) 175 __err |= ios_base::eofbit; 176 else 177 { 178 if (_M_gcount != __n) 179 ++_M_gcount; 180 __sb->sbumpc(); 181 } 182 } 183 else if (_M_gcount < __n) // implies __c == __delim or EOF 184 { 185 if (traits_type::eq_int_type(__c, __eof)) 186 __err |= ios_base::eofbit; 187 else 188 { 189 ++_M_gcount; 190 __sb->sbumpc(); 191 } 192 } 193 } 194 __catch(__cxxabiv1::__forced_unwind&) 195 { 196 this->_M_setstate(ios_base::badbit); 197 __throw_exception_again; 198 } 199 __catch(...) 200 { this->_M_setstate(ios_base::badbit); } 201 if (__err) 202 this->setstate(__err); 203 } 204 return *this; 205 } 206 207 void __istream_extract(istream & __in,char * __s,streamsize __num)208 __istream_extract(istream& __in, char* __s, streamsize __num) 209 { 210 typedef basic_istream<char> __istream_type; 211 typedef __istream_type::int_type __int_type; 212 typedef __istream_type::char_type __char_type; 213 typedef __istream_type::traits_type __traits_type; 214 typedef __istream_type::__streambuf_type __streambuf_type; 215 typedef __istream_type::__ctype_type __ctype_type; 216 217 streamsize __extracted = 0; 218 ios_base::iostate __err = ios_base::goodbit; 219 __istream_type::sentry __cerb(__in, false); 220 if (__cerb) 221 { 222 __try 223 { 224 // Figure out how many characters to extract. 225 streamsize __width = __in.width(); 226 if (0 < __width && __width < __num) 227 __num = __width; 228 229 const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc()); 230 231 const __int_type __eof = __traits_type::eof(); 232 __streambuf_type* __sb = __in.rdbuf(); 233 __int_type __c = __sb->sgetc(); 234 235 while (__extracted < __num - 1 236 && !__traits_type::eq_int_type(__c, __eof) 237 && !__ct.is(ctype_base::space, 238 __traits_type::to_char_type(__c))) 239 { 240 streamsize __size = std::min(streamsize(__sb->egptr() 241 - __sb->gptr()), 242 streamsize(__num - __extracted 243 - 1)); 244 if (__size > 1) 245 { 246 __size = (__ct.scan_is(ctype_base::space, 247 __sb->gptr() + 1, 248 __sb->gptr() + __size) 249 - __sb->gptr()); 250 __traits_type::copy(__s, __sb->gptr(), __size); 251 __s += __size; 252 __sb->__safe_gbump(__size); 253 __extracted += __size; 254 __c = __sb->sgetc(); 255 } 256 else 257 { 258 *__s++ = __traits_type::to_char_type(__c); 259 ++__extracted; 260 __c = __sb->snextc(); 261 } 262 } 263 264 if (__extracted < __num - 1 265 && __traits_type::eq_int_type(__c, __eof)) 266 __err |= ios_base::eofbit; 267 268 // _GLIBCXX_RESOLVE_LIB_DEFECTS 269 // 68. Extractors for char* should store null at end 270 *__s = __char_type(); 271 __in.width(0); 272 } 273 __catch(__cxxabiv1::__forced_unwind&) 274 { 275 __in._M_setstate(ios_base::badbit); 276 __throw_exception_again; 277 } 278 __catch(...) 279 { __in._M_setstate(ios_base::badbit); } 280 } 281 if (!__extracted) 282 __err |= ios_base::failbit; 283 if (__err) 284 __in.setstate(__err); 285 } 286 287 #ifdef _GLIBCXX_USE_WCHAR_T 288 template<> 289 basic_istream<wchar_t>& 290 basic_istream<wchar_t>:: getline(char_type * __s,streamsize __n,char_type __delim)291 getline(char_type* __s, streamsize __n, char_type __delim) 292 { 293 _M_gcount = 0; 294 ios_base::iostate __err = ios_base::goodbit; 295 sentry __cerb(*this, true); 296 if (__cerb) 297 { 298 __try 299 { 300 const int_type __idelim = traits_type::to_int_type(__delim); 301 const int_type __eof = traits_type::eof(); 302 __streambuf_type* __sb = this->rdbuf(); 303 int_type __c = __sb->sgetc(); 304 305 while (_M_gcount + 1 < __n 306 && !traits_type::eq_int_type(__c, __eof) 307 && !traits_type::eq_int_type(__c, __idelim)) 308 { 309 streamsize __size = std::min(streamsize(__sb->egptr() 310 - __sb->gptr()), 311 streamsize(__n - _M_gcount 312 - 1)); 313 if (__size > 1) 314 { 315 const char_type* __p = traits_type::find(__sb->gptr(), 316 __size, 317 __delim); 318 if (__p) 319 __size = __p - __sb->gptr(); 320 traits_type::copy(__s, __sb->gptr(), __size); 321 __s += __size; 322 __sb->__safe_gbump(__size); 323 _M_gcount += __size; 324 __c = __sb->sgetc(); 325 } 326 else 327 { 328 *__s++ = traits_type::to_char_type(__c); 329 ++_M_gcount; 330 __c = __sb->snextc(); 331 } 332 } 333 334 if (traits_type::eq_int_type(__c, __eof)) 335 __err |= ios_base::eofbit; 336 else if (traits_type::eq_int_type(__c, __idelim)) 337 { 338 ++_M_gcount; 339 __sb->sbumpc(); 340 } 341 else 342 __err |= ios_base::failbit; 343 } 344 __catch(__cxxabiv1::__forced_unwind&) 345 { 346 this->_M_setstate(ios_base::badbit); 347 __throw_exception_again; 348 } 349 __catch(...) 350 { this->_M_setstate(ios_base::badbit); } 351 } 352 // _GLIBCXX_RESOLVE_LIB_DEFECTS 353 // 243. get and getline when sentry reports failure. 354 if (__n > 0) 355 *__s = char_type(); 356 if (!_M_gcount) 357 __err |= ios_base::failbit; 358 if (__err) 359 this->setstate(__err); 360 return *this; 361 } 362 363 template<> 364 basic_istream<wchar_t>& 365 basic_istream<wchar_t>:: ignore(streamsize __n,int_type __delim)366 ignore(streamsize __n, int_type __delim) 367 { 368 if (traits_type::eq_int_type(__delim, traits_type::eof())) 369 return ignore(__n); 370 371 _M_gcount = 0; 372 sentry __cerb(*this, true); 373 if (__n > 0 && __cerb) 374 { 375 ios_base::iostate __err = ios_base::goodbit; 376 __try 377 { 378 const char_type __cdelim = traits_type::to_char_type(__delim); 379 const int_type __eof = traits_type::eof(); 380 __streambuf_type* __sb = this->rdbuf(); 381 int_type __c = __sb->sgetc(); 382 383 bool __large_ignore = false; 384 while (true) 385 { 386 while (_M_gcount < __n 387 && !traits_type::eq_int_type(__c, __eof) 388 && !traits_type::eq_int_type(__c, __delim)) 389 { 390 streamsize __size = std::min(streamsize(__sb->egptr() 391 - __sb->gptr()), 392 streamsize(__n - _M_gcount)); 393 if (__size > 1) 394 { 395 const char_type* __p = traits_type::find(__sb->gptr(), 396 __size, 397 __cdelim); 398 if (__p) 399 __size = __p - __sb->gptr(); 400 __sb->__safe_gbump(__size); 401 _M_gcount += __size; 402 __c = __sb->sgetc(); 403 } 404 else 405 { 406 ++_M_gcount; 407 __c = __sb->snextc(); 408 } 409 } 410 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max 411 && !traits_type::eq_int_type(__c, __eof) 412 && !traits_type::eq_int_type(__c, __delim)) 413 { 414 _M_gcount = 415 __gnu_cxx::__numeric_traits<streamsize>::__min; 416 __large_ignore = true; 417 } 418 else 419 break; 420 } 421 422 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max) 423 { 424 if (__large_ignore) 425 _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max; 426 427 if (traits_type::eq_int_type(__c, __eof)) 428 __err |= ios_base::eofbit; 429 else 430 { 431 if (_M_gcount != __n) 432 ++_M_gcount; 433 __sb->sbumpc(); 434 } 435 } 436 else if (_M_gcount < __n) // implies __c == __delim or EOF 437 { 438 if (traits_type::eq_int_type(__c, __eof)) 439 __err |= ios_base::eofbit; 440 else 441 { 442 ++_M_gcount; 443 __sb->sbumpc(); 444 } 445 } 446 } 447 __catch(__cxxabiv1::__forced_unwind&) 448 { 449 this->_M_setstate(ios_base::badbit); 450 __throw_exception_again; 451 } 452 __catch(...) 453 { this->_M_setstate(ios_base::badbit); } 454 if (__err) 455 this->setstate(__err); 456 } 457 return *this; 458 } 459 #endif 460 461 462 _GLIBCXX_END_NAMESPACE_VERSION 463 } // namespace 464