📄 _fstream.c
字号:
ios_base::openmode /* dummy */) { if (this->is_open()) { if (!_M_seek_init(true)) return pos_type(-1); streamoff __off = off_type(__pos); if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) { _M_state = __pos.state(); return _M_seek_return(__off, __pos.state()); } } return pos_type(-1);}template <class _CharT, class _Traits>int basic_filebuf<_CharT, _Traits>::sync() { if (_M_in_output_mode) return traits_type::eq_int_type(this->overflow(traits_type::eof()), traits_type::eof()) ? -1 : 0; return 0;}// Change the filebuf's locale. This member function has no effect// unless it is called before any I/O is performed on the stream.template <class _CharT, class _Traits>void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) { if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) { this->_M_setup_codecvt(__loc); }}//----------------------------------------------------------------------// basic_filebuf<> helper functions.//----------------------------------------// Helper functions for switching between modes.// This member function is called if we're performing the first I/O// operation on a filebuf, or if we're performing an input operation// immediately after a seek.template <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode() { if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0) && (_M_in_output_mode == 0) && (_M_in_error_mode == 0)) { if (!_M_int_buf && !_M_allocate_buffers()) return false; _M_ext_buf_converted = _M_ext_buf; _M_ext_buf_end = _M_ext_buf; _M_end_state = _M_state; _M_in_input_mode = true; return true; } return false;}// This member function is called if we're performing the first I/O// operation on a filebuf, or if we're performing an output operation// immediately after a seek.template <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode() { if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) && _M_in_input_mode == 0 && _M_in_error_mode == 0) { if (!_M_int_buf && !_M_allocate_buffers()) return false; // In append mode, every write does an implicit seek to the end // of the file. Whenever leaving output mode, the end of file // get put in the initial shift state. if (_M_base.__o_mode() & ios_base::app) _M_state = _State_type(); this->setp(_M_int_buf, _M_int_buf_EOS - 1); _M_in_output_mode = true; return true; } return false;}//----------------------------------------// Helper functions for input// This member function is called if there is an error during input.// It puts the filebuf in error mode, clear the get area buffer, and// returns eof.// returns eof. Error mode is sticky; it is cleared only by close or// seek.template <class _CharT, class _Traits>__BF_int_type__basic_filebuf<_CharT, _Traits>::_M_input_error() { this->_M_exit_input_mode(); _M_in_output_mode = false; _M_in_error_mode = true; this->setg(0, 0, 0); return traits_type::eof();}template <class _CharT, class _Traits>__BF_int_type__basic_filebuf<_CharT, _Traits>::_M_underflow_aux() { // We have the state and file position from the end of the internal // buffer. This round, they become the beginning of the internal buffer. _M_state = _M_end_state; // Fill the external buffer. Start with any leftover characters that // didn't get converted last time. if (_M_ext_buf_end > _M_ext_buf_converted) _M_ext_buf_end = _STLP_STD::copy(_M_ext_buf_converted, _M_ext_buf_end, _M_ext_buf); // boris : copy_backward did not work //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end, //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted)); else _M_ext_buf_end = _M_ext_buf; // Now fill the external buffer with characters from the file. This is // a loop because occasionally we don't get enough external characters // to make progress. for (;;) { ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end); if (__n < 0) { // Read failed, maybe we should set err bit on associated stream... this->setg(0, 0, 0); return traits_type::eof(); } _M_ext_buf_end += __n; // If external buffer is empty there is nothing to do. if (_M_ext_buf == _M_ext_buf_end) { this->setg(0, 0, 0); return traits_type::eof(); } // Convert the external buffer to internal characters. const char* __enext; _CharT* __inext; typename _Codecvt::result __status = _M_codecvt->in(_M_end_state, _M_ext_buf, _M_ext_buf_end, __enext, _M_int_buf, _M_int_buf_EOS, __inext); /* Error conditions: * (1) Return value of error. * (2) Producing internal characters without consuming external characters. * (3) In fixed-width encodings, producing an internal sequence whose length * is inconsistent with that of the internal sequence. * (4) Failure to produce any characters if we have enough characters in * the external buffer, where "enough" means the largest possible width * of a single character. */ if (__status == _Codecvt::noconv) return _Noconv_input<_Traits>::_M_doit(this); else if (__status == _Codecvt::error || (__inext != _M_int_buf && __enext == _M_ext_buf) || (_M_constant_width && (__inext - _M_int_buf) * _M_width != (__enext - _M_ext_buf)) || (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width)) return _M_input_error(); else if (__inext != _M_int_buf) { _M_ext_buf_converted = _M_ext_buf + (__enext - _M_ext_buf); this->setg(_M_int_buf, _M_int_buf, __inext); return traits_type::to_int_type(*_M_int_buf); } /* We need to go around the loop again to get more external characters. * But if the previous read failed then don't try again for now. * Don't enter error mode for a failed read. Error mode is sticky, * and we might succeed if we try again. */ if (__n <= 0) { this->setg(0, 0, 0); return traits_type::eof(); } }}//----------------------------------------// Helper functions for output// This member function is called if there is an error during output.// It puts the filebuf in error mode, clear the put area buffer, and// returns eof. Error mode is sticky; it is cleared only by close or// seek.template <class _CharT, class _Traits>__BF_int_type__basic_filebuf<_CharT, _Traits>::_M_output_error() { _M_in_output_mode = false; _M_in_input_mode = false; _M_in_error_mode = true; this->setp(0, 0); return traits_type::eof();}// Write whatever sequence of characters is necessary to get back to// the initial shift state. This function overwrites the external// buffer, changes the external file position, and changes the state.// Precondition: the internal buffer is empty.template <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_unshift() { if (_M_in_output_mode && !_M_constant_width) { typename _Codecvt::result __status; do { char* __enext = _M_ext_buf; __status = _M_codecvt->unshift(_M_state, _M_ext_buf, _M_ext_buf_EOS, __enext); if (__status == _Codecvt::noconv || (__enext == _M_ext_buf && __status == _Codecvt::ok)) return true; else if (__status == _Codecvt::error) return false; else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf)) return false; } while (__status == _Codecvt::partial); } return true;}//----------------------------------------// Helper functions for buffer allocation and deallocation// This member function is called when we're initializing a filebuf's// internal and external buffers. The argument is the size of the// internal buffer; the external buffer is sized using the character// width in the current encoding. Preconditions: the buffers are currently// null. __n >= 1. __buf is either a null pointer or a pointer to an// array show size is at least __n.// We need __n >= 1 for two different reasons. For input, the base// class always needs a buffer because of the semantics of underflow().// For output, we want to have an internal buffer that's larger by one// element than the buffer that the base class knows about. (See// basic_filebuf<>::overflow() for the reason.)template <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n) { //The major hypothesis in the following implementation is that size_t is unsigned. //We also need streamsize byte representation to be larger or equal to the int //representation to correctly store the encoding information. _STLP_STATIC_ASSERT(!numeric_limits<size_t>::is_signed && sizeof(streamsize) >= sizeof(int)) if (__buf == 0) { streamsize __bufsize = __n * sizeof(_CharT); //We first check that the streamsize representation can't overflow a size_t one. //If it can, we check that __bufsize is not higher than the size_t max value. if ((sizeof(streamsize) > sizeof(size_t)) && (__bufsize > __STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()))) return false; _M_int_buf = __STATIC_CAST(_CharT*, malloc(__STATIC_CAST(size_t, __bufsize))); if (!_M_int_buf) return false; _M_int_buf_dynamic = true; } else { _M_int_buf = __buf; _M_int_buf_dynamic = false; } streamsize __ebufsiz = (max)(__n * __STATIC_CAST(streamsize, _M_width), __STATIC_CAST(streamsize, _M_codecvt->max_length())); _M_ext_buf = 0; if ((sizeof(streamsize) < sizeof(size_t)) || ((sizeof(streamsize) == sizeof(size_t)) && numeric_limits<streamsize>::is_signed) || (__ebufsiz <= __STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()))) { _M_ext_buf = __STATIC_CAST(char*, malloc(__STATIC_CAST(size_t, __ebufsiz))); } if (!_M_ext_buf) { _M_deallocate_buffers(); return false; } _M_int_buf_EOS = _M_int_buf + __STATIC_CAST(ptrdiff_t, __n); _M_ext_buf_EOS = _M_ext_buf + __STATIC_CAST(ptrdiff_t, __ebufsiz); return true;}// Abbreviation for the most common case.template <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers() { // Choose a buffer that's at least 4096 characters long and that's a // multiple of the page size. streamsize __default_bufsiz = ((_M_base.__page_size() + 4095UL) / _M_base.__page_size()) * _M_base.__page_size(); return _M_allocate_buffers(0, __default_bufsiz);}template <class _CharT, class _Traits>void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers() { if (_M_int_buf_dynamic) free(_M_int_buf); free(_M_ext_buf); _M_int_buf = 0; _M_int_buf_EOS = 0; _M_ext_buf = 0; _M_ext_buf_EOS = 0;}//----------------------------------------// Helper functiosn for seek and imbuetemplate <class _CharT, class _Traits>bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) { // If we're in error mode, leave it. _M_in_error_mode = false; // Flush the output buffer if we're in output mode, and (conditionally) // emit an unshift sequence. if (_M_in_output_mode) { bool __ok = !traits_type::eq_int_type(this->overflow(traits_type::eof()), traits_type::eof()); if (__do_unshift) __ok = __ok && this->_M_unshift(); if (!__ok) { _M_in_output_mode = false; _M_in_error_mode = true; this->setp(0, 0); return false; } } // Discard putback characters, if any. if (_M_in_input_mode && _M_in_putback_mode) _M_exit_putback_mode(); return true;}/* Change the filebuf's locale. This member function has no effect * unless it is called before any I/O is performed on the stream. * This function is called on construction and on an imbue call. In the * case of the construction the codecvt facet might be a custom one if * the basic_filebuf user has instanciate it with a custom char_traits. * The user will have to call imbue before any I/O operation. */template <class _CharT, class _Traits>void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc, bool __on_imbue) { if (has_facet<_Codecvt>(__loc)) { _M_codecvt = &use_facet<_Codecvt>(__loc) ; int __encoding = _M_codecvt->encoding(); _M_width = (max)(__encoding, 1); _M_max_width = _M_codecvt->max_length(); _M_constant_width = __encoding > 0; _M_always_noconv = _M_codecvt->always_noconv(); } else { _M_codecvt = 0; _M_width = _M_max_width = 1; _M_constant_width = _M_always_noconv = false; if (__on_imbue) { //This call will generate an exception reporting the problem. use_facet<_Codecvt>(__loc); } }}_STLP_END_NAMESPACE# undef __BF_int_type__# undef __BF_pos_type__# undef __BF_off_type__#endif /* _STLP_FSTREAM_C */// Local Variables:// mode:C++// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -