ReactOS  0.4.13-dev-92-gf251225
_fstream.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1996,1997
3  * Silicon Graphics Computer Systems, Inc.
4  *
5  * Copyright (c) 1999
6  * Boris Fomitchev
7  *
8  * This material is provided "as is", with absolutely no warranty expressed
9  * or implied. Any use is at your own risk.
10  *
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.
16  *
17  */
18 #ifndef _STLP_FSTREAM_C
19 #define _STLP_FSTREAM_C
20 
21 #ifndef _STLP_INTERNAL_FSTREAM_H
22 # include <stl/_fstream.h>
23 #endif
24 
25 #ifndef _STLP_INTERNAL_LIMITS
26 # include <stl/_limits.h>
27 #endif
28 
30 
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
36 # else
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
40 # endif
41 
42 
43 //----------------------------------------------------------------------
44 // Public basic_filebuf<> member functions
45 
46 template <class _CharT, class _Traits>
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),
58  _M_mmap_base(0), _M_mmap_len(0),
59  _M_saved_eback(0), _M_saved_gptr(0), _M_saved_egptr(0),
60  _M_codecvt(0),
61  _M_width(1), _M_max_width(1)
62 {
63  this->_M_setup_codecvt(locale(), false);
64 }
65 
66 template <class _CharT, class _Traits>
68  this->close();
69  _M_deallocate_buffers();
70 }
71 
72 
73 template <class _CharT, class _Traits>
77 }
78 
79 template <class _CharT, class _Traits>
82  bool __ok = this->is_open();
83 
84  if (_M_in_output_mode) {
85  __ok = __ok && !_Traits::eq_int_type(this->overflow(traits_type::eof()),
87  __ok = __ok && this->_M_unshift();
88  }
89  else if (_M_in_input_mode)
90  this->_M_exit_input_mode();
91 
92  // Note order of arguments. We close the file even if __ok is false.
93  __ok = _M_base._M_close() && __ok;
94 
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;
99 
100  _M_mmap_base = 0;
101  _M_mmap_len = 0;
102 
103  this->setg(0, 0, 0);
104  this->setp(0, 0);
105 
106  _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0;
107 
108  _M_in_input_mode = _M_in_output_mode = _M_in_error_mode = _M_in_putback_mode
109  = false;
110 
111  return __ok ? this : 0;
112 }
113 
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>
119  if (_M_mmap_base != 0) {
120  _M_base._M_unmap(_M_mmap_base, _M_mmap_len);
121  _M_mmap_base = 0;
122  _M_mmap_len = 0;
123  }
124  _M_in_input_mode = false;
125 }
126 
127 
128 //----------------------------------------------------------------------
129 // basic_filebuf<> overridden protected virtual member functions
130 
131 template <class _CharT, class _Traits>
133  // Is there any possibility that reads can succeed?
134  if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
135  return -1;
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;
142  }
143  else
144  return 0;
145 }
146 
147 
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>
158  const int_type __eof = traits_type::eof();
159 
160  // If we aren't already in input mode, pushback is impossible.
161  if (!_M_in_input_mode)
162  return __eof;
163 
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]) ||
169  !_M_mmap_base)) {
170  this->gbump(-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());
174  }
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);
182  else
183  return __eof; // No more room in the buffer, so fail.
184  }
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;
191  }
192  }
193  else
194  return __eof;
195 
196  // We have made a putback position available. Assign to it, and return.
197  *this->gptr() = traits_type::to_char_type(__c);
198  return __c;
199 }
200 
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>
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();
213 
214  _CharT* __ibegin = this->_M_int_buf;
215  _CharT* __iend = this->pptr();
216  this->setp(_M_int_buf, _M_int_buf_EOS - 1);
217 
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);
221 
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)
232  : _M_output_error();
233  }
234 
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;
248  else
249  return _M_output_error();
250  }
251  else
252  return _M_output_error();
253  }
254 
255  return traits_type::not_eof(__c);
256 }
257 
258 // This member function must be called before any I/O has been
259 // performed on the stream, otherwise it has no effect.
260 //
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>
269  if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
270  _M_int_buf == 0) {
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);
275  }
276  return this;
277 }
278 
279 #if defined (_STLP_ASSERTIONS)
280 // helper class.
281 template <class _CharT>
282 struct _Filebuf_Tmp_Buf {
283  _CharT* _M_ptr;
284  _Filebuf_Tmp_Buf(ptrdiff_t __n) : _M_ptr(0) { _M_ptr = new _CharT[__n]; }
285  ~_Filebuf_Tmp_Buf() { delete[] _M_ptr; }
286 };
287 #endif
288 
289 template <class _CharT, class _Traits>
292  ios_base::seekdir __whence,
293  ios_base::openmode /* dummy */) {
294  if (!this->is_open())
295  return pos_type(-1);
296 
297  if (!_M_constant_width && __off != 0)
298  return pos_type(-1);
299 
300  if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
301  return pos_type(-1);
302 
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),
306  _State_type());
307 
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),
312  _State_type());
313 
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);
318 
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());
322  }
323 
324  if (_M_constant_width) { // Get or set the position.
325  streamoff __iadj = _M_width * (this->gptr() - this->eback());
326 
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.
331 
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);
334 
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());
337  }
338  }
339  else { // Get the position. Encoding is var width.
340  // Get position in internal buffer.
341  ptrdiff_t __ipos = this->gptr() - this->eback();
342 
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,
346  __ipos);
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;
354  const char* __dummy;
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>()))
367 #endif
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);
376  }
377 
378  return pos_type(-1);
379 }
380 
381 
382 template <class _CharT, class _Traits>
385  ios_base::openmode /* dummy */) {
386  if (this->is_open()) {
387  if (!_M_seek_init(true))
388  return pos_type(-1);
389 
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());
394  }
395  }
396 
397  return pos_type(-1);
398 }
399 
400 
401 template <class _CharT, class _Traits>
403  if (_M_in_output_mode)
404  return traits_type::eq_int_type(this->overflow(traits_type::eof()),
405  traits_type::eof()) ? -1 : 0;
406  return 0;
407 }
408 
409 
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>
414  if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) {
415  this->_M_setup_codecvt(__loc);
416  }
417 }
418 
419 //----------------------------------------------------------------------
420 // basic_filebuf<> helper functions.
421 
422 //----------------------------------------
423 // Helper functions for switching between modes.
424 
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>
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())
433  return false;
434 
435  _M_ext_buf_converted = _M_ext_buf;
436  _M_ext_buf_end = _M_ext_buf;
437 
438  _M_end_state = _M_state;
439 
440  _M_in_input_mode = true;
441  return true;
442  }
443 
444  return false;
445 }
446 
447 
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>
453  if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) &&
454  _M_in_input_mode == 0 && _M_in_error_mode == 0) {
455 
456  if (!_M_int_buf && !_M_allocate_buffers())
457  return false;
458 
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();
464 
465  this->setp(_M_int_buf, _M_int_buf_EOS - 1);
466  _M_in_output_mode = true;
467  return true;
468  }
469 
470  return false;
471 }
472 
473 
474 //----------------------------------------
475 // Helper functions for input
476 
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
479 // returns eof.
480 // returns eof. Error mode is sticky; it is cleared only by close or
481 // seek.
482 
483 template <class _CharT, class _Traits>
486  this->_M_exit_input_mode();
487  _M_in_output_mode = false;
488  _M_in_error_mode = true;
489  this->setg(0, 0, 0);
490  return traits_type::eof();
491 }
492 
493 template <class _CharT, class _Traits>
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;
499 
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)
503 
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));
508  else
509  _M_ext_buf_end = _M_ext_buf;
510 
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
513  // to make progress.
514  for (;;) {
515  ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end);
516  if (__n < 0) {
517  // Read failed, maybe we should set err bit on associated stream...
518  this->setg(0, 0, 0);
519  return traits_type::eof();
520  }
521 
522  _M_ext_buf_end += __n;
523 
524  // If external buffer is empty there is nothing to do.
525  if (_M_ext_buf == _M_ext_buf_end) {
526  this->setg(0, 0, 0);
527  return traits_type::eof();
528  }
529 
530  // Convert the external buffer to internal characters.
531  const char* __enext;
532  _CharT* __inext;
533 
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);
538 
539  /* Error conditions:
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);
558  }
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. */
563  if (__n <= 0) {
564  this->setg(0, 0, 0);
565  return traits_type::eof();
566  }
567  }
568 }
569 
570 //----------------------------------------
571 // Helper functions for output
572 
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
576 // seek.
577 template <class _CharT, class _Traits>
580  _M_in_output_mode = false;
581  _M_in_input_mode = false;
582  _M_in_error_mode = true;
583  this->setp(0, 0);
584  return traits_type::eof();
585 }
586 
587 
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>
594  if (_M_in_output_mode && !_M_constant_width) {
595  typename _Codecvt::result __status;
596  do {
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))
602  return true;
603  else if (__status == _Codecvt::error)
604  return false;
605  else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf))
606  return false;
607  } while (__status == _Codecvt::partial);
608  }
609 
610  return true;
611 }
612 
613 
614 //----------------------------------------
615 // Helper functions for buffer allocation and deallocation
616 
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.
623 
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>
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.
635  sizeof(streamsize) >= sizeof(int))
636 
637  if (__buf == 0) {
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)) &&
643  return false;
644  _M_int_buf = __STATIC_CAST(_CharT*, malloc(__STATIC_CAST(size_t, __bufsize)));
645  if (!_M_int_buf)
646  return false;
647  _M_int_buf_dynamic = true;
648  }
649  else {
650  _M_int_buf = __buf;
651  _M_int_buf_dynamic = false;
652  }
653 
654  streamsize __ebufsiz = (max)(__n * __STATIC_CAST(streamsize, _M_width),
655  __STATIC_CAST(streamsize, _M_codecvt->max_length()));
656 
657  _M_ext_buf = 0;
658  if ((sizeof(streamsize) < sizeof(size_t)) ||
659  ((sizeof(streamsize) == sizeof(size_t)) && numeric_limits<streamsize>::is_signed) ||
661  _M_ext_buf = __STATIC_CAST(char*, malloc(__STATIC_CAST(size_t, __ebufsiz)));
662  }
663 
664  if (!_M_ext_buf) {
665  _M_deallocate_buffers();
666  return false;
667  }
668 
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);
671  return true;
672 }
673 
674 // Abbreviation for the most common case.
675 template <class _CharT, class _Traits>
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);
682 }
683 
684 template <class _CharT, class _Traits>
686  if (_M_int_buf_dynamic)
687  free(_M_int_buf);
688  free(_M_ext_buf);
689  _M_int_buf = 0;
690  _M_int_buf_EOS = 0;
691  _M_ext_buf = 0;
692  _M_ext_buf_EOS = 0;
693 }
694 
695 
696 //----------------------------------------
697 // Helper functiosn for seek and imbue
698 
699 template <class _CharT, class _Traits>
701  // If we're in error mode, leave it.
702  _M_in_error_mode = false;
703 
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()),
708  traits_type::eof());
709  if (__do_unshift)
710  __ok = __ok && this->_M_unshift();
711  if (!__ok) {
712  _M_in_output_mode = false;
713  _M_in_error_mode = true;
714  this->setp(0, 0);
715  return false;
716  }
717  }
718 
719  // Discard putback characters, if any.
720  if (_M_in_input_mode && _M_in_putback_mode)
721  _M_exit_putback_mode();
722 
723  return true;
724 }
725 
726 
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.
733  */
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();
739 
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();
744  }
745  else {
746  _M_codecvt = 0;
747  _M_width = _M_max_width = 1;
748  _M_constant_width = _M_always_noconv = false;
749  if (__on_imbue) {
750  //This call will generate an exception reporting the problem.
751  use_facet<_Codecvt>(__loc);
752  }
753  }
754 }
755 
757 
758 # undef __BF_int_type__
759 # undef __BF_pos_type__
760 # undef __BF_off_type__
761 
762 #endif /* _STLP_FSTREAM_C */
763 
764 // Local Variables:
765 // mode:C++
766 // End:
off_t streamoff
Definition: char_traits.h:74
bool _M_allocate_buffers()
Definition: _fstream.c:676
#define max(a, b)
Definition: svc.c:63
char_traits< char > ::state_type _State_type
Definition: _fstream.h:160
return __n
Definition: _algo.h:75
#define error(str)
Definition: mkdosfs.c:1605
virtual pos_type seekpos(pos_type, ios_base::openmode=ios_base::in|ios_base::out)
Definition: _fstream.c:384
void _M_deallocate_buffers()
Definition: _fstream.c:685
#define __STATIC_CAST(__x, __y)
Definition: features.h:585
#define free
Definition: debug_ros.c:5
bool _M_seek_init(bool __do_unshift)
Definition: _fstream.c:700
_Self * close()
Definition: _fstream.c:81
virtual int_type pbackfail(int_type=traits_type::eof())
Definition: _fstream.c:157
#define equal(x, y)
Definition: reader.cc:56
GLuint GLuint end
Definition: gl.h:1545
int_type _M_output_error()
Definition: _fstream.c:579
#define eq(received, expected, label, type)
Definition: locale.c:144
virtual int_type overflow(int_type=traits_type::eof())
Definition: _fstream.c:208
int seekdir
Definition: _ios_base.h:60
bool _M_switch_to_output_mode()
Definition: _fstream.c:452
#define __c
Definition: schilyio.h:209
char_traits< char > ::pos_type pos_type
Definition: _fstream.h:156
static int_type _STLP_CALL _M_doit(basic_filebuf< char_type, _Traits > *)
Definition: _fstream.h:391
char_traits< char > ::off_type off_type
Definition: _fstream.h:157
Definition: _locale.h:75
virtual int sync()
Definition: _fstream.c:402
virtual int_type underflow()
Definition: _fstream.c:75
static bool _STLP_CALL _M_doit(basic_filebuf< char_type, _Traits > *, char_type *, char_type *)
Definition: _fstream.h:357
#define ok(value,...)
#define _STLP_DEFAULT_CONSTRUCTED(_TTp)
Definition: _construct.h:265
virtual void imbue(const locale &)
Definition: _fstream.c:413
virtual streamsize showmanyc()
Definition: _fstream.c:132
virtual basic_streambuf< _CharT, _Traits > * setbuf(char_type *, streamsize)
Definition: _fstream.c:268
#define __BF_int_type__
Definition: _fstream.c:37
__kernel_size_t size_t
Definition: linux.h:237
_STLP_STATIC_ASSERT(sizeof(nl_catd_type)<=sizeof(int)) class _STLP_CLASS_DECLSPEC _Catalog_nl_catd_map
int openmode
Definition: _ios_base.h:59
static FILE * out
Definition: regtests2xml.c:44
int_type _M_input_error()
Definition: _fstream.c:485
#define false
Definition: stdbool.h:38
bool _M_switch_to_input_mode()
Definition: _fstream.c:429
#define _STLP_PRIV
Definition: _dm.h:70
#define close
Definition: acwin.h:74
void _M_exit_input_mode()
Definition: _fstream.c:118
_Check_return_ _CRTIMP int __cdecl __cdecl eof(_In_ int _FileHandle)
bool _M_unshift()
Definition: _fstream.c:593
static const wchar_t void * locale
Definition: printf.c:73
_Traits::int_type int_type
Definition: _fstream.h:155
GLuint in
Definition: glext.h:9616
~basic_filebuf()
Definition: _fstream.c:67
#define _STLP_END_NAMESPACE
Definition: features.h:503
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
#define _STLP_ASSERT(expr)
Definition: _debug.h:165
void _M_setup_codecvt(const locale &, bool __on_imbue=true)
Definition: _fstream.c:735
#define _STLP_TYPENAME_ON_RETURN_TYPE
Definition: features.h:600
virtual pos_type seekoff(off_type, ios_base::seekdir, ios_base::openmode=ios_base::in|ios_base::out)
Definition: _fstream.c:291
ptrdiff_t streamsize
Definition: char_traits.h:81
#define malloc
Definition: debug_ros.c:4
#define _STLP_BEGIN_NAMESPACE
Definition: features.h:501
#define __BF_pos_type__
Definition: _fstream.c:38
int_type _M_underflow_aux()
Definition: _fstream.c:495
#define UL
Definition: tui.h:70
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static int_type _STLP_CALL _M_doit(basic_filebuf< _CharT, _Traits > *__this)
Definition: _fstream.h:416