]>
Commit | Line | Data |
---|---|---|
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 |
40 | namespace 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 |