]> gcc.gnu.org Git - gcc.git/blame - libstdc++-v3/include/bits/fstream.tcc
df.h (enum df_ref_flags.DF_REF_STRIPPED): 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 {
8fbc5ae7 47 if (!this->_M_buf && this->_M_buf_size_opt)
13187a45 48 {
8fbc5ae7 49 this->_M_buf_size = this->_M_buf_size_opt;
990101f9 50
391cd095
PC
51 // Allocate internal buffer...
52 this->_M_buf = new char_type[this->_M_buf_size];
53 // ... and consistently set the end of buffer pointer.
54 this->_M_out_end = this->_M_buf + this->_M_buf_size;
5cdd50a5 55 _M_buf_allocated = true;
990101f9
BK
56 }
57 }
58
59 // Both close and setbuf need to deallocate internal buffers, if it exists.
60 template<typename _CharT, typename _Traits>
61 void
62 basic_filebuf<_CharT, _Traits>::
63 _M_destroy_internal_buffer()
64 {
65 if (_M_buf_allocated)
66 {
8fbc5ae7
MM
67 delete [] this->_M_buf;
68 this->_M_buf = NULL;
990101f9
BK
69 _M_buf_allocated = false;
70 this->setg(NULL, NULL, NULL);
71 this->setp(NULL, NULL);
72 }
725dc051
BK
73 }
74
75 template<typename _CharT, typename _Traits>
76 basic_filebuf<_CharT, _Traits>::
5cdd50a5
BK
77 basic_filebuf() : __streambuf_type(), _M_file(&_M_lock),
78 _M_state_cur(__state_type()), _M_state_beg(__state_type()),
79 _M_buf_allocated(false), _M_last_overflowed(false)
8fbc5ae7 80 { this->_M_buf_unified = true; }
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
BK
95
96 // Setup initial position of buffer.
725dc051 97 _M_set_indeterminate();
6e52332e 98
6eeb7d7a
BK
99 // Set input buffer to something real.
100 // NB: Must open in non-blocking way to do this, or must
101 // set the initial position in a different manner than
102 // using underflow.
103 if (__mode & ios_base::in && _M_buf_allocated)
104 this->underflow();
105
b7737230 106 if ((__mode & ios_base::ate)
725dc051 107 && this->seekoff(0, ios_base::end, __mode) < 0)
7cd3907b
PC
108 {
109 // 27.8.1.3,4
110 this->close();
111 return __ret;
112 }
6eeb7d7a 113
725dc051
BK
114 __ret = this;
115 }
116 }
117 return __ret;
118 }
119
120 template<typename _CharT, typename _Traits>
31bfa177 121 typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
725dc051
BK
122 basic_filebuf<_CharT, _Traits>::
123 close()
124 {
125 __filebuf_type *__ret = NULL;
126 if (this->is_open())
127 {
e6705174 128 const int_type __eof = traits_type::eof();
8fbc5ae7 129 bool __testput = this->_M_out_cur
391cd095 130 && this->_M_out_beg < this->_M_out_lim;
f13a69ec
BK
131 if (__testput
132 && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
e6705174 133 return __ret;
725dc051 134
e6705174 135 // NB: Do this here so that re-opened filebufs will be cool...
8fbc5ae7 136 this->_M_mode = ios_base::openmode(0);
e6705174 137 _M_destroy_internal_buffer();
e6705174 138 _M_pback_destroy();
e6705174 139
725dc051
BK
140#if 0
141 // XXX not done
142 if (_M_last_overflowed)
143 {
144 _M_output_unshift();
e6705174 145 _M_really_overflow(__eof);
725dc051
BK
146 }
147#endif
725dc051 148
d3a193e3
BK
149 if (_M_file.close())
150 __ret = this;
725dc051 151 }
d3a193e3 152
725dc051
BK
153 _M_last_overflowed = false;
154 return __ret;
155 }
156
157 template<typename _CharT, typename _Traits>
158 streamsize
159 basic_filebuf<_CharT, _Traits>::
160 showmanyc()
161 {
162 streamsize __ret = -1;
8fbc5ae7 163 bool __testin = this->_M_mode & ios_base::in;
725dc051 164
9fbcb61a 165 if (__testin && this->is_open())
8fbc5ae7 166 __ret = this->_M_in_end - this->_M_in_cur;
725dc051
BK
167 _M_last_overflowed = false;
168 return __ret;
169 }
725dc051
BK
170
171 template<typename _CharT, typename _Traits>
31bfa177 172 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
173 basic_filebuf<_CharT, _Traits>::
174 pbackfail(int_type __i)
175 {
176 int_type __ret = traits_type::eof();
8fbc5ae7 177 bool __testin = this->_M_mode & ios_base::in;
725dc051
BK
178
179 if (__testin)
180 {
8fbc5ae7 181 bool __testpb = this->_M_in_beg < this->_M_in_cur;
725dc051
BK
182 char_type __c = traits_type::to_char_type(__i);
183 bool __testeof = traits_type::eq_int_type(__i, __ret);
184
185 if (__testpb)
186 {
8fbc5ae7 187 bool __testout = this->_M_mode & ios_base::out;
725dc051
BK
188 bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
189
190 // Try to put back __c into input sequence in one of three ways.
191 // Order these tests done in is unspecified by the standard.
192 if (!__testeof && __testeq)
193 {
8fbc5ae7 194 --this->_M_in_cur;
725dc051 195 if (__testout)
8fbc5ae7 196 --this->_M_out_cur;
725dc051
BK
197 __ret = __i;
198 }
199 else if (__testeof)
200 {
8fbc5ae7 201 --this->_M_in_cur;
725dc051 202 if (__testout)
8fbc5ae7 203 --this->_M_out_cur;
725dc051
BK
204 __ret = traits_type::not_eof(__i);
205 }
206 else if (!__testeof)
207 {
8fbc5ae7 208 --this->_M_in_cur;
725dc051 209 if (__testout)
8fbc5ae7 210 --this->_M_out_cur;
725dc051 211 _M_pback_create();
8fbc5ae7 212 *this->_M_in_cur = __c;
725dc051
BK
213 __ret = __i;
214 }
215 }
216 else
217 {
218 // At the beginning of the buffer, need to make a
219 // putback position available.
52b62c0e
PC
220 // But the seek may fail (f.i., at the beginning of
221 // a file, see libstdc++/9439) and in that case
222 // we return traits_type::eof()
223 if (this->seekoff(-1, ios_base::cur) >= 0)
224 {
225 this->underflow();
226 if (!__testeof)
725dc051 227 {
52b62c0e
PC
228 if (!traits_type::eq(__c, *this->_M_in_cur))
229 {
230 _M_pback_create();
231 *this->_M_in_cur = __c;
232 }
233 __ret = __i;
725dc051 234 }
52b62c0e
PC
235 else
236 __ret = traits_type::not_eof(__i);
237 }
725dc051
BK
238 }
239 }
240 _M_last_overflowed = false;
241 return __ret;
242 }
243
244 template<typename _CharT, typename _Traits>
31bfa177 245 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
246 basic_filebuf<_CharT, _Traits>::
247 overflow(int_type __c)
248 {
249 int_type __ret = traits_type::eof();
391cd095 250 bool __testput = _M_out_buf_size();
8fbc5ae7 251 bool __testout = this->_M_mode & ios_base::out;
725dc051
BK
252
253 if (__testout)
254 {
5fa9abc3 255 if (__testput)
725dc051 256 {
8fbc5ae7 257 *this->_M_out_cur = traits_type::to_char_type(__c);
725dc051
BK
258 _M_out_cur_move(1);
259 __ret = traits_type::not_eof(__c);
260 }
261 else
262 __ret = this->_M_really_overflow(__c);
263 }
264
265 _M_last_overflowed = false; // Set in _M_really_overflow, below.
266 return __ret;
267 }
268
07814743
BK
269 template<typename _CharT, typename _Traits>
270 void
271 basic_filebuf<_CharT, _Traits>::
272 _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
273 streamsize& __elen, streamsize& __plen)
274 {
07814743
BK
275 const locale __loc = this->getloc();
276 const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
277
278 if (__cvt.always_noconv() && __ilen)
279 {
d3a193e3 280 __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
07814743
BK
281 __plen += __ilen;
282 }
283 else
284 {
285 // Worst-case number of external bytes needed.
286 int __ext_multiplier = __cvt.encoding();
287 if (__ext_multiplier == -1 || __ext_multiplier == 0)
288 __ext_multiplier = sizeof(char_type);
289 streamsize __blen = __ilen * __ext_multiplier;
290 char* __buf = static_cast<char*>(__builtin_alloca(__blen));
291 char* __bend;
292 const char_type* __iend;
293 __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
294 __iend, __buf, __buf + __blen, __bend);
130cd3e1
PC
295
296 if (__r == codecvt_base::ok || __r == codecvt_base::partial)
07814743 297 __blen = __bend - __buf;
130cd3e1
PC
298 // Similarly to the always_noconv case above.
299 else if (__r == codecvt_base::noconv)
300 {
301 __buf = reinterpret_cast<char*>(__ibuf);
302 __blen = __ilen;
303 }
07814743
BK
304 // Result == error
305 else
306 __blen = 0;
307
308 if (__blen)
309 {
d3a193e3 310 __elen += _M_file.xsputn(__buf, __blen);
07814743
BK
311 __plen += __blen;
312 }
313
314 // Try once more for partial conversions.
315 if (__r == codecvt_base::partial)
316 {
317 const char_type* __iresume = __iend;
391cd095 318 streamsize __rlen = this->_M_out_lim - __iend;
07814743
BK
319 __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,
320 __iend, __buf, __buf + __blen, __bend);
321 if (__r != codecvt_base::error)
322 __rlen = __bend - __buf;
323 else
324 __rlen = 0;
325 if (__rlen)
326 {
d3a193e3 327 __elen += _M_file.xsputn(__buf, __rlen);
07814743
BK
328 __plen += __rlen;
329 }
330 }
331 }
332 }
333
725dc051 334 template<typename _CharT, typename _Traits>
31bfa177 335 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
336 basic_filebuf<_CharT, _Traits>::
337 _M_really_overflow(int_type __c)
338 {
339 int_type __ret = traits_type::eof();
391cd095 340 bool __testput = this->_M_out_cur && this->_M_out_beg < this->_M_out_lim;
8fbc5ae7 341 bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size_opt;
5fa9abc3
BK
342
343 if (__testput || __testunbuffered)
725dc051 344 {
07814743
BK
345 // Sizes of external and pending output.
346 streamsize __elen = 0;
347 streamsize __plen = 0;
348
5066927d
JM
349 // Need to restore current position. The position of the external
350 // byte sequence (_M_file) corresponds to _M_filepos, and we need
351 // to move it to _M_out_beg for the write.
8fbc5ae7 352 if (_M_filepos && _M_filepos != this->_M_out_beg)
5066927d 353 {
8fbc5ae7 354 off_type __off = this->_M_out_beg - _M_filepos;
5066927d
JM
355 _M_file.seekoff(__off, ios_base::cur);
356 }
357
07814743
BK
358 // Convert internal buffer to external representation, output.
359 // NB: In the unbuffered case, no internal buffer exists.
360 if (!__testunbuffered)
8fbc5ae7 361 _M_convert_to_external(this->_M_out_beg,
391cd095 362 this->_M_out_lim - this->_M_out_beg,
07814743
BK
363 __elen, __plen);
364
365 // Convert pending sequence to external representation, output.
9385d9cb 366 // If eof, then just attempt sync.
07814743 367 if (!traits_type::eq_int_type(__c, traits_type::eof()))
725dc051 368 {
07814743
BK
369 char_type __pending = traits_type::to_char_type(__c);
370 _M_convert_to_external(&__pending, 1, __elen, __plen);
5fa9abc3 371
9385d9cb
LR
372 // User code must flush when switching modes (thus don't sync).
373 if (__elen == __plen)
374 {
375 _M_set_indeterminate();
376 __ret = traits_type::not_eof(__c);
377 }
378 }
379 else if (!_M_file.sync())
e6705174
BK
380 {
381 _M_set_indeterminate();
382 __ret = traits_type::not_eof(__c);
383 }
725dc051
BK
384 }
385 _M_last_overflowed = true;
386 return __ret;
387 }
388
990101f9 389 template<typename _CharT, typename _Traits>
31bfa177 390 typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
990101f9
BK
391 basic_filebuf<_CharT, _Traits>::
392 setbuf(char_type* __s, streamsize __n)
393 {
394 if (!this->is_open() && __s == 0 && __n == 0)
8fbc5ae7 395 this->_M_buf_size_opt = 0;
990101f9
BK
396 else if (__s && __n)
397 {
398 // This is implementation-defined behavior, and assumes
399 // that an external char_type array of length (__s + __n)
400 // exists and has been pre-allocated. If this is not the
401 // case, things will quickly blow up.
391cd095 402
990101f9
BK
403 // Step 1: Destroy the current internal array.
404 _M_destroy_internal_buffer();
405
406 // Step 2: Use the external array.
8fbc5ae7
MM
407 this->_M_buf = __s;
408 this->_M_buf_size_opt = this->_M_buf_size = __n;
391cd095
PC
409 // Consistently set the end of buffer pointer.
410 this->_M_out_end = this->_M_buf + this->_M_buf_size;
990101f9 411 _M_set_indeterminate();
990101f9
BK
412 }
413 _M_last_overflowed = false;
414 return this;
415 }
416
725dc051 417 template<typename _CharT, typename _Traits>
31bfa177 418 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
419 basic_filebuf<_CharT, _Traits>::
420 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
421 {
422 pos_type __ret = pos_type(off_type(-1));
8fbc5ae7
MM
423 bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
424 bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
69302d8b
BK
425
426 // Should probably do has_facet checks here.
8fbc5ae7 427 int __width = use_facet<__codecvt_type>(this->_M_buf_locale).encoding();
725dc051
BK
428 if (__width < 0)
429 __width = 0;
b988dfc5 430 bool __testfail = __off != 0 && __width <= 0;
725dc051 431
dcf5a5de 432 if (this->is_open() && !__testfail && (__testin || __testout))
725dc051
BK
433 {
434 // Ditch any pback buffers to avoid confusion.
435 _M_pback_destroy();
436
437 if (__way != ios_base::cur || __off != 0)
438 {
439 off_type __computed_off = __width * __off;
440
8fbc5ae7
MM
441 bool __testget = this->_M_in_cur
442 && this->_M_in_beg < this->_M_in_end;
443 bool __testput = this->_M_out_cur
391cd095 444 && this->_M_out_beg < this->_M_out_lim;
725dc051
BK
445 // Sync the internal and external streams.
446 // out
447 if (__testput || _M_last_overflowed)
448 {
449 // Part one: update the output sequence.
450 this->sync();
451 // Part two: output unshift sequence.
452 _M_output_unshift();
453 }
454 //in
725dc051 455 else if (__testget && __way == ios_base::cur)
8fbc5ae7 456 __computed_off += this->_M_in_cur - _M_filepos;
52b62c0e
PC
457
458 // Return pos_type(off_type(-1)) in case of failure.
d3a193e3 459 __ret = _M_file.seekoff(__computed_off, __way, __mode);
725dc051
BK
460 _M_set_indeterminate();
461 }
462 // NB: Need to do this in case _M_file in indeterminate
d3a193e3 463 // state, ie _M_file._offset == -1
725dc051
BK
464 else
465 {
52b62c0e
PC
466 pos_type __tmp =
467 _M_file.seekoff(__off, ios_base::cur, __mode);
468 if (__tmp >= 0)
74db1461
SS
469 {
470 // Seek successful.
471 __ret = __tmp;
472 __ret +=
473 std::max(this->_M_out_cur, this->_M_in_cur) - _M_filepos;
474 }
725dc051
BK
475 }
476 }
477 _M_last_overflowed = false;
478 return __ret;
479 }
480
481 template<typename _CharT, typename _Traits>
31bfa177 482 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
483 basic_filebuf<_CharT, _Traits>::
484 seekpos(pos_type __pos, ios_base::openmode __mode)
485 {
b988dfc5
BK
486#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
487// 171. Strange seekpos() semantics due to joint position
488 return this->seekoff(off_type(__pos), ios_base::beg, __mode);
489#endif
725dc051
BK
490 }
491
492 template<typename _CharT, typename _Traits>
493 void
494 basic_filebuf<_CharT, _Traits>::
495 _M_output_unshift()
496 { }
497
498 template<typename _CharT, typename _Traits>
499 void
500 basic_filebuf<_CharT, _Traits>::
501 imbue(const locale& __loc)
502 {
503 bool __testbeg = gptr() == eback() && pptr() == pbase();
69302d8b 504
8fbc5ae7 505 if (__testbeg && this->_M_buf_locale != __loc)
1ceb90cf 506 this->_M_buf_locale = __loc;
69302d8b 507
725dc051
BK
508 // NB this may require the reconversion of previously
509 // converted chars. This in turn may cause the reconstruction
510 // of the original file. YIKES!!
511 // XXX The part in the above comment is not done.
512 _M_last_overflowed = false;
513 }
a32e3c09
BK
514
515 // Inhibit implicit instantiations for required instantiations,
516 // which are defined via explicit instantiations elsewhere.
517 // NB: This syntax is a GNU extension.
1bc8b0ad 518#if _GLIBCPP_EXTERN_TEMPLATE
a32e3c09 519 extern template class basic_filebuf<char>;
a32e3c09 520 extern template class basic_ifstream<char>;
a32e3c09 521 extern template class basic_ofstream<char>;
a32e3c09 522 extern template class basic_fstream<char>;
5112ae3a
BK
523
524#ifdef _GLIBCPP_USE_WCHAR_T
525 extern template class basic_filebuf<wchar_t>;
526 extern template class basic_ifstream<wchar_t>;
527 extern template class basic_ofstream<wchar_t>;
a32e3c09 528 extern template class basic_fstream<wchar_t>;
5112ae3a 529#endif
1bc8b0ad 530#endif
725dc051
BK
531} // namespace std
532
6f48900c 533#endif
This page took 0.286595 seconds and 5 git commands to generate.