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 51 namespace std 52 { 53 // [27.8.1.1] template class basic_filebuf 54 /** 55 * @brief The actual work of input and output (for files). 56 * 57 * This class associates both its input and output sequence with an 58 * external disk file, and maintains a joint file position for both 59 * sequences. Many of its sematics are described in terms of similar 60 * behavior in the Standard C Library's @c FILE streams. 61 */ 62 template<typename _CharT, typename _Traits> 63 class basic_filebuf : public basic_streambuf<_CharT, _Traits> 64 { 65 public: 66 // Types: 67 typedef _CharT char_type; 68 typedef _Traits traits_type; 69 typedef typename traits_type::int_type int_type; 70 typedef typename traits_type::pos_type pos_type; 71 typedef typename traits_type::off_type off_type; 72 73 //@{ 74 /** 75 * @if maint 76 * @doctodo 77 * @endif 78 */ 79 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 80 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 81 typedef __basic_file<char> __file_type; 82 typedef typename traits_type::state_type __state_type; 83 typedef codecvt<char_type, char, __state_type> __codecvt_type; 84 typedef ctype<char_type> __ctype_type; 85 //@} 86 87 friend class ios_base; // For sync_with_stdio. 88 89 protected: 90 // Data Members: 91 // MT lock inherited from libio or other low-level io library. 92 /** 93 * @if maint 94 * @doctodo 95 * @endif 96 */ 97 __c_lock _M_lock; 98 99 // External buffer. 100 /** 101 * @if maint 102 * @doctodo 103 * @endif 104 */ 105 __file_type _M_file; 106 107 // Current and beginning state type for codecvt. 108 /** 109 * @if maint 110 * @doctodo 111 * @endif 112 */ 113 __state_type _M_state_cur; 114 __state_type _M_state_beg; 115 116 // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer. 117 /** 118 * @if maint 119 * @doctodo 120 * @endif 121 */ 122 bool _M_buf_allocated; 123 124 // XXX Needed? 125 bool _M_last_overflowed; 126 127 // The position in the buffer corresponding to the external file 128 // pointer. 129 /** 130 * @if maint 131 * @doctodo 132 * @endif 133 */ 134 char_type* _M_filepos; 135 136 public: 137 // Constructors/destructor: 138 /** 139 * @brief Does not open any files. 140 * 141 * The default constructor initializes the parent class using its 142 * own default ctor. 143 */ 144 basic_filebuf(); 145 146 /** 147 * @brief The destructor closes the file first. 148 */ 149 virtual 150 ~basic_filebuf() 151 { 152 this->close(); 153 _M_last_overflowed = false; 154 } 155 156 // Members: 157 /** 158 * @brief Returns true if the external file is open. 159 */ 160 bool 161 is_open() const throw() { return _M_file.is_open(); } 162 163 /** 164 * @brief Opens an external file. 165 * @param s The name of the file. 166 * @param mode The open mode flags. 167 * @return @c this on success, NULL on failure 168 * 169 * If a file is already open, this function immediately fails. 170 * Otherwise it tries to open the file named @a s using the flags 171 * given in @a mode. 172 * 173 * [Table 92 gives the relation between openmode combinations and the 174 * equivalent fopen() flags, but the table has not been copied yet.] 175 */ 176 __filebuf_type* 177 open(const char* __s, ios_base::openmode __mode); 178 179 /** 180 * @brief Closes the currently associated file. 181 * @return @c this on success, NULL on failure 182 * 183 * If no file is currently open, this function immediately fails. 184 * 185 * If a "put buffer area" exists, @c overflow(eof) is called to flush 186 * all the characters. The file is then closed. 187 * 188 * If any operations fail, this function also fails. 189 */ 190 __filebuf_type* 191 close() throw(); 192 193 protected: 194 /** 195 * @if maint 196 * @doctodo 197 * @endif 198 */ 199 void 200 _M_allocate_internal_buffer(); 201 202 /** 203 * @if maint 204 * @doctodo 205 * @endif 206 */ 207 void 208 _M_destroy_internal_buffer() throw(); 209 210 // [27.8.1.4] overridden virtual functions 211 // [documentation is inherited] 212 virtual streamsize 213 showmanyc(); 214 215 // Stroustrup, 1998, p. 628 216 // underflow() and uflow() functions are called to get the next 217 // charater from the real input source when the buffer is empty. 218 // Buffered input uses underflow() 219 220 // The only difference between underflow() and uflow() is that the 221 // latter bumps _M_in_cur after the read. In the sync_with_stdio 222 // case, this is important, as we need to unget the read character in 223 // the underflow() case in order to maintain synchronization. So 224 // instead of calling underflow() from uflow(), we create a common 225 // subroutine to do the real work. 226 /** 227 * @if maint 228 * @doctodo 229 * @endif 230 */ 231 int_type 232 _M_underflow_common(bool __bump); 233 234 // [documentation is inherited] 235 virtual int_type 236 underflow(); 237 238 // [documentation is inherited] 239 virtual int_type 240 uflow(); 241 242 // [documentation is inherited] 243 virtual int_type 244 pbackfail(int_type __c = _Traits::eof()); 245 246 // NB: For what the standard expects of the overflow function, 247 // see _M_really_overflow(), below. Because basic_streambuf's 248 // sputc/sputn call overflow directly, and the complications of 249 // this implementation's setting of the initial pointers all 250 // equal to _M_buf when initializing, it seems essential to have 251 // this in actuality be a helper function that checks for the 252 // eccentricities of this implementation, and then call 253 // overflow() if indeed the buffer is full. 254 255 // [documentation is inherited] 256 virtual int_type 257 overflow(int_type __c = _Traits::eof()); 258 259 // Stroustrup, 1998, p 648 260 // The overflow() function is called to transfer characters to the 261 // real output destination when the buffer is full. A call to 262 // overflow(c) outputs the contents of the buffer plus the 263 // character c. 264 // 27.5.2.4.5 265 // Consume some sequence of the characters in the pending sequence. 266 /** 267 * @if maint 268 * @doctodo 269 * @endif 270 */ 271 int_type 272 _M_really_overflow(int_type __c = _Traits::eof()); 273 274 // Convert internal byte sequence to external, char-based 275 // sequence via codecvt. 276 /** 277 * @if maint 278 * @doctodo 279 * @endif 280 */ 281 void 282 _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&); 283 284 /** 285 * @brief Manipulates the buffer. 286 * @param s Pointer to a buffer area. 287 * @param n Size of @a s. 288 * @return @c this 289 * 290 * If no file has been opened, and both @a s and @a n are zero, then 291 * the stream becomes unbuffered. Otherwise, @c s is used as a 292 * buffer; see 293 * http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#2 294 * for more. 295 */ 296 virtual __streambuf_type* 297 setbuf(char_type* __s, streamsize __n); 298 299 // [documentation is inherited] 300 virtual pos_type 301 seekoff(off_type __off, ios_base::seekdir __way, 302 ios_base::openmode __mode = ios_base::in | ios_base::out); 303 304 // [documentation is inherited] 305 virtual pos_type 306 seekpos(pos_type __pos, 307 ios_base::openmode __mode = ios_base::in | ios_base::out); 308 309 // [documentation is inherited] 310 virtual int 311 sync() 312 { 313 int __ret = 0; 314 bool __testput = _M_out_cur && _M_out_beg < _M_out_end; 315 316 // Make sure that the internal buffer resyncs its idea of 317 // the file position with the external file. 318 if (__testput) 319 { 320 // Need to restore current position after the write. 321 off_type __off = _M_out_cur - _M_out_end; 322 323 // _M_file.sync() will be called within 324 if (traits_type::eq_int_type(_M_really_overflow(), 325 traits_type::eof())) 326 __ret = -1; 327 else if (__off) 328 _M_file.seekoff(__off, ios_base::cur); 329 } 330 else 331 _M_file.sync(); 332 333 _M_last_overflowed = false; 334 return __ret; 335 } 336 337 // [documentation is inherited] 338 virtual void 339 imbue(const locale& __loc); 340 341 // [documentation is inherited] 342 virtual streamsize 343 xsgetn(char_type* __s, streamsize __n) 344 { 345 streamsize __ret = 0; 346 // Clear out pback buffer before going on to the real deal... 347 if (_M_pback_init) 348 { 349 while (__ret < __n && _M_in_cur < _M_in_end) 350 { 351 *__s = *_M_in_cur; 352 ++__ret; 353 ++__s; 354 ++_M_in_cur; 355 } 356 _M_pback_destroy(); 357 } 358 if (__ret < __n) 359 __ret += __streambuf_type::xsgetn(__s, __n - __ret); 360 return __ret; 361 } 362 363 // [documentation is inherited] 364 virtual streamsize 365 xsputn(const char_type* __s, streamsize __n) 366 { 367 _M_pback_destroy(); 368 return __streambuf_type::xsputn(__s, __n); 369 } 370 371 /** 372 * @if maint 373 * @doctodo 374 * @endif 375 */ 376 void 377 _M_output_unshift(); 378 379 // These three functions are used to clarify internal buffer 380 // maintenance. After an overflow, or after a seekoff call that 381 // started at beg or end, or possibly when the stream becomes 382 // unbuffered, and a myrid other obscure corner cases, the 383 // internal buffer does not truly reflect the contents of the 384 // external buffer. At this point, for whatever reason, it is in 385 // an indeterminate state. 386 /** 387 * @if maint 388 * @doctodo 389 * @endif 390 */ 391 void 392 _M_set_indeterminate(void) 393 { 394 if (_M_mode & ios_base::in) 395 this->setg(_M_buf, _M_buf, _M_buf); 396 if (_M_mode & ios_base::out) 397 this->setp(_M_buf, _M_buf); 398 _M_filepos = _M_buf; 399 } 400 401 /** 402 * @if maint 403 * @doctodo 404 * @endif 405 */ 406 void 407 _M_set_determinate(off_type __off) 408 { 409 bool __testin = _M_mode & ios_base::in; 410 bool __testout = _M_mode & ios_base::out; 411 if (__testin) 412 this->setg(_M_buf, _M_buf, _M_buf + __off); 413 if (__testout) 414 this->setp(_M_buf, _M_buf + __off); 415 _M_filepos = _M_buf + __off; 416 } 417 418 /** 419 * @if maint 420 * @doctodo 421 * @endif 422 */ 423 bool 424 _M_is_indeterminate(void) 425 { 426 bool __ret = false; 427 // Don't return true if unbuffered. 428 if (_M_buf) 429 { 430 if (_M_mode & ios_base::in) 431 __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end; 432 if (_M_mode & ios_base::out) 433 __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end; 434 } 435 return __ret; 436 } 437 }; 438 439 // Explicit specialization declarations, defined in src/fstream.cc. 440 template<> 441 basic_filebuf<char>::int_type 442 basic_filebuf<char>::_M_underflow_common(bool __bump); 443 444 #ifdef _GLIBCPP_USE_WCHAR_T 445 template<> 446 basic_filebuf<wchar_t>::int_type 447 basic_filebuf<wchar_t>::_M_underflow_common(bool __bump); 448 #endif 449 450 // Generic definitions. 451 template <typename _CharT, typename _Traits> 452 typename basic_filebuf<_CharT, _Traits>::int_type 453 basic_filebuf<_CharT, _Traits>::underflow() 454 { return _M_underflow_common(false); } 455 456 template <typename _CharT, typename _Traits> 457 typename basic_filebuf<_CharT, _Traits>::int_type 458 basic_filebuf<_CharT, _Traits>::uflow() 459 { return _M_underflow_common(true); } 460 461 462 // [27.8.1.5] Template class basic_ifstream 463 /** 464 * @brief Controlling input for files. 465 * 466 * This class supports reading from named files, using the inherited 467 * functions from std::basic_istream. To control the associated 468 * sequence, an instance of std::basic_filebuf is used, which this page 469 * refers to as @c sb. 470 */ 471 template<typename _CharT, typename _Traits> 472 class basic_ifstream : public basic_istream<_CharT, _Traits> 473 { 474 public: 475 // Types: 476 typedef _CharT char_type; 477 typedef _Traits traits_type; 478 typedef typename traits_type::int_type int_type; 479 typedef typename traits_type::pos_type pos_type; 480 typedef typename traits_type::off_type off_type; 481 482 // Non-standard types: 483 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 484 typedef basic_istream<char_type, traits_type> __istream_type; 485 486 private: 487 /** 488 * @if maint 489 * @doctodo 490 * @endif 491 */ 492 __filebuf_type _M_filebuf; 493 494 public: 495 // Constructors/Destructors: 496 /** 497 * @brief Default constructor. 498 * 499 * Initializes @c sb using its default constructor, and passes 500 * @c &sb to the base class initializer. Does not open any files 501 * (you haven't given it a filename to open). 502 */ 503 basic_ifstream() 504 : __istream_type(NULL), _M_filebuf() 505 { this->init(&_M_filebuf); } 506 507 /** 508 * @brief Create an input file stream. 509 * @param s Null terminated string specifying the filename. 510 * @param mode Open file in specified mode (see std::ios_base). 511 * 512 * @c ios_base::in is automatically included in @a mode. 513 * 514 * Tip: When using std::string to hold the filename, you must use 515 * .c_str() before passing it to this constructor. 516 */ 517 explicit 518 basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) 519 : __istream_type(NULL), _M_filebuf() 520 { 521 this->init(&_M_filebuf); 522 this->open(__s, __mode); 523 } 524 525 /** 526 * @brief The destructor does nothing. 527 * 528 * The file is closed by the filebuf object, not the formatting 529 * stream. 530 */ 531 ~basic_ifstream() 532 { } 533 534 // Members: 535 /** 536 * @brief Accessing the underlying buffer. 537 * @return The current basic_filebuf buffer. 538 * 539 * This hides both signatures of std::basic_ios::rdbuf(). 540 */ 541 __filebuf_type* 542 rdbuf() const 543 { return const_cast<__filebuf_type*>(&_M_filebuf); } 544 545 /** 546 * @brief Wrapper to test for an open file. 547 * @return @c rdbuf()->is_open() 548 */ 549 bool 550 is_open() { return _M_filebuf.is_open(); } 551 552 /** 553 * @brief Opens an external file. 554 * @param s The name of the file. 555 * @param mode The open mode flags. 556 * 557 * Calls @c std::basic_filebuf::open(s,mode|in). If that function 558 * fails, @c failbit is set in the stream's error state. 559 * 560 * Tip: When using std::string to hold the filename, you must use 561 * .c_str() before passing it to this constructor. 562 */ 563 void 564 open(const char* __s, ios_base::openmode __mode = ios_base::in) 565 { 566 if (!_M_filebuf.open(__s, __mode | ios_base::in)) 567 this->setstate(ios_base::failbit); 568 } 569 570 /** 571 * @brief Close the file. 572 * 573 * Calls @c std::basic_filebuf::close(). If that function 574 * fails, @c failbit is set in the stream's error state. 575 */ 576 void 577 close() 578 { 579 if (!_M_filebuf.close()) 580 this->setstate(ios_base::failbit); 581 } 582 }; 583 584 585 // [27.8.1.8] Template class basic_ofstream 586 /** 587 * @brief Controlling output for files. 588 * 589 * This class supports reading from named files, using the inherited 590 * functions from std::basic_ostream. To control the associated 591 * sequence, an instance of std::basic_filebuf is used, which this page 592 * refers to as @c sb. 593 */ 594 template<typename _CharT, typename _Traits> 595 class basic_ofstream : public basic_ostream<_CharT,_Traits> 596 { 597 public: 598 // Types: 599 typedef _CharT char_type; 600 typedef _Traits traits_type; 601 typedef typename traits_type::int_type int_type; 602 typedef typename traits_type::pos_type pos_type; 603 typedef typename traits_type::off_type off_type; 604 605 // Non-standard types: 606 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 607 typedef basic_ostream<char_type, traits_type> __ostream_type; 608 609 private: 610 /** 611 * @if maint 612 * @doctodo 613 * @endif 614 */ 615 __filebuf_type _M_filebuf; 616 617 public: 618 // Constructors: 619 /** 620 * @brief Default constructor. 621 * 622 * Initializes @c sb using its default constructor, and passes 623 * @c &sb to the base class initializer. Does not open any files 624 * (you haven't given it a filename to open). 625 */ 626 basic_ofstream() 627 : __ostream_type(NULL), _M_filebuf() 628 { this->init(&_M_filebuf); } 629 630 /** 631 * @brief Create an output file stream. 632 * @param s Null terminated string specifying the filename. 633 * @param mode Open file in specified mode (see std::ios_base). 634 * 635 * @c ios_base::out|ios_base::trunc is automatically included in 636 * @a mode. 637 * 638 * Tip: When using std::string to hold the filename, you must use 639 * .c_str() before passing it to this constructor. 640 */ 641 explicit 642 basic_ofstream(const char* __s, 643 ios_base::openmode __mode = ios_base::out|ios_base::trunc) 644 : __ostream_type(NULL), _M_filebuf() 645 { 646 this->init(&_M_filebuf); 647 this->open(__s, __mode); 648 } 649 650 /** 651 * @brief The destructor does nothing. 652 * 653 * The file is closed by the filebuf object, not the formatting 654 * stream. 655 */ 656 ~basic_ofstream() 657 { } 658 659 // Members: 660 /** 661 * @brief Accessing the underlying buffer. 662 * @return The current basic_filebuf buffer. 663 * 664 * This hides both signatures of std::basic_ios::rdbuf(). 665 */ 666 __filebuf_type* 667 rdbuf() const 668 { return const_cast<__filebuf_type*>(&_M_filebuf); } 669 670 /** 671 * @brief Wrapper to test for an open file. 672 * @return @c rdbuf()->is_open() 673 */ 674 bool 675 is_open() { return _M_filebuf.is_open(); } 676 677 /** 678 * @brief Opens an external file. 679 * @param s The name of the file. 680 * @param mode The open mode flags. 681 * 682 * Calls @c std::basic_filebuf::open(s,mode|out|trunc). If that 683 * function fails, @c failbit is set in the stream's error state. 684 * 685 * Tip: When using std::string to hold the filename, you must use 686 * .c_str() before passing it to this constructor. 687 */ 688 void 689 open(const char* __s, 690 ios_base::openmode __mode = ios_base::out | ios_base::trunc) 691 { 692 if (!_M_filebuf.open(__s, __mode | ios_base::out)) 693 this->setstate(ios_base::failbit); 694 } 695 696 /** 697 * @brief Close the file. 698 * 699 * Calls @c std::basic_filebuf::close(). If that function 700 * fails, @c failbit is set in the stream's error state. 701 */ 702 void 703 close() 704 { 705 if (!_M_filebuf.close()) 706 this->setstate(ios_base::failbit); 707 } 708 }; 709 710 711 // [27.8.1.11] Template class basic_fstream 712 /** 713 * @brief Controlling intput and output for files. 714 * 715 * This class supports reading from and writing to named files, using 716 * the inherited functions from std::basic_iostream. To control the 717 * associated sequence, an instance of std::basic_filebuf is used, which 718 * this page refers to as @c sb. 719 */ 720 template<typename _CharT, typename _Traits> 721 class basic_fstream : public basic_iostream<_CharT, _Traits> 722 { 723 public: 724 // Types: 725 typedef _CharT char_type; 726 typedef _Traits traits_type; 727 typedef typename traits_type::int_type int_type; 728 typedef typename traits_type::pos_type pos_type; 729 typedef typename traits_type::off_type off_type; 730 731 // Non-standard types: 732 typedef basic_filebuf<char_type, traits_type> __filebuf_type; 733 typedef basic_ios<char_type, traits_type> __ios_type; 734 typedef basic_iostream<char_type, traits_type> __iostream_type; 735 736 private: 737 /** 738 * @if maint 739 * @doctodo 740 * @endif 741 */ 742 __filebuf_type _M_filebuf; 743 744 public: 745 // Constructors/destructor: 746 /** 747 * @brief Default constructor. 748 * 749 * Initializes @c sb using its default constructor, and passes 750 * @c &sb to the base class initializer. Does not open any files 751 * (you haven't given it a filename to open). 752 */ 753 basic_fstream() 754 : __iostream_type(NULL), _M_filebuf() 755 { this->init(&_M_filebuf); } 756 757 /** 758 * @brief Create an input/output file stream. 759 * @param s Null terminated string specifying the filename. 760 * @param mode Open file in specified mode (see std::ios_base). 761 * 762 * Tip: When using std::string to hold the filename, you must use 763 * .c_str() before passing it to this constructor. 764 */ 765 explicit 766 basic_fstream(const char* __s, 767 ios_base::openmode __mode = ios_base::in | ios_base::out) 768 : __iostream_type(NULL), _M_filebuf() 769 { 770 this->init(&_M_filebuf); 771 this->open(__s, __mode); 772 } 773 774 /** 775 * @brief The destructor does nothing. 776 * 777 * The file is closed by the filebuf object, not the formatting 778 * stream. 779 */ 780 ~basic_fstream() 781 { } 782 783 // Members: 784 /** 785 * @brief Accessing the underlying buffer. 786 * @return The current basic_filebuf buffer. 787 * 788 * This hides both signatures of std::basic_ios::rdbuf(). 789 */ 790 __filebuf_type* 791 rdbuf() const 792 { return const_cast<__filebuf_type*>(&_M_filebuf); } 793 794 /** 795 * @brief Wrapper to test for an open file. 796 * @return @c rdbuf()->is_open() 797 */ 798 bool 799 is_open() { return _M_filebuf.is_open(); } 800 801 /** 802 * @brief Opens an external file. 803 * @param s The name of the file. 804 * @param mode The open mode flags. 805 * 806 * Calls @c std::basic_filebuf::open(s,mode). If that 807 * function fails, @c failbit is set in the stream's error state. 808 * 809 * Tip: When using std::string to hold the filename, you must use 810 * .c_str() before passing it to this constructor. 811 */ 812 void 813 open(const char* __s, 814 ios_base::openmode __mode = ios_base::in | ios_base::out) 815 { 816 if (!_M_filebuf.open(__s, __mode)) 817 setstate(ios_base::failbit); 818 } 819 820 /** 821 * @brief Close the file. 822 * 823 * Calls @c std::basic_filebuf::close(). If that function 824 * fails, @c failbit is set in the stream's error state. 825 */ 826 void 827 close() 828 { 829 if (!_M_filebuf.close()) 830 setstate(ios_base::failbit); 831 } 832 }; 833 } // namespace std 834 835 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT 836 # define export 837 #endif 838 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS 839 # include <bits/fstream.tcc> 840 #endif 841 842 #endif 843