]> gcc.gnu.org Git - gcc.git/blame - libstdc++-v3/include/bits/fstream.tcc
2003-10-02 Guilhem Lavaux <guilhem@kaffe.org>
[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
3d7c150e
BK
35#ifndef _FSTREAM_TCC
36#define _FSTREAM_TCC 1
725dc051 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 }
f1813b69
PR
67 delete [] _M_ext_buf;
68 _M_ext_buf = NULL;
69 _M_ext_buf_size = 0;
70 _M_ext_next = NULL;
71 _M_ext_end = NULL;
725dc051
BK
72 }
73
74 template<typename _CharT, typename _Traits>
75 basic_filebuf<_CharT, _Traits>::
5cdd50a5 76 basic_filebuf() : __streambuf_type(), _M_file(&_M_lock),
cd16e04b
PC
77 _M_mode(ios_base::openmode(0)), _M_state_cur(__state_type()),
78 _M_state_beg(__state_type()), _M_buf(NULL), _M_buf_size(BUFSIZ),
79 _M_buf_allocated(false), _M_reading(false), _M_writing(false),
80 _M_last_overflowed(false), _M_pback_cur_save(0), _M_pback_end_save(0),
f1813b69
PR
81 _M_pback_init(false), _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0),
82 _M_ext_next(0), _M_ext_end(0)
0cd1de6f 83 {
46c4e5d6 84 if (has_facet<__codecvt_type>(this->_M_buf_locale))
0cd1de6f
BK
85 _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
86 }
725dc051 87
725dc051 88 template<typename _CharT, typename _Traits>
31bfa177 89 typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
725dc051
BK
90 basic_filebuf<_CharT, _Traits>::
91 open(const char* __s, ios_base::openmode __mode)
92 {
93 __filebuf_type *__ret = NULL;
94 if (!this->is_open())
95 {
d3a193e3 96 _M_file.open(__s, __mode);
13187a45 97 if (this->is_open())
725dc051 98 {
990101f9 99 _M_allocate_internal_buffer();
8fbc5ae7 100 this->_M_mode = __mode;
6eeb7d7a 101
71b46021
PC
102 // Setup initial buffer to 'uncommitted' mode.
103 _M_reading = false;
104 _M_writing = false;
105 _M_set_buffer(-1);
6e52332e 106
cc5112c9 107 // 27.8.1.3,4
e3033a22 108 if ((__mode & ios_base::ate)
725dc051 109 && this->seekoff(0, ios_base::end, __mode) < 0)
cc9d1c78
PC
110 this->close();
111 else
112 __ret = this;
725dc051
BK
113 }
114 }
115 return __ret;
116 }
117
118 template<typename _CharT, typename _Traits>
31bfa177 119 typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
725dc051 120 basic_filebuf<_CharT, _Traits>::
a1796d12 121 close() throw()
725dc051 122 {
0c45b8e0 123 __filebuf_type* __ret = NULL;
725dc051
BK
124 if (this->is_open())
125 {
0c45b8e0 126 bool __testfail = false;
a1796d12
BK
127 try
128 {
71b46021 129 if (this->pbase() < this->pptr()
1f0ef651
PC
130 && traits_type::eq_int_type(this->overflow(),
131 traits_type::eof()))
a1796d12 132 __testfail = true;
725dc051 133#if 0
a1796d12
BK
134 // XXX not done
135 if (_M_last_overflowed)
136 {
137 _M_output_unshift();
002bd606 138 this->overflow();
a1796d12
BK
139 }
140#endif
141 }
142 catch(...)
725dc051 143 {
a1796d12 144 __testfail = true;
725dc051 145 }
a1796d12 146
0c45b8e0
BK
147 // NB: Do this here so that re-opened filebufs will be cool...
148 this->_M_mode = ios_base::openmode(0);
cd96b185 149 this->_M_pback_init = false;
0c45b8e0 150 _M_destroy_internal_buffer();
71b46021
PC
151 _M_reading = false;
152 _M_writing = false;
153 _M_set_buffer(-1);
a1796d12 154
0c45b8e0
BK
155 if (!_M_file.close())
156 __testfail = true;
157
158 if (!__testfail)
d3a193e3 159 __ret = this;
725dc051 160 }
a1796d12 161 _M_last_overflowed = false;
725dc051
BK
162 return __ret;
163 }
164
165 template<typename _CharT, typename _Traits>
166 streamsize
167 basic_filebuf<_CharT, _Traits>::
168 showmanyc()
169 {
170 streamsize __ret = -1;
0b176c1a 171 const bool __testin = this->_M_mode & ios_base::in;
725dc051 172
9fbcb61a 173 if (__testin && this->is_open())
bbacb998 174 {
bbacb998
PC
175 // For a stateful encoding (-1) the pending sequence might be just
176 // shift and unshift prefixes with no actual character.
71b46021 177 __ret = this->egptr() - this->gptr();
0cd1de6f
BK
178 if (__check_facet(_M_codecvt).encoding() >= 0)
179 __ret += _M_file.showmanyc() / _M_codecvt->max_length();
bbacb998
PC
180 }
181
725dc051
BK
182 _M_last_overflowed = false;
183 return __ret;
184 }
725dc051 185
51ff8149
BK
186 template<typename _CharT, typename _Traits>
187 typename basic_filebuf<_CharT, _Traits>::int_type
6e81c6f4 188 basic_filebuf<_CharT, _Traits>::
cd16e04b 189 underflow()
51ff8149
BK
190 {
191 int_type __ret = traits_type::eof();
192 const bool __testin = this->_M_mode & ios_base::in;
193 const bool __testout = this->_M_mode & ios_base::out;
194
71b46021 195 if (__testin && !_M_writing)
51ff8149
BK
196 {
197 // Check for pback madness, and if so swich back to the
198 // normal buffers and jet outta here before expensive
199 // fileops happen...
0aef8de2 200 _M_destroy_pback();
51ff8149 201
71b46021 202 if (this->gptr() < this->egptr())
cd16e04b 203 return traits_type::to_int_type(*this->gptr());
51ff8149 204
f10eea7b 205 // Get and convert input sequence.
9335d80a
PC
206 const size_t __buflen = this->_M_buf_size > 1
207 ? this->_M_buf_size - 1 : 1;
f1813b69
PR
208
209 // Will be set to true if ::read() returns 0 indicating EOF.
210 bool __got_eof = false;
211 // Number of internal characters produced.
f10eea7b
PC
212 streamsize __ilen = 0;
213 if (__check_facet(_M_codecvt).always_noconv())
214 {
f1813b69 215 __ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()),
cc5112c9 216 __buflen);
f1813b69
PR
217 if (__ilen == 0)
218 __got_eof = true;
f10eea7b
PC
219 }
220 else
221 {
f1813b69
PR
222 // Worst-case number of external bytes.
223 // XXX Not done encoding() == -1.
224 const int __enc = _M_codecvt->encoding();
225 streamsize __blen; // Minimum buffer size.
226 streamsize __rlen; // Number of chars to read.
227 if (__enc > 0)
228 __blen = __rlen = __buflen * __enc;
229 else
51ff8149 230 {
f1813b69
PR
231 __blen = __buflen + _M_codecvt->max_length() - 1;
232 __rlen = __buflen;
51ff8149 233 }
f1813b69
PR
234 const streamsize __remainder = _M_ext_end - _M_ext_next;
235 __rlen = __rlen > __remainder ? __rlen - __remainder : 0;
236
237 // Allocate buffer if necessary and move unconverted
238 // bytes to front.
239 if (_M_ext_buf_size < __blen)
240 {
241 char* __buf = new char[__blen];
242 if (__remainder > 0)
243 std::memcpy(__buf, _M_ext_next, __remainder);
244
245 delete [] _M_ext_buf;
246 _M_ext_buf = __buf;
247 _M_ext_buf_size = __blen;
248 }
249 else if (__remainder > 0)
250 std::memmove(_M_ext_buf, _M_ext_next, __remainder);
251
252 _M_ext_next = _M_ext_buf;
253 _M_ext_end = _M_ext_buf + __remainder;
254
255 do
51ff8149 256 {
f1813b69
PR
257 if (__rlen > 0)
258 {
259 // Sanity check!
260 // This may fail if the return value of
261 // codecvt::max_length() is bogus.
262 if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
263 std::abort();
264 streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
265 if (__elen == 0)
266 __got_eof = true;
267 _M_ext_end += __elen;
268 }
269
270 char_type* __iend;
271 codecvt_base::result __r;
272 __r = _M_codecvt->in(_M_state_cur, _M_ext_next,
273 _M_ext_end, _M_ext_next, this->eback(),
274 this->eback() + __buflen, __iend);
275 if (__r == codecvt_base::ok || __r == codecvt_base::partial)
276 __ilen = __iend - this->eback();
277 else if (__r == codecvt_base::noconv)
278 {
279 size_t __avail = _M_ext_end - _M_ext_buf;
280 __ilen = std::min(__avail, __buflen);
281 traits_type::copy(this->eback(),
282 reinterpret_cast<char_type*>(_M_ext_buf),
283 __ilen);
284 _M_ext_next = _M_ext_buf + __ilen;
285 }
286 else
287 {
288 __ilen = 0;
289 break;
290 }
291 __rlen = 1;
51ff8149 292 }
f1813b69 293 while (!__got_eof && __ilen == 0);
46c4e5d6 294 }
f10eea7b
PC
295
296 if (__ilen > 0)
46c4e5d6 297 {
f10eea7b 298 _M_set_buffer(__ilen);
71b46021
PC
299 _M_reading = true;
300 __ret = traits_type::to_int_type(*this->gptr());
2cfe4e68 301 }
f1813b69 302 else if (__got_eof)
2cfe4e68
PC
303 {
304 // If the actual end of file is reached, set 'uncommitted'
305 // mode, thus allowing an immediate write without an
306 // intervening seek.
307 _M_set_buffer(-1);
308 _M_reading = false;
309 }
51ff8149
BK
310 }
311 _M_last_overflowed = false;
312 return __ret;
313 }
314
725dc051 315 template<typename _CharT, typename _Traits>
31bfa177 316 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
317 basic_filebuf<_CharT, _Traits>::
318 pbackfail(int_type __i)
319 {
320 int_type __ret = traits_type::eof();
0b176c1a 321 const bool __testin = this->_M_mode & ios_base::in;
725dc051 322
71b46021 323 if (__testin && !_M_writing)
725dc051 324 {
b166bded
PC
325 // Remember whether the pback buffer is active, otherwise below
326 // we may try to store in it a second char (libstdc++/9761).
327 const bool __testpb = this->_M_pback_init;
0b176c1a 328 const bool __testeof = traits_type::eq_int_type(__i, __ret);
b166bded
PC
329
330 int_type __tmp;
71b46021 331 if (this->eback() < this->gptr())
725dc051 332 {
71b46021
PC
333 this->gbump(-1);
334 __tmp = traits_type::to_int_type(*this->gptr());
b166bded 335 }
f24ce7c1
BK
336 else if (this->seekoff(-1, ios_base::cur) >= 0)
337 {
338 __tmp = this->underflow();
339 if (traits_type::eq_int_type(__tmp, __ret))
340 return __ret;
341 }
342 else
46c4e5d6
BK
343 {
344 // At the beginning of the buffer, need to make a
345 // putback position available. But the seek may fail
346 // (f.i., at the beginning of a file, see
347 // libstdc++/9439) and in that case we return
348 // traits_type::eof().
349 return __ret;
350 }
725dc051 351
b166bded
PC
352 // Try to put back __i into input sequence in one of three ways.
353 // Order these tests done in is unspecified by the standard.
354 if (!__testeof && traits_type::eq_int_type(__i, __tmp))
355 __ret = __i;
356 else if (__testeof)
357 __ret = traits_type::not_eof(__i);
358 else if (!__testpb)
359 {
360 _M_create_pback();
71b46021
PC
361 _M_reading = true;
362 *this->gptr() = traits_type::to_char_type(__i);
b166bded 363 __ret = __i;
725dc051 364 }
725dc051
BK
365 }
366 _M_last_overflowed = false;
367 return __ret;
368 }
369
370 template<typename _CharT, typename _Traits>
31bfa177 371 typename basic_filebuf<_CharT, _Traits>::int_type
725dc051
BK
372 basic_filebuf<_CharT, _Traits>::
373 overflow(int_type __c)
374 {
375 int_type __ret = traits_type::eof();
002bd606 376 const bool __testeof = traits_type::eq_int_type(__c, __ret);
0b176c1a 377 const bool __testout = this->_M_mode & ios_base::out;
725dc051 378
71b46021 379 if (__testout && !_M_reading)
725dc051 380 {
71b46021 381 if (this->pbase() < this->pptr())
002bd606 382 {
002bd606
BK
383 // If appropriate, append the overflow char.
384 if (!__testeof)
71b46021
PC
385 {
386 *this->pptr() = traits_type::to_char_type(__c);
387 this->pbump(1);
388 }
002bd606
BK
389
390 // Convert pending sequence to external representation,
391 // output.
71b46021
PC
392 if (_M_convert_to_external(this->pbase(),
393 this->pptr() - this->pbase())
002bd606
BK
394 && (!__testeof || (__testeof && !_M_file.sync())))
395 {
396 _M_set_buffer(0);
397 __ret = traits_type::not_eof(__c);
398 }
399 }
71b46021
PC
400 else if (this->_M_buf_size > 1)
401 {
402 // Overflow in 'uncommitted' mode: set _M_writing, set
403 // the buffer to the initial 'write' mode, and put __c
404 // into the buffer.
405 _M_set_buffer(0);
406 _M_writing = true;
407 if (!__testeof)
408 {
409 *this->pptr() = traits_type::to_char_type(__c);
410 this->pbump(1);
411 }
412 __ret = traits_type::not_eof(__c);
413 }
002bd606 414 else
725dc051 415 {
002bd606
BK
416 // Unbuffered.
417 char_type __conv = traits_type::to_char_type(__c);
9335d80a 418 if (__testeof || _M_convert_to_external(&__conv, 1))
71b46021
PC
419 {
420 _M_writing = true;
421 __ret = traits_type::not_eof(__c);
422 }
725dc051 423 }
725dc051 424 }
002bd606 425 _M_last_overflowed = true;
725dc051
BK
426 return __ret;
427 }
428
07814743 429 template<typename _CharT, typename _Traits>
6e81c6f4 430 bool
07814743 431 basic_filebuf<_CharT, _Traits>::
6e81c6f4 432 _M_convert_to_external(_CharT* __ibuf, streamsize __ilen)
07814743 433 {
6e81c6f4
BK
434 // Sizes of external and pending output.
435 streamsize __elen = 0;
436 streamsize __plen = 0;
437
c5b6351b 438 if (__check_facet(_M_codecvt).always_noconv())
07814743 439 {
51ff8149 440 __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
07814743
BK
441 __plen += __ilen;
442 }
443 else
444 {
445 // Worst-case number of external bytes needed.
3461133d
PC
446 // XXX Not done encoding() == -1.
447 streamsize __blen = __ilen * _M_codecvt->max_length();
07814743 448 char* __buf = static_cast<char*>(__builtin_alloca(__blen));
3461133d 449
07814743
BK
450 char* __bend;
451 const char_type* __iend;
a1796d12 452 codecvt_base::result __r;
0cd1de6f
BK
453 __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
454 __iend, __buf, __buf + __blen, __bend);
a1796d12 455
130cd3e1 456 if (__r == codecvt_base::ok || __r == codecvt_base::partial)
07814743 457 __blen = __bend - __buf;
130cd3e1
PC
458 else if (__r == codecvt_base::noconv)
459 {
a1796d12 460 // Same as the always_noconv case above.
130cd3e1
PC
461 __buf = reinterpret_cast<char*>(__ibuf);
462 __blen = __ilen;
463 }
a1796d12
BK
464 else
465 {
71b46021 466 // Result == error.
a1796d12
BK
467 __blen = 0;
468 }
07814743
BK
469
470 if (__blen)
471 {
51ff8149 472 __elen += _M_file.xsputn(__buf, __blen);
07814743
BK
473 __plen += __blen;
474 }
a1796d12 475
07814743
BK
476 // Try once more for partial conversions.
477 if (__r == codecvt_base::partial)
478 {
479 const char_type* __iresume = __iend;
71b46021 480 streamsize __rlen = this->pptr() - __iend;
0cd1de6f
BK
481 __r = _M_codecvt->out(_M_state_cur, __iresume,
482 __iresume + __rlen, __iend, __buf,
483 __buf + __blen, __bend);
07814743 484 if (__r != codecvt_base::error)
07814743 485 {
a1796d12 486 __rlen = __bend - __buf;
51ff8149 487 __elen += _M_file.xsputn(__buf, __rlen);
07814743
BK
488 __plen += __rlen;
489 }
490 }
491 }
6e81c6f4 492 return __elen && __elen == __plen;
725dc051
BK
493 }
494
bda243ec
PC
495 template<typename _CharT, typename _Traits>
496 streamsize
497 basic_filebuf<_CharT, _Traits>::
498 xsputn(const _CharT* __s, streamsize __n)
499 {
500 streamsize __ret = 0;
501
502 // Optimization in the always_noconv() case, to be generalized in the
503 // future: when __n is sufficiently large we write directly instead of
504 // using the buffer.
505 const bool __testout = this->_M_mode & ios_base::out;
506 if (__testout && !_M_reading
507 && __check_facet(_M_codecvt).always_noconv())
508 {
509 // Measurement would reveal the best choice.
510 const streamsize __chunk = 1ul << 10;
511 streamsize __bufavail = this->epptr() - this->pptr();
512
513 // Don't mistake 'uncommitted' mode buffered with unbuffered.
514 if (!_M_writing && this->_M_buf_size > 1)
515 __bufavail = this->_M_buf_size - 1;
516
517 const streamsize __limit = std::min(__chunk, __bufavail);
518 if (__n >= __limit)
519 {
520 const streamsize __buffill = this->pptr() - this->pbase();
521 const char* __buf = reinterpret_cast<const char*>(this->pbase());
522 __ret = _M_file.xsputn_2(__buf, __buffill,
523 reinterpret_cast<const char*>(__s), __n);
524 if (__ret == __buffill + __n)
525 {
526 _M_set_buffer(0);
527 _M_writing = true;
528 }
529 if (__ret > __buffill)
530 __ret -= __buffill;
531 else
532 __ret = 0;
533 }
534 else
535 __ret = __streambuf_type::xsputn(__s, __n);
536 }
537 else
538 __ret = __streambuf_type::xsputn(__s, __n);
539
540 return __ret;
541 }
542
990101f9 543 template<typename _CharT, typename _Traits>
31bfa177 544 typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
990101f9
BK
545 basic_filebuf<_CharT, _Traits>::
546 setbuf(char_type* __s, streamsize __n)
547 {
548 if (!this->is_open() && __s == 0 && __n == 0)
f10eea7b 549 this->_M_buf_size = 1;
b82a33d2 550 else if (__s && __n > 0)
990101f9 551 {
e3033a22 552 // This is implementation-defined behavior, and assumes that
c1b74c21
NM
553 // an external char_type array of length __n exists and has
554 // been pre-allocated. If this is not the case, things will
555 // quickly blow up. When __n > 1, __n - 1 positions will be
556 // used for the get area, __n - 1 for the put area and 1
557 // position to host the overflow char of a full put area.
558 // When __n == 1, 1 position will be used for the get area
559 // and 0 for the put area, as in the unbuffered case above.
391cd095 560
990101f9
BK
561 // Step 1: Destroy the current internal array.
562 _M_destroy_internal_buffer();
563
564 // Step 2: Use the external array.
8fbc5ae7 565 this->_M_buf = __s;
7ef9fd85 566 this->_M_buf_size = __n;
71b46021
PC
567 _M_reading = false;
568 _M_writing = false;
569 _M_set_buffer(-1);
990101f9
BK
570 }
571 _M_last_overflowed = false;
572 return this;
573 }
574
725dc051 575 template<typename _CharT, typename _Traits>
31bfa177 576 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
577 basic_filebuf<_CharT, _Traits>::
578 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
579 {
580 pos_type __ret = pos_type(off_type(-1));
0b176c1a
PC
581 const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
582 const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
95dca20c 583
a1796d12 584 int __width = 0;
0cd1de6f 585 if (_M_codecvt)
b417ae14 586 __width = _M_codecvt->encoding();
725dc051
BK
587 if (__width < 0)
588 __width = 0;
a1796d12
BK
589
590 const bool __testfail = __off != 0 && __width <= 0;
dcf5a5de 591 if (this->is_open() && !__testfail && (__testin || __testout))
725dc051
BK
592 {
593 // Ditch any pback buffers to avoid confusion.
aa438e8f 594 _M_destroy_pback();
725dc051 595
8c8dec01 596 off_type __computed_off = __off * __width;
cc5112c9 597 if (this->pbase() < this->pptr())
725dc051 598 {
71b46021
PC
599 // Part one: update the output sequence.
600 this->sync();
601
602 // Part two: output unshift sequence.
603 _M_output_unshift();
725dc051 604 }
71b46021 605 else if (_M_reading && __way == ios_base::cur)
8c8dec01
PR
606 {
607 if (_M_codecvt->always_noconv())
608 __computed_off += this->gptr() - this->egptr();
609 else
610 {
611 // Calculate offset from _M_ext_buf that corresponds
612 // to gptr().
613 const int __gptr_off =
614 _M_codecvt->length(_M_state_cur, _M_ext_buf, _M_ext_next,
615 this->gptr() - this->eback());
616 __computed_off += _M_ext_buf + __gptr_off - _M_ext_end;
617 }
618 }
71b46021 619
cc5112c9 620 // Returns pos_type(off_type(-1)) in case of failure.
8c8dec01 621 __ret = _M_file.seekoff(__computed_off, __way, __mode);
b417ae14 622
71b46021
PC
623 _M_reading = false;
624 _M_writing = false;
8c8dec01 625 _M_ext_next = _M_ext_end = _M_ext_buf;
71b46021 626 _M_set_buffer(-1);
725dc051
BK
627 }
628 _M_last_overflowed = false;
629 return __ret;
630 }
631
632 template<typename _CharT, typename _Traits>
31bfa177 633 typename basic_filebuf<_CharT, _Traits>::pos_type
725dc051
BK
634 basic_filebuf<_CharT, _Traits>::
635 seekpos(pos_type __pos, ios_base::openmode __mode)
636 {
3d7c150e 637#ifdef _GLIBCXX_RESOLVE_LIB_DEFECTS
b988dfc5 638// 171. Strange seekpos() semantics due to joint position
b417ae14
PC
639 pos_type __ret = pos_type(off_type(-1));
640
641 int __width = 0;
642 if (_M_codecvt)
643 __width = _M_codecvt->encoding();
644 if (__width > 0)
645 __ret = this->seekoff(off_type(__pos) / __width, ios_base::beg, __mode);
646
647 return __ret;
b988dfc5 648#endif
725dc051
BK
649 }
650
651 template<typename _CharT, typename _Traits>
652 void
653 basic_filebuf<_CharT, _Traits>::
654 _M_output_unshift()
655 { }
656
657 template<typename _CharT, typename _Traits>
658 void
659 basic_filebuf<_CharT, _Traits>::
660 imbue(const locale& __loc)
661 {
0cd1de6f
BK
662 const bool __testbeg = !this->seekoff(0, ios_base::cur, this->_M_mode);
663 const bool __teststate = __check_facet(_M_codecvt).encoding() == -1;
69302d8b 664
0cd1de6f
BK
665 if (this->_M_buf_locale != __loc
666 && (!this->is_open() || (__testbeg && !__teststate)))
667 {
668 this->_M_buf_locale = __loc;
669 if (__builtin_expect(has_facet<__codecvt_type>(__loc), true))
670 _M_codecvt = &use_facet<__codecvt_type>(__loc);
671
672 // NB This may require the reconversion of previously
673 // converted chars. This in turn may cause the
674 // reconstruction of the original file. YIKES!! This
675 // implementation interprets this requirement as requiring
676 // the file position be at the beginning, and a stateless
677 // encoding, or that the filebuf be closed. Opinions may differ.
678 }
725dc051
BK
679 _M_last_overflowed = false;
680 }
a32e3c09
BK
681
682 // Inhibit implicit instantiations for required instantiations,
683 // which are defined via explicit instantiations elsewhere.
684 // NB: This syntax is a GNU extension.
3d7c150e 685#if _GLIBCXX_EXTERN_TEMPLATE
a32e3c09 686 extern template class basic_filebuf<char>;
a32e3c09 687 extern template class basic_ifstream<char>;
a32e3c09 688 extern template class basic_ofstream<char>;
a32e3c09 689 extern template class basic_fstream<char>;
5112ae3a 690
3d7c150e 691#ifdef _GLIBCXX_USE_WCHAR_T
5112ae3a
BK
692 extern template class basic_filebuf<wchar_t>;
693 extern template class basic_ifstream<wchar_t>;
694 extern template class basic_ofstream<wchar_t>;
a32e3c09 695 extern template class basic_fstream<wchar_t>;
5112ae3a 696#endif
1bc8b0ad 697#endif
725dc051
BK
698} // namespace std
699
6f48900c 700#endif
This page took 0.390308 seconds and 5 git commands to generate.