This is the mail archive of the libstdc++@sources.redhat.com mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] bits/istream.tcc testsuite/27_io/istream_unformatted.cc



This patch corrects the behavior of istream::getline() as well as adding
a couple of tests to verify compliance WRT the modified getline().


2000-07-23  Brent Verner <brent@rcfile.org>

	* bits/istream.tcc: istream::getline(char_type*, streamsize, char_type)
      make compliant
	* testsuite/27_io/istream_unformatted.cc: test for compliant behavior


Index: bits/istream.tcc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/bits/istream.tcc,v
retrieving revision 1.2
diff -c -p -3 -r1.2 istream.tcc
*** istream.tcc	2000/07/07 21:21:57	1.2
--- istream.tcc	2000/07/24 01:31:47
*************** namespace std {
*** 626,674 ****
        if (__cerb) 
  	{
  	  try {
  	    const int_type __idelim = traits_type::to_int_type(__delim);
  	    const int_type __eof = traits_type::eof();
! 	    __streambuf_type* __sb = this->rdbuf();
! 	    bool __testdelim = false;
! 	    bool __testeof = false;
! 
! 	    // This is completely idiotic, but attempts to recreate
! 	    // the smoke-filled air of the committee meeting where
! 	    // getline was defined. It's unspecified for __n == 1,
! 	    // what happens to the extracted char if it is not a
! 	    // delimiter or EOF. Assume it's not extracted, for the
! 	    // time being. . . 
! 	    if (__n == 1)
! 	      {
! 		int_type __c = __sb->sgetc();
! 		__testdelim = __c == __idelim;
  		__testeof = __c == __eof;
! 		if (__testdelim)
! 		  {
! 		    ++_M_gcount;
! 		    __sb->sbumpc();
! 		  }
! 	      }
! 	    else
! 	      {
! 		while (_M_gcount < __n - 1 && !__testdelim && !__testeof)
! 		  {
! 		    int_type __c = __sb->sbumpc();
! 		    __testdelim = __c == __idelim;
! 		    __testeof = __c == __eof;
! 		    if (__testdelim)
! 		      ++_M_gcount;
! 		    else if (!__testeof)
! 		      {
! 			*__s++ = traits_type::to_char_type(__c);
! 			++_M_gcount;
! 		      }
! 		  }
! 	      }
! 	    if (__testeof)
! 	      this->setstate(ios_base::eofbit);
! 	    else if (!__testdelim && _M_gcount == __n - 1)
! 	      this->setstate(ios_base::failbit);
  	  }
  	  catch(exception& __fail){
  	    // 27.6.1.3 paragraph 1
--- 626,653 ----
        if (__cerb) 
  	{
  	  try {
+ 	    __streambuf_type* __sb = this->rdbuf();
+ 	    int_type __c = __sb->sbumpc();
  	    const int_type __idelim = traits_type::to_int_type(__delim);
  	    const int_type __eof = traits_type::eof();
! 	    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);
! 	    }
  	  }
  	  catch(exception& __fail){
  	    // 27.6.1.3 paragraph 1
*************** namespace std {
*** 678,686 ****
  	      throw;
  	  }
  	}
!       *__s = char_type(NULL);
!       if (!_M_gcount)
  	this->setstate(ios_base::failbit);
        return *this;
      }
    
--- 657,665 ----
  	      throw;
  	  }
  	}
!       if(!_M_gcount)
  	this->setstate(ios_base::failbit);
+       *__s = char_type(NULL);
        return *this;
      }
    
Index: testsuite/27_io/istream_unformatted.cc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/testsuite/27_io/istream_unformatted.cc,v
retrieving revision 1.3
diff -c -p -3 -r1.3 istream_unformatted.cc
*** istream_unformatted.cc	2000/07/07 21:21:57	1.3
--- istream_unformatted.cc	2000/07/24 01:31:50
*************** bool test02(void)
*** 161,173 ****
  
    // istream& getline(char* s, streamsize n, char delim)
    // istream& getline(char* s, streamsize n)
!   state1 = is_00.rdstate();
    is_00.getline(carray1, 20, '*');
!   state2 = is_00.rdstate();  
!   test &= is_04.gcount() == 0;
    test &= state1 != state2;
!   test &= bool(state2 & statefail);
  
    state1 = is_04.rdstate();
    is_04.getline(carray1, 1, '\t'); // extracts, throws away
    state2 = is_04.rdstate();  
--- 161,175 ----
  
    // istream& getline(char* s, streamsize n, char delim)
    // istream& getline(char* s, streamsize n)
!   state1 = is_00.rdstate(); 
    is_00.getline(carray1, 20, '*');
!   state2 = is_00.rdstate();
!   // make sure failbit was set, since we couldn't extract
!   // from the NULL streambuf...
    test &= state1 != state2;
!   test &= static_cast<bool>(state2 & statefail); 
  
+   test &= is_04.gcount() == 0;
    state1 = is_04.rdstate();
    is_04.getline(carray1, 1, '\t'); // extracts, throws away
    state2 = is_04.rdstate();  
*************** void test04()
*** 351,357 ****
  // http://sourceware.cygnus.com/ml/libstdc++/2000-07/msg00003.html
  bool test05()
  {
- 
    const char* charray = "
  a
  aa
--- 353,358 ----
*************** aaaaaaaaaaaaaa
*** 376,415 ****
    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())
          {
! 	  // either
! 	  // -> extracted no characters
! 	  // or
! 	  // -> n - 1 characters are stored
!           VERIFY(strlen(tmp) == it - 1);
            ifs.clear(ifs.rdstate() & ~std::ios::failbit);
!           VERIFY(ifs);
            continue;
          }
        else 
          {
! 	  // -> strlen(__s) < n - 1 
! 	  // -> delimiter was seen -> gcount() > strlen(__s)
!           VERIFY(ifs.gcount() > strlen(tmp));
!           VERIFY(it - 1 > strlen(tmp));
            continue;
          }
      }
  
    return 0;
  }
--- 377,437 ----
    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 a sanity check to make sure we've extracted the same
!           // number of chars that were in the streambuf
!           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() )
          {
!           // delimiter not read
!           //
!           // either
!           // -> extracted no characters
!           // or
!           // -> n - 1 characters are stored
            ifs.clear(ifs.rdstate() & ~std::ios::failbit);
!           VERIFY( (ifs.gcount() == 0) || (strlen(tmp) == it - 1) );
!           VERIFY( ifs );
            continue;
          }
        else 
          {
!           // delimiter was read.
!           //
!           // make sure it was extracted/counted, but not stored.
!           VERIFY( ifs.gcount() == strlen(tmp) + 1 );
            continue;
          }
      }
+ 
+ // http://sources.redhat.com/ml/libstdc++/2000-07/msg00126.html
+   const std::streamsize it1 = 5;
+   char tmp1[it1];
+   const char* str_lit = "abcd\n";
+ 
+   std::stringbuf strbuf(str_lit, std::ios_base::in);
+   std::istream istr(&strbuf);
+ 
+   istr.getline(tmp1, it1);
+   VERIFY( istr.gcount() == it1 );  // extracted whole string
+   VERIFY( strlen(tmp1) == 4 );     // stored all but '\n'
+   VERIFY( !istr.eof() );           // extracted up to but not eof
+   VERIFY( !istr.fail() );          // failbit not set
+ 
+   char c = 'z';
+   istr.get(c);
+   VERIFY( c == 'z' );
+   VERIFY( istr.eof() );
  
    return 0;
  }
-- 
Damon Brent Verner                        o      _     _         _
Cracker Jack? Surprise Certified  _o     /\_   _ \\o  (_)\__/o  (_)
brent@rcfile.org                _< \_   _>(_) (_)/<_    \_| \   _|/' \/
brent@linux1.org               (_)>(_) (_)        (_)   (_)    (_)'  _\o_

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]