From: Benjamin Kosnik Date: Fri, 8 Feb 2002 01:34:41 +0000 (+0000) Subject: std_fstream.h (filebuf::__file_type): Change to __basic_file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=07814743cf9b934c94d540a7820a3683abacfb38;p=gcc.git std_fstream.h (filebuf::__file_type): Change to __basic_file. 2002-02-07 Benjamin Kosnik libstdc++/5286 libstdc++/3860 * include/std/std_fstream.h (filebuf::__file_type): Change to __basic_file. (filebuf::_M_convert_to_external): Declare. * include/bits/fstream.tcc (filebuf::_M_convert_to_external): Define codecvt bits for wide streams. (filebuf::_M_really_overflow): Use it. (filebuf::underflow): Use codecvt. * config/locale/codecvt_specializations_ieee_1003.1-200x.h: (codecvt<__enc_traits>::do_out): Deal with partial. (codecvt<__enc_traits>::do_encoding): Return something useful. * src/codecvt.cc (codecvt::do_encoding): Return sizeof wchar_t. * testsuite/22_locale/codecvt_members_unicode_char.cc (test01): Change expected encoding output. (test02): Same. * testsuite/22_locale/codecvt_members_wchar_t_char.cc (test01): Same. (test02): Same. From-SVN: r49601 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d38dca4a57d..485d5d0ae27 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2002-02-07 Benjamin Kosnik + + libstdc++/5286 + libstdc++/3860 + * include/std/std_fstream.h (filebuf::__file_type): Change to + __basic_file. + (filebuf::_M_convert_to_external): Declare. + * include/bits/fstream.tcc (filebuf::_M_convert_to_external): Define + codecvt bits for wide streams. + (filebuf::_M_really_overflow): Use it. + (filebuf::underflow): Use codecvt. + * config/locale/codecvt_specializations_ieee_1003.1-200x.h: + (codecvt<__enc_traits>::do_out): Deal with partial. + (codecvt<__enc_traits>::do_encoding): Return something useful. + * src/codecvt.cc (codecvt::do_encoding): Return sizeof + wchar_t. + * testsuite/22_locale/codecvt_members_unicode_char.cc (test01): + Change expected encoding output. + (test02): Same. + * testsuite/22_locale/codecvt_members_wchar_t_char.cc (test01): Same. + (test02): Same. + 2002-02-07 Benjamin Kosnik Wolfgang Bangerth diff --git a/libstdc++-v3/config/locale/codecvt_specializations_ieee_1003.1-200x.h b/libstdc++-v3/config/locale/codecvt_specializations_ieee_1003.1-200x.h index 5cacffb81f8..8cac2995d48 100644 --- a/libstdc++-v3/config/locale/codecvt_specializations_ieee_1003.1-200x.h +++ b/libstdc++-v3/config/locale/codecvt_specializations_ieee_1003.1-200x.h @@ -263,14 +263,14 @@ // This adaptor works around the signature problems of the second // argument to iconv(): SUSv2 and others use 'const char**', but glibc 2.2 - // uses 'char**', which is what the standard is (apparently) due to use - // in the future. Using this adaptor, g++ will do the work for us. + // uses 'char**', which matches the POSIX 1003.1-2001 standard. + // Using this adaptor, g++ will do the work for us. template inline size_t - __iconv_adaptor(size_t(*iconv_func)(iconv_t, _T, size_t*, char**, size_t*), - iconv_t cd, char** inbuf, size_t* inbytesleft, - char** outbuf, size_t* outbytesleft) - { return iconv_func(cd, (_T)inbuf, inbytesleft, outbuf, outbytesleft); } + __iconv_adaptor(size_t(*__func)(iconv_t, _T, size_t*, char**, size_t*), + iconv_t __cd, char** __inbuf, size_t* __inbytes, + char** __outbuf, size_t* __outbytes) + { return __func(__cd, (_T)__inbuf, __inbytes, __outbuf, __outbytes); } template codecvt_base::result @@ -286,9 +286,9 @@ typedef state_type::__desc_type __desc_type; const __desc_type* __desc = __state._M_get_out_descriptor(); const size_t __fmultiple = sizeof(intern_type) / sizeof(char); - size_t __flen = __fmultiple * (__from_end - __from); + size_t __fbytes = __fmultiple * (__from_end - __from); const size_t __tmultiple = sizeof(extern_type) / sizeof(char); - size_t __tlen = __tmultiple * (__to_end - __to); + size_t __tbytes = __tmultiple * (__to_end - __to); // Argument list for iconv specifies a byte sequence. Thus, // all to/from arrays must be brutally casted to char*. @@ -310,14 +310,14 @@ char_traits::copy(__cfixed + 1, __from, __size); __cfrom = reinterpret_cast(__cfixed); __conv = __iconv_adaptor(iconv, *__desc, &__cfrom, - &__flen, &__cto, &__tlen); + &__fbytes, &__cto, &__tbytes); } else { intern_type* __cfixed = const_cast(__from); __cfrom = reinterpret_cast(__cfixed); - __conv = __iconv_adaptor(iconv, *__desc, &__cfrom, - &__flen, &__cto, &__tlen); + __conv = __iconv_adaptor(iconv, *__desc, &__cfrom, &__fbytes, + &__cto, &__tbytes); } if (__conv != size_t(-1)) @@ -328,7 +328,7 @@ } else { - if (__flen < static_cast(__from_end - __from)) + if (__fbytes < __fmultiple * (__from_end - __from)) { __from_next = reinterpret_cast(__cfrom); __to_next = reinterpret_cast(__cto); @@ -451,7 +451,12 @@ int codecvt<_InternT, _ExternT, __enc_traits>:: do_encoding() const throw() - { return 0; } + { + int __ret = 0; + if (sizeof(_ExternT) <= sizeof(_InternT)) + __ret = sizeof(_InternT)/sizeof(_ExternT); + return __ret; + } template bool diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index 85a0e085e3f..4ef0bcccecc 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -246,7 +246,6 @@ namespace std bool __testin = _M_mode & ios_base::in; bool __testout = _M_mode & ios_base::out; - // XXX Should re-enable codecvt bits disabled after 2.90.8. if (__testin) { // Check for pback madness, and if so swich back to the @@ -259,10 +258,10 @@ namespace std return traits_type::to_int_type(*_M_in_cur); } - bool __testget = _M_in_cur && _M_in_beg < _M_in_cur; - bool __testinit = _M_is_indeterminate(); // Sync internal and external buffers. // NB: __testget -> __testput as _M_buf_unified here. + bool __testget = _M_in_cur && _M_in_beg < _M_in_cur; + bool __testinit = _M_is_indeterminate(); if (__testget) { if (__testout) @@ -278,26 +277,51 @@ namespace std if (__testinit || __testget) { - // Assume buffered case, need to refill internal buffers. - streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size); - if (0 < __size) + typedef codecvt __codecvt_type; + const locale __loc = this->getloc(); + const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); + + streamsize __elen = 0; + streamsize __ilen = 0; + if (__cvt.always_noconv()) + { + __elen = _M_file->xsgetn(reinterpret_cast(_M_in_beg), + _M_buf_size); + __ilen = __elen; + } + else { - _M_set_determinate(__size); + char* __buf = static_cast(__builtin_alloca(_M_buf_size)); + __elen = _M_file->xsgetn(__buf, _M_buf_size); + + 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); + if (__r == codecvt_base::ok) + __ilen = __iend - _M_in_beg; + else + { + // Unwind. + __ilen = 0; + _M_file->seekoff(-__elen, ios_base::cur, ios_base::in); + } + } + + if (0 < __ilen) + { + _M_set_determinate(__ilen); if (__testout) _M_out_cur = _M_in_cur; __ret = traits_type::to_int_type(*_M_in_cur); #if _GLIBCPP_AVOID_FSEEK - if (__size == 1) + if (__elen == 1) _M_file->sys_ungetc(*_M_in_cur); else { #endif - streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, - ios_base::in); - if (__p == -1) - { - // XXX Something is wrong, do error checking. - } + _M_file->seekoff(-__elen, ios_base::cur, ios_base::in); #if _GLIBCPP_AVOID_FSEEK } #endif @@ -401,6 +425,66 @@ namespace std return __ret; } + template + void + basic_filebuf<_CharT, _Traits>:: + _M_convert_to_external(_CharT* __ibuf, streamsize __ilen, + streamsize& __elen, streamsize& __plen) + { + typedef codecvt __codecvt_type; + const locale __loc = this->getloc(); + const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); + + if (__cvt.always_noconv() && __ilen) + { + __elen += _M_file->xsputn(reinterpret_cast(__ibuf), __ilen); + __plen += __ilen; + } + else + { + // Worst-case number of external bytes needed. + int __ext_multiplier = __cvt.encoding(); + if (__ext_multiplier == -1 || __ext_multiplier == 0) + __ext_multiplier = sizeof(char_type); + streamsize __blen = __ilen * __ext_multiplier; + char* __buf = static_cast(__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) + __blen = __bend - __buf; + // Result == error + else + __blen = 0; + + if (__blen) + { + __elen += _M_file->xsputn(__buf, __blen); + __plen += __blen; + } + + // Try once more for partial conversions. + if (__r == codecvt_base::partial) + { + const char_type* __iresume = __iend; + streamsize __rlen = _M_out_end - __iend; + __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) + { + __elen += _M_file->xsputn(__buf, __rlen); + __plen += __rlen; + } + } + } + } + template typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>:: @@ -412,68 +496,31 @@ namespace std if (__testput || __testunbuffered) { -#if 1 - int __plen = _M_out_end - _M_out_beg; - streamsize __len = 0; - - if (__plen) - __len = _M_file->xsputn(_M_out_beg, __plen); - - if (__c != traits_type::eof()) + // Sizes of external and pending output. + streamsize __elen = 0; + streamsize __plen = 0; + + // Convert internal buffer to external representation, output. + // NB: In the unbuffered case, no internal buffer exists. + if (!__testunbuffered) + _M_convert_to_external(_M_out_beg, _M_out_end - _M_out_beg, + __elen, __plen); + + // Convert pending sequence to external representation, output. + if (!traits_type::eq_int_type(__c, traits_type::eof())) { - char_type __pending = traits_type::to_char_type(__c); - __len += _M_file->xsputn(&__pending, 1); - ++__plen; + char_type __pending = traits_type::to_char_type(__c); + _M_convert_to_external(&__pending, 1, __elen, __plen); } + // Last, sync internal and external buffers. // NB: Need this so that external byte sequence reflects - // internal buffer. - if (__len == __plen && !_M_file->sync()) + // internal buffer plus pending sequence. + if (__elen == __plen && !_M_file->sync()) { _M_set_indeterminate(); __ret = traits_type::not_eof(__c); } -#else - // Part one: Allocate temporary conversion buffer on - // stack. Convert internal buffer plus __c (ie, - // "pending sequence") to temporary conversion buffer. - int __plen = _M_out_end - _M_out_beg; - char_type* __pbuf = static_cast(__builtin_alloca(sizeof(char_type) * __plen + 1)); - traits_type::copy(__pbuf, this->pbase(), __plen); - if (!__testeof) - { - __pbuf[__plen] = traits_type::to_char_type(__c); - ++__plen; - } - - char_type* __pend; - char* __conv_buf = static_cast(__builtin_alloca(__plen)); - char* __conv_end; - _M_state_beg = _M_state_cur; - - __res_type __r = _M_fcvt->out(_M_state_cur, - __pbuf, __pbuf + __plen, - const_cast(__pend), - __conv_buf, __conv_buf + __plen, - __conv_end); - - // Part two: (Re)spill converted "pending sequence" - // contents (now in temporary conversion buffer) to - // external buffer (_M_file->_IO_*) using - // _M_file->sys_write(), and do error (minimal) checking. - if (__r != codecvt_base::error) - { - streamsize __len = _M_file->xsputn(__conv_buf, __plen); - // NB: Need this so that external byte sequence reflects - // internal buffer. - _M_file->sync(); // XXX error check - if (__len == __plen) - { - _M_set_indeterminate(); - __ret = traits_type::not_eof(__c); - } - } -#endif } _M_last_overflowed = true; return __ret; diff --git a/libstdc++-v3/include/std/std_fstream.h b/libstdc++-v3/include/std/std_fstream.h index 4483e3f4899..92839753bd6 100644 --- a/libstdc++-v3/include/std/std_fstream.h +++ b/libstdc++-v3/include/std/std_fstream.h @@ -64,7 +64,7 @@ namespace std // Non-standard Types: typedef basic_streambuf __streambuf_type; typedef basic_filebuf __filebuf_type; - typedef __basic_file __file_type; + typedef __basic_file __file_type; typedef typename traits_type::state_type __state_type; typedef codecvt __codecvt_type; typedef typename __codecvt_type::result __res_type; @@ -111,13 +111,13 @@ namespace std // Members: bool - is_open(void) const { return _M_file ? _M_file->is_open() : false; } + is_open() const { return _M_file ? _M_file->is_open() : false; } __filebuf_type* open(const char* __s, ios_base::openmode __mode); __filebuf_type* - close(void); + close(); protected: void @@ -135,14 +135,14 @@ namespace std // Overridden virtual functions: virtual streamsize - showmanyc(void); + showmanyc(); // Stroustrup, 1998, p. 628 // underflow() and uflow() functions are called to get the next // charater from the real input source when the buffer is empty. // Buffered input uses underflow() virtual int_type - underflow(void); + underflow(); virtual int_type pbackfail(int_type __c = _Traits::eof()); @@ -168,6 +168,11 @@ namespace std int_type _M_really_overflow(int_type __c = _Traits::eof()); + // Convert internal byte sequence to external, char-based + // sequence via codecvt. + void + _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&); + virtual __streambuf_type* setbuf(char_type* __s, streamsize __n); @@ -180,7 +185,7 @@ namespace std ios_base::openmode __mode = ios_base::in | ios_base::out); virtual int - sync(void) + sync() { bool __testput = _M_out_cur && _M_out_beg < _M_out_end; @@ -296,7 +301,7 @@ namespace std { return const_cast<__filebuf_type*>(&_M_filebuf); } bool - is_open(void) { return _M_filebuf.is_open(); } + is_open() { return _M_filebuf.is_open(); } void open(const char* __s, ios_base::openmode __mode = ios_base::in) @@ -307,7 +312,7 @@ namespace std /** Close the file. */ void - close(void) + close() { if (!_M_filebuf.close()) this->setstate(ios_base::failbit); @@ -370,7 +375,7 @@ namespace std * @return Pointer to basic_filebuf. */ __filebuf_type* - rdbuf(void) const + rdbuf() const { return const_cast<__filebuf_type*>(&_M_filebuf); } /** @@ -378,7 +383,7 @@ namespace std * @return True if stream is open. */ bool - is_open(void) { return _M_filebuf.is_open(); } + is_open() { return _M_filebuf.is_open(); } /** * @brief Specify a file to open for output. @@ -398,7 +403,7 @@ namespace std /** Close the file stream. */ void - close(void) + close() { if (!_M_filebuf.close()) this->setstate(ios_base::failbit); @@ -462,7 +467,7 @@ namespace std * @return Pointer to basic_filebuf. */ __filebuf_type* - rdbuf(void) const + rdbuf() const { return const_cast<__filebuf_type*>(&_M_filebuf); } /** @@ -470,7 +475,7 @@ namespace std * @return True if stream is open. */ bool - is_open(void) { return _M_filebuf.is_open(); } + is_open() { return _M_filebuf.is_open(); } /** * @brief Specify a file to open for input and/or output. @@ -490,7 +495,7 @@ namespace std /** Close the file stream. */ void - close(void) + close() { if (!_M_filebuf.close()) setstate(ios_base::failbit); diff --git a/libstdc++-v3/src/codecvt.cc b/libstdc++-v3/src/codecvt.cc index c5474c6c7a7..032667e3f13 100644 --- a/libstdc++-v3/src/codecvt.cc +++ b/libstdc++-v3/src/codecvt.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2000 Free Software Foundation, Inc. +// Copyright (C) 2000, 2002 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 @@ -181,7 +181,7 @@ namespace std int codecvt:: do_encoding() const throw() - { return 0; } + { return sizeof(wchar_t); } bool codecvt:: diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc b/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc index 2a135f67df1..026e6091397 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc +++ b/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc @@ -1,6 +1,6 @@ // 2000-08-22 Benjamin Kosnik -// Copyright (C) 2000, 2001 Free Software Foundation +// Copyright (C) 2000, 2001, 2002 Free Software Foundation // // 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 @@ -124,7 +124,7 @@ void test01() VERIFY( eto_next == e_arr ); int i = cvt.encoding(); - VERIFY( i == 0 ); + VERIFY( i == 2 ); // Target-dependent. VERIFY( !cvt.always_noconv() ); @@ -210,7 +210,7 @@ void test02() VERIFY( eto_next == e_arr ); int i = cvt.encoding(); - VERIFY( i == 0 ); + VERIFY( i == 2 ); // Target-dependent. VERIFY( !cvt.always_noconv() ); diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc b/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc index 9ff83e9069a..45655b7a601 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc +++ b/libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc @@ -95,7 +95,7 @@ void test01() VERIFY( eto_next == e_arr ); int i = cvt->encoding(); - VERIFY( i == 0 ); + VERIFY( i == 4 ); // Target-dependent. VERIFY( !cvt->always_noconv() );