summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-06 00:17:28 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-06 00:17:28 +0000
commit3611e17c9eab6e6ba9f68140748086621b6c9484 (patch)
tree18fe427c552ba9001525397586833ca0ed3484e3 /libstdc++-v3
parente4a854435652a93427c5e51a37127b033c97a465 (diff)
downloadgcc-3611e17c9eab6e6ba9f68140748086621b6c9484.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165009 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog12
-rw-r--r--libstdc++-v3/include/bits/fstream.tcc228
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/45841.cc41
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc41
4 files changed, 211 insertions, 111 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index ef4ad4dc515..94aa9f1aa80 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,15 @@
+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>
* include/bits/locale_facets_nonio.h (time_get::get_time): Doc typo.
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index 2f661ebd23e..d32de8f8d37 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -207,14 +207,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const bool __testin = _M_mode & ios_base::in;
if (__testin)
{
- if (_M_writing)
- {
- __ret = overflow();
- if (__ret == traits_type::eof())
- return __ret;
- _M_set_buffer(-1);
- _M_writing = false;
- }
+ if (_M_writing)
+ {
+ if (overflow() == traits_type::eof())
+ return __ret;
+ _M_set_buffer(-1);
+ _M_writing = false;
+ }
// Check for pback madness, and if so switch back to the
// normal buffers and jet outta here before expensive
// fileops happen...
@@ -367,14 +366,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
const bool __testin = _M_mode & ios_base::in;
if (__testin)
{
- if (_M_writing)
- {
- __ret = overflow();
- if (__ret == traits_type::eof())
- return __ret;
- _M_set_buffer(-1);
- _M_writing = false;
- }
+ if (_M_writing)
+ {
+ if (overflow() == traits_type::eof())
+ return __ret;
+ _M_set_buffer(-1);
+ _M_writing = false;
+ }
// Remember whether the pback buffer is active, otherwise below
// we may try to store in it a second char (libstdc++/9761).
const bool __testpb = _M_pback_init;
@@ -545,101 +543,108 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
return __elen == __plen;
}
- template<typename _CharT, typename _Traits>
- streamsize
- basic_filebuf<_CharT, _Traits>::
- xsgetn(_CharT* __s, streamsize __n)
- {
- // Clear out pback buffer before going on to the real deal...
- streamsize __ret = 0;
- if (_M_pback_init)
- {
- if (__n > 0 && this->gptr() == this->eback())
- {
- *__s++ = *this->gptr();
- this->gbump(1);
- __ret = 1;
- --__n;
- }
- _M_destroy_pback();
- }
-
- // Optimization in the always_noconv() case, to be generalized in the
- // future: when __n > __buflen we read directly instead of using the
- // buffer repeatedly.
- const bool __testin = _M_mode & ios_base::in;
- const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
-
- if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
- && __testin && !_M_writing)
- {
- // First, copy the chars already present in the buffer.
- const streamsize __avail = this->egptr() - this->gptr();
- if (__avail != 0)
- {
- if (__avail == 1)
- *__s = *this->gptr();
- else
- traits_type::copy(__s, this->gptr(), __avail);
- __s += __avail;
- this->gbump(__avail);
- __ret += __avail;
- __n -= __avail;
- }
-
- // Need to loop in case of short reads (relatively common
- // with pipes).
- streamsize __len;
- for (;;)
- {
- __len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
- __n);
- if (__len == -1)
- __throw_ios_failure(__N("basic_filebuf::xsgetn "
- "error reading the file"));
- if (__len == 0)
- break;
-
- __n -= __len;
- __ret += __len;
- if (__n == 0)
- break;
-
- __s += __len;
- }
-
- if (__n == 0)
- {
- _M_set_buffer(0);
- _M_reading = true;
- }
- else if (__len == 0)
- {
- // If end of file is reached, set 'uncommitted'
- // mode, thus allowing an immediate write without
- // an intervening seek.
- _M_set_buffer(-1);
- _M_reading = false;
- }
- }
- else
- __ret += __streambuf_type::xsgetn(__s, __n);
+ template<typename _CharT, typename _Traits>
+ streamsize
+ basic_filebuf<_CharT, _Traits>::
+ xsgetn(_CharT* __s, streamsize __n)
+ {
+ // Clear out pback buffer before going on to the real deal...
+ streamsize __ret = 0;
+ if (_M_pback_init)
+ {
+ if (__n > 0 && this->gptr() == this->eback())
+ {
+ *__s++ = *this->gptr(); // emulate non-underflowing sbumpc
+ this->gbump(1);
+ __ret = 1;
+ --__n;
+ }
+ _M_destroy_pback();
+ }
+ else if (_M_writing)
+ {
+ if (overflow() == traits_type::eof())
+ return __ret;
+ _M_set_buffer(-1);
+ _M_writing = false;
+ }
+
+ // Optimization in the always_noconv() case, to be generalized in the
+ // future: when __n > __buflen we read directly instead of using the
+ // buffer repeatedly.
+ const bool __testin = _M_mode & ios_base::in;
+ const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
+
+ if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
+ && __testin)
+ {
+ // First, copy the chars already present in the buffer.
+ const streamsize __avail = this->egptr() - this->gptr();
+ if (__avail != 0)
+ {
+ if (__avail == 1)
+ *__s = *this->gptr();
+ else
+ traits_type::copy(__s, this->gptr(), __avail);
+ __s += __avail;
+ this->gbump(__avail);
+ __ret += __avail;
+ __n -= __avail;
+ }
+
+ // Need to loop in case of short reads (relatively common
+ // with pipes).
+ streamsize __len;
+ for (;;)
+ {
+ __len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
+ __n);
+ if (__len == -1)
+ __throw_ios_failure(__N("basic_filebuf::xsgetn "
+ "error reading the file"));
+ if (__len == 0)
+ break;
+
+ __n -= __len;
+ __ret += __len;
+ if (__n == 0)
+ break;
+
+ __s += __len;
+ }
+
+ if (__n == 0)
+ {
+ _M_set_buffer(0);
+ _M_reading = true;
+ }
+ else if (__len == 0)
+ {
+ // If end of file is reached, set 'uncommitted'
+ // 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>::
- 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
- // using the buffer.
- streamsize __ret = 0;
- const bool __testout = _M_mode & ios_base::out;
- if (__check_facet(_M_codecvt).always_noconv()
- && __testout && !_M_reading)
+ template<typename _CharT, typename _Traits>
+ streamsize
+ basic_filebuf<_CharT, _Traits>::
+ xsputn(const _CharT* __s, streamsize __n)
+ {
+ streamsize __ret = 0;
+ // Optimization in the always_noconv() case, to be generalized in the
+ // future: when __n is sufficiently large we write directly instead of
+ // using the buffer.
+ const bool __testout = _M_mode & ios_base::out;
+ if (__check_facet(_M_codecvt).always_noconv()
+ && __testout && !_M_reading)
{
// Measurement would reveal the best choice.
const streamsize __chunk = 1ul << 10;
@@ -933,7 +938,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
{
// External position corresponding to gptr().
_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());
const streamsize __remainder = _M_ext_end - _M_ext_next;
if (__remainder)
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/45841.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/45841.cc
new file mode 100644
index 00000000000..a356d626e06
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/45841.cc
@@ -0,0 +1,41 @@
+// 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;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc
new file mode 100644
index 00000000000..2d7cb7af22a
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/45841.cc
@@ -0,0 +1,41 @@
+// 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;
+}