]> gcc.gnu.org Git - gcc.git/blame - libstdc++-v3/include/bits/fstream.tcc
value-prof.c: New.
[gcc.git] / libstdc++-v3 / include / bits / fstream.tcc
CommitLineData
725dc051
BK
1// File based streams -*- C++ -*-
2
8fbc5ae7 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
e6705174 4// Free Software Foundation, Inc.
725dc051
BK
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#ifndef _CPP_BITS_FSTREAM_TCC
36#define _CPP_BITS_FSTREAM_TCC 1
37
3b794528
BK
38#pragma GCC system_header
39
725dc051
BK
40namespace std
41{
725dc051
BK
42 template<typename _CharT, typename _Traits>
43 void
44 basic_filebuf<_CharT, _Traits>::
990101f9 45 _M_allocate_internal_buffer()
725dc051 46 {
e3033a22 47 if (!_M_buf_allocated && this->_M_buf_size)
13187a45 48 {
eb98bd16 49 // Allocate internal buffer.
391cd095 50 this->_M_buf = new char_type[this->_M_buf_size];
5cdd50a5 51 _M_buf_allocated = true;
990101f9
BK
52 }
53 }
54
55 // Both close and setbuf need to deallocate internal buffers, if it exists.
56 template<typename _CharT, typename _Traits>
57 void
58 basic_filebuf<_CharT, _Traits>::
a1796d12 59 _M_destroy_internal_buffer() throw()
990101f9
BK
60 {
61 if (_M_buf_allocated)
62 {
8fbc5ae7
MM
63 delete [] this->_M_buf;
64 this->_M_buf = NULL;
990101f9 65 _M_buf_allocated = false;
990101f9 66 }
725dc051
BK
67 }
68
69 template<typename _CharT, typename _Traits>
70 basic_filebuf<_CharT, _Traits>::
5cdd50a5 71 basic_filebuf() : __streambuf_type(), _M_file(&_M_lock),
f10eea7b
PC
72 _M_state_cur(__state_type()), _M_state_beg(__state_type()),
73 _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false),
71b46021
PC
74 _M_reading(false), _M_writing(false), _M_last_overflowed(false),
75 _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false),
76 _M_codecvt(0)
0cd1de6f 77 {
46c4e5d6 78 if (has_facet<__codecvt_type>(this->_M_buf_locale))
0cd1de6f
BK
79 _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
80 }
725dc051 81
725dc051 82 template<typename _CharT, typename _Traits>
31bfa177 83 typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
725dc051
BK
84 basic_filebuf<_CharT, _Traits>::
85 open(const char* __s, ios_base::openmode __mode)
86 {
87 __filebuf_type *__ret = NULL;
88 if (!this->is_open())
89 {
d3a193e3 90 _M_file.open(__s, __mode);
13187a45 91 if (this->is_open())
725dc051 92 {
990101f9 93 _M_allocate_internal_buffer();
8fbc5ae7 94 this->_M_mode = __mode;
6eeb7d7a 95
71b46021
PC
96 // Setup initial buffer to 'uncommitted' mode.
97 _M_reading = false;
98 _M_writing = false;
99 _M_set_buffer(-1);
6e52332e 100
e3033a22 101 if ((__mode & ios_base::ate)
725dc051 102 && this->seekoff(0, ios_base::end, __mode) < 0)
cc9d1c78
PC
103 // 27.8.1.3,4
104 this->close();
105 else
106 __ret = this;
725dc051
BK
107 }
108 }
109 return __ret;
110 }
111
112 template<typename _CharT, typename _Traits>
31bfa177 113 typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
725dc051 114 basic_filebuf<_CharT, _Traits>::
a1796d12 115 close() throw()
725dc051 116 {
0c45b8e0 117 __filebuf_type* __ret = NULL;
725dc051
BK
118 if (this->is_open())
119 {
0c45b8e0 120 bool __testfail = false;
a1796d12
BK
121 try
122 {
71b46021 123 if (this->pbase() < this->pptr()
1f0ef651
PC
124 && traits_type::eq_int_type(this->overflow(),
125 traits_type::eof()))
a1796d12 126 __testfail = true;
725dc051 127#if 0
a1796d12
BK
128 // XXX not done
129 if (_M_last_overflowed)
130 {
131 _M_output_unshift();
002bd606 132 this->overflow();
a1796d12
BK
133 }
134#endif
135 }
136 catch(...)
725dc051 137 {
a1796d12 138 __testfail = true;
725dc051 139 }
a1796d12 140
0c45b8e0
BK
141 // NB: Do this here so that re-opened filebufs will be cool...
142 this->_M_mode = ios_base::openmode(0);
cd96b185 143 this->_M_pback_init = false;
0c45b8e0 144 _M_destroy_internal_buffer();
71b46021
PC
145 _M_reading = false;
146 _M_writing = false;
147 _M_set_buffer(-1);
a1796d12 148
0c45b8e0
BK
149 if (!_M_file.close())
150 __testfail = true;
151
152 if (!__testfail)
d3a193e3 153 __ret = this;
725dc051 154 }
a1796d12 155 _M_last_overflowed = false;
725dc051
BK
156 return __ret;
157 }
158
159 template<typename _CharT, typename _Traits>
160 streamsize
161 basic_filebuf<_CharT, _Traits>::
162 showmanyc()
163 {
164 streamsize __ret = -1;
0b176c1a 165 const bool __testin = this->_M_mode & ios_base::in;
725dc051 166
9fbcb61a 167 if (__testin && this->is_open())
bbacb998 168 {
bbacb998
PC
169 // For a stateful encoding (-1) the pending sequence might be just
170 // shift and unshift prefixes with no actual character.
71b46021 171 __ret = this->egptr() - this->gptr();
0cd1de6f
BK
172 if (__check_facet(_M_codecvt).encoding() >= 0)
173 __ret += _M_file.showmanyc() / _M_codecvt->max_length();
bbacb998
PC
174 }
175
725dc051
BK
176 _M_last_overflowed = false;
177 return __ret;
178 }
725dc051 179
51ff8149
BK
180 template<typename _CharT, typename _Traits>
181 typename basic_filebuf<_CharT, _Traits>::int_type
6e81c6f4
BK
182 basic_filebuf<_CharT, _Traits>::
183 _M_underflow(bool __bump)
51ff8149
BK
184 {
185 int_type __ret = traits_type::eof();
186 const bool __testin = this->_M_mode & ios_base::in;
187 const bool __testout = this->_M_mode & ios_base::out;
188
71b46021 189 if (__testin && !_M_writing)
51ff8149
BK
190 {
191 // Check for pback madness, and if so swich back to the
192 // normal buffers and jet outta here before expensive
193 // fileops happen...
0aef8de2 194 _M_destroy_pback();
51ff8149 195
71b46021 196 if (this->gptr() < this->egptr())
f10eea7b 197 {
71b46021 198 __ret = traits_type::to_int_type(*this->gptr());
f10eea7b 199 if (__bump)
71b46021 200 this->gbump(1);
f10eea7b
PC
201 return __ret;
202 }
51ff8149 203
f10eea7b 204 // Get and convert input sequence.
9335d80a
PC
205 const size_t __buflen = this->_M_buf_size > 1
206 ? this->_M_buf_size - 1 : 1;
f10eea7b
PC
207 streamsize __elen = 0;
208 streamsize __ilen = 0;
209 if (__check_facet(_M_codecvt).always_noconv())
210 {
71b46021 211 __elen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()), __buflen);
f10eea7b
PC
212 __ilen = __elen;
213 }
214 else
215 {
216 char* __buf = static_cast<char*>(__builtin_alloca(__buflen));
217 __elen = _M_file.xsgetn(__buf, __buflen);
218
219 const char* __eend;
220 char_type* __iend;
221 codecvt_base::result __r;
222 __r = _M_codecvt->in(_M_state_cur, __buf, __buf + __elen,
71b46021
PC
223 __eend, this->eback(),
224 this->eback() + __buflen, __iend);
f10eea7b 225 if (__r == codecvt_base::ok)
71b46021 226 __ilen = __iend - this->eback();
f10eea7b 227 else if (__r == codecvt_base::noconv)
51ff8149 228 {
71b46021 229 traits_type::copy(this->eback(),
f10eea7b
PC
230 reinterpret_cast<char_type*>(__buf),
231 __elen);
51ff8149
BK
232 __ilen = __elen;
233 }
f10eea7b 234 else
51ff8149 235 {
f10eea7b
PC
236 // Unwind.
237 __ilen = 0;
238 _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
51ff8149 239 }
46c4e5d6 240 }
f10eea7b
PC
241
242 if (__ilen > 0)
46c4e5d6 243 {
f10eea7b 244 _M_set_buffer(__ilen);
71b46021
PC
245 _M_reading = true;
246 __ret = traits_type::to_int_type(*this->gptr());
f10eea7b 247 if (__bump)
71b46021 248 this->gbump(1);
f10eea7b 249 }
51ff8149
BK
250 }
251 _M_last_overflowed = false;
252 return __ret;
253 }
254
725dc051 255 template<typename _CharT, typename _Traits>
31bfa177 256 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
257 basic_filebuf<_CharT, _Traits>::
258 pbackfail(int_type __i)
259 {
260 int_type __ret = traits_type::eof();
0b176c1a 261 const bool __testin = this->_M_mode & ios_base::in;
725dc051 262
71b46021 263 if (__testin && !_M_writing)
725dc051 264 {
b166bded
PC
265 // Remember whether the pback buffer is active, otherwise below
266 // we may try to store in it a second char (libstdc++/9761).
267 const bool __testpb = this->_M_pback_init;
0b176c1a 268 const bool __testeof = traits_type::eq_int_type(__i, __ret);
b166bded
PC
269
270 int_type __tmp;
71b46021 271 if (this->eback() < this->gptr())
725dc051 272 {
71b46021
PC
273 this->gbump(-1);
274 __tmp = traits_type::to_int_type(*this->gptr());
b166bded 275 }
f24ce7c1
BK
276 else if (this->seekoff(-1, ios_base::cur) >= 0)
277 {
278 __tmp = this->underflow();
279 if (traits_type::eq_int_type(__tmp, __ret))
280 return __ret;
281 }
282 else
46c4e5d6
BK
283 {
284 // At the beginning of the buffer, need to make a
285 // putback position available. But the seek may fail
286 // (f.i., at the beginning of a file, see
287 // libstdc++/9439) and in that case we return
288 // traits_type::eof().
289 return __ret;
290 }
725dc051 291
b166bded
PC
292 // Try to put back __i into input sequence in one of three ways.
293 // Order these tests done in is unspecified by the standard.
294 if (!__testeof && traits_type::eq_int_type(__i, __tmp))
295 __ret = __i;
296 else if (__testeof)
297 __ret = traits_type::not_eof(__i);
298 else if (!__testpb)
299 {
300 _M_create_pback();
71b46021
PC
301 _M_reading = true;
302 *this->gptr() = traits_type::to_char_type(__i);
b166bded 303 __ret = __i;
725dc051 304 }
725dc051
BK
305 }
306 _M_last_overflowed = false;
307 return __ret;
308 }
309
310 template<typename _CharT, typename _Traits>
31bfa177 311 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
312 basic_filebuf<_CharT, _Traits>::
313 overflow(int_type __c)
314 {
315 int_type __ret = traits_type::eof();
002bd606 316 const bool __testeof = traits_type::eq_int_type(__c, __ret);
0b176c1a 317 const bool __testout = this->_M_mode & ios_base::out;
725dc051 318
71b46021 319 if (__testout && !_M_reading)
725dc051 320 {
71b46021 321 if (this->pbase() < this->pptr())
002bd606 322 {
002bd606
BK
323 // If appropriate, append the overflow char.
324 if (!__testeof)
71b46021
PC
325 {
326 *this->pptr() = traits_type::to_char_type(__c);
327 this->pbump(1);
328 }
002bd606
BK
329
330 // Convert pending sequence to external representation,
331 // output.
71b46021
PC
332 if (_M_convert_to_external(this->pbase(),
333 this->pptr() - this->pbase())
002bd606
BK
334 && (!__testeof || (__testeof && !_M_file.sync())))
335 {
336 _M_set_buffer(0);
337 __ret = traits_type::not_eof(__c);
338 }
339 }
71b46021
PC
340 else if (this->_M_buf_size > 1)
341 {
342 // Overflow in 'uncommitted' mode: set _M_writing, set
343 // the buffer to the initial 'write' mode, and put __c
344 // into the buffer.
345 _M_set_buffer(0);
346 _M_writing = true;
347 if (!__testeof)
348 {
349 *this->pptr() = traits_type::to_char_type(__c);
350 this->pbump(1);
351 }
352 __ret = traits_type::not_eof(__c);
353 }
002bd606 354 else
725dc051 355 {
002bd606
BK
356 // Unbuffered.
357 char_type __conv = traits_type::to_char_type(__c);
9335d80a 358 if (__testeof || _M_convert_to_external(&__conv, 1))
71b46021
PC
359 {
360 _M_writing = true;
361 __ret = traits_type::not_eof(__c);
362 }
725dc051 363 }
725dc051 364 }
002bd606 365 _M_last_overflowed = true;
725dc051
BK
366 return __ret;
367 }
368
07814743 369 template<typename _CharT, typename _Traits>
6e81c6f4 370 bool
07814743 371 basic_filebuf<_CharT, _Traits>::
6e81c6f4 372 _M_convert_to_external(_CharT* __ibuf, streamsize __ilen)
07814743 373 {
6e81c6f4
BK
374 // Sizes of external and pending output.
375 streamsize __elen = 0;
376 streamsize __plen = 0;
377
c5b6351b 378 if (__check_facet(_M_codecvt).always_noconv())
07814743 379 {
51ff8149 380 __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
07814743
BK
381 __plen += __ilen;
382 }
383 else
384 {
385 // Worst-case number of external bytes needed.
0cd1de6f 386 int __ext_multiplier = _M_codecvt->encoding();
07814743
BK
387 if (__ext_multiplier == -1 || __ext_multiplier == 0)
388 __ext_multiplier = sizeof(char_type);
389 streamsize __blen = __ilen * __ext_multiplier;
390 char* __buf = static_cast<char*>(__builtin_alloca(__blen));
391 char* __bend;
392 const char_type* __iend;
a1796d12 393 codecvt_base::result __r;
0cd1de6f
BK
394 __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
395 __iend, __buf, __buf + __blen, __bend);
a1796d12 396
130cd3e1 397 if (__r == codecvt_base::ok || __r == codecvt_base::partial)
07814743 398 __blen = __bend - __buf;
130cd3e1
PC
399 else if (__r == codecvt_base::noconv)
400 {
a1796d12 401 // Same as the always_noconv case above.
130cd3e1
PC
402 __buf = reinterpret_cast<char*>(__ibuf);
403 __blen = __ilen;
404 }
a1796d12
BK
405 else
406 {
71b46021 407 // Result == error.
a1796d12
BK
408 __blen = 0;
409 }
07814743
BK
410
411 if (__blen)
412 {
51ff8149 413 __elen += _M_file.xsputn(__buf, __blen);
07814743
BK
414 __plen += __blen;
415 }
a1796d12 416
07814743
BK
417 // Try once more for partial conversions.
418 if (__r == codecvt_base::partial)
419 {
420 const char_type* __iresume = __iend;
71b46021 421 streamsize __rlen = this->pptr() - __iend;
0cd1de6f
BK
422 __r = _M_codecvt->out(_M_state_cur, __iresume,
423 __iresume + __rlen, __iend, __buf,
424 __buf + __blen, __bend);
07814743 425 if (__r != codecvt_base::error)
07814743 426 {
a1796d12 427 __rlen = __bend - __buf;
51ff8149 428 __elen += _M_file.xsputn(__buf, __rlen);
07814743
BK
429 __plen += __rlen;
430 }
431 }
432 }
6e81c6f4 433 return __elen && __elen == __plen;
725dc051
BK
434 }
435
990101f9 436 template<typename _CharT, typename _Traits>
31bfa177 437 typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
990101f9
BK
438 basic_filebuf<_CharT, _Traits>::
439 setbuf(char_type* __s, streamsize __n)
440 {
441 if (!this->is_open() && __s == 0 && __n == 0)
f10eea7b 442 this->_M_buf_size = 1;
b82a33d2 443 else if (__s && __n > 0)
990101f9 444 {
e3033a22 445 // This is implementation-defined behavior, and assumes that
c1b74c21
NM
446 // an external char_type array of length __n exists and has
447 // been pre-allocated. If this is not the case, things will
448 // quickly blow up. When __n > 1, __n - 1 positions will be
449 // used for the get area, __n - 1 for the put area and 1
450 // position to host the overflow char of a full put area.
451 // When __n == 1, 1 position will be used for the get area
452 // and 0 for the put area, as in the unbuffered case above.
391cd095 453
990101f9
BK
454 // Step 1: Destroy the current internal array.
455 _M_destroy_internal_buffer();
456
457 // Step 2: Use the external array.
8fbc5ae7 458 this->_M_buf = __s;
7ef9fd85 459 this->_M_buf_size = __n;
71b46021
PC
460 _M_reading = false;
461 _M_writing = false;
462 _M_set_buffer(-1);
990101f9
BK
463 }
464 _M_last_overflowed = false;
465 return this;
466 }
467
725dc051 468 template<typename _CharT, typename _Traits>
31bfa177 469 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
470 basic_filebuf<_CharT, _Traits>::
471 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
472 {
473 pos_type __ret = pos_type(off_type(-1));
0b176c1a
PC
474 const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
475 const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
95dca20c 476
a1796d12 477 int __width = 0;
0cd1de6f
BK
478 if (_M_codecvt)
479 __width = _M_codecvt->encoding();
725dc051
BK
480 if (__width < 0)
481 __width = 0;
a1796d12
BK
482
483 const bool __testfail = __off != 0 && __width <= 0;
dcf5a5de 484 if (this->is_open() && !__testfail && (__testin || __testout))
725dc051
BK
485 {
486 // Ditch any pback buffers to avoid confusion.
aa438e8f 487 _M_destroy_pback();
725dc051 488
71b46021
PC
489 // Sync the internal and external streams.
490 off_type __computed_off = __width * __off;
491
492 if (this->pbase() < this->pptr()
493 || _M_last_overflowed)
725dc051 494 {
71b46021
PC
495 // Part one: update the output sequence.
496 this->sync();
497
498 // Part two: output unshift sequence.
499 _M_output_unshift();
725dc051 500 }
71b46021
PC
501 else if (_M_reading && __way == ios_base::cur)
502 __computed_off += this->gptr() - this->egptr();
503
504 // Return pos_type(off_type(-1)) in case of failure.
505 __ret = _M_file.seekoff(__computed_off, __way, __mode);
506 _M_reading = false;
507 _M_writing = false;
508 _M_set_buffer(-1);
725dc051
BK
509 }
510 _M_last_overflowed = false;
511 return __ret;
512 }
513
514 template<typename _CharT, typename _Traits>
31bfa177 515 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
516 basic_filebuf<_CharT, _Traits>::
517 seekpos(pos_type __pos, ios_base::openmode __mode)
518 {
b988dfc5
BK
519#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
520// 171. Strange seekpos() semantics due to joint position
521 return this->seekoff(off_type(__pos), ios_base::beg, __mode);
522#endif
725dc051
BK
523 }
524
525 template<typename _CharT, typename _Traits>
526 void
527 basic_filebuf<_CharT, _Traits>::
528 _M_output_unshift()
529 { }
530
531 template<typename _CharT, typename _Traits>
532 void
533 basic_filebuf<_CharT, _Traits>::
534 imbue(const locale& __loc)
535 {
0cd1de6f
BK
536 const bool __testbeg = !this->seekoff(0, ios_base::cur, this->_M_mode);
537 const bool __teststate = __check_facet(_M_codecvt).encoding() == -1;
69302d8b 538
0cd1de6f
BK
539 if (this->_M_buf_locale != __loc
540 && (!this->is_open() || (__testbeg && !__teststate)))
541 {
542 this->_M_buf_locale = __loc;
543 if (__builtin_expect(has_facet<__codecvt_type>(__loc), true))
544 _M_codecvt = &use_facet<__codecvt_type>(__loc);
545
546 // NB This may require the reconversion of previously
547 // converted chars. This in turn may cause the
548 // reconstruction of the original file. YIKES!! This
549 // implementation interprets this requirement as requiring
550 // the file position be at the beginning, and a stateless
551 // encoding, or that the filebuf be closed. Opinions may differ.
552 }
725dc051
BK
553 _M_last_overflowed = false;
554 }
a32e3c09
BK
555
556 // Inhibit implicit instantiations for required instantiations,
557 // which are defined via explicit instantiations elsewhere.
558 // NB: This syntax is a GNU extension.
1bc8b0ad 559#if _GLIBCPP_EXTERN_TEMPLATE
a32e3c09 560 extern template class basic_filebuf<char>;
a32e3c09 561 extern template class basic_ifstream<char>;
a32e3c09 562 extern template class basic_ofstream<char>;
a32e3c09 563 extern template class basic_fstream<char>;
5112ae3a
BK
564
565#ifdef _GLIBCPP_USE_WCHAR_T
566 extern template class basic_filebuf<wchar_t>;
567 extern template class basic_ifstream<wchar_t>;
568 extern template class basic_ofstream<wchar_t>;
a32e3c09 569 extern template class basic_fstream<wchar_t>;
5112ae3a 570#endif
1bc8b0ad 571#endif
725dc051
BK
572} // namespace std
573
6f48900c 574#endif
This page took 0.346862 seconds and 5 git commands to generate.