Commit b3329ad5c94b14b696de9f80b400b8c29f9e8bb2

fstream: internal flags changed; fix bug #2881622

Replace few char-used-as-bool flags by single int and bit masks.

Fix bug #2881622: force situation, when read from file
fail (right), then clear file stream flags and make attempt
to write into file (at EOF). Bug: write fail too, but shouldn't.

There was workaround: do some seek (even 0).

Problem is: basic_filebuf when switch to output mode, try to check
(why it needs?) that it wasn't in input mode. The same issue
in switch to input mode. Test added in the fstream_test.cpp (rewind).

BTW, workaround was correct: seek clear input mode flag.
  
3939 typedef char_traits<char> traits_type;
4040 typedef traits_type::int_type int_type;
4141
42 if (!__this->_M_in_input_mode) {
43 if (!__this->_M_switch_to_input_mode())
42 if ( (__this->int_flags_ & basic_filebuf<char, char_traits<char> >::_in_input_mode) == 0 ) {
43 if ( !__this->_M_switch_to_input_mode() ) {
4444 return traits_type::eof();
45 }
46 else if (__this->_M_in_putback_mode) {
45 }
46 } else if ( __this->int_flags_ & basic_filebuf<char, char_traits<char> >::_in_putback_mode ) {
4747 __this->_M_exit_putback_mode();
4848 if (__this->gptr() != __this->egptr()) {
4949 int_type __c = traits_type::to_int_type(*__this->gptr());
5555 // sequences are guaranteed to be identical, then try to use memory
5656 // mapped I/O. Otherwise, revert to ordinary read.
5757 if (__this->_M_base.__regular_file()
58 && __this->_M_always_noconv
58 && ((__this->int_flags_ & basic_filebuf<char, char_traits<char> >::_always_noconv) != 0)
5959 && __this->_M_base._M_in_binary_mode()) {
6060 // If we've mmapped part of the file already, then unmap it.
6161 if (__this->_M_mmap_base)
  
4444// Public basic_filebuf<> member functions
4545
4646template <class _CharT, class _Traits>
47basic_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),
47basic_filebuf<_CharT, _Traits>::basic_filebuf() :
48 basic_streambuf<_CharT, _Traits>(),
49 _M_base(),
50 int_flags_(0),
51 _M_int_buf(0),
52 _M_int_buf_EOS(0),
53 _M_ext_buf(0),
54 _M_ext_buf_EOS(0),
55 _M_ext_buf_converted(0),
56 _M_ext_buf_end(0),
5657 _M_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
5758 _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),
59 _M_mmap_base(0),
60 _M_mmap_len(0),
61 _M_saved_eback(0),
62 _M_saved_gptr(0),
63 _M_saved_egptr(0),
6064 _M_codecvt(0),
61 _M_width(1), _M_max_width(1)
65 _M_width(1),
66 _M_max_width(1)
6267{
6368 this->_M_setup_codecvt(locale(), false);
6469}
8383
8484template <class _CharT, class _Traits>
8585basic_filebuf<_CharT, _Traits>*
86basic_filebuf<_CharT, _Traits>::close() {
86basic_filebuf<_CharT, _Traits>::close()
87{
8788 bool __ok = this->is_open();
8889
89 if (_M_in_output_mode) {
90 if ( int_flags_ & _in_output_mode ) {
9091 __ok = __ok && !_Traits::eq_int_type(this->overflow(traits_type::eof()),
9192 traits_type::eof());
9293 __ok == __ok && this->_M_unshift();
94 } else if ( int_flags_ & _in_input_mode ) {
95 this->_M_exit_input_mode();
9396 }
94 else if (_M_in_input_mode)
95 this->_M_exit_input_mode();
9697
9798 // Note order of arguments. We close the file even if __ok is false.
9899 __ok = _M_base._M_close() && __ok;
111111
112112 _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0;
113113
114 _M_in_input_mode = _M_in_output_mode = _M_in_error_mode = _M_in_putback_mode
115 = false;
114 int_flags_ &= ~(_in_input_mode | _in_output_mode & _in_error_mode | _in_putback_mode );
116115
117116 return __ok ? this : 0;
118117}
120120// It unmaps the memory-mapped file, if any, and sets
121121// _M_in_input_mode to false.
122122template <class _CharT, class _Traits>
123void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode() {
123void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode()
124{
124125 if (_M_mmap_base != 0) {
125126 _M_base._M_unmap(_M_mmap_base, _M_mmap_len);
126127 _M_mmap_base = 0;
127128 _M_mmap_len = 0;
128129 }
129 _M_in_input_mode = false;
130
131 int_flags_ &= ~_in_input_mode;
130132}
131133
132134
136136// basic_filebuf<> overridden protected virtual member functions
137137
138138template <class _CharT, class _Traits>
139streamsize basic_filebuf<_CharT, _Traits>::showmanyc() {
139streamsize basic_filebuf<_CharT, _Traits>::showmanyc()
140{
140141 // Is there any possibility that reads can succeed?
141 if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
142 if ( !this->is_open() || ((int_flags_ & (_in_output_mode | _in_error_mode)) != 0 ) ) {
142143 return -1;
143 else if (_M_in_putback_mode)
144 } else if ( (int_flags_ & _in_putback_mode) ) {
144145 return this->egptr() - this->gptr();
145 else if (_M_constant_width) {
146 } else if ( (int_flags_ & _constant_width) ) {
146147 streamoff __pos = _M_base._M_seek(0, ios_base::cur);
147148 streamoff __size = _M_base._M_file_size();
148149 return __pos >= 0 && __size > __pos ? __size - __pos : 0;
149150 }
150 else
151 return 0;
151
152 return 0;
152153}
153154
154155
162162// but the beginning is usually not _M_pback_buf.
163163template <class _CharT, class _Traits>
164164__BF_int_type__
165basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) {
165basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c)
166{
166167 const int_type __eof = traits_type::eof();
167168
168169 // If we aren't already in input mode, pushback is impossible.
169 if (!_M_in_input_mode)
170 if ( (int_flags_ & _in_input_mode) == 0 ) {
170171 return __eof;
172 }
171173
172174 // We can use the ordinary get buffer if there's enough space, and
173175 // if it's a buffer that we're allowed to write to.
181181 if (traits_type::eq_int_type(__c, __eof) ||
182182 traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
183183 return traits_type::to_int_type(*this->gptr());
184 }
185 else if (!traits_type::eq_int_type(__c, __eof)) {
184 } else if (!traits_type::eq_int_type(__c, __eof)) {
186185 // Are we in the putback buffer already?
187186 _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
188 if (_M_in_putback_mode) {
187 if ( int_flags_ & _in_putback_mode ) {
189188 // Do we have more room in the putback buffer?
190 if (this->eback() != _M_pback_buf)
189 if (this->eback() != _M_pback_buf) {
191190 this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
192 else
191 } else {
193192 return __eof; // No more room in the buffer, so fail.
194 }
195 else { // We're not yet in the putback buffer.
193 }
194 } else { // We're not yet in the putback buffer.
196195 _M_saved_eback = this->eback();
197196 _M_saved_gptr = this->gptr();
198197 _M_saved_egptr = this->egptr();
199198 this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
200 _M_in_putback_mode = true;
199 int_flags_ |= _in_putback_mode;
201200 }
202 }
203 else
201 } else {
204202 return __eof;
203 }
205204
206205 // We have made a putback position available. Assign to it, and return.
207206 *this->gptr() = traits_type::to_char_type(__c);
214214// the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
215215template <class _CharT, class _Traits>
216216__BF_int_type__
217basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
217basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
218{
218219 // Switch to output mode, if necessary.
219 if (!_M_in_output_mode)
220 if (!_M_switch_to_output_mode())
220 if ( (int_flags_ & _in_output_mode) == 0 ) {
221 if ( !_M_switch_to_output_mode() ) {
221222 return traits_type::eof();
223 }
224 }
222225
223226 _CharT* __ibegin = this->_M_int_buf;
224227 _CharT* __iend = this->pptr();
231231 if (!traits_type::eq_int_type(__c, traits_type::eof()))
232232 *__iend++ = _Traits::to_char_type(__c);
233233
234 const _CharT* __inext;
235 char* __enext;
236 typename _Codecvt::result __status;
237
234238 // For variable-width encodings, output may take more than one pass.
235 while (__ibegin != __iend) {
236 const _CharT* __inext = __ibegin;
237 char* __enext = _M_ext_buf;
238 typename _Codecvt::result __status
239 = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
240 _M_ext_buf, _M_ext_buf_EOS, __enext);
239 while ( __ibegin != __iend ) {
240 __inext = __ibegin;
241 __enext = _M_ext_buf;
242 __status = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
243 _M_ext_buf, _M_ext_buf_EOS, __enext);
241244 if (__status == _Codecvt::noconv) {
242245 return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
243246 ? traits_type::not_eof(__c)
255255 else if (__status != _Codecvt::error &&
256256 (((__inext == __iend) &&
257257 (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) ||
258 (!_M_constant_width && __inext != __ibegin))) {
258 ( ((int_flags_ & _constant_width) == 0) && __inext != __ibegin))) {
259259 // We successfully converted part or all of the internal buffer.
260260 ptrdiff_t __n = __enext - _M_ext_buf;
261 if (_M_write(_M_ext_buf, __n))
261 if (_M_write(_M_ext_buf, __n)) {
262262 __ibegin += __inext - __ibegin;
263 else
263 } else {
264264 return _M_output_error();
265 }
266 else
265 }
266 } else {
267267 return _M_output_error();
268 }
268269 }
269270
270271 return traits_type::not_eof(__c);
281281// size is at least __n.
282282template <class _CharT, class _Traits>
283283basic_streambuf<_CharT, _Traits>*
284basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) {
285 if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
286 _M_int_buf == 0) {
287 if (__buf == 0 && __n == 0)
284basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n)
285{
286 if ( ((int_flags_ & (_in_input_mode | _in_output_mode | _in_error_mode)) == 0) &&
287 (_M_int_buf == 0) ) {
288 if ((__buf == 0) && (__n == 0)) {
288289 _M_allocate_buffers(0, 1);
289 else if (__buf != 0 && __n > 0)
290 } else if (__buf != 0 && __n > 0) {
290291 _M_allocate_buffers(__buf, __n);
292 }
291293 }
292294 return this;
293295}
312312 if (!this->is_open())
313313 return pos_type(-1);
314314
315 if (!_M_constant_width && __off != 0)
315 if ( ((int_flags_ & _constant_width) == 0) && (__off != 0) ) {
316316 return pos_type(-1);
317 }
317318
318319 if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
319320 return pos_type(-1);
326326
327327 // Seek relative to current position. Complicated if we're in input mode.
328328 _STLP_ASSERT(__whence == ios_base::cur)
329 if (!_M_in_input_mode)
330 return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
331 _State_type());
329 if ( ((int_flags_ & _in_input_mode) == 0) ) {
330 return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence), _State_type());
331 }
332332
333333 if (_M_mmap_base != 0) {
334334 // __off is relative to gptr(). We need to do a bit of arithmetic
340340 : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
341341 }
342342
343 if (_M_constant_width) { // Get or set the position.
343 if ( (int_flags_ & _constant_width) ) { // Get or set the position.
344344 streamoff __iadj = _M_width * (this->gptr() - this->eback());
345345
346346 // Compensate for offset relative to gptr versus offset relative
354354 return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj)
355355 : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
356356 }
357 }
358 else { // Get the position. Encoding is var width.
357 } else { // Get the position. Encoding is var width.
359358 // Get position in internal buffer.
360359 ptrdiff_t __ipos = this->gptr() - this->eback();
361360
417417
418418
419419template <class _CharT, class _Traits>
420int basic_filebuf<_CharT, _Traits>::sync() {
421 if (_M_in_output_mode)
420int basic_filebuf<_CharT, _Traits>::sync()
421{
422 if ( int_flags_ & _in_output_mode ) {
422423 return traits_type::eq_int_type(this->overflow(traits_type::eof()),
423424 traits_type::eof()) ? -1 : 0;
425 }
424426 return 0;
425427}
426428
430430// Change the filebuf's locale. This member function has no effect
431431// unless it is called before any I/O is performed on the stream.
432432template <class _CharT, class _Traits>
433void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) {
434 if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) {
433void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc)
434{
435 if ( (int_flags_ & (_in_input_mode | _in_output_mode | _in_error_mode)) == 0 ) {
435436 this->_M_setup_codecvt(__loc);
436437 }
437438}
447447// operation on a filebuf, or if we're performing an input operation
448448// immediately after a seek.
449449template <class _CharT, class _Traits>
450bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode() {
451 if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0)
452 && (_M_in_output_mode == 0) && (_M_in_error_mode == 0)) {
453 if (!_M_int_buf && !_M_allocate_buffers())
450bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode()
451{
452 if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) != 0)
453 && ( (int_flags_ & (/* _in_output_mode | */ _in_error_mode)) == 0 ) ) {
454 if (!_M_int_buf && !_M_allocate_buffers()) {
454455 return false;
456 }
455457
456458 _M_ext_buf_converted = _M_ext_buf;
457459 _M_ext_buf_end = _M_ext_buf;
458460
459 _M_end_state = _M_state;
461 _M_end_state = _M_state;
462 int_flags_ |= _in_input_mode;
460463
461 _M_in_input_mode = true;
462464 return true;
463465 }
464466
472472// operation on a filebuf, or if we're performing an output operation
473473// immediately after a seek.
474474template <class _CharT, class _Traits>
475bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode() {
476 if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) &&
477 _M_in_input_mode == 0 && _M_in_error_mode == 0) {
475bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode()
476{
477 if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::out) != 0)
478 && ( (int_flags_ & (/* _in_input_mode | */ _in_error_mode)) == 0 ) ) {
478479
479 if (!_M_int_buf && !_M_allocate_buffers())
480 if (!_M_int_buf && !_M_allocate_buffers()) {
480481 return false;
482 }
481483
482484 // In append mode, every write does an implicit seek to the end
483485 // of the file. Whenever leaving output mode, the end of file
484486 // get put in the initial shift state.
485 if (_M_base.__o_mode() & ios_base::app)
487 if (_M_base.__o_mode() & ios_base::app) {
486488 _M_state = _State_type();
489 }
487490
488491 this->setp(_M_int_buf, _M_int_buf_EOS - 1);
489 _M_in_output_mode = true;
492 int_flags_ |= _in_output_mode;
493
490494 return true;
491495 }
492496
509509
510510template <class _CharT, class _Traits>
511511__BF_int_type__
512basic_filebuf<_CharT, _Traits>::_M_input_error() {
513 this->_M_exit_input_mode();
514 _M_in_output_mode = false;
515 _M_in_error_mode = true;
512basic_filebuf<_CharT, _Traits>::_M_input_error()
513{
514 this->_M_exit_input_mode();
515 int_flags_ |= _in_error_mode;
516 int_flags_ &= ~_in_output_mode;
516517 this->setg(0, 0, 0);
518
517519 return traits_type::eof();
518520}
519521
577577 return _Noconv_input<_Traits>::_M_doit(this);
578578 else if (__status == _Codecvt::error ||
579579 (__inext != _M_int_buf && __enext == _M_ext_buf) ||
580 (_M_constant_width && (__inext - _M_int_buf) * _M_width != (__enext - _M_ext_buf)) ||
580 ( ((int_flags_ & _constant_width) != 0) && (__inext - _M_int_buf) * _M_width != (__enext - _M_ext_buf)) ||
581581 (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width))
582582 return _M_input_error();
583583 else if (__inext != _M_int_buf) {
605605// seek.
606606template <class _CharT, class _Traits>
607607__BF_int_type__
608basic_filebuf<_CharT, _Traits>::_M_output_error() {
609 _M_in_output_mode = false;
610 _M_in_input_mode = false;
611 _M_in_error_mode = true;
608basic_filebuf<_CharT, _Traits>::_M_output_error()
609{
610 int_flags_ &= ~(_in_output_mode | _in_input_mode);
611 int_flags_ |= _in_error_mode;
612612 this->setp(0, 0);
613
613614 return traits_type::eof();
614615}
615616
620620// buffer, changes the external file position, and changes the state.
621621// Precondition: the internal buffer is empty.
622622template <class _CharT, class _Traits>
623bool basic_filebuf<_CharT, _Traits>::_M_unshift() {
624 if (_M_in_output_mode && !_M_constant_width) {
623bool basic_filebuf<_CharT, _Traits>::_M_unshift()
624{
625 if ( ((int_flags_ & _in_output_mode) != 0) && ((int_flags_ & _constant_width) == 0) ) {
625626 typename _Codecvt::result __status;
627 char* __enext;
626628 do {
627 char* __enext = _M_ext_buf;
629 __enext = _M_ext_buf;
628630 __status = _M_codecvt->unshift(_M_state,
629631 _M_ext_buf, _M_ext_buf_EOS, __enext);
630632 if (__status == _Codecvt::noconv ||
674674 (__bufsize > __STATIC_CAST(streamsize, (numeric_limits<size_t>::max)())))
675675 return false;
676676 _M_int_buf = __STATIC_CAST(_CharT*, malloc(__STATIC_CAST(size_t, __bufsize)));
677 if (!_M_int_buf)
677 if ( !_M_int_buf ) {
678678 return false;
679 _M_int_buf_dynamic = true;
680 }
681 else {
679 }
680 int_flags_ |= _int_buf_dynamic;
681 } else {
682682 _M_int_buf = __buf;
683 _M_int_buf_dynamic = false;
683 int_flags_ &= ~_int_buf_dynamic;
684684 }
685685
686686 streamsize __ebufsiz = (max)(__n * __STATIC_CAST(streamsize, _M_width),
715715
716716template <class _CharT, class _Traits>
717717void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers() {
718 if (_M_int_buf_dynamic)
718 if ( int_flags_ & _int_buf_dynamic ) {
719719 free(_M_int_buf);
720 }
720721 free(_M_ext_buf);
721722 _M_int_buf = 0;
722723 _M_int_buf_EOS = 0;
730730// Helper functiosn for seek and imbue
731731
732732template <class _CharT, class _Traits>
733bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) {
733bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift)
734{
734735 // If we're in error mode, leave it.
735 _M_in_error_mode = false;
736 int_flags_ &= ~_in_error_mode;
736737
737738 // Flush the output buffer if we're in output mode, and (conditionally)
738739 // emit an unshift sequence.
739 if (_M_in_output_mode) {
740 if ( int_flags_ & _in_output_mode ) {
740741 bool __ok = !traits_type::eq_int_type(this->overflow(traits_type::eof()),
741742 traits_type::eof());
742 if (__do_unshift)
743 if (__do_unshift) {
743744 __ok = __ok && this->_M_unshift();
745 }
744746 if (!__ok) {
745 _M_in_output_mode = false;
746 _M_in_error_mode = true;
747 int_flags_ &= ~_in_output_mode;
748 int_flags_ |= _in_error_mode;
747749 this->setp(0, 0);
750
748751 return false;
749752 }
750753 }
751754
752755 // Discard putback characters, if any.
753 if (_M_in_input_mode && _M_in_putback_mode)
756 if ( (int_flags_ & (_in_input_mode | _in_putback_mode) ) == (_in_input_mode | _in_putback_mode) ) {
754757 _M_exit_putback_mode();
758 }
755759
756760 return true;
757761}
769769 * The user will have to call imbue before any I/O operation.
770770 */
771771template <class _CharT, class _Traits>
772void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc, bool __on_imbue) {
772void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc, bool __on_imbue)
773{
773774 if (has_facet<_Codecvt>(__loc)) {
774775 _M_codecvt = &use_facet<_Codecvt>(__loc) ;
775776 int __encoding = _M_codecvt->encoding();
776777
777778 _M_width = (max)(__encoding, 1);
778779 _M_max_width = _M_codecvt->max_length();
779 _M_constant_width = __encoding > 0;
780 _M_always_noconv = _M_codecvt->always_noconv();
781 }
782 else {
780
781 int_flags_ = __encoding > 0 ? (int_flags_ | _constant_width) : (int_flags_ & ~_constant_width);
782 int_flags_ = _M_codecvt->always_noconv() ? (int_flags_ | _always_noconv) : (int_flags_ & ~_always_noconv);
783 } else {
783784 _M_codecvt = 0;
784785 _M_width = _M_max_width = 1;
785 _M_constant_width = _M_always_noconv = false;
786 int_flags_ &= ~(_constant_width | _always_noconv);
786787 if (__on_imbue) {
787788 //This call will generate an exception reporting the problem.
788789 use_facet<_Codecvt>(__loc);
  
224224 virtual int sync();
225225 virtual void imbue(const locale&);
226226
227private: // Helper functions.
227 private: // Helper functions.
228228
229 // Precondition: we are currently in putback input mode. Effect:
230 // switches back to ordinary input mode.
231 void _M_exit_putback_mode() {
232 this->setg(_M_saved_eback, _M_saved_gptr, _M_saved_egptr);
233 _M_in_putback_mode = false;
234 }
229 // Precondition: we are currently in putback input mode. Effect:
230 // switches back to ordinary input mode.
231 void _M_exit_putback_mode()
232 {
233 this->setg(_M_saved_eback, _M_saved_gptr, _M_saved_egptr);
234 int_flags_ &= ~_in_putback_mode;
235 }
235236 bool _M_switch_to_input_mode();
236237 void _M_exit_input_mode();
237238 bool _M_switch_to_output_mode();
248248 bool _M_allocate_buffers();
249249 void _M_deallocate_buffers();
250250
251 pos_type _M_seek_return(off_type __off, _State_type __state) {
252 if (__off != -1) {
253 if (_M_in_input_mode)
254 _M_exit_input_mode();
255 _M_in_input_mode = false;
256 _M_in_output_mode = false;
257 _M_in_putback_mode = false;
258 _M_in_error_mode = false;
259 this->setg(0, 0, 0);
260 this->setp(0, 0);
261 }
251 pos_type _M_seek_return(off_type __off, _State_type __state)
252 {
253 if (__off != -1) {
254 if ( int_flags_ & _in_input_mode ) {
255 _M_exit_input_mode();
256 }
257 int_flags_ &= ~(_in_input_mode | _in_output_mode | _in_putback_mode | _in_error_mode );
258 this->setg(0, 0, 0);
259 this->setp(0, 0);
260 }
262261
263 pos_type __result(__off);
264 __result.state(__state);
265 return __result;
266 }
262 pos_type __result(__off);
263 __result.state(__state);
264 return __result;
265 }
267266
268267 bool _M_seek_init(bool __do_unshift);
269268
274274
275275private: // Locale-related information.
276276
277 unsigned char _M_constant_width;
278 unsigned char _M_always_noconv;
277 enum {
278 _constant_width = 0x1,
279 _always_noconv = 0x2,
280 _int_buf_dynamic = 0x4, // set if internal buffer is heap allocated,
281 // unset if it was supplied by the user;
282 _in_input_mode = 0x8,
283 _in_output_mode = 0x10,
284 _in_error_mode = 0x20,
285 _in_putback_mode = 0x40
286 };
279287
280 // private: // Mode flags.
281 unsigned char _M_int_buf_dynamic; // True if internal buffer is heap allocated,
282 // false if it was supplied by the user.
283 unsigned char _M_in_input_mode;
284 unsigned char _M_in_output_mode;
285 unsigned char _M_in_error_mode;
286 unsigned char _M_in_putback_mode;
288 unsigned int_flags_;
287289
288290 // Internal buffer: characters seen by the filebuf's clients.
289291 _CharT* _M_int_buf;
419419 // There is a specialized version of underflow, for basic_filebuf<char>,
420420 // in fstream.cpp.
421421 static int_type _STLP_CALL _M_doit(basic_filebuf<_CharT, _Traits>* __this) {
422 if (!__this->_M_in_input_mode) {
423 if (!__this->_M_switch_to_input_mode())
422 if ( (__this->int_flags_ & basic_filebuf<_CharT, _Traits>::_in_input_mode) == 0) {
423 if (!__this->_M_switch_to_input_mode()) {
424424 return traits_type::eof();
425 }
426 else if (__this->_M_in_putback_mode) {
425 }
426 } else if ( __this->int_flags_ & basic_filebuf<_CharT, _Traits>::_in_putback_mode ) {
427427 __this->_M_exit_putback_mode();
428428 if (__this->gptr() != __this->egptr()) {
429429 int_type __c = traits_type::to_int_type(*__this->gptr());
  
1// -*- C++ -*- Time-stamp: <09/01/28 14:38:25 ptr>
1// -*- C++ -*- Time-stamp: <09/10/22 23:31:10 ptr>
22
33/*
44 * Copyright (c) 2004-2008
2525#include <stdexcept>
2626#include <stdio.h>
2727
28#ifdef __unix__
29#include <unistd.h>
30#endif
31
2832#include "full_streambuf.h"
2933
3034#if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
297297 EXAM_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(10) );
298298 EXAM_CHECK( o.tellp() == ofstream::pos_type(10) );
299299 }
300
301 return EXAM_RESULT;
302}
303
304int EXAM_IMPL(fstream_test::rewind)
305{
306#ifdef __unix__
307 const char fname[] = "/tmp/stlport.test";
308 {
309 fstream f( fname, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary );
310
311 int n = 0;
312
313 EXAM_CHECK( f.is_open() );
314 EXAM_CHECK( f.good() );
315
316 f.write( (const char*)&n, sizeof(int) );
317 EXAM_CHECK( f.good() );
318 f.seekg( sizeof(int), ios_base::beg );
319 EXAM_CHECK( f.good() );
320 f.read( (char *)&n, sizeof(int) );
321 EXAM_CHECK( f.fail() );
322 f.clear();
323 EXAM_CHECK( f.good() );
324 n = 0;
325 f.write( (const char*)&n, sizeof(int) );
326 EXAM_CHECK( f.good() );
327 }
328 {
329 ifstream f( fname );
330 char c = -1;
331 for ( int i = 0; i < 2 * sizeof(int); ++i ) {
332 f.get( c );
333 EXAM_CHECK( !f.fail() );
334 EXAM_CHECK( c == '\0' );
335 }
336 f.get( c );
337 EXAM_CHECK( f.fail() );
338 }
339
340 unlink( fname );
341#else
342 throw exam::skip_exception();
343#endif
300344
301345 return EXAM_RESULT;
302346}
  
1// -*- C++ -*- Time-stamp: <09/04/03 17:06:37 ptr>
1// -*- C++ -*- Time-stamp: <09/10/16 22:15:32 ptr>
22
33/*
44 * Copyright (c) 2004-2008
6161 int EXAM_DECL(seek_binary);
6262 int EXAM_DECL(seek_text);
6363 int EXAM_DECL(seek_wide_stream);
64 int EXAM_DECL(rewind);
6465 int EXAM_DECL(buf);
6566 int EXAM_DECL(rdbuf);
6667 int EXAM_DECL(streambuf_output);
  
1// -*- C++ -*- Time-stamp: <09/04/21 10:28:44 ptr>
1// -*- C++ -*- Time-stamp: <09/10/16 22:18:36 ptr>
22
33/*
44 * Copyright (c) 2008, 2009
417417 t.add( &fstream_test::offset, fstrm_test, "fstream offset", fstream_tc[0] );
418418 t.add( &fstream_test::big_file, fstrm_test, "fstream big_file", fstream_tc[0] );
419419 fstream_tc[2] = t.add( &fstream_test::custom_facet, fstrm_test, "fstream custom_facet", fstream_tc[0] );
420
420
421 t.add( &fstream_test::rewind, fstrm_test, "fstream write after read fail", fstream_tc[1] );
422
421423 search_test sch_test;
422424
423425 t.add( &search_test::search0, sch_test, "search0" );