genericopenlibs/cppstdlib/stl/stlport/stl/_fstream.c
changeset 22 ddc455616bd6
parent 0 e4d67989cc36
child 45 4b03adbd26ca
equal deleted inserted replaced
18:47c74d1534e1 22:ddc455616bd6
    61     _M_width(1), _M_max_width(1)
    61     _M_width(1), _M_max_width(1)
    62 {
    62 {
    63   this->_M_setup_codecvt(locale(), false);
    63   this->_M_setup_codecvt(locale(), false);
    64 }
    64 }
    65 
    65 
    66 template <class _CharT, class _Traits>
       
    67 basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
       
    68   this->close();
       
    69   _M_deallocate_buffers();
       
    70 }
       
    71 
       
    72 
       
    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);
       
    77 }
       
    78 
    66 
    79 template <class _CharT, class _Traits>
    67 template <class _CharT, class _Traits>
    80 basic_filebuf<_CharT, _Traits>*
    68 basic_filebuf<_CharT, _Traits>*
    81 basic_filebuf<_CharT, _Traits>::close() {
    69 basic_filebuf<_CharT, _Traits>::close() {
    82   bool __ok = this->is_open();
    70   bool __ok = this->is_open();
   121    _M_in_input_mode = false;
   109    _M_in_input_mode = false;
   122    _M_mmap_base = 0;
   110    _M_mmap_base = 0;
   123 }
   111 }
   124 
   112 
   125 
   113 
   126 //----------------------------------------------------------------------
       
   127 // basic_filebuf<> overridden protected virtual member functions
       
   128 
       
   129 template <class _CharT, class _Traits>
       
   130 streamsize basic_filebuf<_CharT, _Traits>::showmanyc() {
       
   131   // Is there any possibility that reads can succeed?
       
   132   if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
       
   133     return -1;
       
   134   else if (_M_in_putback_mode)
       
   135     return this->egptr() - this->gptr();
       
   136   else if (_M_constant_width) {
       
   137     streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
       
   138     streamoff __size = _M_base._M_file_size();
       
   139     return __pos >= 0 && __size > __pos ? __size - __pos : 0;
       
   140   }
       
   141   else
       
   142     return 0;
       
   143 }
       
   144 
       
   145 
       
   146 // Make a putback position available, if necessary, by switching to a
       
   147 // special internal buffer used only for putback.  The buffer is
       
   148 // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base
       
   149 // class only sees a piece of it at a time.  (We want to make sure
       
   150 // that we don't try to read a character that hasn't been initialized.)
       
   151 // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size,
       
   152 // but the beginning is usually not _M_pback_buf.
       
   153 template <class _CharT, class _Traits>
       
   154 __BF_int_type__
       
   155 basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) {
       
   156   const int_type __eof = traits_type::eof();
       
   157 
       
   158   // If we aren't already in input mode, pushback is impossible.
       
   159   if (!_M_in_input_mode)
       
   160     return __eof;
       
   161 
       
   162   // We can use the ordinary get buffer if there's enough space, and
       
   163   // if it's a buffer that we're allowed to write to.
       
   164   if (this->gptr() != this->eback() &&
       
   165       (traits_type::eq_int_type(__c, __eof) ||
       
   166        traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) ||
       
   167        !_M_mmap_base)) {
       
   168     this->gbump(-1);
       
   169     if (traits_type::eq_int_type(__c, __eof) ||
       
   170         traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
       
   171       return traits_type::to_int_type(*this->gptr());
       
   172   }
       
   173   else if (!traits_type::eq_int_type(__c, __eof)) {
       
   174     // Are we in the putback buffer already?
       
   175     _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
       
   176     if (_M_in_putback_mode) {
       
   177       // Do we have more room in the putback buffer?
       
   178       if (this->eback() != _M_pback_buf)
       
   179         this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
       
   180       else
       
   181         return __eof;           // No more room in the buffer, so fail.
       
   182     }
       
   183     else {                      // We're not yet in the putback buffer.
       
   184       _M_saved_eback = this->eback();
       
   185       _M_saved_gptr  = this->gptr();
       
   186       _M_saved_egptr = this->egptr();
       
   187       this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
       
   188       _M_in_putback_mode = true;
       
   189     }
       
   190   }
       
   191   else
       
   192     return __eof;
       
   193 
       
   194   // We have made a putback position available.  Assign to it, and return.
       
   195   *this->gptr() = traits_type::to_char_type(__c);
       
   196   return __c;
       
   197 }
       
   198 
       
   199 // This member function flushes the put area, and also outputs the
       
   200 // character __c (unless __c is eof).  Invariant: we always leave room
       
   201 // in the internal buffer for one character more than the base class knows
       
   202 // about.  We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but
       
   203 // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
       
   204 template <class _CharT, class _Traits>
       
   205 __BF_int_type__
       
   206 basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
       
   207   // Switch to output mode, if necessary.
       
   208   if (!_M_in_output_mode)
       
   209     if (!_M_switch_to_output_mode())
       
   210       return traits_type::eof();
       
   211 
       
   212   _CharT* __ibegin = this->_M_int_buf;
       
   213   _CharT* __iend   = this->pptr();
       
   214   this->setp(_M_int_buf, _M_int_buf_EOS - 1);
       
   215 
       
   216   // Put __c at the end of the internal buffer.
       
   217   if (!traits_type::eq_int_type(__c, traits_type::eof()))
       
   218     *__iend++ = _Traits::to_char_type(__c);
       
   219 
       
   220   // For variable-width encodings, output may take more than one pass.
       
   221   while (__ibegin != __iend) {
       
   222     const _CharT* __inext = __ibegin;
       
   223     char* __enext         = _M_ext_buf;
       
   224     typename _Codecvt::result __status
       
   225       = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
       
   226                         _M_ext_buf, _M_ext_buf_EOS, __enext);
       
   227     if (__status == _Codecvt::noconv) {
       
   228       return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
       
   229         ? traits_type::not_eof(__c)
       
   230         : _M_output_error();
       
   231     }
       
   232 
       
   233     // For a constant-width encoding we know that the external buffer
       
   234     // is large enough, so failure to consume the entire internal buffer
       
   235     // or to produce the correct number of external characters, is an error.
       
   236     // For a variable-width encoding, however, we require only that we
       
   237     // consume at least one internal character
       
   238     else if (__status != _Codecvt::error &&
       
   239              (((__inext == __iend) &&
       
   240                (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) ||
       
   241               (!_M_constant_width && __inext != __ibegin))) {
       
   242         // We successfully converted part or all of the internal buffer.
       
   243       ptrdiff_t __n = __enext - _M_ext_buf;
       
   244       if (_M_write(_M_ext_buf, __n))
       
   245         __ibegin += __inext - __ibegin;
       
   246       else
       
   247         return _M_output_error();
       
   248     }
       
   249     else
       
   250       return _M_output_error();
       
   251   }
       
   252 
       
   253   return traits_type::not_eof(__c);
       
   254 }
       
   255 
       
   256 // This member function must be called before any I/O has been
       
   257 // performed on the stream, otherwise it has no effect.
       
   258 //
       
   259 // __buf == 0 && __n == 0 means to make this stream unbuffered.
       
   260 // __buf != 0 && __n > 0 means to use __buf as the stream's internal
       
   261 // buffer, rather than the buffer that would otherwise be allocated
       
   262 // automatically.  __buf must be a pointer to an array of _CharT whose
       
   263 // size is at least __n.
       
   264 template <class _CharT, class _Traits>
       
   265 basic_streambuf<_CharT, _Traits>*
       
   266 basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) {
       
   267   if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
       
   268       _M_int_buf == 0) {
       
   269     if (__buf == 0 && __n == 0)
       
   270       _M_allocate_buffers(0, 1);
       
   271     else if (__buf != 0 && __n > 0)
       
   272       _M_allocate_buffers(__buf, __n);
       
   273   }
       
   274   return this;
       
   275 }
       
   276 
       
   277 template <class _CharT, class _Traits>
       
   278 __BF_pos_type__
       
   279 basic_filebuf<_CharT, _Traits>::seekoff(off_type __off,
       
   280                                         ios_base::seekdir __whence,
       
   281                                         ios_base::openmode /* dummy */) {
       
   282   if (this->is_open() &&
       
   283       (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) {
       
   284 
       
   285     if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
       
   286       return pos_type(-1);
       
   287 
       
   288     // Seek to beginning or end, regardless of whether we're in input mode.
       
   289     if (__whence == ios_base::beg || __whence == ios_base::end)
       
   290       return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
       
   291                             _State_type());
       
   292 
       
   293     // Seek relative to current position. Complicated if we're in input mode.
       
   294     else if (__whence == ios_base::cur) {
       
   295       if (!_M_in_input_mode)
       
   296         return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
       
   297                               _State_type());
       
   298       else if (_M_mmap_base != 0) {
       
   299         // __off is relative to gptr().  We need to do a bit of arithmetic
       
   300         // to get an offset relative to the external file pointer.
       
   301         streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);
       
   302 
       
   303         // if __off == 0, we do not need to exit input mode and to shift file pointer
       
   304         return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust)
       
   305                           : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
       
   306       }
       
   307       else if (_M_constant_width) { // Get or set the position.
       
   308         streamoff __iadj = _M_width * (this->gptr() - this->eback());
       
   309 
       
   310         // Compensate for offset relative to gptr versus offset relative
       
   311         // to external pointer.  For a text-oriented stream, where the
       
   312         // compensation is more than just pointer arithmetic, we may get
       
   313         // but not set the current position.
       
   314 
       
   315         if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
       
   316           streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __STATIC_CAST(ptrdiff_t, __iadj), _M_ext_buf_end);
       
   317 
       
   318           return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj)
       
   319                             : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
       
   320         }
       
   321       } else {                    // Get the position.  Encoding is var width.
       
   322         // Get position in internal buffer.
       
   323         ptrdiff_t __ipos = this->gptr() - this->eback();
       
   324 
       
   325         // Get corresponding position in external buffer.
       
   326         _State_type __state = _M_state;
       
   327         int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end,
       
   328                                         __ipos);
       
   329 
       
   330         if (__epos >= 0) {
       
   331           // Sanity check (expensive): make sure __epos is the right answer.
       
   332           _State_type __tmp_state = _M_state;
       
   333           _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
       
   334           _CharT* __ibegin = __buf._M_ptr;
       
   335           _CharT* __inext  = __ibegin;
       
   336 
       
   337           const char* __dummy;
       
   338           typename _Codecvt::result __status
       
   339             = _M_codecvt->in(__tmp_state,
       
   340                              _M_ext_buf, _M_ext_buf + __epos, __dummy,
       
   341                              __ibegin, __ibegin + __ipos, __inext);
       
   342           if (__status != _Codecvt::error &&
       
   343               (__status == _Codecvt::noconv ||
       
   344                (__inext == __ibegin + __ipos &&
       
   345                 equal(this->eback(), this->gptr(), __ibegin, _STLP_PRIV _Eq_traits<traits_type>())))) {
       
   346             // Get the current position (at the end of the external buffer),
       
   347             // then adjust it.  Again, it might be a text-oriented stream.
       
   348             streamoff __cur = _M_base._M_seek(0, ios_base::cur);
       
   349             streamoff __adj =
       
   350               _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
       
   351               _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
       
   352             if (__cur != -1 && __cur + __adj >= 0)
       
   353               return __off == 0 ? pos_type(__cur + __adj)
       
   354                                 : _M_seek_return(__cur + __adj, __state);
       
   355               //return _M_seek_return(__cur + __adj, __state);
       
   356           }
       
   357           // We failed the sanity check here.
       
   358         }
       
   359       }
       
   360     }
       
   361     // Unrecognized value for __whence here.
       
   362   }
       
   363 
       
   364   return pos_type(-1);
       
   365 }
       
   366 
       
   367 
       
   368 template <class _CharT, class _Traits>
       
   369 __BF_pos_type__
       
   370 basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos,
       
   371                                         ios_base::openmode /* dummy */) {
       
   372   if (this->is_open()) {
       
   373     if (!_M_seek_init(true))
       
   374       return pos_type(-1);
       
   375 
       
   376     streamoff __off = off_type(__pos);
       
   377     if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) {
       
   378       _M_state = __pos.state();
       
   379       return _M_seek_return(__off, __pos.state());
       
   380     }
       
   381   }
       
   382 
       
   383   return pos_type(-1);
       
   384 }
       
   385 
       
   386 
       
   387 template <class _CharT, class _Traits>
       
   388 int basic_filebuf<_CharT, _Traits>::sync() {
       
   389   if (_M_in_output_mode)
       
   390     return traits_type::eq_int_type(this->overflow(traits_type::eof()),
       
   391                                     traits_type::eof()) ? -1 : 0;
       
   392   return 0;
       
   393 }
       
   394 
       
   395 
       
   396 // Change the filebuf's locale.  This member function has no effect
       
   397 // unless it is called before any I/O is performed on the stream.
       
   398 template <class _CharT, class _Traits>
       
   399 void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) {
       
   400   if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) {
       
   401     this->_M_setup_codecvt(__loc);
       
   402   }
       
   403 }
       
   404 
   114 
   405 //----------------------------------------------------------------------
   115 //----------------------------------------------------------------------
   406 // basic_filebuf<> helper functions.
   116 // basic_filebuf<> helper functions.
   407 
   117 
   408 //----------------------------------------
   118 //----------------------------------------