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...
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;
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;
{
// 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)
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}