aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/fstream.tcc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits/fstream.tcc')
-rw-r--r--libstdc++-v3/include/bits/fstream.tcc211
1 files changed, 126 insertions, 85 deletions
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index 387f099ae98..c69ac9c7226 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -1,6 +1,6 @@
// File based streams -*- C++ -*-
-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -58,7 +58,7 @@ namespace std
template<typename _CharT, typename _Traits>
void
basic_filebuf<_CharT, _Traits>::
- _M_destroy_internal_buffer()
+ _M_destroy_internal_buffer() throw()
{
if (_M_buf_allocated)
{
@@ -94,16 +94,13 @@ namespace std
// Setup initial position of buffer.
_M_set_indeterminate();
- // Set input buffer to something real.
- // NB: Must open in non-blocking way to do this, or must
- // set the initial position in a different manner than
- // using underflow.
- if (__mode & ios_base::in && _M_buf_allocated)
- this->underflow();
-
if ((__mode & ios_base::ate)
&& this->seekoff(0, ios_base::end, __mode) < 0)
- this->close();
+ {
+ // 27.8.1.3,4
+ this->close();
+ return __ret;
+ }
__ret = this;
}
@@ -114,35 +111,46 @@ namespace std
template<typename _CharT, typename _Traits>
typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
basic_filebuf<_CharT, _Traits>::
- close()
+ close() throw()
{
- __filebuf_type *__ret = NULL;
+ __filebuf_type* __ret = NULL;
if (this->is_open())
{
- const int_type __eof = traits_type::eof();
- bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
- if (__testput
- && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
- return __ret;
+ bool __testfail = false;
+ try
+ {
+ const int_type __eof = traits_type::eof();
+ bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
+ if (__testput
+ && traits_type::eq_int_type(_M_really_overflow(__eof),
+ __eof))
+ __testfail = true;
+
+#if 0
+ // XXX not done
+ if (_M_last_overflowed)
+ {
+ _M_output_unshift();
+ _M_really_overflow(__eof);
+ }
+#endif
+ }
+ catch(...)
+ {
+ __testfail = true;
+ }
// NB: Do this here so that re-opened filebufs will be cool...
- _M_mode = ios_base::openmode(0);
+ this->_M_mode = ios_base::openmode(0);
_M_destroy_internal_buffer();
_M_pback_destroy();
-
-#if 0
- // XXX not done
- if (_M_last_overflowed)
- {
- _M_output_unshift();
- _M_really_overflow(__eof);
- }
-#endif
- if (_M_file.close())
+ if (!_M_file.close())
+ __testfail = true;
+
+ if (!__testfail)
__ret = this;
}
-
_M_last_overflowed = false;
return __ret;
}
@@ -154,9 +162,16 @@ namespace std
{
streamsize __ret = -1;
bool __testin = _M_mode & ios_base::in;
+ const locale __loc = this->getloc();
+ const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
if (__testin && this->is_open())
- __ret = _M_in_end - _M_in_cur;
+ {
+ __ret = _M_in_end - _M_in_cur;
+ if (__cvt.always_noconv())
+ __ret += _M_file.showmanyc_helper();
+ }
+
_M_last_overflowed = false;
return __ret;
}
@@ -208,21 +223,26 @@ namespace std
}
else
{
- // At the beginning of the buffer, need to make a
- // putback position available.
- this->seekoff(-1, ios_base::cur);
- this->underflow();
- if (!__testeof)
+ // At the beginning of the buffer, need to make a
+ // putback position available.
+ // But the seek may fail (f.i., at the beginning of
+ // a file, see libstdc++/9439) and in that case
+ // we return traits_type::eof()
+ if (this->seekoff(-1, ios_base::cur) >= 0)
{
- if (!traits_type::eq(__c, *_M_in_cur))
- {
- _M_pback_create();
- *_M_in_cur = __c;
- }
- __ret = __i;
+ this->underflow();
+ if (!__testeof)
+ {
+ if (!traits_type::eq(__c, *_M_in_cur))
+ {
+ _M_pback_create();
+ *_M_in_cur = __c;
+ }
+ __ret = __i;
+ }
+ else
+ __ret = traits_type::not_eof(__i);
}
- else
- __ret = traits_type::not_eof(__i);
}
}
_M_last_overflowed = false;
@@ -240,7 +260,9 @@ namespace std
if (__testout)
{
- if (__testput)
+ if (traits_type::eq_int_type(__c, traits_type::eof()))
+ __ret = traits_type::not_eof(__c);
+ else if (__testput)
{
*_M_out_cur = traits_type::to_char_type(__c);
_M_out_cur_move(1);
@@ -278,14 +300,23 @@ namespace std
char* __buf = static_cast<char*>(__builtin_alloca(__blen));
char* __bend;
const char_type* __iend;
- __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
- __iend, __buf, __buf + __blen, __bend);
- // Result == ok, partial, noconv
- if (__r != codecvt_base::error)
+ codecvt_base::result __r;
+ __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
+ __iend, __buf, __buf + __blen, __bend);
+
+ if (__r == codecvt_base::ok || __r == codecvt_base::partial)
__blen = __bend - __buf;
- // Result == error
- else
- __blen = 0;
+ else if (__r == codecvt_base::noconv)
+ {
+ // Same as the always_noconv case above.
+ __buf = reinterpret_cast<char*>(__ibuf);
+ __blen = __ilen;
+ }
+ else
+ {
+ // Result == error
+ __blen = 0;
+ }
if (__blen)
{
@@ -301,11 +332,8 @@ namespace std
__r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,
__iend, __buf, __buf + __blen, __bend);
if (__r != codecvt_base::error)
- __rlen = __bend - __buf;
- else
- __rlen = 0;
- if (__rlen)
{
+ __rlen = __bend - __buf;
__elen += _M_file.xsputn(__buf, __rlen);
__plen += __rlen;
}
@@ -320,7 +348,7 @@ namespace std
{
int_type __ret = traits_type::eof();
bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
- bool __testunbuffered = _M_file.is_open() && !_M_buf_size_opt;
+ bool __testunbuffered = _M_file.is_open() && !_M_buf_size;
if (__testput || __testunbuffered)
{
@@ -343,26 +371,32 @@ namespace std
_M_convert_to_external(_M_out_beg, _M_out_end - _M_out_beg,
__elen, __plen);
- // Convert pending sequence to external representation, output.
- // If eof, then just attempt sync.
- if (!traits_type::eq_int_type(__c, traits_type::eof()))
- {
- char_type __pending = traits_type::to_char_type(__c);
- _M_convert_to_external(&__pending, 1, __elen, __plen);
-
- // User code must flush when switching modes (thus don't sync).
- if (__elen == __plen)
+ // Checks for codecvt.out failures and _M_file.xsputn failures,
+ // respectively, inside _M_convert_to_external.
+ if (__testunbuffered || (__elen && __elen == __plen))
+ {
+ // Convert pending sequence to external representation, output.
+ // If eof, then just attempt sync.
+ if (!traits_type::eq_int_type(__c, traits_type::eof()))
{
- _M_set_indeterminate();
- __ret = traits_type::not_eof(__c);
+ char_type __pending = traits_type::to_char_type(__c);
+ _M_convert_to_external(&__pending, 1, __elen, __plen);
+
+ // User code must flush when switching modes (thus
+ // don't sync).
+ if (__elen == __plen && __elen)
+ {
+ _M_set_indeterminate();
+ __ret = traits_type::not_eof(__c);
+ }
}
- }
- else if (!_M_file.sync())
- {
- _M_set_indeterminate();
- __ret = traits_type::not_eof(__c);
- }
- }
+ else if (!_M_file.sync())
+ {
+ _M_set_indeterminate();
+ __ret = traits_type::not_eof(__c);
+ }
+ }
+ }
_M_last_overflowed = true;
return __ret;
}
@@ -401,12 +435,13 @@ namespace std
bool __testin = (ios_base::in & _M_mode & __mode) != 0;
bool __testout = (ios_base::out & _M_mode & __mode) != 0;
- // Should probably do has_facet checks here.
- int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding();
+ int __width = 0;
+ if (has_facet<__codecvt_type>(this->_M_buf_locale))
+ __width = use_facet<__codecvt_type>(this->_M_buf_locale).encoding();
if (__width < 0)
__width = 0;
- bool __testfail = __off != 0 && __width <= 0;
-
+
+ bool __testfail = __off != 0 && __width <= 0;
if (this->is_open() && !__testfail && (__testin || __testout))
{
// Ditch any pback buffers to avoid confusion.
@@ -430,7 +465,8 @@ namespace std
//in
else if (__testget && __way == ios_base::cur)
__computed_off += _M_in_cur - _M_filepos;
-
+
+ // Return pos_type(off_type(-1)) in case of failure.
__ret = _M_file.seekoff(__computed_off, __way, __mode);
_M_set_indeterminate();
}
@@ -438,8 +474,14 @@ namespace std
// state, ie _M_file._offset == -1
else
{
- __ret = _M_file.seekoff(__off, ios_base::cur, __mode);
- __ret += max(_M_out_cur, _M_in_cur) - _M_filepos;
+ pos_type __tmp =
+ _M_file.seekoff(__off, ios_base::cur, __mode);
+ if (__tmp >= 0)
+ {
+ // Seek successful.
+ __ret = __tmp;
+ __ret += max(_M_out_cur, _M_in_cur) - _M_filepos;
+ }
}
}
_M_last_overflowed = false;
@@ -471,10 +513,7 @@ namespace std
bool __testbeg = gptr() == eback() && pptr() == pbase();
if (__testbeg && _M_buf_locale != __loc)
- {
- _M_buf_locale = __loc;
- _M_buf_locale_init = true;
- }
+ _M_buf_locale = __loc;
// NB this may require the reconversion of previously
// converted chars. This in turn may cause the reconstruction
@@ -486,6 +525,7 @@ namespace std
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
// NB: This syntax is a GNU extension.
+#if _GLIBCPP_EXTERN_TEMPLATE
extern template class basic_filebuf<char>;
extern template class basic_ifstream<char>;
extern template class basic_ofstream<char>;
@@ -497,6 +537,7 @@ namespace std
extern template class basic_ofstream<wchar_t>;
extern template class basic_fstream<wchar_t>;
#endif
+#endif
} // namespace std
#endif