Commit 07814743 by Benjamin Kosnik Committed by Benjamin Kosnik

std_fstream.h (filebuf::__file_type): Change to __basic_file<char>.


2002-02-07  Benjamin Kosnik  <bkoz@redhat.com>

	libstdc++/5286
	libstdc++/3860
	* include/std/std_fstream.h (filebuf::__file_type): Change to
	__basic_file<char>.
	(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<wchar_t>::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
parent e291c8db
2002-02-07 Benjamin Kosnik <bkoz@redhat.com>
libstdc++/5286
libstdc++/3860
* include/std/std_fstream.h (filebuf::__file_type): Change to
__basic_file<char>.
(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<wchar_t>::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 <bkoz@redhat.com>
Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
* include/bits/basic_ios.tcc (basic_ios::narrow): Add default value.
......
......@@ -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<typename _T>
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<typename _InternT, typename _ExternT>
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<intern_type>::copy(__cfixed + 1, __from, __size);
__cfrom = reinterpret_cast<char*>(__cfixed);
__conv = __iconv_adaptor(iconv, *__desc, &__cfrom,
&__flen, &__cto, &__tlen);
&__fbytes, &__cto, &__tbytes);
}
else
{
intern_type* __cfixed = const_cast<intern_type*>(__from);
__cfrom = reinterpret_cast<char*>(__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<size_t>(__from_end - __from))
if (__fbytes < __fmultiple * (__from_end - __from))
{
__from_next = reinterpret_cast<const intern_type*>(__cfrom);
__to_next = reinterpret_cast<extern_type*>(__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<typename _InternT, typename _ExternT>
bool
......
......@@ -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<char_type, char, __state_type> __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<char*>(_M_in_beg),
_M_buf_size);
__ilen = __elen;
}
else
{
_M_set_determinate(__size);
char* __buf = static_cast<char*>(__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
......@@ -402,6 +426,66 @@ namespace std
}
template<typename _CharT, typename _Traits>
void
basic_filebuf<_CharT, _Traits>::
_M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
streamsize& __elen, streamsize& __plen)
{
typedef codecvt<char_type, char, __state_type> __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<char*>(__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<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)
__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 _CharT, typename _Traits>
typename basic_filebuf<_CharT, _Traits>::int_type
basic_filebuf<_CharT, _Traits>::
_M_really_overflow(int_type __c)
......@@ -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<char_type*>(__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<char*>(__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<const char_type*&>(__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;
......
......@@ -64,7 +64,7 @@ namespace std
// Non-standard Types:
typedef basic_streambuf<char_type, traits_type> __streambuf_type;
typedef basic_filebuf<char_type, traits_type> __filebuf_type;
typedef __basic_file<char_type> __file_type;
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;
......@@ -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);
......
// 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<wchar_t, char, mbstate_t>::
do_encoding() const throw()
{ return 0; }
{ return sizeof(wchar_t); }
bool
codecvt<wchar_t, char, mbstate_t>::
......
// 2000-08-22 Benjamin Kosnik <bkoz@cygnus.com>
// 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() );
......
......@@ -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() );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment