ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

_fstream.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1996,1997
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 #ifndef _STLP_FSTREAM_C
00019 #define _STLP_FSTREAM_C
00020 
00021 #ifndef _STLP_INTERNAL_FSTREAM_H
00022 #  include <stl/_fstream.h>
00023 #endif
00024 
00025 #ifndef _STLP_INTERNAL_LIMITS
00026 #  include <stl/_limits.h>
00027 #endif
00028 
00029 _STLP_BEGIN_NAMESPACE
00030 
00031 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
00032 // no wchar_t is supported for this mode
00033 # define __BF_int_type__ int
00034 # define __BF_pos_type__ streampos
00035 # define __BF_off_type__ streamoff
00036 # else
00037 # define __BF_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type
00038 # define __BF_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::pos_type
00039 # define __BF_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::off_type
00040 # endif
00041 
00042 
00043 //----------------------------------------------------------------------
00044 // Public basic_filebuf<> member functions
00045 
00046 template <class _CharT, class _Traits>
00047 basic_filebuf<_CharT, _Traits>::basic_filebuf()
00048      :  basic_streambuf<_CharT, _Traits>(), _M_base(),
00049     _M_constant_width(false), _M_always_noconv(false),
00050     _M_int_buf_dynamic(false),
00051     _M_in_input_mode(false), _M_in_output_mode(false),
00052     _M_in_error_mode(false), _M_in_putback_mode(false),
00053     _M_int_buf(0), _M_int_buf_EOS(0),
00054     _M_ext_buf(0), _M_ext_buf_EOS(0),
00055     _M_ext_buf_converted(0), _M_ext_buf_end(0),
00056     _M_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
00057     _M_end_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
00058     _M_mmap_base(0), _M_mmap_len(0),
00059     _M_saved_eback(0), _M_saved_gptr(0), _M_saved_egptr(0),
00060     _M_codecvt(0),
00061     _M_width(1), _M_max_width(1)
00062 {
00063   this->_M_setup_codecvt(locale(), false);
00064 }
00065 
00066 template <class _CharT, class _Traits>
00067 basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
00068   this->close();
00069   _M_deallocate_buffers();
00070 }
00071 
00072 
00073 template <class _CharT, class _Traits>
00074 _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type
00075 basic_filebuf<_CharT, _Traits>::underflow() {
00076   return _Underflow<_CharT, _Traits>::_M_doit(this);
00077 }
00078 
00079 template <class _CharT, class _Traits>
00080 basic_filebuf<_CharT, _Traits>*
00081 basic_filebuf<_CharT, _Traits>::close() {
00082   bool __ok = this->is_open();
00083 
00084   if (_M_in_output_mode) {
00085     __ok = __ok && !_Traits::eq_int_type(this->overflow(traits_type::eof()),
00086                                          traits_type::eof());
00087     __ok == __ok && this->_M_unshift();
00088   }
00089   else if (_M_in_input_mode)
00090       this->_M_exit_input_mode();
00091 
00092   // Note order of arguments.  We close the file even if __ok is false.
00093   __ok = _M_base._M_close() && __ok;
00094 
00095   // Restore the initial state, except that we don't deallocate the buffer
00096   // or mess with the cached codecvt information.
00097   _M_state = _M_end_state = _State_type();
00098   _M_ext_buf_converted = _M_ext_buf_end = 0;
00099 
00100   _M_mmap_base = 0;
00101   _M_mmap_len = 0;
00102 
00103   this->setg(0, 0, 0);
00104   this->setp(0, 0);
00105 
00106   _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0;
00107 
00108   _M_in_input_mode = _M_in_output_mode = _M_in_error_mode = _M_in_putback_mode
00109     = false;
00110 
00111   return __ok ? this : 0;
00112 }
00113 
00114 // This member function is called whenever we exit input mode.
00115 // It unmaps the memory-mapped file, if any, and sets
00116 // _M_in_input_mode to false.
00117 template <class _CharT, class _Traits>
00118 void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode() {
00119   if (_M_mmap_base != 0) {
00120     _M_base._M_unmap(_M_mmap_base, _M_mmap_len);
00121     _M_mmap_base = 0;
00122     _M_mmap_len = 0;
00123   }
00124   _M_in_input_mode = false;
00125 }
00126 
00127 
00128 //----------------------------------------------------------------------
00129 // basic_filebuf<> overridden protected virtual member functions
00130 
00131 template <class _CharT, class _Traits>
00132 streamsize basic_filebuf<_CharT, _Traits>::showmanyc() {
00133   // Is there any possibility that reads can succeed?
00134   if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
00135     return -1;
00136   else if (_M_in_putback_mode)
00137     return this->egptr() - this->gptr();
00138   else if (_M_constant_width) {
00139     streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
00140     streamoff __size = _M_base._M_file_size();
00141     return __pos >= 0 && __size > __pos ? __size - __pos : 0;
00142   }
00143   else
00144     return 0;
00145 }
00146 
00147 
00148 // Make a putback position available, if necessary, by switching to a
00149 // special internal buffer used only for putback.  The buffer is
00150 // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base
00151 // class only sees a piece of it at a time.  (We want to make sure
00152 // that we don't try to read a character that hasn't been initialized.)
00153 // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size,
00154 // but the beginning is usually not _M_pback_buf.
00155 template <class _CharT, class _Traits>
00156 __BF_int_type__
00157 basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) {
00158   const int_type __eof = traits_type::eof();
00159 
00160   // If we aren't already in input mode, pushback is impossible.
00161   if (!_M_in_input_mode)
00162     return __eof;
00163 
00164   // We can use the ordinary get buffer if there's enough space, and
00165   // if it's a buffer that we're allowed to write to.
00166   if (this->gptr() != this->eback() &&
00167       (traits_type::eq_int_type(__c, __eof) ||
00168        traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) ||
00169        !_M_mmap_base)) {
00170     this->gbump(-1);
00171     if (traits_type::eq_int_type(__c, __eof) ||
00172         traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
00173       return traits_type::to_int_type(*this->gptr());
00174   }
00175   else if (!traits_type::eq_int_type(__c, __eof)) {
00176     // Are we in the putback buffer already?
00177     _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
00178     if (_M_in_putback_mode) {
00179       // Do we have more room in the putback buffer?
00180       if (this->eback() != _M_pback_buf)
00181         this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
00182       else
00183         return __eof;           // No more room in the buffer, so fail.
00184     }
00185     else {                      // We're not yet in the putback buffer.
00186       _M_saved_eback = this->eback();
00187       _M_saved_gptr  = this->gptr();
00188       _M_saved_egptr = this->egptr();
00189       this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
00190       _M_in_putback_mode = true;
00191     }
00192   }
00193   else
00194     return __eof;
00195 
00196   // We have made a putback position available.  Assign to it, and return.
00197   *this->gptr() = traits_type::to_char_type(__c);
00198   return __c;
00199 }
00200 
00201 // This member function flushes the put area, and also outputs the
00202 // character __c (unless __c is eof).  Invariant: we always leave room
00203 // in the internal buffer for one character more than the base class knows
00204 // about.  We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but
00205 // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
00206 template <class _CharT, class _Traits>
00207 __BF_int_type__
00208 basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
00209   // Switch to output mode, if necessary.
00210   if (!_M_in_output_mode)
00211     if (!_M_switch_to_output_mode())
00212       return traits_type::eof();
00213 
00214   _CharT* __ibegin = this->_M_int_buf;
00215   _CharT* __iend   = this->pptr();
00216   this->setp(_M_int_buf, _M_int_buf_EOS - 1);
00217 
00218   // Put __c at the end of the internal buffer.
00219   if (!traits_type::eq_int_type(__c, traits_type::eof()))
00220     *__iend++ = _Traits::to_char_type(__c);
00221 
00222   // For variable-width encodings, output may take more than one pass.
00223   while (__ibegin != __iend) {
00224     const _CharT* __inext = __ibegin;
00225     char* __enext         = _M_ext_buf;
00226     typename _Codecvt::result __status
00227       = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
00228                         _M_ext_buf, _M_ext_buf_EOS, __enext);
00229     if (__status == _Codecvt::noconv) {
00230       return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
00231         ? traits_type::not_eof(__c)
00232         : _M_output_error();
00233     }
00234 
00235     // For a constant-width encoding we know that the external buffer
00236     // is large enough, so failure to consume the entire internal buffer
00237     // or to produce the correct number of external characters, is an error.
00238     // For a variable-width encoding, however, we require only that we
00239     // consume at least one internal character
00240     else if (__status != _Codecvt::error &&
00241              (((__inext == __iend) &&
00242                (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) ||
00243               (!_M_constant_width && __inext != __ibegin))) {
00244         // We successfully converted part or all of the internal buffer.
00245       ptrdiff_t __n = __enext - _M_ext_buf;
00246       if (_M_write(_M_ext_buf, __n))
00247         __ibegin += __inext - __ibegin;
00248       else
00249         return _M_output_error();
00250     }
00251     else
00252       return _M_output_error();
00253   }
00254 
00255   return traits_type::not_eof(__c);
00256 }
00257 
00258 // This member function must be called before any I/O has been
00259 // performed on the stream, otherwise it has no effect.
00260 //
00261 // __buf == 0 && __n == 0 means to make this stream unbuffered.
00262 // __buf != 0 && __n > 0 means to use __buf as the stream's internal
00263 // buffer, rather than the buffer that would otherwise be allocated
00264 // automatically.  __buf must be a pointer to an array of _CharT whose
00265 // size is at least __n.
00266 template <class _CharT, class _Traits>
00267 basic_streambuf<_CharT, _Traits>*
00268 basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) {
00269   if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
00270       _M_int_buf == 0) {
00271     if (__buf == 0 && __n == 0)
00272       _M_allocate_buffers(0, 1);
00273     else if (__buf != 0 && __n > 0)
00274       _M_allocate_buffers(__buf, __n);
00275   }
00276   return this;
00277 }
00278 
00279 #if defined (_STLP_ASSERTIONS)
00280 // helper class.
00281 template <class _CharT>
00282 struct _Filebuf_Tmp_Buf {
00283   _CharT* _M_ptr;
00284   _Filebuf_Tmp_Buf(ptrdiff_t __n) : _M_ptr(0) { _M_ptr = new _CharT[__n]; }
00285   ~_Filebuf_Tmp_Buf() { delete[] _M_ptr; }
00286 };
00287 #endif
00288 
00289 template <class _CharT, class _Traits>
00290 __BF_pos_type__
00291 basic_filebuf<_CharT, _Traits>::seekoff(off_type __off,
00292                                         ios_base::seekdir __whence,
00293                                         ios_base::openmode /* dummy */) {
00294   if (!this->is_open())
00295     return pos_type(-1);
00296 
00297   if (!_M_constant_width && __off != 0)
00298     return pos_type(-1);
00299 
00300   if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
00301     return pos_type(-1);
00302 
00303   // Seek to beginning or end, regardless of whether we're in input mode.
00304   if (__whence == ios_base::beg || __whence == ios_base::end)
00305     return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
00306                           _State_type());
00307 
00308   // Seek relative to current position.  Complicated if we're in input mode.
00309   _STLP_ASSERT(__whence == ios_base::cur)
00310   if (!_M_in_input_mode)
00311     return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
00312                           _State_type());
00313 
00314   if (_M_mmap_base != 0) {
00315     // __off is relative to gptr().  We need to do a bit of arithmetic
00316     // to get an offset relative to the external file pointer.
00317     streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);
00318 
00319     // if __off == 0, we do not need to exit input mode and to shift file pointer
00320     return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust)
00321                       : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
00322   }
00323 
00324   if (_M_constant_width) { // Get or set the position.
00325     streamoff __iadj = _M_width * (this->gptr() - this->eback());
00326 
00327     // Compensate for offset relative to gptr versus offset relative
00328     // to external pointer.  For a text-oriented stream, where the
00329     // compensation is more than just pointer arithmetic, we may get
00330     // but not set the current position.
00331 
00332     if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
00333       streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __STATIC_CAST(ptrdiff_t, __iadj), _M_ext_buf_end);
00334 
00335       return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj)
00336                         : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
00337     }
00338   }
00339   else {                    // Get the position.  Encoding is var width.
00340     // Get position in internal buffer.
00341     ptrdiff_t __ipos = this->gptr() - this->eback();
00342 
00343     // Get corresponding position in external buffer.
00344     _State_type __state = _M_state;
00345     int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_converted,
00346                                     __ipos);
00347 #if defined (_STLP_ASSERTIONS)
00348     // Sanity check (expensive): make sure __epos is the right answer.
00349     _STLP_ASSERT(__epos >= 0)
00350     _State_type __tmp_state = _M_state;
00351     _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
00352     _CharT* __ibegin = __buf._M_ptr;
00353     _CharT* __inext  = __ibegin;
00354     const char* __dummy;
00355     typename _Codecvt::result __status
00356       = _M_codecvt->in(__tmp_state,
00357                        _M_ext_buf, _M_ext_buf + __epos, __dummy,
00358                        __ibegin, __ibegin + __ipos, __inext);
00359     // The result code is necessarily ok because:
00360     // - noconv: impossible for a variable encoding
00361     // - error: length method is supposed to count until it reach max value or find an error so we cannot have
00362     //          an error again when decoding an external buffer up to length return value.
00363     // - partial: idem error, it is also a reason for length to stop counting.
00364     _STLP_ASSERT(__status == _Codecvt::ok)
00365     _STLP_ASSERT(__inext == __ibegin + __ipos)
00366     _STLP_ASSERT(equal(this->eback(), this->gptr(), __ibegin, _STLP_PRIV _Eq_traits<traits_type>()))
00367 #endif
00368     // Get the current position (at the end of the external buffer),
00369     // then adjust it.  Again, it might be a text-oriented stream.
00370     streamoff __cur = _M_base._M_seek(0, ios_base::cur);
00371     streamoff __adj = _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
00372                       _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
00373     if (__cur != -1 && __cur + __adj >= 0)
00374       return __off == 0 ? pos_type(__cur + __adj)
00375                         : _M_seek_return(__cur + __adj, __state);
00376   }
00377 
00378   return pos_type(-1);
00379 }
00380 
00381 
00382 template <class _CharT, class _Traits>
00383 __BF_pos_type__
00384 basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos,
00385                                         ios_base::openmode /* dummy */) {
00386   if (this->is_open()) {
00387     if (!_M_seek_init(true))
00388       return pos_type(-1);
00389 
00390     streamoff __off = off_type(__pos);
00391     if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) {
00392       _M_state = __pos.state();
00393       return _M_seek_return(__off, __pos.state());
00394     }
00395   }
00396 
00397   return pos_type(-1);
00398 }
00399 
00400 
00401 template <class _CharT, class _Traits>
00402 int basic_filebuf<_CharT, _Traits>::sync() {
00403   if (_M_in_output_mode)
00404     return traits_type::eq_int_type(this->overflow(traits_type::eof()),
00405                                     traits_type::eof()) ? -1 : 0;
00406   return 0;
00407 }
00408 
00409 
00410 // Change the filebuf's locale.  This member function has no effect
00411 // unless it is called before any I/O is performed on the stream.
00412 template <class _CharT, class _Traits>
00413 void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) {
00414   if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) {
00415     this->_M_setup_codecvt(__loc);
00416   }
00417 }
00418 
00419 //----------------------------------------------------------------------
00420 // basic_filebuf<> helper functions.
00421 
00422 //----------------------------------------
00423 // Helper functions for switching between modes.
00424 
00425 // This member function is called if we're performing the first I/O
00426 // operation on a filebuf, or if we're performing an input operation
00427 // immediately after a seek.
00428 template <class _CharT, class _Traits>
00429 bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode() {
00430   if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0)
00431       && (_M_in_output_mode == 0) && (_M_in_error_mode == 0)) {
00432     if (!_M_int_buf && !_M_allocate_buffers())
00433       return false;
00434 
00435     _M_ext_buf_converted = _M_ext_buf;
00436     _M_ext_buf_end       = _M_ext_buf;
00437 
00438     _M_end_state    = _M_state;
00439 
00440     _M_in_input_mode = true;
00441     return true;
00442   }
00443 
00444   return false;
00445 }
00446 
00447 
00448 // This member function is called if we're performing the first I/O
00449 // operation on a filebuf, or if we're performing an output operation
00450 // immediately after a seek.
00451 template <class _CharT, class _Traits>
00452 bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode() {
00453   if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) &&
00454       _M_in_input_mode == 0 && _M_in_error_mode == 0) {
00455 
00456     if (!_M_int_buf && !_M_allocate_buffers())
00457       return false;
00458 
00459     // In append mode, every write does an implicit seek to the end
00460     // of the file.  Whenever leaving output mode, the end of file
00461     // get put in the initial shift state.
00462     if (_M_base.__o_mode() & ios_base::app)
00463       _M_state = _State_type();
00464 
00465     this->setp(_M_int_buf, _M_int_buf_EOS - 1);
00466     _M_in_output_mode = true;
00467     return true;
00468   }
00469 
00470   return false;
00471 }
00472 
00473 
00474 //----------------------------------------
00475 // Helper functions for input
00476 
00477 // This member function is called if there is an error during input.
00478 // It puts the filebuf in error mode, clear the get area buffer, and
00479 // returns eof.
00480 // returns eof.  Error mode is sticky; it is cleared only by close or
00481 // seek.
00482 
00483 template <class _CharT, class _Traits>
00484 __BF_int_type__
00485 basic_filebuf<_CharT, _Traits>::_M_input_error() {
00486    this->_M_exit_input_mode();
00487   _M_in_output_mode = false;
00488   _M_in_error_mode = true;
00489   this->setg(0, 0, 0);
00490   return traits_type::eof();
00491 }
00492 
00493 template <class _CharT, class _Traits>
00494 __BF_int_type__
00495 basic_filebuf<_CharT, _Traits>::_M_underflow_aux() {
00496   // We have the state and file position from the end of the internal
00497   // buffer.  This round, they become the beginning of the internal buffer.
00498   _M_state    = _M_end_state;
00499 
00500   // Fill the external buffer.  Start with any leftover characters that
00501   // didn't get converted last time.
00502   if (_M_ext_buf_end > _M_ext_buf_converted)
00503 
00504     _M_ext_buf_end = _STLP_STD::copy(_M_ext_buf_converted, _M_ext_buf_end, _M_ext_buf);
00505     // boris : copy_backward did not work
00506     //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end,
00507     //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted));
00508   else
00509     _M_ext_buf_end = _M_ext_buf;
00510 
00511   // Now fill the external buffer with characters from the file.  This is
00512   // a loop because occasionally we don't get enough external characters
00513   // to make progress.
00514   for (;;) {
00515     ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end);
00516     if (__n < 0) {
00517       // Read failed, maybe we should set err bit on associated stream...
00518       this->setg(0, 0, 0);
00519       return traits_type::eof();
00520     }
00521 
00522     _M_ext_buf_end += __n;
00523 
00524     // If external buffer is empty there is nothing to do. 
00525     if (_M_ext_buf == _M_ext_buf_end) {
00526       this->setg(0, 0, 0);
00527       return traits_type::eof();
00528     }
00529 
00530     // Convert the external buffer to internal characters.
00531     const char* __enext;
00532     _CharT* __inext;
00533 
00534     typename _Codecvt::result __status
00535       = _M_codecvt->in(_M_end_state,
00536                        _M_ext_buf, _M_ext_buf_end, __enext,
00537                        _M_int_buf, _M_int_buf_EOS, __inext);
00538 
00539     /* Error conditions:
00540      * (1) Return value of error.
00541      * (2) Producing internal characters without consuming external characters.
00542      * (3) In fixed-width encodings, producing an internal sequence whose length
00543      * is inconsistent with that of the internal sequence.
00544      * (4) Failure to produce any characters if we have enough characters in
00545      * the external buffer, where "enough" means the largest possible width
00546      * of a single character. */
00547     if (__status == _Codecvt::noconv)
00548       return _Noconv_input<_Traits>::_M_doit(this);
00549     else if (__status == _Codecvt::error ||
00550             (__inext != _M_int_buf && __enext == _M_ext_buf) ||
00551             (_M_constant_width && (__inext - _M_int_buf) *  _M_width != (__enext - _M_ext_buf)) ||
00552             (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width))
00553       return _M_input_error();
00554     else if (__inext != _M_int_buf) {
00555       _M_ext_buf_converted = _M_ext_buf + (__enext - _M_ext_buf);
00556       this->setg(_M_int_buf, _M_int_buf, __inext);
00557       return traits_type::to_int_type(*_M_int_buf);
00558     }
00559     /* We need to go around the loop again to get more external characters.
00560      * But if the previous read failed then don't try again for now.
00561      * Don't enter error mode for a failed read. Error mode is sticky,
00562      * and we might succeed if we try again. */
00563     if (__n <= 0) {
00564       this->setg(0, 0, 0);
00565       return traits_type::eof();
00566     }
00567   }
00568 }
00569 
00570 //----------------------------------------
00571 // Helper functions for output
00572 
00573 // This member function is called if there is an error during output.
00574 // It puts the filebuf in error mode, clear the put area buffer, and
00575 // returns eof.  Error mode is sticky; it is cleared only by close or
00576 // seek.
00577 template <class _CharT, class _Traits>
00578 __BF_int_type__
00579 basic_filebuf<_CharT, _Traits>::_M_output_error() {
00580   _M_in_output_mode = false;
00581   _M_in_input_mode = false;
00582   _M_in_error_mode = true;
00583   this->setp(0, 0);
00584   return traits_type::eof();
00585 }
00586 
00587 
00588 // Write whatever sequence of characters is necessary to get back to
00589 // the initial shift state.  This function overwrites the external
00590 // buffer, changes the external file position, and changes the state.
00591 // Precondition: the internal buffer is empty.
00592 template <class _CharT, class _Traits>
00593 bool basic_filebuf<_CharT, _Traits>::_M_unshift() {
00594   if (_M_in_output_mode && !_M_constant_width) {
00595     typename _Codecvt::result __status;
00596     do {
00597       char* __enext = _M_ext_buf;
00598       __status = _M_codecvt->unshift(_M_state,
00599                                      _M_ext_buf, _M_ext_buf_EOS, __enext);
00600       if (__status == _Codecvt::noconv ||
00601           (__enext == _M_ext_buf && __status == _Codecvt::ok))
00602         return true;
00603       else if (__status == _Codecvt::error)
00604         return false;
00605       else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf))
00606         return false;
00607     } while (__status == _Codecvt::partial);
00608   }
00609 
00610   return true;
00611 }
00612 
00613 
00614 //----------------------------------------
00615 // Helper functions for buffer allocation and deallocation
00616 
00617 // This member function is called when we're initializing a filebuf's
00618 // internal and external buffers.  The argument is the size of the
00619 // internal buffer; the external buffer is sized using the character
00620 // width in the current encoding.  Preconditions: the buffers are currently
00621 // null.  __n >= 1.  __buf is either a null pointer or a pointer to an
00622 // array show size is at least __n.
00623 
00624 // We need __n >= 1 for two different reasons.  For input, the base
00625 // class always needs a buffer because of the semantics of underflow().
00626 // For output, we want to have an internal buffer that's larger by one
00627 // element than the buffer that the base class knows about.  (See
00628 // basic_filebuf<>::overflow() for the reason.)
00629 template <class _CharT, class _Traits>
00630 bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n) {
00631   //The major hypothesis in the following implementation is that size_t is unsigned.
00632   //We also need streamsize byte representation to be larger or equal to the int
00633   //representation to correctly store the encoding information.
00634   _STLP_STATIC_ASSERT(!numeric_limits<size_t>::is_signed &&
00635                       sizeof(streamsize) >= sizeof(int))
00636 
00637   if (__buf == 0) {
00638     streamsize __bufsize = __n * sizeof(_CharT);
00639     //We first check that the streamsize representation can't overflow a size_t one.
00640     //If it can, we check that __bufsize is not higher than the size_t max value.
00641     if ((sizeof(streamsize) > sizeof(size_t)) &&
00642         (__bufsize > __STATIC_CAST(streamsize, (numeric_limits<size_t>::max)())))
00643       return false;
00644     _M_int_buf = __STATIC_CAST(_CharT*, malloc(__STATIC_CAST(size_t, __bufsize)));
00645     if (!_M_int_buf)
00646       return false;
00647     _M_int_buf_dynamic = true;
00648   }
00649   else {
00650     _M_int_buf = __buf;
00651     _M_int_buf_dynamic = false;
00652   }
00653 
00654   streamsize __ebufsiz = (max)(__n * __STATIC_CAST(streamsize, _M_width),
00655                                __STATIC_CAST(streamsize, _M_codecvt->max_length()));
00656 
00657   _M_ext_buf = 0;
00658   if ((sizeof(streamsize) < sizeof(size_t)) ||
00659       ((sizeof(streamsize) == sizeof(size_t)) && numeric_limits<streamsize>::is_signed) ||
00660       (__ebufsiz <= __STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()))) {
00661     _M_ext_buf = __STATIC_CAST(char*, malloc(__STATIC_CAST(size_t, __ebufsiz)));
00662   }
00663 
00664   if (!_M_ext_buf) {
00665     _M_deallocate_buffers();
00666     return false;
00667   }
00668 
00669   _M_int_buf_EOS = _M_int_buf + __STATIC_CAST(ptrdiff_t, __n);
00670   _M_ext_buf_EOS = _M_ext_buf + __STATIC_CAST(ptrdiff_t, __ebufsiz);
00671   return true;
00672 }
00673 
00674 // Abbreviation for the most common case.
00675 template <class _CharT, class _Traits>
00676 bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers() {
00677   // Choose a buffer that's at least 4096 characters long and that's a
00678   // multiple of the page size.
00679   streamsize __default_bufsiz =
00680     ((_M_base.__page_size() + 4095UL) / _M_base.__page_size()) * _M_base.__page_size();
00681   return _M_allocate_buffers(0, __default_bufsiz);
00682 }
00683 
00684 template <class _CharT, class _Traits>
00685 void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers() {
00686   if (_M_int_buf_dynamic)
00687     free(_M_int_buf);
00688   free(_M_ext_buf);
00689   _M_int_buf     = 0;
00690   _M_int_buf_EOS = 0;
00691   _M_ext_buf     = 0;
00692   _M_ext_buf_EOS = 0;
00693 }
00694 
00695 
00696 //----------------------------------------
00697 // Helper functiosn for seek and imbue
00698 
00699 template <class _CharT, class _Traits>
00700 bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) {
00701   // If we're in error mode, leave it.
00702    _M_in_error_mode = false;
00703 
00704   // Flush the output buffer if we're in output mode, and (conditionally)
00705   // emit an unshift sequence.
00706   if (_M_in_output_mode) {
00707     bool __ok = !traits_type::eq_int_type(this->overflow(traits_type::eof()),
00708                                           traits_type::eof());
00709     if (__do_unshift)
00710       __ok = __ok && this->_M_unshift();
00711     if (!__ok) {
00712       _M_in_output_mode = false;
00713       _M_in_error_mode = true;
00714       this->setp(0, 0);
00715       return false;
00716     }
00717   }
00718 
00719   // Discard putback characters, if any.
00720   if (_M_in_input_mode && _M_in_putback_mode)
00721     _M_exit_putback_mode();
00722 
00723   return true;
00724 }
00725 
00726 
00727 /* Change the filebuf's locale.  This member function has no effect
00728  * unless it is called before any I/O is performed on the stream.
00729  * This function is called on construction and on an imbue call. In the
00730  * case of the construction the codecvt facet might be a custom one if
00731  * the basic_filebuf user has instanciate it with a custom char_traits.
00732  * The user will have to call imbue before any I/O operation.
00733  */
00734 template <class _CharT, class _Traits>
00735 void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc, bool __on_imbue) {
00736   if (has_facet<_Codecvt>(__loc)) {
00737     _M_codecvt = &use_facet<_Codecvt>(__loc) ;
00738     int __encoding    = _M_codecvt->encoding();
00739 
00740     _M_width          = (max)(__encoding, 1);
00741     _M_max_width      = _M_codecvt->max_length();
00742     _M_constant_width = __encoding > 0;
00743     _M_always_noconv  = _M_codecvt->always_noconv();
00744   }
00745   else {
00746     _M_codecvt = 0;
00747     _M_width = _M_max_width = 1;
00748     _M_constant_width = _M_always_noconv  = false;
00749     if (__on_imbue) {
00750       //This call will generate an exception reporting the problem.
00751       use_facet<_Codecvt>(__loc);
00752     }
00753   }
00754 }
00755 
00756 _STLP_END_NAMESPACE
00757 
00758 # undef __BF_int_type__
00759 # undef __BF_pos_type__
00760 # undef __BF_off_type__
00761 
00762 #endif /* _STLP_FSTREAM_C */
00763 
00764 // Local Variables:
00765 // mode:C++
00766 // End:

Generated on Sat May 26 2012 04:27:36 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.