source: trunk/src/gcc/libstdc++-v3/include/std/std_fstream.h@ 615

Last change on this file since 615 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 17.0 KB
Line 
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
Note: See TracBrowser for help on using the repository browser.