📄 fstream.cc
字号:
__base = __from_next; // do the next chunk
}
} // end conversion block
// adjust the current position in the file
_C_cur_pos += __nwrote;
_C_cur_pos.state (__state);
// reset the put area
if (!this->_C_is_unbuffered ())
this->setp (this->_C_buffer, this->_C_buf_end ());
}
// now that there's room in the buffer, call sputc() recursively
// to actually place the character in the buffer (unless we're
// in unbuffered mode because we just wrote it out)
if (!this->_C_is_eof (__c) && !this->_C_is_unbuffered ())
this->sputc (__c);
this->_C_out_last (true); // needed by close ()
return traits_type::not_eof (__c);
}
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::pbackfail (int_type __c)
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!is_open ())
return traits_type::eof ();
// we could get here if gptr = eback or if __c != *(gptr-1)
if (!this->_C_putback_avail ()) {
// try to make a putback area available
if (this->seekoff (-1, ios_base::cur) == _RWSTD_INVALID_FPOS)
return traits_type::eof ();
if (this->_C_is_eof (underflow ()))
return traits_type::eof ();
this->gbump (1);
}
if (traits_type::eq (traits_type::to_char_type (__c), *(this->gptr () - 1))
|| this->_C_is_eof (__c)) {
// "put back" original value
this->gbump (-1);
return traits_type::not_eof (__c);
}
else if (this->_C_is_out ()) {
// overwrite existing value with new value
this->gbump (-1);
*this->gptr () = traits_type::to_char_type (__c);
return __c;
}
else
return traits_type::eof ();
}
template<class _CharT, class _Traits>
basic_streambuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::setbuf (char_type *__buf, streamsize __len)
{
_RWSTD_ASSERT (this->_C_is_valid ());
// sync the buffer to the external file so it can be deallocated
if (sync () != 0)
return 0;
bool __own_old_buf = this->_C_own_buf ();
if (__len > 0) {
// replace the buffer...
if (__buf == 0) {
// ...newly allocated buffer...
__buf = new char_type[__len]; // try to allocate before deleting
this->_C_own_buf (true);
}
else
// ...or with supplied buffer
this->_C_own_buf (false);
if (__own_old_buf)
delete [] this->_C_buffer;
this->_C_buffer = __buf;
this->_C_bufsize = __len;
this->_C_set_unbuffered (false);
}
else {
// unbuffer this stream
if (__buf != 0) // invalid input (__len == 0 => __buf == 0)
return 0;
// character buffer is preserved (used as get area only),
// streambuf object unbuffered for writing
// to put a streambuf object into an unbuffered mode (see 27.8.1.4,
// p10) and affect the size of the get area, setbuf() should first
// be called with the desired (non-zero) size and then again with
// both arguments being 0
this->_C_set_unbuffered (true);
}
this->setg (0, 0, 0);
this->setp (0, 0);
// a character buffer of nonzero size must exist
// even in unbuffered mode
_RWSTD_ASSERT (0 != this->_C_buffer);
_RWSTD_ASSERT (0 != this->_C_bufsize);
return this;
}
// 27.8.1.4, p 11
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::
seekoff (off_type __off, ios_base::seekdir __way, ios_base::openmode)
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!is_open ())
return _RWSTD_INVALID_FPOS;
int __width = _USE_FACET (_C_codecvt_t, this->getloc ()).encoding ();
// offset must be zero with multibyte encoding
if (0 != __off && __width <= 0)
return _RWSTD_INVALID_FPOS;
// sync the buffer... (this also invalidates the get/put area)
if (sync () != 0)
return _RWSTD_INVALID_FPOS;
// ...and, if last op was output, append an unshift sequence
if (this->_C_out_last ())
_C_unshift ();
// perform the seek
pos_type __new_pos;
if (__width > 0)
__new_pos = _C_file_seek (__width * __off, __way);
else
__new_pos = _C_file_seek (0, __way);
if (__new_pos != _RWSTD_INVALID_FPOS)
_C_cur_pos = _C_beg_pos = __new_pos;
this->_C_out_last (false); // needed by close()
return __new_pos;
}
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::pos_type
basic_filebuf<_CharT, _Traits>::seekpos (pos_type __pos, ios_base::openmode)
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!is_open ())
return _RWSTD_INVALID_FPOS;
// flush the output area if it exists
if (this->pptr () != 0) {
if (this->_C_is_eof (this->overflow (traits_type::eof ())))
return _RWSTD_INVALID_FPOS;
}
if (_C_file_seek (__pos, ios_base::beg) == _RWSTD_INVALID_FPOS)
return _RWSTD_INVALID_FPOS;
_C_cur_pos = _C_beg_pos = __pos;
this->setg (0, 0, 0);
this->setp (0, 0);
this->_C_out_last (false); // needed by close()
return __pos;
}
template<class _CharT, class _Traits>
int
basic_filebuf<_CharT, _Traits>::sync ()
{
_RWSTD_ASSERT (this->_C_is_valid ());
// put area active
if (this->pptr () != 0) {
// flush the buffer to the file
if (this->_C_is_eof (overflow (traits_type::eof ())))
return -1;
}
// get area active
if (this->gptr () != 0) {
// get the number of chars consumed in the buffer
streamoff __consumed = (this->gptr () - this->eback ()) - _C_pbacksize;
const _C_codecvt_t &__cvt = _USE_FACET (_C_codecvt_t, this->getloc ());
int __width = __cvt.encoding ();
if (__width > 0) {
// constant width conversion:
// adjust the current position/state in the file,
// taking into account CR/LF conversion on Win32
_C_cur_pos = _C_beg_pos;
_C_cur_pos += (__width * __consumed)
+ _C_crlf_intern_count (this->eback () + _C_pbacksize,
this->gptr());
}
else {
// This gets a bit tricky here because we don't know the external
// file position corresponding to the position in the
// internal buffer. To figure this out, we'll use the known
// file position/state corresponding to the start of the buffer
// (which we have carefully saved in _C_beg_pos) and
// convert the characters up to the current position in the
// buffer, counting how many external chars result. We can
// then use the offset from _C_beg_pos and the state
// returned from codecvt::out() to construct the current file
// position
streamoff __ext_chars = 0; // converted external chars
char __xbuf[_RWSTD_DEFAULT_BUFSIZE];
char* __xbuf_end = __xbuf + sizeof __xbuf;
char* __to_next = 0;
const char_type* __from_next = 0;
const char_type* __from_end = this->gptr ();
state_type __state = _C_beg_pos.state ();
const char_type* __base = this->eback () + _C_pbacksize;
while (__from_next != __from_end) {
codecvt_base::result __res =
__cvt.out (__state, __base, __from_end, __from_next,
__xbuf, __xbuf_end, __to_next);
if (__res == codecvt_base::error)
return -1;
// take into account CR/LF conversion on Win32
__ext_chars += (__to_next - __xbuf) +
_C_crlf_extern_count (__xbuf, __to_next);
// repeat with next chunk
__base = __from_next;
}
_C_cur_pos = _C_beg_pos + __ext_chars;
_C_cur_pos.state (__state);
}
if (_C_file_seek (_C_cur_pos, ios_base::beg) == _RWSTD_INVALID_FPOS)
return -1;
traits_type::move (this->eback(), this->gptr () - _C_pbacksize,
_C_pbacksize);
this->setg (this->eback(), this->eback() + _C_pbacksize,
this->eback() + _C_pbacksize);
}
_C_beg_pos = _C_cur_pos;
this->setp (0, 0);
return 0;
}
template<class _CharT, class _Traits>
streamsize
basic_filebuf<_CharT, _Traits>::xsputn (const char_type* __s, streamsize __len)
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!__s || (__len == 0) || !this->_C_is_out ())
return 0;
if (this->pptr () != 0 && (this->pptr () + __len) < this->epptr ()) {
traits_type::copy (this->pptr (), __s, __len);
this->pbump (int(__len));
}
else {
for (streamsize __n = 0; __n < __len; ++__n) {
if (this->_C_is_eof (this->sputc (*__s++)))
return __n;
}
}
return __len;
}
template<class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::_C_open (_RW::__rw_file_t __frep,
char_type *__buf,
streamsize __n)
{
if (is_open () || !setbuf (__buf,__n) || !__frep._C_is_open ())
return 0;
_C_file = __frep;
this->_C_iomode = _C_file._C_get_mode ();
this->setg (0, 0, 0);
this->setp (0, 0);
_C_cur_pos = _C_beg_pos = pos_type(); // offset == 0, state = state()
return this;
}
// write an unshift sequence if not in initial state
// N.B.: this is a no-op unless the stream is imbued with user-defined
// locale/facet because the default implementations of unshift()
// always return noconv
// returns: true on success
template<class _CharT, class _Traits>
bool
basic_filebuf<_CharT, _Traits>::_C_unshift ()
{
// unshifting isn't necessary if encoding isn't state dependent or
// if state is equivalent to initial state (determined by mbsinit())
state_type __state = _C_cur_pos.state ();
if ( _USE_FACET (_C_codecvt_t, this->getloc ()).encoding () >= 0
|| _MBSINIT (&__state) != 0)
return true;
// buf to hold unshift sequence - assumes that the shift
// sequence will be less than 64 chars (we can't safely
// use dynamic allocation because _C_unshift
// could be called as a result of memory alloc exception)
char __useq[64];
char* __useq_end = 0;
codecvt_base::result __res =
_USE_FACET (_C_codecvt_t, this->getloc ()).unshift (
__state, __useq, __useq + sizeof __useq,
__useq_end);
streamoff __nbytes = __useq_end - __useq;
// in the unlikely event that the buffer isn't big enough, assert
_RWSTD_ASSERT(__res != codecvt_base::partial);
if (__res == codecvt_base::error)
return false;
if (__res == codecvt_base::noconv)
return true;
if (_C_file._C_write (__useq, sizeof (char), __nbytes))
return false;
_C_cur_pos += __nbytes; // CR/LF conversion not an issue here
return true;
}
_RWSTD_NAMESPACE_END // std
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -