From 75555da78d42ce001a9bc680036ac8a43589e444 Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Fri, 7 Jul 2000 21:21:57 +0000 Subject: [PATCH] [multiple changes] 2000-07-07 brent verner * testsuite/27_io/istream_unformatted.cc (test05): New test. 2000-07-07 Benjamin Kosnik * bits/istream.tcc (istream::getline): Minor tweaks. From-SVN: r34913 --- libstdc++-v3/ChangeLog | 8 +++ libstdc++-v3/bits/istream.tcc | 78 +++++++++++++--------- .../testsuite/27_io/istream_unformatted.cc | 76 ++++++++++++++++++++- 3 files changed, 129 insertions(+), 33 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d84bf7c..d2438e1 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2000-07-07 brent verner + + * testsuite/27_io/istream_unformatted.cc (test05): New test. + +2000-07-07 Benjamin Kosnik + + * bits/istream.tcc (istream::getline): Minor tweaks. + 2000-07-07 Phil Edwards * docs/download.html: Mention gcc_update. diff --git a/libstdc++-v3/bits/istream.tcc b/libstdc++-v3/bits/istream.tcc index 71cc961..370bbe7 100644 --- a/libstdc++-v3/bits/istream.tcc +++ b/libstdc++-v3/bits/istream.tcc @@ -503,10 +503,9 @@ namespace std { sentry __cerb(*this, true); if (__cerb) { - const int_type __eof = traits_type::eof(); - int_type __bufval; try { - __bufval = this->rdbuf()->sbumpc(); + const int_type __eof = traits_type::eof(); + int_type __bufval = this->rdbuf()->sbumpc(); // 27.6.1.1 paragraph 3 if (__bufval != __eof) { @@ -537,10 +536,10 @@ namespace std { if (__cerb && __n > 1) { try { - int_type __idelim = traits_type::to_int_type(__delim); + const int_type __idelim = traits_type::to_int_type(__delim); + const int_type __eof = traits_type::eof(); __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; @@ -580,12 +579,12 @@ namespace std { sentry __cerb(*this, true); if (__cerb) { - __streambuf_type* __this_sb = this->rdbuf(); int_type __c; + __streambuf_type* __this_sb = this->rdbuf(); try { - int_type __idelim = traits_type::to_int_type(__delim); - __c = __this_sb->sbumpc(); + const int_type __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); + __c = __this_sb->sbumpc(); bool __testdelim = __c == __idelim; bool __testeof = __c == __eof; bool __testput = true; @@ -627,30 +626,49 @@ namespace std { 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 __idelim = traits_type::to_int_type(__delim); const int_type __eof = traits_type::eof(); - bool __testdelim = __c == __idelim; - bool __testeof = __c == __eof; - - while (_M_gcount < __n - 1 && !__testeof && !__testdelim) + __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) { - *__s++ = traits_type::to_char_type(__c); - ++_M_gcount; - __c = __sb->sbumpc(); - __testeof = __c == __eof; + int_type __c = __sb->sgetc(); __testdelim = __c == __idelim; + __testeof = __c == __eof; + if (__testdelim) + { + ++_M_gcount; + __sb->sbumpc(); + } } - if (_M_gcount == __n - 1 && !__testeof && !__testdelim) + else { - __sb->sputbackc(traits_type::to_char_type(__c)); - this->setstate(ios_base::failbit); - } - if (__testdelim) - ++_M_gcount; + 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 @@ -661,7 +679,7 @@ namespace std { } } *__s = char_type(NULL); - if (!_M_gcount || _M_gcount == __n - 1) + if (!_M_gcount) this->setstate(ios_base::failbit); return *this; } @@ -676,10 +694,10 @@ namespace std { if (__cerb && __n > 0) { try { - int_type __idelim = traits_type::to_int_type(__delim); + const int_type __idelim = traits_type::to_int_type(__delim); + const int_type __eof = traits_type::eof(); __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; @@ -743,9 +761,9 @@ namespace std { if (__n > 0) { try { + const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); int_type __c = __sb->sbumpc(); - const int_type __eof = traits_type::eof(); bool __testeof = __c == __eof; while (_M_gcount < __n - 1 && !__testeof) @@ -847,12 +865,12 @@ namespace std { basic_istream<_CharT, _Traits>:: unget(void) { - const int_type __eof = traits_type::eof(); _M_gcount = 0; sentry __cerb(*this, true); if (__cerb) { try { + const int_type __eof = traits_type::eof(); __streambuf_type* __sb = this->rdbuf(); if (!__sb || __eof == __sb->sungetc()) this->setstate(ios_base::badbit); diff --git a/libstdc++-v3/testsuite/27_io/istream_unformatted.cc b/libstdc++-v3/testsuite/27_io/istream_unformatted.cc index 59f40eb..56b86a5 100644 --- a/libstdc++-v3/testsuite/27_io/istream_unformatted.cc +++ b/libstdc++-v3/testsuite/27_io/istream_unformatted.cc @@ -24,7 +24,10 @@ #include #include #ifdef DEBUG_ASSERT - #include +#include +# define VERIFY(fn) assert(fn) +#else +# define VERIFY(fn) #endif bool test01() { @@ -317,7 +320,7 @@ bool test03(void) } // http://sourceware.cygnus.com/ml/libstdc++/2000-q1/msg00177.html -void test06() +void test04() { bool test = true; @@ -345,12 +348,79 @@ void test06() #endif } +// http://sourceware.cygnus.com/ml/libstdc++/2000-07/msg00003.html +bool test05() +{ + + const char* charray = " +a +aa +aaa +aaaa +aaaaa +aaaaaa +aaaaaaa +aaaaaaaa +aaaaaaaaa +aaaaaaaaaa +aaaaaaaaaaa +aaaaaaaaaaaa +aaaaaaaaaaaaa +aaaaaaaaaaaaaa +"; + + bool test = true; + 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()) + { + // 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; +} + int main() { test01(); test02(); test03(); - test06(); + test04(); + test05(); return 0; } -- 2.7.4