diff options
author | Petur Runolfsson <peturr02@ru.is> | 2003-09-03 14:54:03 +0000 |
---|---|---|
committer | Benjamin Kosnik <bkoz@gcc.gnu.org> | 2003-09-03 14:54:03 +0000 |
commit | 149639d4f14ae921b4d14f6e35a840755b29f098 (patch) | |
tree | 171f78496fb967c04d39c1a4fabcdd7216ddcb8c /libstdc++-v3/include/ext/stdio_sync_filebuf.h | |
parent | 916b57cedabb2d80ac3e947a682efa3bce15cf4e (diff) | |
download | gcc-149639d4f14ae921b4d14f6e35a840755b29f098.zip gcc-149639d4f14ae921b4d14f6e35a840755b29f098.tar.gz gcc-149639d4f14ae921b4d14f6e35a840755b29f098.tar.bz2 |
re PR libstdc++/12048 (unget does not work)
2003-09-03 Petur Runolfsson <peturr02@ru.is>
PR libstdc++/12048
* include/ext/stdio_sync_filebuf.h
(stdio_sync_filebuf::_M_unget_buf): Declare it.
(stdio_sync_filebuf::stdio_sync_filebuf): Initialize _M_unget_buf.
(stdio_sync_filebuf::uflow): Store the returned character in
_M_unget_buf.
(stdio_sync_filebuf::pbackfail): If argument is eof(), pass
_M_unget_buf to syncungetc(). Set _M_unget_buf to eof().
(stdio_sync_filebuf<char>::xsgetn): Store last read character in
_M_unget_buf, if any, else eof().
(stdio_sync_filebuf<wchar_t>::xsgetn: Store last read character in
_M_unget_buf, if any, else eof().
* testsuite/27_io/objects/char/12048.cc: Rename to...
* testsuite/27_io/objects/char/12048-1.cc: ...this.
* testsuite/27_io/objects/char/12048-2.cc: New test.
* testsuite/27_io/objects/char/12048-3.cc: New test.
* testsuite/27_io/objects/char/12048-4.cc: New test.
* testsuite/27_io/objects/char/12048-5.cc: New test. XFAIL.
* testsuite/27_io/objects/wchar_t/12048-1.cc: New test.
* testsuite/27_io/objects/wchar_t/12048-2.cc: New test.
* testsuite/27_io/objects/wchar_t/12048-3.cc: New test.
* testsuite/27_io/objects/wchar_t/12048-4.cc: New test.
* testsuite/27_io/objects/wchar_t/12048-5.cc: New test. XFAIL.
* testsuite/ext/stdio_sync_filebuf_char.cc
(test02, test03, test04, test05): New tests.
* testsuite/ext/stdio_sync_filebuf_wchar_t.cc
(test02, test03, test04, test05): New tests.
2003-09-03 Petur Runolfsson <peturr02@ru.is>
* docs/html/27_io/howto.html: setbuf(0, 0) has no effect on
stringbuf or strstreambuf. Fix typos.
From-SVN: r71026
Diffstat (limited to 'libstdc++-v3/include/ext/stdio_sync_filebuf.h')
-rw-r--r-- | libstdc++-v3/include/ext/stdio_sync_filebuf.h | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/libstdc++-v3/include/ext/stdio_sync_filebuf.h b/libstdc++-v3/include/ext/stdio_sync_filebuf.h index 64ec2d9..7697d86 100644 --- a/libstdc++-v3/include/ext/stdio_sync_filebuf.h +++ b/libstdc++-v3/include/ext/stdio_sync_filebuf.h @@ -57,10 +57,7 @@ namespace __gnu_cxx template<typename _CharT, typename _Traits = std::char_traits<_CharT> > class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits> { - private: - std::__c_file* const _M_file; - - public: + public: // Types: typedef _CharT char_type; typedef _Traits traits_type; @@ -68,8 +65,19 @@ namespace __gnu_cxx typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; + private: + // Underlying stdio FILE + std::__c_file* const _M_file; + + // Last character gotten. This is used when pbackfail is + // called from basic_streambuf::sungetc() + int_type _M_unget_buf; + + public: explicit - stdio_sync_filebuf(std::__c_file* __f) : _M_file(__f) { } + stdio_sync_filebuf(std::__c_file* __f) + : _M_file(__f), _M_unget_buf(traits_type::eof()) + { } protected: @@ -91,11 +99,33 @@ namespace __gnu_cxx virtual int_type uflow() - { return this->syncgetc(); } + { + // Store the gotten character in case we need to unget it. + _M_unget_buf = this->syncgetc(); + return _M_unget_buf; + } virtual int_type pbackfail(int_type __c = traits_type::eof()) - { return this->syncungetc(__c); } + { + int_type __ret; + const int_type __eof = traits_type::eof(); + + // Check if the unget or putback was requested + if (traits_type::eq_int_type(__c, __eof)) // unget + { + if (!traits_type::eq_int_type(_M_unget_buf, __eof)) + __ret = this->syncungetc(_M_unget_buf); + else // buffer invalid, fail. + __ret = __eof; + } + else // putback + __ret = this->syncungetc(__c); + + // The buffered character is no longer valid, discard it. + _M_unget_buf = __eof; + return __ret; + } virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n); @@ -179,7 +209,14 @@ namespace __gnu_cxx template<> inline std::streamsize stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n) - { return std::fread(__s, 1, __n, _M_file); } + { + std::streamsize __ret = std::fread(__s, 1, __n, _M_file); + if (__ret > 0) + _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); + else + _M_unget_buf = traits_type::eof(); + return __ret; + } template<> inline std::streamsize @@ -213,9 +250,14 @@ namespace __gnu_cxx int_type __c = this->syncgetc(); if (traits_type::eq_int_type(__c, __eof)) break; - *__s++ = __c; + __s[__ret] = traits_type::to_char_type(__c); ++__ret; } + + if (__ret > 0) + _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); + else + _M_unget_buf = traits_type::eof(); return __ret; } |