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