1 // File based streams -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 // ISO C++ 14882: 27.8 File-based streams
34 #ifndef _CPP_BITS_FSTREAM_TCC
35 #define _CPP_BITS_FSTREAM_TCC 1
39 template<typename _CharT, typename _Traits>
41 basic_filebuf<_CharT, _Traits>::
46 _M_buf_unified = true; // Tie input to output for basic_filebuf.
48 { _M_file = new __file_type(&_M_lock); }
52 __throw_exception_again;
57 template<typename _CharT, typename _Traits>
59 basic_filebuf<_CharT, _Traits>::
64 _M_buf_size = _M_buf_size_opt;
65 // Allocate internal buffer.
66 try { _M_buf = new char_type[_M_buf_size]; }
70 __throw_exception_again;
73 // Allocate pback buffer.
75 { _M_pback = new char_type[_M_pback_size]; }
79 __throw_exception_again;
84 template<typename _CharT, typename _Traits>
85 basic_filebuf<_CharT, _Traits>::
87 : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()),
88 _M_state_beg(__state_type()), _M_last_overflowed(false)
89 { _M_fcvt = &use_facet<__codecvt_type>(this->getloc()); }
91 template<typename _CharT, typename _Traits>
92 basic_filebuf<_CharT, _Traits>::
93 basic_filebuf(int __fd, const char* /*__name*/, ios_base::openmode __mode)
94 : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()),
95 _M_state_beg(__state_type()), _M_last_overflowed(false)
97 _M_fcvt = &use_facet<__codecvt_type>(this->getloc());
99 _M_file->sys_open(__fd, __mode);
102 _M_allocate_buffers();
105 // XXX So that istream::getc() will only need to get 1 char,
106 // as opposed to BUF_SIZE.
110 this->_M_set_indeterminate();
114 template<typename _CharT, typename _Traits>
115 basic_filebuf<_CharT, _Traits>::__filebuf_type*
116 basic_filebuf<_CharT, _Traits>::
117 open(const char* __s, ios_base::openmode __mode)
119 __filebuf_type *__ret = NULL;
120 if (!this->is_open())
123 _M_file->open(__s, __mode);
126 _M_allocate_buffers();
129 // For time being, set both (in/out) sets of pointers.
130 _M_set_indeterminate();
131 if (__mode & ios_base::ate
132 && this->seekoff(0, ios_base::end, __mode) < 0)
140 template<typename _CharT, typename _Traits>
141 basic_filebuf<_CharT, _Traits>::__filebuf_type*
142 basic_filebuf<_CharT, _Traits>::
145 __filebuf_type *__ret = NULL;
148 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
150 _M_really_overflow(traits_type::eof());
152 // NB: Do this here so that re-opened filebufs will be cool...
157 if (_M_last_overflowed)
160 _M_really_overflow(traits_type::eof());
164 _M_mode = ios_base::openmode(0);
171 this->setg(NULL, NULL, NULL);
172 this->setp(NULL, NULL);
177 // Can actually allocate this file as part of an open and never
178 // have it be opened.....
184 _M_last_overflowed = false;
188 template<typename _CharT, typename _Traits>
190 basic_filebuf<_CharT, _Traits>::
193 streamsize __ret = -1;
194 bool __testin = _M_mode & ios_base::in;
198 bool __testeof = false;
199 if (_M_in_cur >= _M_in_end)
200 __testeof = this->underflow() == traits_type::eof();
202 __ret = _M_in_end - _M_in_cur;
204 _M_last_overflowed = false;
208 template<typename _CharT, typename _Traits>
209 basic_filebuf<_CharT, _Traits>::int_type
210 basic_filebuf<_CharT, _Traits>::
213 int_type __ret = traits_type::eof();
214 bool __testin = _M_mode & ios_base::in;
218 // Check for pback madness, and if so swich back to the
219 // normal buffers and jet outta here before expensive
224 if (_M_in_cur < _M_in_end)
225 return traits_type::to_int_type(*_M_in_cur);
228 bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
229 bool __testinit = _M_is_indeterminate();
230 bool __testout = _M_mode & ios_base::out;
232 // Sync internal and external buffers.
233 // NB: __testget -> __testput as _M_buf_unified here.
237 _M_really_overflow();
239 _M_file->seekoff(_M_in_cur - _M_in_beg,
240 ios_base::cur, ios_base::in);
243 if (__testinit || __testget)
246 streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size);
249 _M_set_determinate(__size);
251 _M_out_cur = _M_in_cur;
252 __ret = traits_type::to_int_type(*_M_in_cur);
253 streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur,
257 // XXX Something is wrong, do error checking.
261 // 2000-08-04 bkoz disable
262 // Part one: (Re)fill external buf (_M_file->_IO_*) from
263 // external byte sequence (whatever physical byte sink or
264 // FILE actually is.)
265 char_type __conv_buf[_M_buf_size];
266 streamsize __size = _M_file->xsgetn(__conv_buf, _M_buf_size);
268 // Part two: (Re)fill internal buf contents from external buf.
271 _M_set_determinate(__size);
273 char* __conv_cur = __conv_buf;
274 _M_state_beg = _M_state_cur;
275 __res_type __r = _M_fcvt->in(_M_state_cur,
278 const_cast<const char*&>(__conv_cur),
279 _M_in_beg, _M_in_end, _M_in_cur);
281 if (__r == codecvt_base::partial)
283 // XXX Retry with larger _M_buf size.
286 // Set pointers to internal and external buffers
288 if (__r != codecvt_base::error)
291 _M_out_cur = _M_in_cur;
292 __ret = traits_type::to_int_type(*_M_in_cur);
295 // Part three: Sync the current internal buffer
296 // position with the (now overshot) external buffer
298 streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur,
302 // XXX Something is wrong, do error checking.
308 _M_last_overflowed = false;
312 template<typename _CharT, typename _Traits>
313 basic_filebuf<_CharT, _Traits>::int_type
314 basic_filebuf<_CharT, _Traits>::
315 pbackfail(int_type __i)
317 int_type __ret = traits_type::eof();
318 bool __testin = _M_mode & ios_base::in;
322 bool __testpb = _M_in_beg < _M_in_cur;
323 char_type __c = traits_type::to_char_type(__i);
324 bool __testeof = traits_type::eq_int_type(__i, __ret);
328 bool __testout = _M_mode & ios_base::out;
329 bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
331 // Try to put back __c into input sequence in one of three ways.
332 // Order these tests done in is unspecified by the standard.
333 if (!__testeof && __testeq)
345 __ret = traits_type::not_eof(__i);
359 // At the beginning of the buffer, need to make a
360 // putback position available.
361 this->seekoff(-1, ios_base::cur);
365 if (!traits_type::eq(__c, *_M_in_cur))
373 __ret = traits_type::not_eof(__i);
376 _M_last_overflowed = false;
380 template<typename _CharT, typename _Traits>
381 basic_filebuf<_CharT, _Traits>::int_type
382 basic_filebuf<_CharT, _Traits>::
383 overflow(int_type __c)
385 int_type __ret = traits_type::eof();
386 bool __testpos = _M_out_cur && _M_out_cur >= _M_buf + _M_buf_size;
387 bool __testout = _M_mode & ios_base::out;
393 *_M_out_cur = traits_type::to_char_type(__c);
395 __ret = traits_type::not_eof(__c);
398 __ret = this->_M_really_overflow(__c);
401 _M_last_overflowed = false; // Set in _M_really_overflow, below.
405 template<typename _CharT, typename _Traits>
406 basic_filebuf<_CharT, _Traits>::int_type
407 basic_filebuf<_CharT, _Traits>::
408 _M_really_overflow(int_type __c)
410 int_type __ret = traits_type::eof();
411 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
415 bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
417 int __plen = _M_out_end - _M_out_beg;
418 streamsize __len = _M_file->xsputn(_M_out_beg, __plen);
421 char_type __pending = traits_type::to_char_type(__c);
422 __len += _M_file->xsputn(&__pending, 1);
425 traits_type::to_char_type(__c);
426 // NB: Need this so that external byte sequence reflects
431 _M_set_indeterminate();
432 __ret = traits_type::not_eof(__c);
435 // Part one: Allocate temporary conversion buffer on
436 // stack. Convert internal buffer plus __c (ie,
437 // "pending sequence") to temporary conversion buffer.
438 int __plen = _M_out_end - _M_out_beg;
439 char_type __pbuf[__plen + 1];
440 traits_type::copy(__pbuf, this->pbase(), __plen);
443 __pbuf[__plen] = traits_type::to_char_type(__c);
448 char __conv_buf[__plen];
450 _M_state_beg = _M_state_cur;
452 __res_type __r = _M_fcvt->out(_M_state_cur,
453 __pbuf, __pbuf + __plen,
454 const_cast<const char_type*&>(__pend),
455 __conv_buf, __conv_buf + __plen,
458 // Part two: (Re)spill converted "pending sequence"
459 // contents (now in temporary conversion buffer) to
460 // external buffer (_M_file->_IO_*) using
461 // _M_file->sys_write(), and do error (minimal) checking.
462 if (__r != codecvt_base::error)
464 streamsize __len = _M_file->xsputn(__conv_buf, __plen);
465 // NB: Need this so that external byte sequence reflects
470 _M_set_indeterminate();
471 __ret = traits_type::not_eof(__c);
476 _M_last_overflowed = true;
480 template<typename _CharT, typename _Traits>
481 basic_filebuf<_CharT, _Traits>::pos_type
482 basic_filebuf<_CharT, _Traits>::
483 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
485 pos_type __ret = pos_type(off_type(-1));
486 bool __testopen = this->is_open();
487 bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
488 bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
489 int __width = _M_fcvt->encoding();
492 bool __testfail = __off != 0 && __width <= 0;
494 if (__testopen && !__testfail && (__testin || __testout))
496 // Ditch any pback buffers to avoid confusion.
499 if (__way != ios_base::cur || __off != 0)
501 off_type __computed_off = __width * __off;
503 bool __testget = _M_in_cur && _M_in_beg < _M_in_end;
504 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
505 // Sync the internal and external streams.
507 if (__testput || _M_last_overflowed)
509 // Part one: update the output sequence.
511 // Part two: output unshift sequence.
515 // NB: underflow() rewinds the external buffer.
516 else if (__testget && __way == ios_base::cur)
517 __computed_off += _M_in_cur - _M_in_beg;
519 __ret = _M_file->seekoff(__computed_off, __way, __mode);
520 _M_set_indeterminate();
522 // NB: Need to do this in case _M_file in indeterminate
523 // state, ie _M_file->_offset == -1
526 __ret = _M_file->seekoff(__off, ios_base::cur, __mode);
527 __ret += max(_M_out_cur, _M_in_cur) - _M_buf;
530 _M_last_overflowed = false;
534 template<typename _CharT, typename _Traits>
535 basic_filebuf<_CharT, _Traits>::pos_type
536 basic_filebuf<_CharT, _Traits>::
537 seekpos(pos_type __pos, ios_base::openmode __mode)
540 off_type __off = __pos;
542 __ret = this->seekoff(__off, ios_base::beg, __mode);
544 _M_last_overflowed = false;
548 template<typename _CharT, typename _Traits>
550 basic_filebuf<_CharT, _Traits>::
554 template<typename _CharT, typename _Traits>
556 basic_filebuf<_CharT, _Traits>::
557 imbue(const locale& __loc)
559 bool __testbeg = gptr() == eback() && pptr() == pbase();
560 bool __teststate = _M_fcvt->encoding() == -1;
562 _M_buf_locale_init = true;
563 if (__testbeg && !__teststate && _M_buf_locale != __loc)
565 // XXX Will need to save these older values.
566 _M_buf_locale = __loc;
567 _M_fcvt = &use_facet<__codecvt_type>(_M_buf_locale);
569 _M_buf_fctype = &use_facet<__ctype_type>(_M_buf_locale);
571 // NB this may require the reconversion of previously
572 // converted chars. This in turn may cause the reconstruction
573 // of the original file. YIKES!!
574 // XXX The part in the above comment is not done.
575 _M_last_overflowed = false;
580 #endif // _CPP_BITS_FSTREAM_TCC