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