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