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 290 291 // 27.8.1.5 Template class basic_ifstream 292 /** 293 * Derivation of general input streams, specific to files. 294 */ 295 template<typename _CharT, typename _Traits> 296 class basic_ifstream : public basic_istream<_CharT, _Traits> 297 { 298 public: 299 // Types: 300 typedef _CharT char_type; 301 typedef _Traits traits_type; 302 typedef typename traits_type::int_type int_type; 303 typedef typename traits_type::pos_type pos_type; 304 typedef typename traits_type::off_type off_type; 305 306 // Non-standard types: 307 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 308 typedef basic_istream<char_type, traits_type> __istream_type; 309 310 private: 311 __filebuf_type _M_filebuf; 312 313 public: 314 // Constructors/Destructors: 315 /** Default constructor. Create an input file stream. */ 316 basic_ifstream() 317 : __istream_type(NULL), _M_filebuf() 318 { this->init(&_M_filebuf); } 319 320 /** 321 * @brief Create an input file stream. 322 * @param s Null terminated string specifying filename. 323 * @param mode Open file in specified mode (see std::ios_base). 324 * 325 * Tip: When using std::string to hold the filename, you must use 326 * .c_str() before passing it to this constructor. 327 */ 328 explicit 329 basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) 330 : __istream_type(NULL), _M_filebuf() 331 { 332 this->init(&_M_filebuf); 333 this->open(__s, __mode); 334 } 335 336 ~basic_ifstream() 337 { } 338 339 // Members: 340 /** 341 * @brief Get a pointer to the file stream's buffer. 342 * @return Pointer to basic_filebuf. 343 */ 344 __filebuf_type* 345 rdbuf() const 346 { return const_cast<__filebuf_type*>(&_M_filebuf); } 347 348 bool 349 is_open() { return _M_filebuf.is_open(); } 350 351 void 352 open(const char* __s, ios_base::openmode __mode = ios_base::in) 353 { 354 if (!_M_filebuf.open(__s, __mode | ios_base::in)) 355 this->setstate(ios_base::failbit); 356 } 357 358 /** Close the file. */ 359 void 360 close() 361 { 362 if (!_M_filebuf.close()) 363 this->setstate(ios_base::failbit); 364 } 365 }; 366 367 368 // 27.8.1.8 Template class basic_ofstream 369 /** 370 * Derivation of general output streams, specific to files. 371 */ 372 template<typename _CharT, typename _Traits> 373 class basic_ofstream : public basic_ostream<_CharT,_Traits> 374 { 375 public: 376 // Types: 377 typedef _CharT char_type; 378 typedef _Traits traits_type; 379 typedef typename traits_type::int_type int_type; 380 typedef typename traits_type::pos_type pos_type; 381 typedef typename traits_type::off_type off_type; 382 383 // Non-standard types: 384 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 385 typedef basic_ostream<char_type, traits_type> __ostream_type; 386 387 private: 388 __filebuf_type _M_filebuf; 389 390 public: 391 // Constructors: 392 /** Default constructor for output file_stream. */ 393 basic_ofstream() 394 : __ostream_type(NULL), _M_filebuf() 395 { this->init(&_M_filebuf); } 396 397 /** 398 * @brief Create an output stream. 399 * @param s Null terminated string specifying filename. 400 * @param mode Open file in specified mode (see std::ios_base). 401 * 402 * Tip: When using std::string to hold the filename, you must use 403 * .c_str() before passing it to this constructor. 404 */ 405 explicit 406 basic_ofstream(const char* __s, 407 ios_base::openmode __mode = ios_base::out|ios_base::trunc) 408 : __ostream_type(NULL), _M_filebuf() 409 { 410 this->init(&_M_filebuf); 411 this->open(__s, __mode); 412 } 413 414 ~basic_ofstream() 415 { } 416 417 // Members: 418 /** 419 * @brief Get a pointer to the file stream's buffer. 420 * @return Pointer to basic_filebuf. 421 */ 422 __filebuf_type* 423 rdbuf() const 424 { return const_cast<__filebuf_type*>(&_M_filebuf); } 425 426 /** 427 * @brief Query to see if file stream is open. 428 * @return True if stream is open. 429 */ 430 bool 431 is_open() { return _M_filebuf.is_open(); } 432 433 /** 434 * @brief Specify a file to open for output. 435 * @param s Null terminated string specifying filename. 436 * @param mode Mode in which to open file (see std::ios_base). 437 * 438 * Tip: When using std::string to hold the filename, you must use 439 * .c_str() before passing it to this constructor. 440 */ 441 void 442 open(const char* __s, 443 ios_base::openmode __mode = ios_base::out | ios_base::trunc) 444 { 445 if (!_M_filebuf.open(__s, __mode | ios_base::out)) 446 this->setstate(ios_base::failbit); 447 } 448 449 /** Close the file stream. */ 450 void 451 close() 452 { 453 if (!_M_filebuf.close()) 454 this->setstate(ios_base::failbit); 455 } 456 }; 457 458 459 // 27.8.1.11 Template class basic_fstream 460 /** 461 * Derivation of general input/output streams, specific to files. 462 */ 463 template<typename _CharT, typename _Traits> 464 class basic_fstream : public basic_iostream<_CharT, _Traits> 465 { 466 public: 467 // Types: 468 typedef _CharT char_type; 469 typedef _Traits traits_type; 470 typedef typename traits_type::int_type int_type; 471 typedef typename traits_type::pos_type pos_type; 472 typedef typename traits_type::off_type off_type; 473 474 // Non-standard types: 475 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 476 typedef basic_ios<char_type, traits_type> __ios_type; 477 typedef basic_iostream<char_type, traits_type> __iostream_type; 478 479 private: 480 __filebuf_type _M_filebuf; 481 482 public: 483 // Constructors/destructor: 484 /** Default constructor. Create a file stream. */ 485 basic_fstream() 486 : __iostream_type(NULL), _M_filebuf() 487 { this->init(&_M_filebuf); } 488 489 /** 490 * @brief Create an input/output stream. 491 * @param s Null terminated string specifying filename. 492 * @param mode Open file in specified mode (see std::ios_base). 493 * 494 * Tip: When using std::string to hold the filename, you must use 495 * .c_str() before passing it to this constructor. 496 */ 497 explicit 498 basic_fstream(const char* __s, 499 ios_base::openmode __mode = ios_base::in | ios_base::out) 500 : __iostream_type(NULL), _M_filebuf() 501 { 502 this->init(&_M_filebuf); 503 this->open(__s, __mode); 504 } 505 506 ~basic_fstream() 507 { } 508 509 // Members: 510 /** 511 * @brief Get a pointer to the file stream's buffer. 512 * @return Pointer to basic_filebuf. 513 */ 514 __filebuf_type* 515 rdbuf() const 516 { return const_cast<__filebuf_type*>(&_M_filebuf); } 517 518 /** 519 * @brief Query to see if file stream is open. 520 * @return True if stream is open. 521 */ 522 bool 523 is_open() { return _M_filebuf.is_open(); } 524 525 /** 526 * @brief Specify a file to open for input and/or output. 527 * @param s Null terminated string specifying filename. 528 * @param mode Mode in which to open file (see std::ios_base). 529 * 530 * Tip: When using std::string to hold the filename, you must use 531 * .c_str() before passing it to this constructor. 532 */ 533 void 534 open(const char* __s, 535 ios_base::openmode __mode = ios_base::in | ios_base::out) 536 { 537 if (!_M_filebuf.open(__s, __mode)) 538 setstate(ios_base::failbit); 539 } 540 541 /** Close the file stream. */ 542 void 543 close() 544 { 545 if (!_M_filebuf.close()) 546 setstate(ios_base::failbit); 547 } 548 }; 549 } // namespace std 550 551 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT 552 # define export 553 #endif 554 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS 555 # include <bits/fstream.tcc> 556 #endif 557 558 #endif 559