genericopenlibs/cppstdlib/stl/stlport/stl/_fstream.h
changeset 22 ddc455616bd6
parent 0 e4d67989cc36
child 45 4b03adbd26ca
equal deleted inserted replaced
18:47c74d1534e1 22:ddc455616bd6
   183 template <class _CharT, class _Traits>
   183 template <class _CharT, class _Traits>
   184 class _Underflow;
   184 class _Underflow;
   185 
   185 
   186 _STLP_TEMPLATE_NULL class _Underflow< char, char_traits<char> >;
   186 _STLP_TEMPLATE_NULL class _Underflow< char, char_traits<char> >;
   187 
   187 
       
   188 // public:
       
   189 // helper class.
       
   190 template <class _CharT>
       
   191 struct _Filebuf_Tmp_Buf {
       
   192   _CharT* _M_ptr;
       
   193   _Filebuf_Tmp_Buf(ptrdiff_t __n) : _M_ptr(0) { _M_ptr = new _CharT[__n]; }
       
   194   ~_Filebuf_Tmp_Buf() { delete[] _M_ptr; }
       
   195 };
       
   196 
   188 template <class _CharT, class _Traits>
   197 template <class _CharT, class _Traits>
   189 class basic_filebuf : public basic_streambuf<_CharT, _Traits> {
   198 class basic_filebuf : public basic_streambuf<_CharT, _Traits> {
   190 public:                         // Types.
   199 public:                         // Types.
   191   typedef _CharT                     char_type;
   200   typedef _CharT                     char_type;
   192   typedef typename _Traits::int_type int_type;
   201   typedef typename _Traits::int_type int_type;
   198   typedef basic_streambuf<_CharT, _Traits> _Base;
   207   typedef basic_streambuf<_CharT, _Traits> _Base;
   199   typedef basic_filebuf<_CharT, _Traits> _Self;
   208   typedef basic_filebuf<_CharT, _Traits> _Self;
   200 
   209 
   201 public:                         // Constructors, destructor.
   210 public:                         // Constructors, destructor.
   202   basic_filebuf();
   211   basic_filebuf();
   203   ~basic_filebuf();
   212   ~basic_filebuf()
       
   213   {
       
   214 	this->close();
       
   215 	_M_deallocate_buffers();
       
   216   }
   204 
   217 
   205 public:                         // Opening and closing files.
   218 public:                         // Opening and closing files.
   206   bool is_open() const { return _M_base.__is_open(); }
   219   bool is_open() const { return _M_base.__is_open(); }
   207 
   220 
   208   _Self* open(const char* __s, ios_base::openmode __m) {
   221   _Self* open(const char* __s, ios_base::openmode __m) {
   234     return _M_base._M_open(__id, _Init_mode) ? this : 0;
   247     return _M_base._M_open(__id, _Init_mode) ? this : 0;
   235   }
   248   }
   236 
   249 
   237   _Self* close();
   250   _Self* close();
   238 
   251 
   239 protected:                      // Virtual functions from basic_streambuf.
   252 protected:         // Virtual functions from basic_streambuf.
   240   virtual streamsize showmanyc();
   253   
   241   virtual int_type underflow();
   254   virtual streamsize showmanyc() {
   242 
   255 
   243   virtual int_type pbackfail(int_type = traits_type::eof());
   256       // Is there any possibility that reads can succeed?
   244   virtual int_type overflow(int_type = traits_type::eof());
   257       if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
   245 
   258         return -1;
   246   virtual basic_streambuf<_CharT, _Traits>* setbuf(char_type*, streamsize);
   259       else if (_M_in_putback_mode)
   247   virtual pos_type seekoff(off_type, ios_base::seekdir,
   260         return this->egptr() - this->gptr();
   248                            ios_base::openmode = ios_base::in | ios_base::out);
   261       else if (_M_constant_width) {
   249   virtual pos_type seekpos(pos_type,
   262         streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
   250                            ios_base::openmode = ios_base::in | ios_base::out);
   263         streamoff __size = _M_base._M_file_size();
   251 
   264         return __pos >= 0 && __size > __pos ? __size - __pos : 0;
   252   virtual int sync();
   265       }
   253   virtual void imbue(const locale&);
   266       else
   254 
   267         return 0;
       
   268 
       
   269   }
       
   270   virtual int_type underflow() {
       
   271 
       
   272       return _Underflow<_CharT, _Traits>::_M_doit(this);
       
   273 
       
   274   }
       
   275 
       
   276   virtual int_type pbackfail(int_type __c= traits_type::eof()) {
       
   277 
       
   278       const int_type __eof = traits_type::eof();
       
   279 
       
   280       // If we aren't already in input mode, pushback is impossible.
       
   281       if (!_M_in_input_mode)
       
   282         return __eof;
       
   283 
       
   284       // We can use the ordinary get buffer if there's enough space, and
       
   285       // if it's a buffer that we're allowed to write to.
       
   286       if (this->gptr() != this->eback() &&
       
   287           (traits_type::eq_int_type(__c, __eof) ||
       
   288            traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) ||
       
   289            !_M_mmap_base)) {
       
   290         this->gbump(-1);
       
   291         if (traits_type::eq_int_type(__c, __eof) ||
       
   292             traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
       
   293           return traits_type::to_int_type(*this->gptr());
       
   294       }
       
   295       else if (!traits_type::eq_int_type(__c, __eof)) {
       
   296         // Are we in the putback buffer already?
       
   297         _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
       
   298         if (_M_in_putback_mode) {
       
   299           // Do we have more room in the putback buffer?
       
   300           if (this->eback() != _M_pback_buf)
       
   301             this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
       
   302           else
       
   303             return __eof;           // No more room in the buffer, so fail.
       
   304         }
       
   305         else {                      // We're not yet in the putback buffer.
       
   306           _M_saved_eback = this->eback();
       
   307           _M_saved_gptr  = this->gptr();
       
   308           _M_saved_egptr = this->egptr();
       
   309           this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
       
   310           _M_in_putback_mode = true;
       
   311         }
       
   312       }
       
   313       else
       
   314         return __eof;
       
   315 
       
   316       // We have made a putback position available.  Assign to it, and return.
       
   317       *this->gptr() = traits_type::to_char_type(__c);
       
   318       return __c;
       
   319 
       
   320   }
       
   321   
       
   322   virtual int_type overflow(int_type __c) {
       
   323 
       
   324       // Switch to output mode, if necessary.
       
   325       if (!_M_in_output_mode)
       
   326         if (!_M_switch_to_output_mode())
       
   327           return traits_type::eof();
       
   328 
       
   329       _CharT* __ibegin = this->_M_int_buf;
       
   330       _CharT* __iend   = this->pptr();
       
   331       this->setp(_M_int_buf, _M_int_buf_EOS - 1);
       
   332 
       
   333       // Put __c at the end of the internal buffer.
       
   334       if (!traits_type::eq_int_type(__c, traits_type::eof()))
       
   335         *__iend++ = _Traits::to_char_type(__c);
       
   336 
       
   337       // For variable-width encodings, output may take more than one pass.
       
   338       while (__ibegin != __iend) {
       
   339         const _CharT* __inext = __ibegin;
       
   340         char* __enext         = _M_ext_buf;
       
   341         typename _Codecvt::result __status
       
   342           = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
       
   343                             _M_ext_buf, _M_ext_buf_EOS, __enext);
       
   344         if (__status == _Codecvt::noconv) {
       
   345           return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
       
   346             ? traits_type::not_eof(__c)
       
   347             : _M_output_error();
       
   348         }
       
   349 
       
   350         // For a constant-width encoding we know that the external buffer
       
   351         // is large enough, so failure to consume the entire internal buffer
       
   352         // or to produce the correct number of external characters, is an error.
       
   353         // For a variable-width encoding, however, we require only that we
       
   354         // consume at least one internal character
       
   355         else if (__status != _Codecvt::error &&
       
   356                  (((__inext == __iend) &&
       
   357                    (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) ||
       
   358                   (!_M_constant_width && __inext != __ibegin))) {
       
   359             // We successfully converted part or all of the internal buffer.
       
   360           ptrdiff_t __n = __enext - _M_ext_buf;
       
   361           if (_M_write(_M_ext_buf, __n))
       
   362             __ibegin += __inext - __ibegin;
       
   363           else
       
   364             return _M_output_error();
       
   365         }
       
   366         else
       
   367           return _M_output_error();
       
   368       }
       
   369 
       
   370       return traits_type::not_eof(__c);
       
   371 
       
   372   }
       
   373 
       
   374   virtual basic_streambuf<_CharT, _Traits>* setbuf(_CharT* __buf, streamsize __n) {
       
   375 
       
   376       if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
       
   377           _M_int_buf == 0) {
       
   378         if (__buf == 0 && __n == 0)
       
   379           _M_allocate_buffers(0, 1);
       
   380         else if (__buf != 0 && __n > 0)
       
   381           _M_allocate_buffers(__buf, __n);
       
   382       }
       
   383       return this;
       
   384 
       
   385   }
       
   386   
       
   387   virtual pos_type seekoff(off_type __off,
       
   388           ios_base::seekdir __whence,
       
   389           ios_base::openmode /* dummy */) {
       
   390 
       
   391       if (this->is_open() &&
       
   392           (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) {
       
   393 
       
   394         if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
       
   395           return pos_type(-1);
       
   396 
       
   397         // Seek to beginning or end, regardless of whether we're in input mode.
       
   398         if (__whence == ios_base::beg || __whence == ios_base::end)
       
   399           return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
       
   400                                 _State_type());
       
   401 
       
   402         // Seek relative to current position. Complicated if we're in input mode.
       
   403         else if (__whence == ios_base::cur) {
       
   404           if (!_M_in_input_mode)
       
   405             return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
       
   406                                   _State_type());
       
   407           else if (_M_mmap_base != 0) {
       
   408             // __off is relative to gptr().  We need to do a bit of arithmetic
       
   409             // to get an offset relative to the external file pointer.
       
   410             streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);
       
   411 
       
   412             // if __off == 0, we do not need to exit input mode and to shift file pointer
       
   413             return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust)
       
   414                               : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
       
   415           }
       
   416           else if (_M_constant_width) { // Get or set the position.
       
   417             streamoff __iadj = _M_width * (this->gptr() - this->eback());
       
   418 
       
   419             // Compensate for offset relative to gptr versus offset relative
       
   420             // to external pointer.  For a text-oriented stream, where the
       
   421             // compensation is more than just pointer arithmetic, we may get
       
   422             // but not set the current position.
       
   423 
       
   424             if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
       
   425               streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __STATIC_CAST(ptrdiff_t, __iadj), _M_ext_buf_end);
       
   426 
       
   427               return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj)
       
   428                                 : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
       
   429             }
       
   430           } else {                    // Get the position.  Encoding is var width.
       
   431             // Get position in internal buffer.
       
   432             ptrdiff_t __ipos = this->gptr() - this->eback();
       
   433 
       
   434             // Get corresponding position in external buffer.
       
   435             _State_type __state = _M_state;
       
   436             int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end,
       
   437                                             __ipos);
       
   438 
       
   439             if (__epos >= 0) {
       
   440               // Sanity check (expensive): make sure __epos is the right answer.
       
   441               _State_type __tmp_state = _M_state;
       
   442               _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
       
   443               _CharT* __ibegin = __buf._M_ptr; 
       
   444               _CharT* __inext  = __ibegin;
       
   445 
       
   446               const char* __dummy;
       
   447               typename _Codecvt::result __status
       
   448                 = _M_codecvt->in(__tmp_state,
       
   449                                  _M_ext_buf, _M_ext_buf + __epos, __dummy,
       
   450                                  __ibegin, __ibegin + __ipos, __inext);
       
   451               if (__status != _Codecvt::error &&
       
   452                   (__status == _Codecvt::noconv ||
       
   453                    (__inext == __ibegin + __ipos &&
       
   454                     equal(this->eback(), this->gptr(), __ibegin, _STLP_PRIV _Eq_traits<traits_type>())))) {
       
   455                 // Get the current position (at the end of the external buffer),
       
   456                 // then adjust it.  Again, it might be a text-oriented stream.
       
   457                 streamoff __cur = _M_base._M_seek(0, ios_base::cur);
       
   458                 streamoff __adj =
       
   459                   _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
       
   460                   _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
       
   461                 if (__cur != -1 && __cur + __adj >= 0)
       
   462                   return __off == 0 ? pos_type(__cur + __adj)
       
   463                                     : _M_seek_return(__cur + __adj, __state);
       
   464                   //return _M_seek_return(__cur + __adj, __state);
       
   465               }
       
   466               // We failed the sanity check here.
       
   467             }
       
   468           }
       
   469         }
       
   470         // Unrecognized value for __whence here.
       
   471       }
       
   472 
       
   473       return pos_type(-1);
       
   474 
       
   475   }
       
   476   
       
   477   virtual pos_type seekpos(pos_type __pos,
       
   478           ios_base::openmode /* dummy */) {
       
   479 
       
   480       if (this->is_open()) {
       
   481         if (!_M_seek_init(true))
       
   482           return pos_type(-1);
       
   483 
       
   484         streamoff __off = off_type(__pos);
       
   485         if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) {
       
   486           _M_state = __pos.state();
       
   487           return _M_seek_return(__off, __pos.state());
       
   488         }
       
   489       }
       
   490 
       
   491       return pos_type(-1);
       
   492 
       
   493   }
       
   494 
       
   495   virtual int sync() {
       
   496 
       
   497       if (_M_in_output_mode)
       
   498         return traits_type::eq_int_type(this->overflow(traits_type::eof()),
       
   499                                         traits_type::eof()) ? -1 : 0;
       
   500       return 0;
       
   501 
       
   502   }
       
   503   
       
   504   virtual void imbue(const locale& __loc) {
       
   505 
       
   506       if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) {
       
   507         this->_M_setup_codecvt(__loc);
       
   508       }
       
   509 
       
   510   }
       
   511   
       
   512   
   255 private:                        // Helper functions.
   513 private:                        // Helper functions.
   256 
   514 
   257   // Precondition: we are currently in putback input mode.  Effect:
   515   // Precondition: we are currently in putback input mode.  Effect:
   258   // switches back to ordinary input mode.
   516   // switches back to ordinary input mode.
   259   void _M_exit_putback_mode() {
   517   void _M_exit_putback_mode() {
   377 #  if ! defined (_STLP_NO_WCHAR_T)
   635 #  if ! defined (_STLP_NO_WCHAR_T)
   378 _STLP_EXPORT_TEMPLATE_CLASS basic_filebuf<wchar_t, char_traits<wchar_t> >;
   636 _STLP_EXPORT_TEMPLATE_CLASS basic_filebuf<wchar_t, char_traits<wchar_t> >;
   379 #  endif
   637 #  endif
   380 #endif /* _STLP_USE_TEMPLATE_EXPORT */
   638 #endif /* _STLP_USE_TEMPLATE_EXPORT */
   381 
   639 
   382 // public:
       
   383 // helper class.
       
   384 template <class _CharT>
       
   385 struct _Filebuf_Tmp_Buf {
       
   386   _CharT* _M_ptr;
       
   387   _Filebuf_Tmp_Buf(ptrdiff_t __n) : _M_ptr(0) { _M_ptr = new _CharT[__n]; }
       
   388   ~_Filebuf_Tmp_Buf() { delete[] _M_ptr; }
       
   389 };
       
   390 
       
   391 
       
   392 //
   640 //
   393 // This class had to be designed very carefully to work
   641 // This class had to be designed very carefully to work
   394 // with Visual C++.
   642 // with Visual C++.
   395 //
   643 //
   396 template <class _Traits>
   644 template <class _Traits>