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