aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorDavid Krauss <potswa@mac.com>2010-09-22 19:40:43 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2010-09-22 19:40:43 +0000
commit3531cf5ef365860700c5e89483f3a86ac969c6a4 (patch)
treea04325d2591098556af14addef9debb056684968 /libstdc++-v3
parent5d64ee190c8875dec5f15c0287a425a1e62041a9 (diff)
downloadgcc-3531cf5ef365860700c5e89483f3a86ac969c6a4.zip
gcc-3531cf5ef365860700c5e89483f3a86ac969c6a4.tar.gz
gcc-3531cf5ef365860700c5e89483f3a86ac969c6a4.tar.bz2
re PR libstdc++/45628 (std::fstream::tellg invalidates I/O buffer)
2010-09-22 David Krauss <potswa@mac.com> PR libstdc++/45628 * include/bits/fstream.tcc (basic_filebuf::underflow): Add state transition to avoid modality requiring seekoff(0,ios::cur). (basic_filebuf::pbackfail): Likewise. (basic_filebuf::overflow): Likewise. (basic_filebuf::_M_seek): Avoid minor unnecessary conversion. (basic_filebuf::seekoff): Remove code to _M_get_ext_pos; make (0, ios::cur) a special case preserving buffer contents. (basic_filebuf::_M_get_ext_pos): New function to obtain status about codecvt extern_t buffer for overflow and seekoff. * include/std/fstream (basic_filebuf::_M_get_ext_pos): Likewise. * config/abi/pre/gnu.ver: Export new symbols. * testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc: New, verifies that seekoff(0, ios::cur) preserves buffers. * testsuite/27_io/basic_filebuf/seekoff/char/45628-2.cc: Likewise. for codecvt case. More lenient as it may still flush put area. * testsuite/27_io/basic_filebuf/seekoff/char/4.cc: Modify to check that seekoff is not required between read and write. * testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc: Likewise. * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Remove. * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Likewise. * testsuite/util/testsuite_character.h (codecvt::do_length): Comply with 22.2.1.5.2/10 "Returns ... the LARGEST value in the range..." From-SVN: r164529
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog26
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver11
-rw-r--r--libstdc++-v3/include/bits/fstream.tcc100
-rw-r--r--libstdc++-v3/include/std/fstream5
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc103
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc20
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc79
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc20
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc51
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc51
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_character.h4
11 files changed, 329 insertions, 141 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 8f5dc71..551b23f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,29 @@
+2010-09-22 David Krauss <potswa@mac.com>
+
+ PR libstdc++/45628
+ * include/bits/fstream.tcc (basic_filebuf::underflow): Add state
+ transition to avoid modality requiring seekoff(0,ios::cur).
+ (basic_filebuf::pbackfail): Likewise.
+ (basic_filebuf::overflow): Likewise.
+ (basic_filebuf::_M_seek): Avoid minor unnecessary conversion.
+ (basic_filebuf::seekoff): Remove code to _M_get_ext_pos; make
+ (0, ios::cur) a special case preserving buffer contents.
+ (basic_filebuf::_M_get_ext_pos): New function to obtain status
+ about codecvt extern_t buffer for overflow and seekoff.
+ * include/std/fstream (basic_filebuf::_M_get_ext_pos): Likewise.
+ * config/abi/pre/gnu.ver: Export new symbols.
+ * testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc: New,
+ verifies that seekoff(0, ios::cur) preserves buffers.
+ * testsuite/27_io/basic_filebuf/seekoff/char/45628-2.cc: Likewise.
+ for codecvt case. More lenient as it may still flush put area.
+ * testsuite/27_io/basic_filebuf/seekoff/char/4.cc: Modify to
+ check that seekoff is not required between read and write.
+ * testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc: Likewise.
+ * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Remove.
+ * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Likewise.
+ * testsuite/util/testsuite_character.h (codecvt::do_length): Comply
+ with 22.2.1.5.2/10 "Returns ... the LARGEST value in the range..."
+
2010-09-22 Paolo Carlini <paolo.carlini@oracle.com>
* include/bits/functional_hash.h (__hash_base): Add.
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 435f857..4981ca9 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -332,7 +332,13 @@ GLIBCXX_3.4 {
# std::basic_filebuf
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EEC*;
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EED*;
- _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE[0-3]*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE0*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE13*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE15*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE16*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE19*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE2*;
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE3*;
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4openEPKc*;
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4sync*;
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE[5-9]*;
@@ -1178,6 +1184,9 @@ GLIBCXX_3.4.15 {
_ZNSbIwSt11char_traitsIwESaIwEE4backEv;
_ZNKSbIwSt11char_traitsIwESaIwEE4backEv;
+ # basic_filebuf::_M_get_ext_pos
+ _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE14_M_get_ext_pos*;
+
} GLIBCXX_3.4.14;
# Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index c498f48..2f661eb 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -1,7 +1,7 @@
// File based streams -*- C++ -*-
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-// 2007, 2008, 2009
+// 2007, 2008, 2009, 2010
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -205,8 +205,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
{
int_type __ret = traits_type::eof();
const bool __testin = _M_mode & ios_base::in;
- if (__testin && !_M_writing)
+ if (__testin)
{
+ if (_M_writing)
+ {
+ __ret = overflow();
+ if (__ret == 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...
@@ -357,8 +365,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
{
int_type __ret = traits_type::eof();
const bool __testin = _M_mode & ios_base::in;
- if (__testin && !_M_writing)
+ if (__testin)
{
+ if (_M_writing)
+ {
+ __ret = overflow();
+ if (__ret == 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;
@@ -410,8 +426,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
int_type __ret = traits_type::eof();
const bool __testeof = traits_type::eq_int_type(__c, __ret);
const bool __testout = _M_mode & ios_base::out;
- if (__testout && !_M_reading)
+ if (__testout)
{
+ if (_M_reading)
+ {
+ _M_destroy_pback();
+ const int __gptr_off = _M_get_ext_pos(_M_state_last);
+ if (_M_seek(__gptr_off, ios_base::cur, _M_state_last)
+ == pos_type(off_type(-1)))
+ return __ret;
+ }
if (this->pbase() < this->pptr())
{
// If appropriate, append the overflow char.
@@ -691,12 +715,20 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
if (__width < 0)
__width = 0;
- pos_type __ret = pos_type(off_type(-1));
+ pos_type __ret = pos_type(off_type(-1));
const bool __testfail = __off != 0 && __width <= 0;
if (this->is_open() && !__testfail)
{
+ // tellg and tellp queries do not affect any state, unless
+ // ! always_noconv and the put sequence is not empty.
+ // In that case, determining the position requires converting the
+ // put sequence. That doesn't use ext_buf, so requires a flush.
+ bool __no_movement = __way == ios_base::cur && __off == 0
+ && (!_M_writing || _M_codecvt->always_noconv());
+
// Ditch any pback buffers to avoid confusion.
- _M_destroy_pback();
+ if (!__no_movement)
+ _M_destroy_pback();
// Correct state at destination. Note that this is the correct
// state for the current position during output, because
@@ -707,24 +739,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
off_type __computed_off = __off * __width;
if (_M_reading && __way == ios_base::cur)
{
- if (_M_codecvt->always_noconv())
- __computed_off += this->gptr() - this->egptr();
- else
+ __state = _M_state_last;
+ __computed_off += _M_get_ext_pos(__state);
+ }
+ if (!__no_movement)
+ __ret = _M_seek(__computed_off, __way, __state);
+ else
+ {
+ if (_M_writing)
+ __computed_off = this->pptr() - this->pbase();
+
+ off_type __file_off = _M_file.seekoff(0, ios_base::cur);
+ if (__file_off != off_type(-1))
{
- // Calculate offset from _M_ext_buf that corresponds
- // to gptr(). Note: uses _M_state_last, which
- // corresponds to eback().
- const int __gptr_off =
- _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next,
- this->gptr() - this->eback());
- __computed_off += _M_ext_buf + __gptr_off - _M_ext_end;
-
- // _M_state_last is modified by codecvt::length() so
- // it now corresponds to gptr().
- __state = _M_state_last;
+ __ret = __file_off + __computed_off;
+ __ret.state(__state);
}
}
- __ret = _M_seek(__computed_off, __way, __state);
}
return __ret;
}
@@ -756,21 +787,42 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
pos_type __ret = pos_type(off_type(-1));
if (_M_terminate_output())
{
- // Returns pos_type(off_type(-1)) in case of failure.
- __ret = pos_type(_M_file.seekoff(__off, __way));
- if (__ret != pos_type(off_type(-1)))
+ off_type __file_off = _M_file.seekoff(__off, __way);
+ if (__file_off != off_type(-1))
{
_M_reading = false;
_M_writing = false;
_M_ext_next = _M_ext_end = _M_ext_buf;
_M_set_buffer(-1);
_M_state_cur = __state;
+ __ret = __file_off;
__ret.state(_M_state_cur);
}
}
return __ret;
}
+ // Returns the distance from the end of the ext buffer to the point
+ // corresponding to gptr(). This is a negative value. Updates __state
+ // from eback() correspondence to gptr().
+ template<typename _CharT, typename _Traits>
+ int basic_filebuf<_CharT, _Traits>::
+ _M_get_ext_pos(__state_type& __state)
+ {
+ if (_M_codecvt->always_noconv())
+ return this->gptr() - this->egptr();
+ else
+ {
+ // Calculate offset from _M_ext_buf that corresponds to
+ // gptr(). Precondition: __state == _M_state_last, which
+ // corresponds to eback().
+ const int __gptr_off =
+ _M_codecvt->length(__state, _M_ext_buf, _M_ext_next,
+ this->gptr() - this->eback());
+ return _M_ext_buf + __gptr_off - _M_ext_end;
+ }
+ }
+
template<typename _CharT, typename _Traits>
bool
basic_filebuf<_CharT, _Traits>::
diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream
index 00690be..0ffd33d 100644
--- a/libstdc++-v3/include/std/fstream
+++ b/libstdc++-v3/include/std/fstream
@@ -351,9 +351,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
seekpos(pos_type __pos,
ios_base::openmode __mode = ios_base::in | ios_base::out);
- // Common code for seekoff and seekpos
+ // Common code for seekoff, seekpos, and overflow
pos_type
_M_seek(off_type __off, ios_base::seekdir __way, __state_type __state);
+
+ int
+ _M_get_ext_pos(__state_type &__state);
virtual int
sync();
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc
new file mode 100644
index 0000000..6e40a89
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc
@@ -0,0 +1,103 @@
+// 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>
+#include <testsuite_character.h>
+
+const char name_01[] = "tmp_seekoff_45628.tst";
+
+unsigned underflows, overflows;
+
+class my_filebuf
+: public std::basic_filebuf<__gnu_test::pod_uchar>
+{
+ virtual int_type
+ underflow()
+ {
+ ++underflows;
+ return std::basic_filebuf<__gnu_test::pod_uchar>::underflow();
+ }
+ virtual int_type
+ overflow(int_type c)
+ {
+ ++overflows;
+ return std::basic_filebuf<__gnu_test::pod_uchar>::overflow(c);
+ }
+};
+
+// libstdc++/45628
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ using __gnu_test::pod_uchar;
+ std::locale loc(std::locale::classic(),
+ new std::codecvt<my_filebuf::traits_type::char_type, char,
+ my_filebuf::traits_type::state_type>);
+
+ my_filebuf::pos_type opos[3], ipos[3];
+ my_filebuf q;
+ q.pubimbue(loc);
+
+ q.open(name_01, std::ios_base::in | std::ios_base::out
+ | std::ios_base::trunc);
+
+ q.sputc(pod_uchar::from<char>('a'));
+ opos[0] = q.pubseekoff(0, std::ios_base::cur);
+ q.sputc(pod_uchar::from<char>('b'));
+ opos[1] = q.pubseekoff(0, std::ios_base::cur);
+ q.sputc(pod_uchar::from<char>('c'));
+ opos[2] = q.pubseekoff(0, std::ios_base::cur);
+
+ VERIFY( overflows <= 9 ); // pubseekoff calls overflow twice if converting.
+ // NB: checking opos==ipos is not very rigorous as long as it flushes, since
+ // all positions will be at initial state.
+ q.pubseekoff(0, std::ios_base::beg);
+
+ q.sbumpc();
+ VERIFY( underflows == 1 );
+
+ ipos[0] = q.pubseekoff(0, std::ios_base::cur);
+ VERIFY( ipos[0] == opos[0] );
+ q.sbumpc();
+ ipos[1] = q.pubseekoff(0, std::ios_base::cur);
+ VERIFY( ipos[1] == opos[1] );
+ q.sbumpc();
+ ipos[2] = q.pubseekoff(0, std::ios_base::cur);
+ VERIFY( ipos[2] == opos[2] );
+
+ VERIFY( underflows == 1 ); // pubseekoff never flushes get area
+
+ // Bonus test: check automatic mode switches.
+ q.sputc(pod_uchar::from<char>('d'));
+
+ q.pubseekpos( ipos[1] );
+ q.sputc(pod_uchar::from<char>('e'));
+
+ VERIFY( my_filebuf::traits_type::eq(
+ my_filebuf::traits_type::to_char_type(q.sgetc()),
+ pod_uchar::from<char>('d')) );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc
index 9422f29..fe21b3a 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc
@@ -31,7 +31,7 @@ void test01()
typedef filebuf::pos_type pos_type;
const char name[] = "tmp_seekoff-4.tst";
- const size_t size = 10;
+ const size_t size = 12;
char buf[size];
streamsize n;
@@ -46,7 +46,7 @@ void test01()
VERIFY( n == 3 );
VERIFY( !memcmp(buf, "abc", 3) );
- fb.pubseekoff(0, ios_base::cur);
+ // Check read => write without pubseekoff(0, ios_base::cur)
n = fb.sputn("ef", 2);
VERIFY( n == 2 );
@@ -58,9 +58,17 @@ void test01()
VERIFY( !memcmp(buf, "abcef", 5) );
fb.pubseekoff(0, ios_base::beg);
- n = fb.sputn("ghijkl", 6);
- VERIFY( n == 6 );
+ n = fb.sputn("gh", 2);
+ VERIFY( n == 2 );
+
+ // Check write => read without pubseekoff(0, ios_base::cur)
+
+ n = fb.sgetn( buf, 3 );
+ VERIFY( !memcmp(buf, "cef", 3) );
+ n = fb.sputn("ijkl", 4);
+ VERIFY( n == 4 );
+
fb.pubseekoff(0, ios_base::beg);
n = fb.sgetn(buf, 2);
VERIFY( n == 2 );
@@ -72,8 +80,8 @@ void test01()
fb.pubseekoff(0, ios_base::beg);
n = fb.sgetn(buf, size);
- VERIFY( n == 9 );
- VERIFY( !memcmp(buf, "ghijklmno", 9) );
+ VERIFY( n == 12 );
+ VERIFY( !memcmp(buf, "ghcefijklmno", 12) );
fb.close();
}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc
new file mode 100644
index 0000000..a80a338
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc
@@ -0,0 +1,79 @@
+// 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>
+
+const char name_01[] = "tmp_seekoff_45628.tst";
+
+unsigned underflows, overflows;
+
+class my_filebuf
+: public std::filebuf
+{
+ virtual int_type
+ underflow()
+ {
+ ++underflows;
+ return std::filebuf::underflow();
+ }
+ virtual int_type
+ overflow(int_type c)
+ {
+ ++overflows;
+ return std::filebuf::overflow(c);
+ }
+};
+
+// libstdc++/45628
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ my_filebuf q;
+ q.open(name_01, std::ios_base::in | std::ios_base::out
+ | std::ios_base::trunc);
+
+ q.sputc('a');
+ q.pubseekoff(0, std::ios_base::cur);
+ q.sputc('b');
+ q.pubseekoff(0, std::ios_base::cur);
+ q.sputc('c');
+ q.pubseekoff(0, std::ios_base::cur);
+
+ VERIFY( overflows <= 1 ); // only initial sputc allowed to overflow
+ q.pubseekoff(0, std::ios_base::beg);
+
+ q.sbumpc();
+ VERIFY( underflows == 1 );
+
+ q.pubseekoff(0, std::ios_base::cur);
+ q.sbumpc();
+ q.pubseekoff(0, std::ios_base::cur);
+ q.sbumpc();
+ q.pubseekoff(0, std::ios_base::cur);
+
+ VERIFY( underflows == 1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc
index 95338cf..a6bba98 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc
@@ -31,7 +31,7 @@ void test01()
typedef wfilebuf::pos_type pos_type;
const char name[] = "tmp_seekoff-4.tst";
- const size_t size = 10;
+ const size_t size = 12;
wchar_t buf[size];
streamsize n;
@@ -46,7 +46,7 @@ void test01()
VERIFY( n == 3 );
VERIFY( !wmemcmp(buf, L"abc", 3) );
- fb.pubseekoff(0, ios_base::cur);
+ // Check read => write without pubseekoff(0, ios_base::cur)
n = fb.sputn(L"ef", 2);
VERIFY( n == 2 );
@@ -58,8 +58,16 @@ void test01()
VERIFY( !wmemcmp(buf, L"abcef", 5) );
fb.pubseekoff(0, ios_base::beg);
- n = fb.sputn(L"ghijkl", 6);
- VERIFY( n == 6 );
+ n = fb.sputn(L"gh", 2);
+ VERIFY( n == 2 );
+
+ // Check write => read without pubseekoff(0, ios_base::cur)
+
+ n = fb.sgetn( buf, 3 );
+ VERIFY( !memcmp(buf, L"cef", 3) );
+
+ n = fb.sputn(L"ijkl", 4);
+ VERIFY( n == 4 );
fb.pubseekoff(0, ios_base::beg);
n = fb.sgetn(buf, 2);
@@ -72,8 +80,8 @@ void test01()
fb.pubseekoff(0, ios_base::beg);
n = fb.sgetn(buf, size);
- VERIFY( n == 9 );
- VERIFY( !wmemcmp(buf, L"ghijklmno", 9) );
+ VERIFY( n == 12 );
+ VERIFY( !wmemcmp(buf, L"ghcefijklmno", 12) );
fb.close();
}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc
deleted file mode 100644
index 0a11c43..0000000
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2003, 2009 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/>.
-
-// 27.8.1.4 Overridden virtual functions
-
-#include <fstream>
-#include <testsuite_hooks.h>
-
-void test01()
-{
- using namespace std;
-
- bool test __attribute__((unused)) = true;
- const char* name = "tmp_sync_1";
-
- filebuf fb;
-
- fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
- fb.sputn("abc", 3);
-
- fb.pubseekoff(0, ios_base::beg);
- fb.sputc('1');
-
- // Sync can't be used to switch from write mode to read mode.
- fb.pubsync();
-
- filebuf::int_type c = fb.sbumpc();
- VERIFY( c == filebuf::traits_type::eof() );
-
- fb.close();
-}
-
-int main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc
deleted file mode 100644
index a64f455..0000000
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2003, 2009 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/>.
-
-// 27.8.1.4 Overridden virtual functions
-
-#include <fstream>
-#include <testsuite_hooks.h>
-
-void test01()
-{
- using namespace std;
-
- bool test __attribute__((unused)) = true;
- const char* name = "tmp_sync_1";
-
- wfilebuf fb;
-
- fb.open(name, ios_base::in | ios_base::out | ios_base::trunc);
- fb.sputn(L"abc", 3);
-
- fb.pubseekoff(0, ios_base::beg);
- fb.sputc(L'1');
-
- // Sync can't be used to switch from write mode to read mode.
- fb.pubsync();
-
- wfilebuf::int_type c = fb.sbumpc();
- VERIFY( c == wfilebuf::traits_type::eof() );
-
- fb.close();
-}
-
-int main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/util/testsuite_character.h b/libstdc++-v3/testsuite/util/testsuite_character.h
index 35ccfa8..ceda1f5 100644
--- a/libstdc++-v3/testsuite/util/testsuite_character.h
+++ b/libstdc++-v3/testsuite/util/testsuite_character.h
@@ -294,7 +294,7 @@ namespace std
const extern_type* end, size_t max) const
{
const extern_type* beg = from;
- while (from < end && max)
+ while (from < end)
{
unsigned char c = *from;
if (c & 0xc0)
@@ -304,6 +304,8 @@ namespace std
++from;
continue;
}
+
+ if (max == 0) break;
unsigned char tmp;
if (state.value & 0x8)