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   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