+2003-04-25 Benjamin Kosnik <bkoz@redhat.com>
+
+ PR libstdc++/10132
+ * include/std/std_fstream.h (basic_filebuf::is_open): Add throw()
+ exception specifications.
+ (basic_filebuf::close): Same.
+ (basic_filebuf::_M_pback_destroy): Same.
+ (basic_filebuf::_M_destroy_internal_buffer): Same.
+ (basic_filebuf): Remove __res_type typedef.
+ * src/fstream.cc: Same.
+ * include/bits/fstream.tcc
+ (basic_filebuf::_M_convert_to_external): Simplify.
+ (basic_filebuf::seekoff): Use has_facet before use_facet.
+ (basic_filebuf::close): Add exception specification of throw().
+ * testsuite/27_io/basic_filebuf/cons: New.
+ * testsuite/27_io/basic_filebuf/cons/wchar_t: New.
+ * testsuite/27_io/basic_filebuf/cons/wchar_t/10132-1.cc: New.
+ * testsuite/27_io/basic_filebuf/seekoff/10132-2.cc: New.
+ * testsuite/27_io/basic_filebuf/seekpos/10132-3.cc: New.
+
2003-04-25 Benjamin Kosnik <bkoz@redhat.com>
* include/bits/locale_classes.h
template<typename _CharT, typename _Traits>
void
basic_filebuf<_CharT, _Traits>::
- _M_destroy_internal_buffer()
+ _M_destroy_internal_buffer() throw()
{
if (_M_buf_allocated)
{
template<typename _CharT, typename _Traits>
typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
basic_filebuf<_CharT, _Traits>::
- close()
+ close() throw()
{
__filebuf_type* __ret = NULL;
if (this->is_open())
{
bool __testfail = false;
- const int_type __eof = traits_type::eof();
- const bool __testput = this->_M_out_beg < this->_M_out_lim;
+ try
+ {
+ const int_type __eof = traits_type::eof();
+ const bool __testput = this->_M_out_beg < this->_M_out_lim;
- if (__testput
- && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
- __testfail = true;
+ if (__testput
+ && traits_type::eq_int_type(_M_really_overflow(__eof),
+ __eof))
+ __testfail = true;
#if 0
- // XXX not done
- if (_M_last_overflowed)
+ // XXX not done
+ if (_M_last_overflowed)
+ {
+ _M_output_unshift();
+ _M_really_overflow(__eof);
+ }
+#endif
+ }
+ catch(...)
{
- _M_output_unshift();
- _M_really_overflow(__eof);
+ __testfail = true;
}
-#endif
-
+
// NB: Do this here so that re-opened filebufs will be cool...
this->_M_mode = ios_base::openmode(0);
_M_destroy_internal_buffer();
_M_pback_destroy();
-
+
if (!_M_file.close())
__testfail = true;
if (!__testfail)
__ret = this;
}
- _M_last_overflowed = false;
+ _M_last_overflowed = false;
return __ret;
}
const bool __testin = this->_M_mode & ios_base::in;
const locale __loc = this->getloc();
const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
- // Sync with stdio.
- const bool __sync = this->_M_buf_size <= 1;
+ const bool __testsync = this->_M_buf_size <= 1;
if (__testin && this->is_open())
{
// For a stateful encoding (-1) the pending sequence might be just
// shift and unshift prefixes with no actual character.
if (__cvt.encoding() >= 0)
- __ret += _M_file.showmanyc_helper(__sync) / __cvt.max_length();
+ __ret += _M_file.showmanyc_helper(__testsync) / __cvt.max_length();
}
_M_last_overflowed = false;
_M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
streamsize& __elen, streamsize& __plen)
{
+ const bool __testsync = this->_M_buf_size <= 1;
const locale __loc = this->getloc();
const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
- // Sync with stdio.
- const bool __sync = this->_M_buf_size <= 1;
if (__cvt.always_noconv() && __ilen)
{
- __elen +=
- _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen, __sync);
+ __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf),
+ __ilen, __testsync);
__plen += __ilen;
}
else
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);
-
+ 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;
- // Similarly to the always_noconv case above.
else if (__r == codecvt_base::noconv)
{
+ // Same as the always_noconv case above.
__buf = reinterpret_cast<char*>(__ibuf);
__blen = __ilen;
}
- // Result == error
- else
- __blen = 0;
+ else
+ {
+ // Result == error
+ __blen = 0;
+ }
if (__blen)
{
- __elen += _M_file.xsputn(__buf, __blen, __sync);
+ __elen += _M_file.xsputn(__buf, __blen, __testsync);
__plen += __blen;
}
-
+
// Try once more for partial conversions.
if (__r == codecvt_base::partial)
{
__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;
- // Signal to the caller (_M_really_overflow) that
- // codecvt::out eventually failed.
- __elen = 0;
- }
- if (__rlen)
{
- __elen += _M_file.xsputn(__buf, __rlen, __sync);
+ __rlen = __bend - __buf;
+ __elen += _M_file.xsputn(__buf, __rlen, __testsync);
__plen += __rlen;
}
}
int_type __ret = traits_type::eof();
const bool __testput = this->_M_out_beg < this->_M_out_lim;
const bool __testunbuffered = _M_file.is_open() && !this->_M_buf_size;
- // Sync with stdio.
- const bool __sync = this->_M_buf_size <= 1;
+ const bool __testsync = this->_M_buf_size <= 1;
if (__testput || __testunbuffered)
{
if (_M_filepos && _M_filepos != this->_M_out_beg)
{
off_type __off = this->_M_out_beg - _M_filepos;
- _M_file.seekoff(__off, ios_base::cur, __sync);
+ _M_file.seekoff(__off, ios_base::cur, __testsync);
}
// Convert internal buffer to external representation, output.
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).
+ // User code must flush when switching modes (thus
+ // don't sync).
if (__elen == __plen && __elen)
{
_M_set_indeterminate();
pos_type __ret = pos_type(off_type(-1));
const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
- // Sync with stdio.
- const bool __sync = this->_M_buf_size <= 1;
+ const bool __testsync = this->_M_buf_size <= 1;
- // Should probably do has_facet checks here.
- int __width = use_facet<__codecvt_type>(this->_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;
- const bool __testfail = __off != 0 && __width <= 0;
-
+
+ const bool __testfail = __off != 0 && __width <= 0;
if (this->is_open() && !__testfail && (__testin || __testout))
{
// Ditch any pback buffers to avoid confusion.
__computed_off += this->_M_in_cur - _M_filepos;
// Return pos_type(off_type(-1)) in case of failure.
- __ret = _M_file.seekoff(__computed_off, __way, __sync, __mode);
+ __ret = _M_file.seekoff(__computed_off, __way, __testsync,
+ __mode);
_M_set_indeterminate();
}
// NB: Need to do this in case _M_file in indeterminate
// state, ie _M_file._offset == -1
else
{
- pos_type __tmp =
- _M_file.seekoff(__off, ios_base::cur,
- __sync, __mode);
+ pos_type __tmp = _M_file.seekoff(__off, ios_base::cur,
+ __testsync, __mode);
if (__tmp >= 0)
{
// Seek successful.
__ret = __tmp;
- __ret +=
- std::max(this->_M_out_cur, this->_M_in_cur) - _M_filepos;
+ __ret += std::max(this->_M_out_cur, this->_M_in_cur)
+ - _M_filepos;
}
}
}
typedef __basic_file<char> __file_type;
typedef typename traits_type::state_type __state_type;
typedef codecvt<char_type, char, __state_type> __codecvt_type;
- typedef typename __codecvt_type::result __res_type;
typedef ctype<char_type> __ctype_type;
//@}
// Assumptions:
// The pback buffer has only moved forward.
void
- _M_pback_destroy()
+ _M_pback_destroy() throw()
{
if (_M_pback_init)
{
* @brief Returns true if the external file is open.
*/
bool
- is_open() const { return _M_file.is_open(); }
+ is_open() const throw() { return _M_file.is_open(); }
/**
* @brief Opens an external file.
* If any operations fail, this function also fails.
*/
__filebuf_type*
- close();
+ close() throw();
protected:
/**
* @endif
*/
void
- _M_destroy_internal_buffer();
+ _M_destroy_internal_buffer() throw();
// [27.8.1.4] overridden virtual functions
// [documentation is inherited]
int_type __ret = traits_type::eof();
const bool __testin = _M_mode & ios_base::in;
const bool __testout = _M_mode & ios_base::out;
- // Sync with stdio.
- const bool __sync = _M_buf_size <= 1;
+ const bool __testsync = _M_buf_size <= 1;
if (__testin)
{
_M_really_overflow();
else if (_M_in_cur != _M_filepos)
_M_file.seekoff(_M_in_cur - _M_filepos,
- ios_base::cur, __sync, ios_base::in);
+ ios_base::cur, __testsync, ios_base::in);
}
if (__testinit || __testget)
streamsize __ilen = 0;
__elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
- _M_buf_size, __sync);
+ _M_buf_size, __testsync);
__ilen = __elen;
if (0 < __ilen)
__ret = traits_type::to_int_type(*_M_in_cur);
if (__bump)
_M_in_cur_move(1);
- else if (__sync)
+ else if (__testsync)
{
// If we are synced with stdio, we have to unget the
// character we just read so that the file pointer
int_type __ret = traits_type::eof();
const bool __testin = _M_mode & ios_base::in;
const bool __testout = _M_mode & ios_base::out;
- // Sync with stdio.
- const bool __sync = _M_buf_size <= 1;
+ const bool __testsync = _M_buf_size <= 1;
if (__testin)
{
_M_really_overflow();
else if (_M_in_cur != _M_filepos)
_M_file.seekoff(_M_in_cur - _M_filepos,
- ios_base::cur, __sync, ios_base::in);
+ ios_base::cur, __testsync, ios_base::in);
}
if (__testinit || __testget)
{
- const locale __loc = this->getloc();
- const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
-
streamsize __elen = 0;
streamsize __ilen = 0;
+ const locale __loc = this->getloc();
+ const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
if (__cvt.always_noconv())
{
__elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
- _M_buf_size, __sync);
+ _M_buf_size, __testsync);
__ilen = __elen;
}
else
{
char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
- __elen = _M_file.xsgetn(__buf, _M_buf_size, __sync);
-
+ __elen = _M_file.xsgetn(__buf, _M_buf_size, __testsync);
+
const char* __eend;
char_type* __iend;
- __res_type __r = __cvt.in(_M_state_cur, __buf,
- __buf + __elen, __eend, _M_in_beg,
- _M_in_beg + _M_buf_size, __iend);
+ codecvt_base::result __r;
+ __r = __cvt.in(_M_state_cur, __buf, __buf + __elen, __eend,
+ _M_in_beg, _M_in_beg + _M_buf_size, __iend);
if (__r == codecvt_base::ok)
__ilen = __iend - _M_in_beg;
else
{
// Unwind.
__ilen = 0;
- _M_file.seekoff(-__elen, ios_base::cur, __sync, ios_base::in);
+ _M_file.seekoff(-__elen, ios_base::cur, __testsync,
+ ios_base::in);
}
}
__ret = traits_type::to_int_type(*_M_in_cur);
if (__bump)
_M_in_cur_move(1);
- else if (__sync)
+ else if (__testsync)
{
// If we are synced with stdio, we have to unget the
// character we just read so that the file pointer
--- /dev/null
+// 2003-04-24 Pétur Runólfsson <peturr02@ru.is>
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+#include <fstream>
+#include <locale>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+class Cvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+protected:
+ virtual std::codecvt_base::result
+ do_out(std::mbstate_t&, const wchar_t*, const wchar_t*, const wchar_t*&,
+ char*, char*, char*&) const
+ { throw std::runtime_error("codecvt failed"); }
+};
+
+int main()
+{
+ using namespace std;
+ bool test = true;
+
+ locale loc = locale(locale::classic(), new Cvt);
+ wfilebuf* fb = new wfilebuf;
+ fb->pubimbue(loc);
+ fb->open("tmp_10132", ios_base::out);
+ fb->sputc(L'a');
+
+ try
+ {
+ delete fb;
+ }
+ catch(exception& obj)
+ {
+ VERIFY( false );
+ }
+ return 0;
+}
--- /dev/null
+// 2003-04-24 bkoz
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.1 - Template class basic_filebuf
+// NB: This file is for testing basic_filebuf with NO OTHER INCLUDES.
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+// libstdc++/10132, add on
+class gnu_char_type
+{
+ unsigned long character;
+public:
+ // operator ==
+ bool
+ operator==(const gnu_char_type& __lhs)
+ { return character == __lhs.character; }
+
+ // operator <
+ bool
+ operator<(const gnu_char_type& __lhs)
+ { return character < __lhs.character; }
+
+ // default ctor
+ gnu_char_type() { }
+
+ // to_char_type
+ gnu_char_type(const unsigned long& __l) : character(__l) { }
+
+ // to_int_type
+ operator unsigned long() const { return character; }
+};
+
+// char_traits specialization
+struct gnu_char_traits
+{
+ typedef gnu_char_type char_type;
+ typedef long int_type;
+ typedef long pos_type;
+ typedef unsigned long off_type;
+ typedef long state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2) { }
+
+ static bool
+ eq(const char_type& __c1, const char_type& __c2) { return true; }
+
+ static bool
+ lt(const char_type& __c1, const char_type& __c2) { return true; }
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n)
+ { return 0; }
+
+ static size_t
+ length(const char_type* __s) { return 0; }
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ { return __s; }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ { return __s1; }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ { return __s1; }
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ { return __s; }
+
+ static char_type
+ to_char_type(const int_type& __c)
+ { return char_type(); }
+
+ static int_type
+ to_int_type(const char_type& __c)
+ { return int_type(); }
+
+ static bool
+ eq_int_type(const int_type& __c1, const int_type& __c2)
+ { return true; }
+
+ static int_type
+ eof()
+ { return int_type(); }
+
+ static int_type
+ not_eof(const int_type& __c)
+ { return int_type(); }
+};
+
+void test07()
+{
+ bool test = true;
+ typedef std::basic_filebuf<gnu_char_type, gnu_char_traits> gnu_filebuf;
+
+ try
+ {
+ // Need codecvt facet for width argument in seekoff.
+ gnu_filebuf obj;
+ obj.pubseekoff(2, std::ios_base::beg);
+ }
+ catch(std::exception& obj)
+ {
+ test = false;
+ VERIFY( test );
+ }
+}
+
+#if !__GXX_WEAK__
+// Explicitly instantiate for systems with no COMDAT or weak support.
+template
+ std::basic_filebuf<gnu_char_type>::int_type
+ std::basic_filebuf<gnu_char_type>::_S_pback_size;
+#endif
+
+int main()
+{
+ test07();
+ return 0;
+}
+
+
+
+// more surf!!!
--- /dev/null
+// 2003-04-24 bkoz
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 27.8.1.1 - Template class basic_filebuf
+// NB: This file is for testing basic_filebuf with NO OTHER INCLUDES.
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+// libstdc++/10132, add on
+class gnu_char_type
+{
+ unsigned long character;
+public:
+ // operator ==
+ bool
+ operator==(const gnu_char_type& __lhs)
+ { return character == __lhs.character; }
+
+ // operator <
+ bool
+ operator<(const gnu_char_type& __lhs)
+ { return character < __lhs.character; }
+
+ // default ctor
+ gnu_char_type() { }
+
+ // to_char_type
+ gnu_char_type(const unsigned long& __l) : character(__l) { }
+
+ // to_int_type
+ operator unsigned long() const { return character; }
+};
+
+// char_traits specialization
+struct gnu_char_traits
+{
+ typedef gnu_char_type char_type;
+ typedef long int_type;
+ typedef long pos_type;
+ typedef unsigned long off_type;
+ typedef long state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2) { }
+
+ static bool
+ eq(const char_type& __c1, const char_type& __c2) { return true; }
+
+ static bool
+ lt(const char_type& __c1, const char_type& __c2) { return true; }
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n)
+ { return 0; }
+
+ static size_t
+ length(const char_type* __s) { return 0; }
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a)
+ { return __s; }
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n)
+ { return __s1; }
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n)
+ { return __s1; }
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a)
+ { return __s; }
+
+ static char_type
+ to_char_type(const int_type& __c)
+ { return char_type(); }
+
+ static int_type
+ to_int_type(const char_type& __c)
+ { return int_type(); }
+
+ static bool
+ eq_int_type(const int_type& __c1, const int_type& __c2)
+ { return true; }
+
+ static int_type
+ eof()
+ { return int_type(); }
+
+ static int_type
+ not_eof(const int_type& __c)
+ { return int_type(); }
+};
+
+void test07()
+{
+ bool test = true;
+ typedef std::basic_filebuf<gnu_char_type, gnu_char_traits> gnu_filebuf;
+
+ try
+ {
+ // Need codecvt facet for width argument in seekpos.
+ gnu_filebuf obj;
+ obj.pubseekpos(0);
+ }
+ catch(std::exception& obj)
+ {
+ test = false;
+ VERIFY( test );
+ }
+}
+
+#if !__GXX_WEAK__
+// Explicitly instantiate for systems with no COMDAT or weak support.
+template
+ std::basic_filebuf<gnu_char_type>::int_type
+ std::basic_filebuf<gnu_char_type>::_S_pback_size;
+#endif
+
+int main()
+{
+ test07();
+ return 0;
+}
+
+
+
+// more surf!!!