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