This is the mail archive of the
libstdc++@sourceware.cygnus.com
mailing list for the libstdc++ project.
[patch] bits/istream.tcc - getline(char_type*,streamsize,char_type)
- To: libstdc++ at sourceware dot cygnus dot com
- Subject: [patch] bits/istream.tcc - getline(char_type*,streamsize,char_type)
- From: brent verner <brent at rcfile dot org>
- Date: Sat, 1 Jul 2000 15:34:30 -0400
I ran across a bug with ifstream::getline(...). Basically, when reading
a partial line with n as max readlength, n-2 chars will be stored if
char n-1 is the delimiter. The following patch corrects this. The
testsuite can be used to verify the new behavior, as prescribed by
27.6.1.3 of the std.
cheers.
--
Damon Brent Verner
Cracker JackŪ Certified Professional
brent@rcfile.org, brent@linux1.org
Index: istream.tcc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/bits/istream.tcc,v
retrieving revision 1.1
diff -c -p -3 -r1.1 istream.tcc
*** istream.tcc 2000/04/21 20:33:28 1.1
--- istream.tcc 2000/07/01 11:51:36
*************** namespace std {
*** 627,656 ****
if (__cerb)
{
try {
- int_type __idelim = traits_type::to_int_type(__delim);
__streambuf_type* __sb = this->rdbuf();
! int_type __c = __sb->sbumpc();
const int_type __eof = traits_type::eof();
bool __testdelim = __c == __idelim;
bool __testeof = __c == __eof;
!
! while (_M_gcount < __n - 1 && !__testeof && !__testdelim)
! {
*__s++ = traits_type::to_char_type(__c);
- ++_M_gcount;
__c = __sb->sbumpc();
__testeof = __c == __eof;
__testdelim = __c == __idelim;
! }
! if (_M_gcount == __n - 1 && !__testeof && !__testdelim)
! {
__sb->sputbackc(traits_type::to_char_type(__c));
this->setstate(ios_base::failbit);
- }
- if (__testdelim)
- ++_M_gcount;
- if (__testeof)
- this->setstate(ios_base::eofbit);
}
catch(exception& __fail){
// 27.6.1.3 paragraph 1
--- 627,656 ----
if (__cerb)
{
try {
__streambuf_type* __sb = this->rdbuf();
! const int_type __idelim = traits_type::to_int_type(__delim);
const int_type __eof = traits_type::eof();
+ int_type __c = __sb->sbumpc();
bool __testdelim = __c == __idelim;
bool __testeof = __c == __eof;
!
! while (!__testeof && ++_M_gcount < __n && !__testdelim){
*__s++ = traits_type::to_char_type(__c);
__c = __sb->sbumpc();
__testeof = __c == __eof;
__testdelim = __c == __idelim;
! }
!
! if(__testeof){
! this->setstate(ios_base::eofbit);
! }
! else if(!__testdelim){
! --_M_gcount;
__sb->sputbackc(traits_type::to_char_type(__c));
+ this->setstate(ios_base::failbit);
+ }
+ if(!_M_gcount)
this->setstate(ios_base::failbit);
}
catch(exception& __fail){
// 27.6.1.3 paragraph 1
*************** namespace std {
*** 661,668 ****
}
}
*__s = char_type(NULL);
- if (!_M_gcount || _M_gcount == __n - 1)
- this->setstate(ios_base::failbit);
return *this;
}
--- 661,666 ----
#include <cstring>
#include <istream>
#include <sstream>
// just because it speeds up debugging when you _know_
// __which__ test fails :)
#ifdef DEBUG_ASSERT
#include <cassert>
# define VERIFY(fn) assert(fn)
#else
# define VERIFY(fn)
#endif
int
main()
{
const char* charray = "
a
aa
aaa
aaaa
aaaaa
aaaaaa
aaaaaaa
aaaaaaaa
aaaaaaaaa
aaaaaaaaaa
aaaaaaaaaaa
aaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaaa
";
const std::streamsize it = 5;
std::streamsize br = 0;
char tmp[it];
std::stringbuf sb(charray, std::ios_base::in);
std::istream ifs(&sb);
std::streamsize blen = strlen(charray);
VERIFY( ifs );
while( ifs.getline(tmp,it) || ifs.gcount() ){
br += ifs.gcount();
if( ifs.eof() ){
// just sanity checks to make sure we've
// extracted the same number of chars that
// were in the file.
VERIFY( br == blen );
// also, we should only set the failbit if
// we could _extract_ no chars from the
// stream, i.e. the first read returned EOF
VERIFY( ifs.fail() && ifs.gcount() == 0 );
}
else if( ifs.fail() ){
// we've extracted 'it' chars from the stream
// without finding the delimiter, but we only
// store 'it - 1' chars and put the last read
// char back into the stream. also, make sure
// that eofbit is not getting set.
VERIFY( ifs.gcount() == it - 1 );
VERIFY( ifs.gcount() == (int)strlen(tmp) );
ifs.clear(ifs.rdstate() & ~std::ios::failbit);
VERIFY( ifs );
continue;
}
else {
// read a delimiter. make sure it was counted.
// other stuff ???
VERIFY( ifs.gcount() == (int)strlen(tmp) + 1 );
continue;
}
}
return 0;
}