]> gcc.gnu.org Git - gcc.git/blame - libstdc++-v3/bits/fstream.tcc
filebuf.cc: Tweak.
[gcc.git] / libstdc++-v3 / bits / fstream.tcc
CommitLineData
b2dad0e3
BK
1// File based streams -*- C++ -*-
2
d207c3f7 3// Copyright (C) 1997-1999, 2000 Free Software Foundation, Inc.
b2dad0e3
BK
4//
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)
9// any later version.
10
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.
15
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,
19// USA.
20
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.
29
30//
31// ISO C++ 14882: 27.8 File-based streams
32//
33
34#ifndef _CPP_BITS_FSTREAM_TCC
35#define _CPP_BITS_FSTREAM_TCC 1
36
37namespace std
38{
39 template<typename _CharT, typename _Traits>
40 void
41 basic_filebuf<_CharT, _Traits>::
42 _M_init_filebuf(void)
43 {
44 _M_buf_unified = true; // Tie input to output for basic_filebuf.
d207c3f7 45 _M_buf_size = _M_buf_size_opt;
b2dad0e3
BK
46 try {
47 _M_file = new __file_type(&_M_lock);
48 }
49 catch(...) {
50 delete _M_file;
51 throw;
52 }
53 }
54
55 template<typename _CharT, typename _Traits>
56 basic_filebuf<_CharT, _Traits>::
57 basic_filebuf()
81ef1479 58 : __streambuf_type(), _M_file(NULL), _M_state_cur(), _M_state_beg(),
ab30ba5c 59 _M_last_overflowed(false)
b2dad0e3
BK
60 { _M_fcvt = &use_facet<__codecvt_type>(this->getloc()); }
61
b2dad0e3
BK
62 template<typename _CharT, typename _Traits>
63 basic_filebuf<_CharT, _Traits>::
64 basic_filebuf(int __fd, const char* /*__name*/, ios_base::openmode __mode)
81ef1479
BK
65 : __streambuf_type(), _M_state_cur(), _M_state_beg(),
66 _M_last_overflowed(false)
b2dad0e3
BK
67 {
68 _M_fcvt = &use_facet<__codecvt_type>(this->getloc());
69 _M_init_filebuf();
70 _M_file->sys_open(__fd, __mode);
71 if (this->is_open() && _M_buf_size)
72 {
73 _M_mode = __mode;
74 // XXX So that istream::getc() will only need to get 1 char,
75 // as opposed to BUF_SIZE.
76 if (__fd == 0)
77 _M_buf_size = 1;
78
79 try {
80 _M_buf = new char_type[_M_buf_size];
81 }
82 catch(...) {
83 delete [] _M_buf;
84 throw;
85 }
86
87 this->_M_set_indeterminate();
88 }
89 }
90
91 template<typename _CharT, typename _Traits>
92 basic_filebuf<_CharT, _Traits>::__filebuf_type*
93 basic_filebuf<_CharT, _Traits>::
94 open(const char* __s, ios_base::openmode __mode)
95 {
96 __filebuf_type *__retval = NULL;
97 if (!this->is_open())
98 {
99 _M_init_filebuf();
100 _M_file->open(__s, __mode);
101 if (this->is_open() && _M_buf_size)
102 {
103 _M_mode = __mode;
104
105 try {
106 _M_buf = new char_type[_M_buf_size];
107 }
108 catch(...) {
109 delete [] _M_buf;
110 throw;
111 }
112
113 // For time being, set both (in/out) sets of pointers.
114 _M_set_indeterminate();
115 if (__mode & ios_base::ate
116 && this->seekoff(0, ios_base::end, __mode) < 0)
117 this->close();
118 __retval = this;
119 }
120 }
121 return __retval;
122 }
123
124 template<typename _CharT, typename _Traits>
125 basic_filebuf<_CharT, _Traits>::__filebuf_type*
126 basic_filebuf<_CharT, _Traits>::
127 close()
128 {
129 __filebuf_type *__retval = NULL;
130 if (this->is_open())
131 {
132 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
133 if (__testput)
134 _M_really_overflow(traits_type::eof());
135
136#if 0
137 // XXX not done
138 if (_M_last_overflowed)
139 {
140 _M_output_unshift();
141 _M_really_overflow(traits_type::eof());
142 }
143#endif
81ef1479 144
ab30ba5c 145 if (_M_file)
b2dad0e3 146 {
ab30ba5c
BK
147 delete _M_file;
148 _M_file = NULL;
b2dad0e3
BK
149 _M_mode = ios_base::openmode(0);
150 if (_M_buf_size)
151 delete [] _M_buf;
152 _M_buf = NULL;
153 this->setg(NULL, NULL, NULL);
154 this->setp(NULL, NULL);
155 __retval = this;
156 }
157 }
158 _M_last_overflowed = false;
159 return __retval;
160 }
161
162 template<typename _CharT, typename _Traits>
163 streamsize
164 basic_filebuf<_CharT, _Traits>::
165 showmanyc()
166 {
167 streamsize __retval = -1;
168 bool __testin = _M_mode & ios_base::in;
169
170 if (__testin)
171 {
172 bool __testeof = false;
173 if (_M_in_cur >= _M_in_end)
174 __testeof = this->underflow() == traits_type::eof();
175 if (!__testeof)
176 __retval = (_M_in_end - _M_in_cur) / sizeof(char_type);
177 }
178 _M_last_overflowed = false;
179 return __retval;
180 }
181
182 template<typename _CharT, typename _Traits>
183 basic_filebuf<_CharT, _Traits>::int_type
184 basic_filebuf<_CharT, _Traits>::
185 underflow()
186 {
187 int_type __retval = traits_type::eof();
188 bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
189 bool __testinit = _M_is_indeterminate();
190 bool __testout = _M_mode & ios_base::out;
191 bool __testin = _M_mode & ios_base::in;
192
193 if (__testin)
194 {
195 // Sync internal and external buffers.
196 // NB: __testget -> __testput as _M_buf_unified here.
197 if (__testget)
198 {
199 if (__testout)
200 _M_really_overflow();
201 else
f3b004d8
BK
202 _M_file->seekoff(_M_in_cur - _M_in_beg,
203 ios_base::cur, ios_base::in);
b2dad0e3
BK
204 }
205
206 if (__testinit || __testget)
207 {
208 // Part one: (Re)fill external buf (_M_file->_IO_*) from
209 // external byte sequence (whatever physical byte sink or
210 // FILE actually is.)
211 char __conv_buf[_M_buf_size];
f3b004d8 212 streamsize __size = _M_file->xsgetn(__conv_buf, _M_buf_size);
b2dad0e3
BK
213
214 // Part two: (Re)fill internal buf contents from external buf.
215 if (0 < __size)
216 {
217 _M_set_determinate(__size);
218
219 char* __conv_cur = __conv_buf;
220 _M_state_beg = _M_state_cur;
221 __res_type __r = _M_fcvt->in(_M_state_cur,
222 __conv_buf,
223 __conv_buf + __size,
224 const_cast<const char*&>(__conv_cur),
225 _M_in_beg, _M_in_end, _M_in_cur);
226
227 if (__r == codecvt_base::partial)
228 {
229 // XXX Retry with larger _M_buf size.
230 }
231
232 // Set pointers to internal and external buffers
233 // correctly. . .
234 if (__r != codecvt_base::error)
235 {
236 if (__testout)
237 _M_out_cur = _M_in_cur;
238 __retval = traits_type::to_int_type(*_M_in_cur);
239 }
240
241 // Part three: Sync the current internal buffer
242 // position with the (now overshot) external buffer
243 // position.
f3b004d8 244 streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur,
b2dad0e3 245 ios_base::in);
f3b004d8 246 if (__p == -1)
b2dad0e3
BK
247 {
248 // XXX Something is wrong, do error checking.
249 }
250 }
251 }
252 }
253 _M_last_overflowed = false;
254 return __retval;
255 }
256
257 template<typename _CharT, typename _Traits>
258 basic_filebuf<_CharT, _Traits>::int_type
259 basic_filebuf<_CharT, _Traits>::
260 pbackfail(int_type __i)
261 {
262 int_type __retval = traits_type::eof();
263 char_type __c = traits_type::to_char_type(__i);
264 bool __testeof = traits_type::eq_int_type(__i, traits_type::eof());
265 bool __testout = _M_mode & ios_base::out;
266 bool __testin = _M_mode & ios_base::in;
267
268 if (__testin)
269 {
270 if (!_M_is_indeterminate())
271 {
272 bool __testpb = _M_in_beg < _M_in_cur;
273 bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
274
275 // Try to put back __c into input sequence in one of three ways.
276 // Order these tests done in is unspecified by the standard.
277 if (!__testeof && __testpb && __testeq)
278 {
279 --_M_in_cur;
280 if (__testout)
281 --_M_out_cur;
282 __retval = __i;
283 }
284 else if (!__testeof && __testpb && __testout)
285 {
286 --_M_in_cur;
287 if (__testout)
288 --_M_out_cur;
289 *_M_in_cur = __c;
290 __retval = __i;
291 }
292 else if (__testeof && __testpb)
293 {
294 --_M_in_cur;
295 if (__testout)
296 --_M_out_cur;
297 __retval = traits_type::not_eof(__i);
298 }
299 }
300 else
301 {
302 // Need to make a putback position available.
303 this->seekoff(-1, ios_base::cur);
304 this->underflow();
305 if (!__testeof)
306 {
307 *_M_in_cur = __c;
308 __retval = __c;
309 }
310 else
311 __retval = traits_type::not_eof(__i);
312 }
313 }
314 _M_last_overflowed = false;
315 return __retval;
316 }
317
318 template<typename _CharT, typename _Traits>
319 basic_filebuf<_CharT, _Traits>::int_type
320 basic_filebuf<_CharT, _Traits>::
321 overflow(int_type __c)
322 {
323 int_type __retval = traits_type::eof();
324 bool __testpos = _M_out_cur && _M_out_cur >= _M_buf + _M_buf_size;
325 bool __testout = _M_mode & ios_base::out;
326
327 if (__testout)
328 {
329 if (!__testpos)
330 {
331 *_M_out_cur = traits_type::to_char_type(__c);
332 _M_buf_bump(1);
333 __retval = traits_type::not_eof(__c);
334 }
335 else
336 __retval = this->_M_really_overflow(__c);
337 }
338
339 _M_last_overflowed = false; // Set in _M_really_overflow, below.
340 return __retval;
341 }
342
343 template<typename _CharT, typename _Traits>
344 basic_filebuf<_CharT, _Traits>::int_type
345 basic_filebuf<_CharT, _Traits>::
346 _M_really_overflow(int_type __c)
347 {
348 int_type __retval = traits_type::eof();
349 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
350 bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
351
352 if (__testput)
353 {
354 // Part one: Allocate temporary conversion buffer on
355 // stack. Convert internal buffer plus __c (ie,
356 // "pending sequence") to temporary conversion buffer.
357 int __plen = _M_out_end - _M_out_beg;
358 char_type __pbuf[__plen + sizeof(char_type)];
359 traits_type::copy(__pbuf, this->pbase(), __plen);
360 if (!__testeof)
361 {
362 __pbuf[__plen] = traits_type::to_char_type(__c);
363 ++__plen;
364 }
365
366 char_type* __pend;
367 char __conv_buf[__plen];
368 char* __conv_end;
369 _M_state_beg = _M_state_cur;
370
371 __res_type __r = _M_fcvt->out(_M_state_cur,
372 __pbuf, __pbuf + __plen,
373 const_cast<const char_type*&>(__pend),
374 __conv_buf, __conv_buf + __plen,
375 __conv_end);
376
377 // Part two: (Re)spill converted "pending sequence"
378 // contents (now in temporary conversion buffer) to
379 // external buffer (_M_file->_IO_*) using
380 // _M_file->sys_write(), and do error (minimal) checking.
381 if (__r != codecvt_base::error)
382 {
f3b004d8 383 streamsize __len = _M_file->xsputn(__conv_buf, __plen);
b2dad0e3
BK
384 // NB: Need this so that external byte sequence reflects
385 // internal buffer.
386 _M_file->sync();
f3b004d8 387 if (__len == __plen)
b2dad0e3
BK
388 {
389 _M_set_indeterminate();
390 __retval = traits_type::not_eof(__c);
391 }
392 }
393 }
394 _M_last_overflowed = true;
395 return __retval;
396 }
397
398 template<typename _CharT, typename _Traits>
399 basic_filebuf<_CharT, _Traits>::pos_type
400 basic_filebuf<_CharT, _Traits>::
401 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
402 {
403 pos_type __retval = pos_type(off_type(-1));
404 bool __testopen = this->is_open();
405 bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
406 bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
407 int __width = _M_fcvt->encoding();
408 if (__width < 0)
409 __width = 0;
410 bool __testfail = __off != 0 && __width <= 0;
411
412 if (__testopen && !__testfail && (__testin || __testout))
413 {
414 if (__way != ios_base::cur || __off != 0)
415 {
416 off_type __computed_off = __width * __off;
417
418 bool __testget = _M_in_cur && _M_in_beg < _M_in_end;
419 bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
420 // Sync the internal and external streams.
421 // out
422 if (__testput || _M_last_overflowed)
423 {
424 // Part one: update the output sequence.
425 this->sync();
426 // Part two: output unshift sequence.
427 _M_output_unshift();
428 }
429 //in
430 // NB: underflow() rewinds the external buffer.
431 else if (__testget && __way == ios_base::cur)
432 __computed_off += _M_in_cur - _M_in_beg;
433
434 __retval = _M_file->seekoff(__computed_off, __way, __mode);
b2dad0e3
BK
435 _M_set_indeterminate();
436 }
437 // NB: Need to do this in case _M_file in indeterminate
438 // state, ie _M_file->_offset == -1
439 else
440 {
441 __retval = _M_file->seekoff(__off, ios_base::cur, __mode);
442 __retval += max(_M_out_cur, _M_in_cur) - _M_buf;
443 }
444 }
445 _M_last_overflowed = false;
446 return __retval;
447 }
448
449 template<typename _CharT, typename _Traits>
450 basic_filebuf<_CharT, _Traits>::pos_type
451 basic_filebuf<_CharT, _Traits>::
452 seekpos(pos_type __pos, ios_base::openmode __mode)
453 {
454 pos_type __retval;
455 off_type __off = __pos;
456
457 __retval = this->seekoff(__off, ios_base::beg, __mode);
458
459 _M_last_overflowed = false;
460 return __retval;
461 }
462
463 template<typename _CharT, typename _Traits>
464 void
465 basic_filebuf<_CharT, _Traits>::
466 _M_output_unshift()
467 {
468#if 0
469 // XXX Not complete, or correct.
470 int __width = _M_fcvt->encoding();
471
472 if (__width < 0)
473 {
474 // Part one: call codecvt::unshift
475 int __unsft_len = 0;
476 char_type __unsft_buf[_M_buf_size];
477 char_type* __unsft_cur; // XXX Set to external buf.
478 _M_state_beg = _M_state_cur;
479 __res_type __r = _M_fcvt->unshift(_M_state_cur,
480 __unsft_buf,
481 __unsft_buf + _M_buf_size,
482 __unsft_cur);
483
484 // Note, for char_type == char, wchar_t unshift
485 // should store no charachers.
486 if (__r == codecvt_base::ok || __r == codecvt_base::noconv)
487 __unsft_len = __unsft_cur - __unsft_buf;
488
489 // "Output the resulting sequence."
490 if (__unsft_len)
491 {
492 int __plen = _M_out_cur - _M_out_beg;
493 int __rlen = __plen + __unsft_len;
494 char_type __rbuf[__rlen];
495 char_type* __rend;
496 traits_type::copy(__rbuf, this->pbase(), __plen);
497 traits_type::copy(__rbuf + __plen, __unsft_buf,
498 __unsft_len);
499
500 char __conv_buf[__rlen];
501 char* __conv_end;
502
503 _M_state_beg = _M_state_cur; // XXX Needed?
504 __r = _M_fcvt->out(_M_state_cur,
505 __rbuf, __rbuf + __rlen,
506 const_cast<const char_type*&>(__rend),
507 __conv_buf,
508 __conv_buf + __rlen,
509 __conv_end);
510
511 if (__r != codecvt_base::error)
512 {
f3b004d8 513 streamsize __r = _M_file->xsputn(__conv_buf, __rlen);
b2dad0e3
BK
514 if (__r == __rlen)
515 {
516 _M_out_cur = _M_out_beg;
517 if (_M_mode & ios_base::in)
518 _M_in_cur = _M_out_cur;
519 }
520 else
521 {
522 // XXX Throw "wig out and die exception?"
523 }
524 }
525 }
526 }
527#endif
528 }
529
530 template<typename _CharT, typename _Traits>
531 void
532 basic_filebuf<_CharT, _Traits>::
533 imbue(const locale& __loc)
534 {
535 bool __testbeg = gptr() == eback() && pptr() == pbase();
536 bool __teststate = _M_fcvt->encoding() == -1;
537
538 _M_locale_set = true;
539 if (__testbeg && !__teststate && _M_locale_buf != __loc)
540 {
541 // XXX Will need to save these older values.
542 _M_locale_buf = __loc;
543 _M_fcvt = &use_facet<__codecvt_type>(_M_locale_buf);
544 // XXX Necessary?
545 _M_fctype_buf = &use_facet<__ctype_type>(_M_locale_buf);
546 }
547 // NB this may require the reconversion of previously
548 // converted chars. This in turn may cause the reconstruction
549 // of the original file. YIKES!!
550 // XXX The part in the above comment is not done.
551 _M_last_overflowed = false;
552 }
553
554} // namespace std
555
556#endif // _CPP_BITS_FSTREAM_TCC
557
558
559
560
561
562
563
564
565
566
This page took 0.105093 seconds and 5 git commands to generate.