Commit 47b90d6b by David Krauss Committed by Paolo Carlini

re PR libstdc++/45841 (r164529 cris-elf libstdc++ 27_io/basic_filebuf/seekoff/char/2-io.cc)

2010-10-05  David Krauss  <potswa@mac.com>

	PR libstdc++/45841
	* include/bits/fstream.h (basic_filebuf::underflow): Overflow
	success does not preclude returning failure.
	(basic_filebuf::pbackfail): Likewise.
	(basic_filebuf::xsputn): Fix indentation problem.
	(basic_filebuf::xsgetn): Likewise. Also, add similar overflow
	call to enable optimized case from write mode.
	* testsuite/27_io/basic_filebuf/underflow/char/45841.cc: New.
	* testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc: Likewise.

From-SVN: r165009
parent 94a9600c
2010-10-05 David Krauss <potswa@mac.com>
PR libstdc++/45841
* include/bits/fstream.h (basic_filebuf::underflow): Overflow
success does not preclude returning failure.
(basic_filebuf::pbackfail): Likewise.
(basic_filebuf::xsputn): Fix indentation problem.
(basic_filebuf::xsgetn): Likewise. Also, add similar overflow
call to enable optimized case from write mode.
* testsuite/27_io/basic_filebuf/underflow/char/45841.cc: New.
* testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc: Likewise.
2010-10-05 Jonathan Wakely <jwakely.gcc@gmail.com> 2010-10-05 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/bits/locale_facets_nonio.h (time_get::get_time): Doc typo. * include/bits/locale_facets_nonio.h (time_get::get_time): Doc typo.
......
...@@ -207,14 +207,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) ...@@ -207,14 +207,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const bool __testin = _M_mode & ios_base::in; const bool __testin = _M_mode & ios_base::in;
if (__testin) if (__testin)
{ {
if (_M_writing) if (_M_writing)
{ {
__ret = overflow(); if (overflow() == traits_type::eof())
if (__ret == traits_type::eof()) return __ret;
return __ret; _M_set_buffer(-1);
_M_set_buffer(-1); _M_writing = false;
_M_writing = false; }
}
// Check for pback madness, and if so switch back to the // Check for pback madness, and if so switch back to the
// normal buffers and jet outta here before expensive // normal buffers and jet outta here before expensive
// fileops happen... // fileops happen...
...@@ -367,14 +366,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) ...@@ -367,14 +366,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const bool __testin = _M_mode & ios_base::in; const bool __testin = _M_mode & ios_base::in;
if (__testin) if (__testin)
{ {
if (_M_writing) if (_M_writing)
{ {
__ret = overflow(); if (overflow() == traits_type::eof())
if (__ret == traits_type::eof()) return __ret;
return __ret; _M_set_buffer(-1);
_M_set_buffer(-1); _M_writing = false;
_M_writing = false; }
}
// Remember whether the pback buffer is active, otherwise below // Remember whether the pback buffer is active, otherwise below
// we may try to store in it a second char (libstdc++/9761). // we may try to store in it a second char (libstdc++/9761).
const bool __testpb = _M_pback_init; const bool __testpb = _M_pback_init;
...@@ -545,101 +543,108 @@ _GLIBCXX_BEGIN_NAMESPACE(std) ...@@ -545,101 +543,108 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
return __elen == __plen; return __elen == __plen;
} }
template<typename _CharT, typename _Traits> template<typename _CharT, typename _Traits>
streamsize streamsize
basic_filebuf<_CharT, _Traits>:: basic_filebuf<_CharT, _Traits>::
xsgetn(_CharT* __s, streamsize __n) xsgetn(_CharT* __s, streamsize __n)
{ {
// Clear out pback buffer before going on to the real deal... // Clear out pback buffer before going on to the real deal...
streamsize __ret = 0; streamsize __ret = 0;
if (_M_pback_init) if (_M_pback_init)
{ {
if (__n > 0 && this->gptr() == this->eback()) if (__n > 0 && this->gptr() == this->eback())
{ {
*__s++ = *this->gptr(); *__s++ = *this->gptr(); // emulate non-underflowing sbumpc
this->gbump(1); this->gbump(1);
__ret = 1; __ret = 1;
--__n; --__n;
} }
_M_destroy_pback(); _M_destroy_pback();
} }
else if (_M_writing)
// Optimization in the always_noconv() case, to be generalized in the {
// future: when __n > __buflen we read directly instead of using the if (overflow() == traits_type::eof())
// buffer repeatedly. return __ret;
const bool __testin = _M_mode & ios_base::in; _M_set_buffer(-1);
const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; _M_writing = false;
}
if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
&& __testin && !_M_writing) // Optimization in the always_noconv() case, to be generalized in the
{ // future: when __n > __buflen we read directly instead of using the
// First, copy the chars already present in the buffer. // buffer repeatedly.
const streamsize __avail = this->egptr() - this->gptr(); const bool __testin = _M_mode & ios_base::in;
if (__avail != 0) const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
{
if (__avail == 1) if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
*__s = *this->gptr(); && __testin)
else {
traits_type::copy(__s, this->gptr(), __avail); // First, copy the chars already present in the buffer.
__s += __avail; const streamsize __avail = this->egptr() - this->gptr();
this->gbump(__avail); if (__avail != 0)
__ret += __avail; {
__n -= __avail; if (__avail == 1)
} *__s = *this->gptr();
else
// Need to loop in case of short reads (relatively common traits_type::copy(__s, this->gptr(), __avail);
// with pipes). __s += __avail;
streamsize __len; this->gbump(__avail);
for (;;) __ret += __avail;
{ __n -= __avail;
__len = _M_file.xsgetn(reinterpret_cast<char*>(__s), }
__n);
if (__len == -1) // Need to loop in case of short reads (relatively common
__throw_ios_failure(__N("basic_filebuf::xsgetn " // with pipes).
"error reading the file")); streamsize __len;
if (__len == 0) for (;;)
break; {
__len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
__n -= __len; __n);
__ret += __len; if (__len == -1)
if (__n == 0) __throw_ios_failure(__N("basic_filebuf::xsgetn "
break; "error reading the file"));
if (__len == 0)
__s += __len; break;
}
__n -= __len;
if (__n == 0) __ret += __len;
{ if (__n == 0)
_M_set_buffer(0); break;
_M_reading = true;
} __s += __len;
else if (__len == 0) }
{
// If end of file is reached, set 'uncommitted' if (__n == 0)
// mode, thus allowing an immediate write without {
// an intervening seek. _M_set_buffer(0);
_M_set_buffer(-1); _M_reading = true;
_M_reading = false; }
} else if (__len == 0)
} {
else // If end of file is reached, set 'uncommitted'
__ret += __streambuf_type::xsgetn(__s, __n); // mode, thus allowing an immediate write without
// an intervening seek.
_M_set_buffer(-1);
_M_reading = false;
}
}
else
__ret += __streambuf_type::xsgetn(__s, __n);
return __ret;
}
return __ret; template<typename _CharT, typename _Traits>
} streamsize
basic_filebuf<_CharT, _Traits>::
template<typename _CharT, typename _Traits> xsputn(const _CharT* __s, streamsize __n)
streamsize {
basic_filebuf<_CharT, _Traits>:: streamsize __ret = 0;
xsputn(const _CharT* __s, streamsize __n) // Optimization in the always_noconv() case, to be generalized in the
{ // future: when __n is sufficiently large we write directly instead of
// Optimization in the always_noconv() case, to be generalized in the // using the buffer.
// future: when __n is sufficiently large we write directly instead of const bool __testout = _M_mode & ios_base::out;
// using the buffer. if (__check_facet(_M_codecvt).always_noconv()
streamsize __ret = 0; && __testout && !_M_reading)
const bool __testout = _M_mode & ios_base::out;
if (__check_facet(_M_codecvt).always_noconv()
&& __testout && !_M_reading)
{ {
// Measurement would reveal the best choice. // Measurement would reveal the best choice.
const streamsize __chunk = 1ul << 10; const streamsize __chunk = 1ul << 10;
...@@ -933,7 +938,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) ...@@ -933,7 +938,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
{ {
// External position corresponding to gptr(). // External position corresponding to gptr().
_M_ext_next = _M_ext_buf _M_ext_next = _M_ext_buf
+ _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next, + _M_codecvt->length(_M_state_last, _M_ext_buf,
_M_ext_next,
this->gptr() - this->eback()); this->gptr() - this->eback());
const streamsize __remainder = _M_ext_end - _M_ext_next; const streamsize __remainder = _M_ext_end - _M_ext_next;
if (__remainder) if (__remainder)
......
// Copyright (C) 2010 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-require-fileio "" }
#include <fstream>
#include <testsuite_hooks.h>
void test01()
{
bool test __attribute__((unused)) = true;
using namespace std;
filebuf fb_in_out;
fb_in_out.open("tmp_underflow.tst", ios::in | ios::out | ios::trunc);
VERIFY( fb_in_out.sputc('x') == 'x' );
VERIFY( fb_in_out.sgetc() == filebuf::traits_type::eof() );
fb_in_out.close();
}
int main()
{
test01();
return 0;
}
// Copyright (C) 2010 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-require-fileio "" }
#include <fstream>
#include <testsuite_hooks.h>
void test01()
{
bool test __attribute__((unused)) = true;
using namespace std;
wfilebuf fb_in_out;
fb_in_out.open("tmp_underflow.tst", ios::in | ios::out | ios::trunc);
VERIFY( fb_in_out.sputc(L'x') == L'x' );
VERIFY( fb_in_out.sgetc() == wfilebuf::traits_type::eof() );
fb_in_out.close();
}
int main()
{
test01();
return 0;
}
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