📄 fstream.cc
字号:
// -*- C++ -*-
/***************************************************************************
*
* fstream.cc - Definition for the Standard Library file streams
*
* $Id: fstream.cc,v 1.1.1.1 2002/01/10 17:38:29 vkorstan Exp $
*
***************************************************************************
*
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
*
* This computer software is owned by Rogue Wave Software, Inc. and is
* protected by U.S. copyright laws and other laws and by international
* treaties. This computer software is furnished by Rogue Wave Software,
* Inc. pursuant to a written license agreement and may be used, copied,
* transmitted, and stored only in accordance with the terms of such
* license and with the inclusion of the above copyright notice. This
* computer software or any other copies thereof may not be provided or
* otherwise made available to any other person.
*
* U.S. Government Restricted Rights. This computer software is provided
* with Restricted Rights. Use, duplication, or disclosure by the
* Government is subject to restrictions as set forth in subparagraph (c)
* (1) (ii) of The Rights in Technical Data and Computer Software clause
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
* Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
* Flatiron Parkway, Boulder, Colorado 80301 USA.
*
**************************************************************************/
_RWSTD_NAMESPACE_BEGIN (std)
template<class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::
open (const char *__name, ios_base::openmode __mode, long __prot)
{
_RWSTD_ASSERT (0 != __name);
_RWSTD_ASSERT (this->_C_is_valid ());
if (is_open ())
return 0;
this->_C_iomode = __mode;
_C_file._C_open (__name, __mode & ~ios_base::ate, __prot);
if (!is_open ())
return 0;
this->setg (0, 0, 0);
this->setp (0, 0);
if (__mode & ios_base::ate) {
if ((_C_cur_pos = _C_beg_pos = _C_file_seek (0, ios_base::end))
== _RWSTD_INVALID_FPOS) {
close ();
return 0;
}
}
else
_C_cur_pos = _C_beg_pos = pos_type();
return this;
}
template<class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::close ()
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!is_open ())
return 0; // failure
// avoid expensive call to overflow() unless necessary
if (this->pptr () != this->pbase () && this->_C_is_eof (overflow ()))
return 0; // failure
// write out any unshift sequence if necessary
// (applies to multibyte, state dependent encodings only)
if (this->_C_out_last () && !_C_unshift ())
return 0; // failure
_C_cur_pos = _C_beg_pos = _RWSTD_INVALID_FPOS;
this->setg (0, 0, 0);
this->setp (0, 0);
if (!_C_file._C_is_std () && !_C_file._C_close ())
return 0; // failure
_C_file = _RWSTD_INVALID_FILE;
return this;
}
template<class _CharT, class _Traits>
streamsize
basic_filebuf<_CharT, _Traits>::showmanyc ()
{
_RWSTD_ASSERT (this->_C_is_valid ());
if (!this->_C_is_in () || !is_open () || _C_cur_pos == _RWSTD_INVALID_FPOS)
return -1;
// start with the number of chars in get area
streamsize __retval = this->egptr () - this->gptr ();
// no prob if this fails for non-seekable devices
pos_type __end_pos = _C_file_seek (0, ios_base::end);
if (__end_pos != _RWSTD_INVALID_FPOS) {
// restore position within file only if seek succeeded
_C_file_seek (_C_cur_pos, ios_base::beg);
const _C_codecvt_t &__cvt =
_USE_FACET (_C_codecvt_t, this->getloc ());
if (__cvt.always_noconv ())
__retval += __end_pos - _C_cur_pos;
else
// make most pessimistic conversion estimate
__retval += (__end_pos - _C_cur_pos) / __cvt.max_length ();
}
return __retval > 0 ? __retval : 0;
}
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::uflow ()
{
int_type __c = underflow ();
if (!this->_C_is_eof(__c))
this->gbump (1);
return __c;
}
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::underflow ()
{
_RWSTD_ASSERT (this->_C_is_valid ());
this->setp (0, 0); // invalidate put area
this->_C_out_last (false); // needed by close ()
if (!this->_C_is_in () || !is_open())
return traits_type::eof ();
char_type* const __to_end = this->_C_buffer + this->_C_bufsize;
// fill the buffer if it's empty
if (this->gptr () == this->egptr()) { // N.B.: gptr() could be null here
// determine the maximum possible size of putback area (if any)
// make sure putback area isn't too big - try to honor
// _RWSTD_PBACK_SIZE if possible, otherwise shrink
_C_pbacksize = min (this->_C_putback_avail (),
_RWSTD_PBACK_SIZE);
_RWSTD_ASSERT (0 != this->_C_bufsize);
if (_C_pbacksize == this->_C_bufsize)
_C_pbacksize = this->_C_bufsize - 1;
traits_type::move (this->eback(), this->gptr () - _C_pbacksize,
_C_pbacksize);
// fill the get area from the file, performing code conversion if
// necessary
streamsize __nread = 0; // number of bytes read from file
_C_beg_pos = _C_cur_pos;
const _C_codecvt_t &__cvt = _USE_FACET (_C_codecvt_t, this->getloc ());
if (__cvt.always_noconv ()) {
// no conversion required
__nread = (__to_end - this->_C_buffer) - _C_pbacksize;
__nread = _C_file._C_read (this->_C_buffer + _C_pbacksize,
sizeof (char_type), __nread);
if (__nread < 0)
return traits_type::eof (); // error while reading
this->setg (this->_C_buffer,
this->_C_buffer + _C_pbacksize,
this->_C_buffer + _C_pbacksize + __nread);
// adjust the current position in the file,
// taking into account CR/LF conversion on windows
__nread += _C_crlf_intern_count (this->gptr (),
this->gptr () + __nread);
}
else { // conversion required
char __xbuf[_RWSTD_DEFAULT_BUFSIZE];
char* __from_base = __xbuf;
const char* __from_next = 0;
char_type* __to_base = this->_C_buffer + _C_pbacksize;
char_type* __to_next = __to_base;
state_type __state = _C_cur_pos.state ();
codecvt_base::result __res = codecvt_base::ok;
while (__to_next != __to_end) {
// read only as many characters as we have positions left in
// internal buffer - guarantees we won't read more characters
// than we can put into the internal buffer after conversion
// and ending file position isn't in the middle of a shift
// sequence
// N.B.: area between __xbuf and __from_base contains partially
// converted sequences left from previous read
streamsize __n =
min (ptrdiff_t (__to_end - __to_next),
ptrdiff_t (sizeof __xbuf - (__from_base - __xbuf)));
__n = _C_file._C_read (__from_base, sizeof (char), __n);
if (0 > __n)
return traits_type::eof (); // error while reading
if (0 == __n)
break; // reached eof
// take into account CR/LF conversion on Win32
__nread += __n +
_C_crlf_extern_count (__from_base, __from_base + __n);
// adjust `n' to hold the number of external chars in buffer
__n += __from_base - __xbuf;
// convert any partially converted sequence from the previous
// iteration (possibly empty) plus what we just read in
__res = __cvt.in (__state, __xbuf, __xbuf + __n, __from_next,
__to_base, __to_end, __to_next);
if (codecvt_base::partial == __res) {
// compute the length of partially converted sequence
__n -= __from_next - __xbuf;
// copy the sequence to beginning of xbuf
memmove (__xbuf, __from_next, __n);
// will append external chars to end of the sequence
__from_base = __xbuf + __n;
}
else if (codecvt_base::ok == __res)
__from_base = __xbuf;
else // codecvt_base::error
return traits_type::eof ();
__to_base = __to_next; // continue at end of converted seq
}
_RWSTD_ASSERT (codecvt_base::ok == __res);
_C_cur_pos.state (__state);
this->setg (this->_C_buffer, this->_C_buffer + _C_pbacksize,
__to_next);
} // end conversion block
if (__nread == 0)
return traits_type::eof ();
_C_cur_pos += __nread;
}
return traits_type::to_int_type (*this->gptr ());
}
template<class _CharT, class _Traits>
_TYPENAME basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::overflow (int_type __c /* = eof () */)
{
_RWSTD_ASSERT (this->_C_is_valid ());
this->setg (0, 0, 0); // invalidate the get area
if (!this->_C_is_out () || !is_open())
return traits_type::eof ();
char_type* __from_beg; // pointer to start of sequence to write
char_type* __from_end; // pointer to end of sequence to write
char_type __c_to_char; // input arg converted to char_type
// (used only in unbuffered mode)
if (this->_C_is_unbuffered ()) {
__c_to_char = traits_type::to_char_type(__c);
__from_beg = &__c_to_char;
__from_end = __from_beg + 1;
}
else {
__from_beg = this->_C_buffer;
__from_end = this->pptr ();
}
if (this->pptr () == 0 && !this->_C_is_unbuffered ()) {
// put area not valid yet - just need to initialize it
this->setp (this->_C_buffer, this->_C_buf_end ());
}
else if ( this->pptr () == this->epptr ()
|| this->_C_is_eof (__c)
|| this->_C_is_unbuffered ()) {
// flush put area to file,
// performing code conversion if necessary
streamsize __nwrote = 0; // num chars to write
state_type __state = _C_cur_pos.state (); // state of stream
// N.B. the sentry constructed by the ostream currently
// seeks to the end of the file when in append mode
// but we're going to seek anyway because the user
// can manipulate the buffer directly
if (this->_C_iomode & ios_base::app)
_C_cur_pos = _C_file_seek (0, ios_base::end);
_C_beg_pos = _C_cur_pos;
const _C_codecvt_t &__cvt = _USE_FACET (_C_codecvt_t, this->getloc ());
if (__cvt.always_noconv ()) {
// no conversion
__nwrote = __from_end - __from_beg;;
if (!_C_file._C_write (__from_beg, sizeof (char_type), __nwrote))
return traits_type::eof (); // error while writing
}
else {
// conversion required: we do this a chunk at a time
// to avoid dynamic allocation of memory
char __xbuf[_RWSTD_DEFAULT_BUFSIZE];
char* __xbuf_end = __xbuf + sizeof __xbuf;
char* __to_next = 0;
const char_type* __from_next = 0;
const char_type* __base = __from_beg;
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
|| ! _C_file._C_write (__xbuf, sizeof (char),
__to_next - __xbuf))
return traits_type::eof ();
// N.B. a partial conversion will result if there's
// not enough space in the conversion buffer
// to hold the converted sequence, but we're o.k.
// since we'll be passing any remaining unconverted
// characters (starting at __from_next) in the next iteration
// __res is ok or partial
__nwrote += __to_next - __xbuf +
_C_crlf_extern_count (__xbuf, __to_next);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -