1 // File based streams -*- C++ -*- 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 // 32 // ISO C++ 14882: 27.8 File-based streams 33 // 34 35 /** @file fstream 36 * This is a Standard C++ Library header. You should @c #include this header 37 * in your programs, rather than any of the "st[dl]_*.h" implementation files. 38 */ 39 40 #ifndef _CPP_FSTREAM 41 #define _CPP_FSTREAM 1 42 43 #pragma GCC system_header 44 45 #include <istream> 46 #include <ostream> 47 #include <locale> // For codecvt 48 #include <bits/basic_file.h> 49 #include <bits/gthr.h> 50 51 namespace std 52 { 53 template<typename _CharT, typename _Traits> 54 class basic_filebuf : public basic_streambuf<_CharT, _Traits> 55 { 56 public: 57 // Types: 58 typedef _CharT char_type; 59 typedef _Traits traits_type; 60 typedef typename traits_type::int_type int_type; 61 typedef typename traits_type::pos_type pos_type; 62 typedef typename traits_type::off_type off_type; 63 64 // Non-standard Types: 65 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 66 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 67 typedef __basic_file<char> __file_type; 68 typedef typename traits_type::state_type __state_type; 69 typedef codecvt<char_type, char, __state_type> __codecvt_type; 70 typedef typename __codecvt_type::result __res_type; 71 typedef ctype<char_type> __ctype_type; 72 73 friend class ios_base; // For sync_with_stdio. 74 75 protected: 76 // Data Members: 77 // MT lock inherited from libio or other low-level io library. 78 __c_lock _M_lock; 79 80 // External buffer. 81 __file_type _M_file; 82 83 // Current and beginning state type for codecvt. 84 __state_type _M_state_cur; 85 __state_type _M_state_beg; 86 87 // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer. 88 bool _M_buf_allocated; 89 90 // XXX Needed? 91 bool _M_last_overflowed; 92 93 // The position in the buffer corresponding to the external file 94 // pointer. 95 char_type* _M_filepos; 96 97 public: 98 // Constructors/destructor: 99 basic_filebuf(); 100 101 virtual 102 ~basic_filebuf() 103 { 104 this->close(); 105 _M_last_overflowed = false; 106 } 107 108 // Members: 109 bool 110 is_open() const { return _M_file.is_open(); } 111 112 __filebuf_type* 113 open(const char* __s, ios_base::openmode __mode); 114 115 __filebuf_type* 116 close(); 117 118 protected: 119 void 120 _M_allocate_internal_buffer(); 121 122 void 123 _M_destroy_internal_buffer(); 124 125 // Overridden virtual functions: 126 virtual streamsize 127 showmanyc(); 128 129 // Stroustrup, 1998, p. 628 130 // underflow() and uflow() functions are called to get the next 131 // charater from the real input source when the buffer is empty. 132 // Buffered input uses underflow() 133 134 // The only difference between underflow() and uflow() is that the 135 // latter bumps _M_in_cur after the read. In the sync_with_stdio 136 // case, this is important, as we need to unget the read character in 137 // the underflow() case in order to maintain synchronization. So 138 // instead of calling underflow() from uflow(), we create a common 139 // subroutine to do the real work. 140 int_type 141 _M_underflow_common(bool __bump); 142 143 virtual int_type 144 underflow() { return _M_underflow_common(false); } 145 146 virtual int_type 147 uflow() { return _M_underflow_common(true); } 148 149 virtual int_type 150 pbackfail(int_type __c = _Traits::eof()); 151 152 // NB: For what the standard expects of the overflow function, 153 // see _M_really_overflow(), below. Because basic_streambuf's 154 // sputc/sputn call overflow directly, and the complications of 155 // this implementation's setting of the initial pointers all 156 // equal to _M_buf when initializing, it seems essential to have 157 // this in actuality be a helper function that checks for the 158 // eccentricities of this implementation, and then call 159 // overflow() if indeed the buffer is full. 160 virtual int_type 161 overflow(int_type __c = _Traits::eof()); 162 163 // Stroustrup, 1998, p 648 164 // The overflow() function is called to transfer characters to the 165 // real output destination when the buffer is full. A call to 166 // overflow(c) outputs the contents of the buffer plus the 167 // character c. 168 // 27.5.2.4.5 169 // Consume some sequence of the characters in the pending sequence. 170 int_type 171 _M_really_overflow(int_type __c = _Traits::eof()); 172 173 // Convert internal byte sequence to external, char-based 174 // sequence via codecvt. 175 void 176 _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&); 177 178 virtual __streambuf_type* 179 setbuf(char_type* __s, streamsize __n); 180 181 virtual pos_type 182 seekoff(off_type __off, ios_base::seekdir __way, 183 ios_base::openmode __mode = ios_base::in | ios_base::out); 184 185 virtual pos_type 186 seekpos(pos_type __pos, 187 ios_base::openmode __mode = ios_base::in | ios_base::out); 188 189 virtual int 190 sync() 191 { 192 bool __testput = _M_out_cur && _M_out_beg < _M_out_end; 193 194 // Make sure that the internal buffer resyncs its idea of 195 // the file position with the external file. 196 if (__testput) 197 { 198 // Need to restore current position after the write. 199 off_type __off = _M_out_cur - _M_out_end; 200 _M_really_overflow(); // _M_file.sync() will be called within 201 if (__off) 202 _M_file.seekoff(__off, ios_base::cur); 203 } 204 else 205 _M_file.sync(); 206 _M_last_overflowed = false; 207 return 0; 208 } 209 210 virtual void 211 imbue(const locale& __loc); 212 213 virtual streamsize 214 xsgetn(char_type* __s, streamsize __n) 215 { 216 streamsize __ret = 0; 217 // Clear out pback buffer before going on to the real deal... 218 if (_M_pback_init) 219 { 220 while (__ret < __n && _M_in_cur < _M_in_end) 221 { 222 *__s = *_M_in_cur; 223 ++__ret; 224 ++__s; 225 ++_M_in_cur; 226 } 227 _M_pback_destroy(); 228 } 229 if (__ret < __n) 230 __ret += __streambuf_type::xsgetn(__s, __n - __ret); 231 return __ret; 232 } 233 234 virtual streamsize 235 xsputn(const char_type* __s, streamsize __n) 236 { 237 _M_pback_destroy(); 238 return __streambuf_type::xsputn(__s, __n); 239 } 240 241 void 242 _M_output_unshift(); 243 244 // These three functions are used to clarify internal buffer 245 // maintenance. After an overflow, or after a seekoff call that 246 // started at beg or end, or possibly when the stream becomes 247 // unbuffered, and a myrid other obscure corner cases, the 248 // internal buffer does not truly reflect the contents of the 249 // external buffer. At this point, for whatever reason, it is in 250 // an indeterminate state. 251 void 252 _M_set_indeterminate(void) 253 { 254 if (_M_mode & ios_base::in) 255 this->setg(_M_buf, _M_buf, _M_buf); 256 if (_M_mode & ios_base::out) 257 this->setp(_M_buf, _M_buf); 258 _M_filepos = _M_buf; 259 } 260 261 void 262 _M_set_determinate(off_type __off) 263 { 264 bool __testin = _M_mode & ios_base::in; 265 bool __testout = _M_mode & ios_base::out; 266 if (__testin) 267 this->setg(_M_buf, _M_buf, _M_buf + __off); 268 if (__testout) 269 this->setp(_M_buf, _M_buf + __off); 270 _M_filepos = _M_buf + __off; 271 } 272 273 bool 274 _M_is_indeterminate(void) 275 { 276 bool __ret = false; 277 // Don't return true if unbuffered. 278 if (_M_buf) 279 { 280 if (_M_mode & ios_base::in) 281 __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end; 282 if (_M_mode & ios_base::out) 283 __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end; 284 } 285 return __ret; 286 } 287 }; 288 289 // Explicit specializations. 290 template<> 291 basic_filebuf<char>::int_type 292 basic_filebuf<char>::_M_underflow_common(bool __bump); 293 294 #ifdef _GLIBCPP_USE_WCHAR_T 295 template<> 296 basic_filebuf<wchar_t>::int_type 297 basic_filebuf<wchar_t>::_M_underflow_common(bool __bump); 298 #endif 299 300 // 27.8.1.5 Template class basic_ifstream 301 /** 302 * Derivation of general input streams, specific to files. 303 */ 304 template<typename _CharT, typename _Traits> 305 class basic_ifstream : public basic_istream<_CharT, _Traits> 306 { 307 public: 308 // Types: 309 typedef _CharT char_type; 310 typedef _Traits traits_type; 311 typedef typename traits_type::int_type int_type; 312 typedef typename traits_type::pos_type pos_type; 313 typedef typename traits_type::off_type off_type; 314 315 // Non-standard types: 316 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 317 typedef basic_istream<char_type, traits_type> __istream_type; 318 319 private: 320 __filebuf_type _M_filebuf; 321 322 public: 323 // Constructors/Destructors: 324 /** Default constructor. Create an input file stream. */ 325 basic_ifstream() 326 : __istream_type(NULL), _M_filebuf() 327 { this->init(&_M_filebuf); } 328 329 /** 330 * @brief Create an input file stream. 331 * @param s Null terminated string specifying filename. 332 * @param mode Open file in specified mode (see std::ios_base). 333 * 334 * Tip: When using std::string to hold the filename, you must use 335 * .c_str() before passing it to this constructor. 336 */ 337 explicit 338 basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) 339 : __istream_type(NULL), _M_filebuf() 340 { 341 this->init(&_M_filebuf); 342 this->open(__s, __mode); 343 } 344 345 ~basic_ifstream() 346 { } 347 348 // Members: 349 /** 350 * @brief Get a pointer to the file stream's buffer. 351 * @return Pointer to basic_filebuf. 352 */ 353 __filebuf_type* 354 rdbuf() const 355 { return const_cast<__filebuf_type*>(&_M_filebuf); } 356 357 bool 358 is_open() { return _M_filebuf.is_open(); } 359 360 void 361 open(const char* __s, ios_base::openmode __mode = ios_base::in) 362 { 363 if (!_M_filebuf.open(__s, __mode | ios_base::in)) 364 this->setstate(ios_base::failbit); 365 } 366 367 /** Close the file. */ 368 void 369 close() 370 { 371 if (!_M_filebuf.close()) 372 this->setstate(ios_base::failbit); 373 } 374 }; 375 376 377 // 27.8.1.8 Template class basic_ofstream 378 /** 379 * Derivation of general output streams, specific to files. 380 */ 381 template<typename _CharT, typename _Traits> 382 class basic_ofstream : public basic_ostream<_CharT,_Traits> 383 { 384 public: 385 // Types: 386 typedef _CharT char_type; 387 typedef _Traits traits_type; 388 typedef typename traits_type::int_type int_type; 389 typedef typename traits_type::pos_type pos_type; 390 typedef typename traits_type::off_type off_type; 391 392 // Non-standard types: 393 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 394 typedef basic_ostream<char_type, traits_type> __ostream_type; 395 396 private: 397 __filebuf_type _M_filebuf; 398 399 public: 400 // Constructors: 401 /** Default constructor for output file_stream. */ 402 basic_ofstream() 403 : __ostream_type(NULL), _M_filebuf() 404 { this->init(&_M_filebuf); } 405 406 /** 407 * @brief Create an output stream. 408 * @param s Null terminated string specifying filename. 409 * @param mode Open file in specified mode (see std::ios_base). 410 * 411 * Tip: When using std::string to hold the filename, you must use 412 * .c_str() before passing it to this constructor. 413 */ 414 explicit 415 basic_ofstream(const char* __s, 416 ios_base::openmode __mode = ios_base::out|ios_base::trunc) 417 : __ostream_type(NULL), _M_filebuf() 418 { 419 this->init(&_M_filebuf); 420 this->open(__s, __mode); 421 } 422 423 ~basic_ofstream() 424 { } 425 426 // Members: 427 /** 428 * @brief Get a pointer to the file stream's buffer. 429 * @return Pointer to basic_filebuf. 430 */ 431 __filebuf_type* 432 rdbuf() const 433 { return const_cast<__filebuf_type*>(&_M_filebuf); } 434 435 /** 436 * @brief Query to see if file stream is open. 437 * @return True if stream is open. 438 */ 439 bool 440 is_open() { return _M_filebuf.is_open(); } 441 442 /** 443 * @brief Specify a file to open for output. 444 * @param s Null terminated string specifying filename. 445 * @param mode Mode in which to open file (see std::ios_base). 446 * 447 * Tip: When using std::string to hold the filename, you must use 448 * .c_str() before passing it to this constructor. 449 */ 450 void 451 open(const char* __s, 452 ios_base::openmode __mode = ios_base::out | ios_base::trunc) 453 { 454 if (!_M_filebuf.open(__s, __mode | ios_base::out)) 455 this->setstate(ios_base::failbit); 456 } 457 458 /** Close the file stream. */ 459 void 460 close() 461 { 462 if (!_M_filebuf.close()) 463 this->setstate(ios_base::failbit); 464 } 465 }; 466 467 468 // 27.8.1.11 Template class basic_fstream 469 /** 470 * Derivation of general input/output streams, specific to files. 471 */ 472 template<typename _CharT, typename _Traits> 473 class basic_fstream : public basic_iostream<_CharT, _Traits> 474 { 475 public: 476 // Types: 477 typedef _CharT char_type; 478 typedef _Traits traits_type; 479 typedef typename traits_type::int_type int_type; 480 typedef typename traits_type::pos_type pos_type; 481 typedef typename traits_type::off_type off_type; 482 483 // Non-standard types: 484 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 485 typedef basic_ios<char_type, traits_type> __ios_type; 486 typedef basic_iostream<char_type, traits_type> __iostream_type; 487 488 private: 489 __filebuf_type _M_filebuf; 490 491 public: 492 // Constructors/destructor: 493 /** Default constructor. Create a file stream. */ 494 basic_fstream() 495 : __iostream_type(NULL), _M_filebuf() 496 { this->init(&_M_filebuf); } 497 498 /** 499 * @brief Create an input/output stream. 500 * @param s Null terminated string specifying filename. 501 * @param mode Open file in specified mode (see std::ios_base). 502 * 503 * Tip: When using std::string to hold the filename, you must use 504 * .c_str() before passing it to this constructor. 505 */ 506 explicit 507 basic_fstream(const char* __s, 508 ios_base::openmode __mode = ios_base::in | ios_base::out) 509 : __iostream_type(NULL), _M_filebuf() 510 { 511 this->init(&_M_filebuf); 512 this->open(__s, __mode); 513 } 514 515 ~basic_fstream() 516 { } 517 518 // Members: 519 /** 520 * @brief Get a pointer to the file stream's buffer. 521 * @return Pointer to basic_filebuf. 522 */ 523 __filebuf_type* 524 rdbuf() const 525 { return const_cast<__filebuf_type*>(&_M_filebuf); } 526 527 /** 528 * @brief Query to see if file stream is open. 529 * @return True if stream is open. 530 */ 531 bool 532 is_open() { return _M_filebuf.is_open(); } 533 534 /** 535 * @brief Specify a file to open for input and/or output. 536 * @param s Null terminated string specifying filename. 537 * @param mode Mode in which to open file (see std::ios_base). 538 * 539 * Tip: When using std::string to hold the filename, you must use 540 * .c_str() before passing it to this constructor. 541 */ 542 void 543 open(const char* __s, 544 ios_base::openmode __mode = ios_base::in | ios_base::out) 545 { 546 if (!_M_filebuf.open(__s, __mode)) 547 setstate(ios_base::failbit); 548 } 549 550 /** Close the file stream. */ 551 void 552 close() 553 { 554 if (!_M_filebuf.close()) 555 setstate(ios_base::failbit); 556 } 557 }; 558 } // namespace std 559 560 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT 561 # define export 562 #endif 563 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS 564 # include <bits/fstream.tcc> 565 #endif 566 567 #endif 568