2 * Copyright (c) 1996,1997
3 * Silicon Graphics Computer Systems, Inc.
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
11 * Permission to use or copy this software for any purpose is hereby granted
12 * without fee, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
18 #ifndef _STLP_FSTREAM_C
19 #define _STLP_FSTREAM_C
21 #ifndef _STLP_INTERNAL_FSTREAM_H
22 # include <stl/_fstream.h>
25 #ifndef _STLP_INTERNAL_LIMITS
26 # include <stl/_limits.h>
31 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
32 // no wchar_t is supported for this mode
33 # define __BF_int_type__ int
34 # define __BF_pos_type__ streampos
35 # define __BF_off_type__ streamoff
37 # define __BF_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type
38 # define __BF_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::pos_type
39 # define __BF_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::off_type
43 //----------------------------------------------------------------------
44 // Public basic_filebuf<> member functions
46 template <class _CharT
, class _Traits
>
47 basic_filebuf
<_CharT
, _Traits
>::basic_filebuf()
48 : basic_streambuf
<_CharT
, _Traits
>(), _M_base(),
49 _M_constant_width(false), _M_always_noconv(false),
50 _M_int_buf_dynamic(false),
51 _M_in_input_mode(false), _M_in_output_mode(false),
52 _M_in_error_mode(false), _M_in_putback_mode(false),
53 _M_int_buf(0), _M_int_buf_EOS(0),
54 _M_ext_buf(0), _M_ext_buf_EOS(0),
55 _M_ext_buf_converted(0), _M_ext_buf_end(0),
56 _M_state(_STLP_DEFAULT_CONSTRUCTED(_State_type
)),
57 _M_end_state(_STLP_DEFAULT_CONSTRUCTED(_State_type
)),
58 _M_mmap_base(0), _M_mmap_len(0),
59 _M_saved_eback(0), _M_saved_gptr(0), _M_saved_egptr(0),
61 _M_width(1), _M_max_width(1)
63 this->_M_setup_codecvt(locale(), false);
66 template <class _CharT
, class _Traits
>
67 basic_filebuf
<_CharT
, _Traits
>::~basic_filebuf() {
69 _M_deallocate_buffers();
73 template <class _CharT
, class _Traits
>
74 _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf
<_CharT
, _Traits
>::int_type
75 basic_filebuf
<_CharT
, _Traits
>::underflow() {
76 return _Underflow
<_CharT
, _Traits
>::_M_doit(this);
79 template <class _CharT
, class _Traits
>
80 basic_filebuf
<_CharT
, _Traits
>*
81 basic_filebuf
<_CharT
, _Traits
>::close() {
82 bool __ok
= this->is_open();
84 if (_M_in_output_mode
) {
85 __ok
= __ok
&& !_Traits::eq_int_type(this->overflow(traits_type::eof()),
87 __ok
== __ok
&& this->_M_unshift();
89 else if (_M_in_input_mode
)
90 this->_M_exit_input_mode();
92 // Note order of arguments. We close the file even if __ok is false.
93 __ok
= _M_base
._M_close() && __ok
;
95 // Restore the initial state, except that we don't deallocate the buffer
96 // or mess with the cached codecvt information.
97 _M_state
= _M_end_state
= _State_type();
98 _M_ext_buf_converted
= _M_ext_buf_end
= 0;
106 _M_saved_eback
= _M_saved_gptr
= _M_saved_egptr
= 0;
108 _M_in_input_mode
= _M_in_output_mode
= _M_in_error_mode
= _M_in_putback_mode
111 return __ok
? this : 0;
114 // This member function is called whenever we exit input mode.
115 // It unmaps the memory-mapped file, if any, and sets
116 // _M_in_input_mode to false.
117 template <class _CharT
, class _Traits
>
118 void basic_filebuf
<_CharT
, _Traits
>::_M_exit_input_mode() {
119 if (_M_mmap_base
!= 0) {
120 _M_base
._M_unmap(_M_mmap_base
, _M_mmap_len
);
124 _M_in_input_mode
= false;
128 //----------------------------------------------------------------------
129 // basic_filebuf<> overridden protected virtual member functions
131 template <class _CharT
, class _Traits
>
132 streamsize basic_filebuf
<_CharT
, _Traits
>::showmanyc() {
133 // Is there any possibility that reads can succeed?
134 if (!this->is_open() || _M_in_output_mode
|| _M_in_error_mode
)
136 else if (_M_in_putback_mode
)
137 return this->egptr() - this->gptr();
138 else if (_M_constant_width
) {
139 streamoff __pos
= _M_base
._M_seek(0, ios_base::cur
);
140 streamoff __size
= _M_base
._M_file_size();
141 return __pos
>= 0 && __size
> __pos
? __size
- __pos
: 0;
148 // Make a putback position available, if necessary, by switching to a
149 // special internal buffer used only for putback. The buffer is
150 // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base
151 // class only sees a piece of it at a time. (We want to make sure
152 // that we don't try to read a character that hasn't been initialized.)
153 // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size,
154 // but the beginning is usually not _M_pback_buf.
155 template <class _CharT
, class _Traits
>
157 basic_filebuf
<_CharT
, _Traits
>::pbackfail(int_type __c
) {
158 const int_type __eof
= traits_type::eof();
160 // If we aren't already in input mode, pushback is impossible.
161 if (!_M_in_input_mode
)
164 // We can use the ordinary get buffer if there's enough space, and
165 // if it's a buffer that we're allowed to write to.
166 if (this->gptr() != this->eback() &&
167 (traits_type::eq_int_type(__c
, __eof
) ||
168 traits_type::eq(traits_type::to_char_type(__c
), this->gptr()[-1]) ||
171 if (traits_type::eq_int_type(__c
, __eof
) ||
172 traits_type::eq(traits_type::to_char_type(__c
), *this->gptr()))
173 return traits_type::to_int_type(*this->gptr());
175 else if (!traits_type::eq_int_type(__c
, __eof
)) {
176 // Are we in the putback buffer already?
177 _CharT
* __pback_end
= _M_pback_buf
+ __STATIC_CAST(int,_S_pback_buf_size
);
178 if (_M_in_putback_mode
) {
179 // Do we have more room in the putback buffer?
180 if (this->eback() != _M_pback_buf
)
181 this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end
);
183 return __eof
; // No more room in the buffer, so fail.
185 else { // We're not yet in the putback buffer.
186 _M_saved_eback
= this->eback();
187 _M_saved_gptr
= this->gptr();
188 _M_saved_egptr
= this->egptr();
189 this->setg(__pback_end
- 1, __pback_end
- 1, __pback_end
);
190 _M_in_putback_mode
= true;
196 // We have made a putback position available. Assign to it, and return.
197 *this->gptr() = traits_type::to_char_type(__c
);
201 // This member function flushes the put area, and also outputs the
202 // character __c (unless __c is eof). Invariant: we always leave room
203 // in the internal buffer for one character more than the base class knows
204 // about. We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but
205 // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
206 template <class _CharT
, class _Traits
>
208 basic_filebuf
<_CharT
, _Traits
>::overflow(int_type __c
) {
209 // Switch to output mode, if necessary.
210 if (!_M_in_output_mode
)
211 if (!_M_switch_to_output_mode())
212 return traits_type::eof();
214 _CharT
* __ibegin
= this->_M_int_buf
;
215 _CharT
* __iend
= this->pptr();
216 this->setp(_M_int_buf
, _M_int_buf_EOS
- 1);
218 // Put __c at the end of the internal buffer.
219 if (!traits_type::eq_int_type(__c
, traits_type::eof()))
220 *__iend
++ = _Traits::to_char_type(__c
);
222 // For variable-width encodings, output may take more than one pass.
223 while (__ibegin
!= __iend
) {
224 const _CharT
* __inext
= __ibegin
;
225 char* __enext
= _M_ext_buf
;
226 typename
_Codecvt::result __status
227 = _M_codecvt
->out(_M_state
, __ibegin
, __iend
, __inext
,
228 _M_ext_buf
, _M_ext_buf_EOS
, __enext
);
229 if (__status
== _Codecvt::noconv
) {
230 return _Noconv_output
<_Traits
>::_M_doit(this, __ibegin
, __iend
)
231 ? traits_type::not_eof(__c
)
235 // For a constant-width encoding we know that the external buffer
236 // is large enough, so failure to consume the entire internal buffer
237 // or to produce the correct number of external characters, is an error.
238 // For a variable-width encoding, however, we require only that we
239 // consume at least one internal character
240 else if (__status
!= _Codecvt::error
&&
241 (((__inext
== __iend
) &&
242 (__enext
- _M_ext_buf
== _M_width
* (__iend
- __ibegin
))) ||
243 (!_M_constant_width
&& __inext
!= __ibegin
))) {
244 // We successfully converted part or all of the internal buffer.
245 ptrdiff_t __n
= __enext
- _M_ext_buf
;
246 if (_M_write(_M_ext_buf
, __n
))
247 __ibegin
+= __inext
- __ibegin
;
249 return _M_output_error();
252 return _M_output_error();
255 return traits_type::not_eof(__c
);
258 // This member function must be called before any I/O has been
259 // performed on the stream, otherwise it has no effect.
261 // __buf == 0 && __n == 0 means to make this stream unbuffered.
262 // __buf != 0 && __n > 0 means to use __buf as the stream's internal
263 // buffer, rather than the buffer that would otherwise be allocated
264 // automatically. __buf must be a pointer to an array of _CharT whose
265 // size is at least __n.
266 template <class _CharT
, class _Traits
>
267 basic_streambuf
<_CharT
, _Traits
>*
268 basic_filebuf
<_CharT
, _Traits
>::setbuf(_CharT
* __buf
, streamsize __n
) {
269 if (!_M_in_input_mode
&&! _M_in_output_mode
&& !_M_in_error_mode
&&
271 if (__buf
== 0 && __n
== 0)
272 _M_allocate_buffers(0, 1);
273 else if (__buf
!= 0 && __n
> 0)
274 _M_allocate_buffers(__buf
, __n
);
279 #if defined (_STLP_ASSERTIONS)
281 template <class _CharT
>
282 struct _Filebuf_Tmp_Buf
{
284 _Filebuf_Tmp_Buf(ptrdiff_t __n
) : _M_ptr(0) { _M_ptr
= new _CharT
[__n
]; }
285 ~_Filebuf_Tmp_Buf() { delete[] _M_ptr
; }
289 template <class _CharT
, class _Traits
>
291 basic_filebuf
<_CharT
, _Traits
>::seekoff(off_type __off
,
292 ios_base::seekdir __whence
,
293 ios_base::openmode
/* dummy */) {
294 if (!this->is_open())
297 if (!_M_constant_width
&& __off
!= 0)
300 if (!_M_seek_init(__off
!= 0 || __whence
!= ios_base::cur
))
303 // Seek to beginning or end, regardless of whether we're in input mode.
304 if (__whence
== ios_base::beg
|| __whence
== ios_base::end
)
305 return _M_seek_return(_M_base
._M_seek(_M_width
* __off
, __whence
),
308 // Seek relative to current position. Complicated if we're in input mode.
309 _STLP_ASSERT(__whence
== ios_base::cur
)
310 if (!_M_in_input_mode
)
311 return _M_seek_return(_M_base
._M_seek(_M_width
* __off
, __whence
),
314 if (_M_mmap_base
!= 0) {
315 // __off is relative to gptr(). We need to do a bit of arithmetic
316 // to get an offset relative to the external file pointer.
317 streamoff __adjust
= _M_mmap_len
- (this->gptr() - (_CharT
*) _M_mmap_base
);
319 // if __off == 0, we do not need to exit input mode and to shift file pointer
320 return __off
== 0 ? pos_type(_M_base
._M_seek(0, ios_base::cur
) - __adjust
)
321 : _M_seek_return(_M_base
._M_seek(__off
- __adjust
, ios_base::cur
), _State_type());
324 if (_M_constant_width
) { // Get or set the position.
325 streamoff __iadj
= _M_width
* (this->gptr() - this->eback());
327 // Compensate for offset relative to gptr versus offset relative
328 // to external pointer. For a text-oriented stream, where the
329 // compensation is more than just pointer arithmetic, we may get
330 // but not set the current position.
332 if (__iadj
<= _M_ext_buf_end
- _M_ext_buf
) {
333 streamoff __eadj
= _M_base
._M_get_offset(_M_ext_buf
+ __STATIC_CAST(ptrdiff_t, __iadj
), _M_ext_buf_end
);
335 return __off
== 0 ? pos_type(_M_base
._M_seek(0, ios_base::cur
) - __eadj
)
336 : _M_seek_return(_M_base
._M_seek(__off
- __eadj
, ios_base::cur
), _State_type());
339 else { // Get the position. Encoding is var width.
340 // Get position in internal buffer.
341 ptrdiff_t __ipos
= this->gptr() - this->eback();
343 // Get corresponding position in external buffer.
344 _State_type __state
= _M_state
;
345 int __epos
= _M_codecvt
->length(__state
, _M_ext_buf
, _M_ext_buf_converted
,
347 #if defined (_STLP_ASSERTIONS)
348 // Sanity check (expensive): make sure __epos is the right answer.
349 _STLP_ASSERT(__epos
>= 0)
350 _State_type __tmp_state
= _M_state
;
351 _Filebuf_Tmp_Buf
<_CharT
> __buf(__ipos
);
352 _CharT
* __ibegin
= __buf
._M_ptr
;
353 _CharT
* __inext
= __ibegin
;
355 typename
_Codecvt::result __status
356 = _M_codecvt
->in(__tmp_state
,
357 _M_ext_buf
, _M_ext_buf
+ __epos
, __dummy
,
358 __ibegin
, __ibegin
+ __ipos
, __inext
);
359 // The result code is necessarily ok because:
360 // - noconv: impossible for a variable encoding
361 // - error: length method is supposed to count until it reach max value or find an error so we cannot have
362 // an error again when decoding an external buffer up to length return value.
363 // - partial: idem error, it is also a reason for length to stop counting.
364 _STLP_ASSERT(__status
== _Codecvt::ok
)
365 _STLP_ASSERT(__inext
== __ibegin
+ __ipos
)
366 _STLP_ASSERT(equal(this->eback(), this->gptr(), __ibegin
, _STLP_PRIV _Eq_traits
<traits_type
>()))
368 // Get the current position (at the end of the external buffer),
369 // then adjust it. Again, it might be a text-oriented stream.
370 streamoff __cur
= _M_base
._M_seek(0, ios_base::cur
);
371 streamoff __adj
= _M_base
._M_get_offset(_M_ext_buf
, _M_ext_buf
+ __epos
) -
372 _M_base
._M_get_offset(_M_ext_buf
, _M_ext_buf_end
);
373 if (__cur
!= -1 && __cur
+ __adj
>= 0)
374 return __off
== 0 ? pos_type(__cur
+ __adj
)
375 : _M_seek_return(__cur
+ __adj
, __state
);
382 template <class _CharT
, class _Traits
>
384 basic_filebuf
<_CharT
, _Traits
>::seekpos(pos_type __pos
,
385 ios_base::openmode
/* dummy */) {
386 if (this->is_open()) {
387 if (!_M_seek_init(true))
390 streamoff __off
= off_type(__pos
);
391 if (__off
!= -1 && _M_base
._M_seek(__off
, ios_base::beg
) != -1) {
392 _M_state
= __pos
.state();
393 return _M_seek_return(__off
, __pos
.state());
401 template <class _CharT
, class _Traits
>
402 int basic_filebuf
<_CharT
, _Traits
>::sync() {
403 if (_M_in_output_mode
)
404 return traits_type::eq_int_type(this->overflow(traits_type::eof()),
405 traits_type::eof()) ? -1 : 0;
410 // Change the filebuf's locale. This member function has no effect
411 // unless it is called before any I/O is performed on the stream.
412 template <class _CharT
, class _Traits
>
413 void basic_filebuf
<_CharT
, _Traits
>::imbue(const locale
& __loc
) {
414 if (!_M_in_input_mode
&& !_M_in_output_mode
&& !_M_in_error_mode
) {
415 this->_M_setup_codecvt(__loc
);
419 //----------------------------------------------------------------------
420 // basic_filebuf<> helper functions.
422 //----------------------------------------
423 // Helper functions for switching between modes.
425 // This member function is called if we're performing the first I/O
426 // operation on a filebuf, or if we're performing an input operation
427 // immediately after a seek.
428 template <class _CharT
, class _Traits
>
429 bool basic_filebuf
<_CharT
, _Traits
>::_M_switch_to_input_mode() {
430 if (this->is_open() && (((int)_M_base
.__o_mode() & (int)ios_base::in
) !=0)
431 && (_M_in_output_mode
== 0) && (_M_in_error_mode
== 0)) {
432 if (!_M_int_buf
&& !_M_allocate_buffers())
435 _M_ext_buf_converted
= _M_ext_buf
;
436 _M_ext_buf_end
= _M_ext_buf
;
438 _M_end_state
= _M_state
;
440 _M_in_input_mode
= true;
448 // This member function is called if we're performing the first I/O
449 // operation on a filebuf, or if we're performing an output operation
450 // immediately after a seek.
451 template <class _CharT
, class _Traits
>
452 bool basic_filebuf
<_CharT
, _Traits
>::_M_switch_to_output_mode() {
453 if (this->is_open() && (_M_base
.__o_mode() & (int)ios_base::out
) &&
454 _M_in_input_mode
== 0 && _M_in_error_mode
== 0) {
456 if (!_M_int_buf
&& !_M_allocate_buffers())
459 // In append mode, every write does an implicit seek to the end
460 // of the file. Whenever leaving output mode, the end of file
461 // get put in the initial shift state.
462 if (_M_base
.__o_mode() & ios_base::app
)
463 _M_state
= _State_type();
465 this->setp(_M_int_buf
, _M_int_buf_EOS
- 1);
466 _M_in_output_mode
= true;
474 //----------------------------------------
475 // Helper functions for input
477 // This member function is called if there is an error during input.
478 // It puts the filebuf in error mode, clear the get area buffer, and
480 // returns eof. Error mode is sticky; it is cleared only by close or
483 template <class _CharT
, class _Traits
>
485 basic_filebuf
<_CharT
, _Traits
>::_M_input_error() {
486 this->_M_exit_input_mode();
487 _M_in_output_mode
= false;
488 _M_in_error_mode
= true;
490 return traits_type::eof();
493 template <class _CharT
, class _Traits
>
495 basic_filebuf
<_CharT
, _Traits
>::_M_underflow_aux() {
496 // We have the state and file position from the end of the internal
497 // buffer. This round, they become the beginning of the internal buffer.
498 _M_state
= _M_end_state
;
500 // Fill the external buffer. Start with any leftover characters that
501 // didn't get converted last time.
502 if (_M_ext_buf_end
> _M_ext_buf_converted
)
504 _M_ext_buf_end
= _STLP_STD::copy(_M_ext_buf_converted
, _M_ext_buf_end
, _M_ext_buf
);
505 // boris : copy_backward did not work
506 //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end,
507 //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted));
509 _M_ext_buf_end
= _M_ext_buf
;
511 // Now fill the external buffer with characters from the file. This is
512 // a loop because occasionally we don't get enough external characters
515 ptrdiff_t __n
= _M_base
._M_read(_M_ext_buf_end
, _M_ext_buf_EOS
- _M_ext_buf_end
);
517 // Read failed, maybe we should set err bit on associated stream...
519 return traits_type::eof();
522 _M_ext_buf_end
+= __n
;
524 // If external buffer is empty there is nothing to do.
525 if (_M_ext_buf
== _M_ext_buf_end
) {
527 return traits_type::eof();
530 // Convert the external buffer to internal characters.
534 typename
_Codecvt::result __status
535 = _M_codecvt
->in(_M_end_state
,
536 _M_ext_buf
, _M_ext_buf_end
, __enext
,
537 _M_int_buf
, _M_int_buf_EOS
, __inext
);
540 * (1) Return value of error.
541 * (2) Producing internal characters without consuming external characters.
542 * (3) In fixed-width encodings, producing an internal sequence whose length
543 * is inconsistent with that of the internal sequence.
544 * (4) Failure to produce any characters if we have enough characters in
545 * the external buffer, where "enough" means the largest possible width
546 * of a single character. */
547 if (__status
== _Codecvt::noconv
)
548 return _Noconv_input
<_Traits
>::_M_doit(this);
549 else if (__status
== _Codecvt::error
||
550 (__inext
!= _M_int_buf
&& __enext
== _M_ext_buf
) ||
551 (_M_constant_width
&& (__inext
- _M_int_buf
) * _M_width
!= (__enext
- _M_ext_buf
)) ||
552 (__inext
== _M_int_buf
&& __enext
- _M_ext_buf
>= _M_max_width
))
553 return _M_input_error();
554 else if (__inext
!= _M_int_buf
) {
555 _M_ext_buf_converted
= _M_ext_buf
+ (__enext
- _M_ext_buf
);
556 this->setg(_M_int_buf
, _M_int_buf
, __inext
);
557 return traits_type::to_int_type(*_M_int_buf
);
559 /* We need to go around the loop again to get more external characters.
560 * But if the previous read failed then don't try again for now.
561 * Don't enter error mode for a failed read. Error mode is sticky,
562 * and we might succeed if we try again. */
565 return traits_type::eof();
570 //----------------------------------------
571 // Helper functions for output
573 // This member function is called if there is an error during output.
574 // It puts the filebuf in error mode, clear the put area buffer, and
575 // returns eof. Error mode is sticky; it is cleared only by close or
577 template <class _CharT
, class _Traits
>
579 basic_filebuf
<_CharT
, _Traits
>::_M_output_error() {
580 _M_in_output_mode
= false;
581 _M_in_input_mode
= false;
582 _M_in_error_mode
= true;
584 return traits_type::eof();
588 // Write whatever sequence of characters is necessary to get back to
589 // the initial shift state. This function overwrites the external
590 // buffer, changes the external file position, and changes the state.
591 // Precondition: the internal buffer is empty.
592 template <class _CharT
, class _Traits
>
593 bool basic_filebuf
<_CharT
, _Traits
>::_M_unshift() {
594 if (_M_in_output_mode
&& !_M_constant_width
) {
595 typename
_Codecvt::result __status
;
597 char* __enext
= _M_ext_buf
;
598 __status
= _M_codecvt
->unshift(_M_state
,
599 _M_ext_buf
, _M_ext_buf_EOS
, __enext
);
600 if (__status
== _Codecvt::noconv
||
601 (__enext
== _M_ext_buf
&& __status
== _Codecvt::ok
))
603 else if (__status
== _Codecvt::error
)
605 else if (!_M_write(_M_ext_buf
, __enext
- _M_ext_buf
))
607 } while (__status
== _Codecvt::partial
);
614 //----------------------------------------
615 // Helper functions for buffer allocation and deallocation
617 // This member function is called when we're initializing a filebuf's
618 // internal and external buffers. The argument is the size of the
619 // internal buffer; the external buffer is sized using the character
620 // width in the current encoding. Preconditions: the buffers are currently
621 // null. __n >= 1. __buf is either a null pointer or a pointer to an
622 // array show size is at least __n.
624 // We need __n >= 1 for two different reasons. For input, the base
625 // class always needs a buffer because of the semantics of underflow().
626 // For output, we want to have an internal buffer that's larger by one
627 // element than the buffer that the base class knows about. (See
628 // basic_filebuf<>::overflow() for the reason.)
629 template <class _CharT
, class _Traits
>
630 bool basic_filebuf
<_CharT
, _Traits
>::_M_allocate_buffers(_CharT
* __buf
, streamsize __n
) {
631 //The major hypothesis in the following implementation is that size_t is unsigned.
632 //We also need streamsize byte representation to be larger or equal to the int
633 //representation to correctly store the encoding information.
634 _STLP_STATIC_ASSERT(!numeric_limits
<size_t>::is_signed
&&
635 sizeof(streamsize
) >= sizeof(int))
638 streamsize __bufsize
= __n
* sizeof(_CharT
);
639 //We first check that the streamsize representation can't overflow a size_t one.
640 //If it can, we check that __bufsize is not higher than the size_t max value.
641 if ((sizeof(streamsize
) > sizeof(size_t)) &&
642 (__bufsize
> __STATIC_CAST(streamsize
, (numeric_limits
<size_t>::max
)())))
644 _M_int_buf
= __STATIC_CAST(_CharT
*, malloc(__STATIC_CAST(size_t, __bufsize
)));
647 _M_int_buf_dynamic
= true;
651 _M_int_buf_dynamic
= false;
654 streamsize __ebufsiz
= (max
)(__n
* __STATIC_CAST(streamsize
, _M_width
),
655 __STATIC_CAST(streamsize
, _M_codecvt
->max_length()));
658 if ((sizeof(streamsize
) < sizeof(size_t)) ||
659 ((sizeof(streamsize
) == sizeof(size_t)) && numeric_limits
<streamsize
>::is_signed
) ||
660 (__ebufsiz
<= __STATIC_CAST(streamsize
, (numeric_limits
<size_t>::max
)()))) {
661 _M_ext_buf
= __STATIC_CAST(char*, malloc(__STATIC_CAST(size_t, __ebufsiz
)));
665 _M_deallocate_buffers();
669 _M_int_buf_EOS
= _M_int_buf
+ __STATIC_CAST(ptrdiff_t, __n
);
670 _M_ext_buf_EOS
= _M_ext_buf
+ __STATIC_CAST(ptrdiff_t, __ebufsiz
);
674 // Abbreviation for the most common case.
675 template <class _CharT
, class _Traits
>
676 bool basic_filebuf
<_CharT
, _Traits
>::_M_allocate_buffers() {
677 // Choose a buffer that's at least 4096 characters long and that's a
678 // multiple of the page size.
679 streamsize __default_bufsiz
=
680 ((_M_base
.__page_size() + 4095UL) / _M_base
.__page_size()) * _M_base
.__page_size();
681 return _M_allocate_buffers(0, __default_bufsiz
);
684 template <class _CharT
, class _Traits
>
685 void basic_filebuf
<_CharT
, _Traits
>::_M_deallocate_buffers() {
686 if (_M_int_buf_dynamic
)
696 //----------------------------------------
697 // Helper functiosn for seek and imbue
699 template <class _CharT
, class _Traits
>
700 bool basic_filebuf
<_CharT
, _Traits
>::_M_seek_init(bool __do_unshift
) {
701 // If we're in error mode, leave it.
702 _M_in_error_mode
= false;
704 // Flush the output buffer if we're in output mode, and (conditionally)
705 // emit an unshift sequence.
706 if (_M_in_output_mode
) {
707 bool __ok
= !traits_type::eq_int_type(this->overflow(traits_type::eof()),
710 __ok
= __ok
&& this->_M_unshift();
712 _M_in_output_mode
= false;
713 _M_in_error_mode
= true;
719 // Discard putback characters, if any.
720 if (_M_in_input_mode
&& _M_in_putback_mode
)
721 _M_exit_putback_mode();
727 /* Change the filebuf's locale. This member function has no effect
728 * unless it is called before any I/O is performed on the stream.
729 * This function is called on construction and on an imbue call. In the
730 * case of the construction the codecvt facet might be a custom one if
731 * the basic_filebuf user has instanciate it with a custom char_traits.
732 * The user will have to call imbue before any I/O operation.
734 template <class _CharT
, class _Traits
>
735 void basic_filebuf
<_CharT
, _Traits
>::_M_setup_codecvt(const locale
& __loc
, bool __on_imbue
) {
736 if (has_facet
<_Codecvt
>(__loc
)) {
737 _M_codecvt
= &use_facet
<_Codecvt
>(__loc
) ;
738 int __encoding
= _M_codecvt
->encoding();
740 _M_width
= (max
)(__encoding
, 1);
741 _M_max_width
= _M_codecvt
->max_length();
742 _M_constant_width
= __encoding
> 0;
743 _M_always_noconv
= _M_codecvt
->always_noconv();
747 _M_width
= _M_max_width
= 1;
748 _M_constant_width
= _M_always_noconv
= false;
750 //This call will generate an exception reporting the problem.
751 use_facet
<_Codecvt
>(__loc
);
758 # undef __BF_int_type__
759 # undef __BF_pos_type__
760 # undef __BF_off_type__
762 #endif /* _STLP_FSTREAM_C */