fstream.tcc (filebuf::seekpos): Fix.

2002-04-08  Benjamin Kosnik  <bkoz@redhat.com>

	libstdc++/5180
	* include/bits/fstream.tcc (filebuf::seekpos): Fix.
	* include/std/std_fstream.h: Clean.
	* include/bits/ostream.tcc: Remove extraneous variables.
	* include/bits/sstream.tcc (stringbuf::seekoff): Be strict about
	open modes and which modes.
	(stringbuf::seekpos): Same.
	* testsuite/27_io/stringbuf_virtuals.cc: New tests.

From-SVN: r52057
This commit is contained in:
Benjamin Kosnik 2002-04-09 06:14:32 +00:00 committed by Benjamin Kosnik
parent 973348ec02
commit b988dfc58f
6 changed files with 109 additions and 53 deletions

View File

@ -1,3 +1,14 @@
2002-04-08 Benjamin Kosnik <bkoz@redhat.com>
libstdc++/5180
* include/bits/fstream.tcc (filebuf::seekpos): Fix.
* include/std/std_fstream.h: Clean.
* include/bits/ostream.tcc: Remove extraneous variables.
* include/bits/sstream.tcc (stringbuf::seekoff): Be strict about
open modes and which modes.
(stringbuf::seekpos): Same.
* testsuite/27_io/stringbuf_virtuals.cc: New tests.
2002-04-05 Jonathan Wakely <jw@kayari.org>
* include/bits/stl_algo.h (unique_copy, __gcd, rotate, rotate_copy,

View File

@ -560,17 +560,17 @@ namespace std
seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
{
pos_type __ret = pos_type(off_type(-1));
bool __testopen = this->is_open();
bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
bool __testin = _M_mode & ios_base::in;
bool __testout = _M_mode & ios_base::out;
// Should probably do has_facet checks here.
int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding();
if (__width < 0)
__width = 0;
bool __testfail = __off != 0 && __width <= 0;
bool __testfail = __off != 0 && __width <= 0;
if (__testopen && !__testfail && (__testin || __testout))
if (this->is_open() && !__testfail
&& __mode & _M_mode && (__testin || __testout))
{
// Ditch any pback buffers to avoid confusion.
_M_pback_destroy();
@ -615,13 +615,10 @@ namespace std
basic_filebuf<_CharT, _Traits>::
seekpos(pos_type __pos, ios_base::openmode __mode)
{
pos_type __ret;
off_type __off = __pos;
__ret = this->seekoff(__off, ios_base::beg, __mode);
_M_last_overflowed = false;
return __ret;
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 171. Strange seekpos() semantics due to joint position
return this->seekoff(off_type(__pos), ios_base::beg, __mode);
#endif
}
template<typename _CharT, typename _Traits>

View File

@ -419,9 +419,7 @@ namespace std
basic_ostream<_CharT, _Traits>::tellp()
{
pos_type __ret = pos_type(-1);
bool __testok = this->fail() != true;
if (__testok)
if (!this->fail())
__ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
return __ret;
}
@ -431,9 +429,7 @@ namespace std
basic_ostream<_CharT, _Traits>&
basic_ostream<_CharT, _Traits>::seekp(pos_type __pos)
{
bool __testok = this->fail() != true;
if (__testok)
if (!this->fail())
{
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 136. seekp, seekg setting wrong streams?
@ -452,9 +448,7 @@ namespace std
basic_ostream<_CharT, _Traits>::
seekp(off_type __off, ios_base::seekdir __d)
{
bool __testok = this->fail() != true;
if (__testok)
if (!this->fail())
{
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 136. seekp, seekg setting wrong streams?

View File

@ -124,8 +124,10 @@ namespace std
bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
bool __testboth = __testin && __testout && __way != ios_base::cur;
if (_M_buf_size && ((__testin != __testout) || __testboth))
__testin &= !(__mode & ios_base::out);
__testout &= !(__mode & ios_base::in);
if (_M_buf_size && (__testin || __testout || __testboth))
{
char_type* __beg = _M_buf;
char_type* __curi = NULL;
@ -133,12 +135,12 @@ namespace std
char_type* __endi = NULL;
char_type* __endo = NULL;
if (__testin)
if (__testin || __testboth)
{
__curi = this->gptr();
__endi = this->egptr();
}
if (__testout)
if (__testout || __testboth)
{
__curo = this->pptr();
__endo = this->epptr();
@ -157,13 +159,13 @@ namespace std
__newoffo = __endo - __beg;
}
if (__testin
if ((__testin || __testboth)
&& __newoffi + __off >= 0 && __endi - __beg >= __newoffi + __off)
{
_M_in_cur = __beg + __newoffi + __off;
__ret = pos_type(__newoffi);
}
if (__testout
if ((__testout || __testboth)
&& __newoffo + __off >= 0 && __endo - __beg >= __newoffo + __off)
{
_M_out_cur_move(__newoffo + __off - (_M_out_cur - __beg));
@ -179,33 +181,44 @@ namespace std
seekpos(pos_type __sp, ios_base::openmode __mode)
{
pos_type __ret = pos_type(off_type(-1));
off_type __pos = __sp._M_position();
char_type* __beg = NULL;
char_type* __end = NULL;
bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
if (__testin)
if (_M_buf_size)
{
__beg = this->eback();
__end = this->egptr();
off_type __pos = __sp._M_position();
char_type* __beg = NULL;
char_type* __end = NULL;
bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
bool __testboth = __testin && __testout;
__testin &= !(__mode & ios_base::out);
__testout &= !(__mode & ios_base::in);
// NB: Ordered.
bool __testposi = false;
bool __testposo = false;
if (__testin || __testboth)
{
__beg = this->eback();
__end = this->egptr();
if (0 <= __pos && __pos <= __end - __beg)
__testposi = true;
}
if (__testout || __testboth)
{
__beg = this->pbase();
__end = _M_buf + _M_buf_size;
if (0 <= __pos && __pos <= __end - __beg)
__testposo = true;
}
if (__testposi || __testposo)
{
if (__testposi)
_M_in_cur = _M_in_beg + __pos;
if (__testposo)
_M_out_cur_move((__pos) - (_M_out_cur - __beg));
__ret = pos_type(off_type(__pos));
}
}
if (__testout)
{
__beg = this->pbase();
__end = _M_buf + _M_buf_size;
}
if (0 <= __pos && __pos <= __end - __beg)
{
// Need to set both of these if applicable
if (__testin)
_M_in_cur = _M_in_beg + __pos;
if (__testout)
_M_out_cur_move((__pos) - (_M_out_cur - __beg));
__ret = pos_type(off_type(__pos));
}
return __ret;
}

View File

@ -306,7 +306,7 @@ namespace std
void
open(const char* __s, ios_base::openmode __mode = ios_base::in)
{
if (_M_filebuf.open(__s, __mode | ios_base::in) == NULL)
if (!_M_filebuf.open(__s, __mode | ios_base::in))
this->setstate(ios_base::failbit);
}

View File

@ -1,6 +1,6 @@
// 2001-05-21 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 Free Software Foundation, Inc.
// Copyright (C) 2001, 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
@ -38,9 +38,50 @@ void test01()
VERIFY( std::strncmp(strlit, buf, strlitsize) != 0 );
}
void test02(std::stringbuf& in, bool pass)
{
using namespace std;
typedef streambuf::pos_type pos_type;
typedef streambuf::off_type off_type;
pos_type bad = pos_type(off_type(-1));
pos_type p = 0;
// seekoff
p = in.pubseekoff(0, ios_base::beg, ios_base::in);
if (pass)
VERIFY( p != bad );
p = in.pubseekoff(0, ios_base::beg, ios_base::out);
VERIFY( p == bad );
p = in.pubseekoff(0, ios_base::beg);
VERIFY( p == bad );
// seekpos
p = in.pubseekpos(0, ios_base::in);
if (pass)
VERIFY( p != bad );
p = in.pubseekpos(0, ios_base::out);
VERIFY( p == bad );
p = in.pubseekpos(0);
VERIFY( p == bad );
}
int main()
{
using namespace std;
test01();
// movie star, submarine scientist!
stringbuf in1("Hedy Lamarr", ios_base::in);
stringbuf in2(ios_base::in);
stringbuf in3("", ios_base::in);
test02(in1, true);
test02(in2, false);
test02(in3, false);
return 0;
}