[PATCH] libstdc++: istreambuf_iterator keep attached streambuf
Petr Ovtchenkov
ptr@void-ptr.info
Sat Sep 23 07:10:00 GMT 2017
istreambuf_iterator should not forget about attached
streambuf when it reach EOF.
Checks in debug mode has no infuence more on character
extraction in istreambuf_iterator increment operators.
In this aspect behaviour in debug and non-debug mode
is similar now.
Test for detached srteambuf in istreambuf_iterator:
When istreambuf_iterator reach EOF of istream, it should not
forget about attached streambuf.
>From fact "EOF in stream reached" not follow that
stream reach end of life and input operation impossible
more.
---
libstdc++-v3/include/bits/streambuf_iterator.h | 41 +++++++--------
.../24_iterators/istreambuf_iterator/3.cc | 61 ++++++++++++++++++++++
2 files changed, 80 insertions(+), 22 deletions(-)
create mode 100644 libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index f0451b1..45c3d89 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -136,12 +136,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
istreambuf_iterator&
operator++()
{
- __glibcxx_requires_cond(!_M_at_eof(),
+ __glibcxx_requires_cond(_M_sbuf,
_M_message(__gnu_debug::__msg_inc_istreambuf)
._M_iterator(*this));
if (_M_sbuf)
{
+#ifdef _GLIBCXX_DEBUG_PEDANTIC
+ int_type _tmp =
+#endif
_M_sbuf->sbumpc();
+#ifdef _GLIBCXX_DEBUG_PEDANTIC
+ __glibcxx_requires_cond(!traits_type::eq_int_type(_tmp,traits_type::eof()),
+ _M_message(__gnu_debug::__msg_inc_istreambuf)
+ ._M_iterator(*this));
+#endif
_M_c = traits_type::eof();
}
return *this;
@@ -151,14 +159,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
istreambuf_iterator
operator++(int)
{
- __glibcxx_requires_cond(!_M_at_eof(),
+ _M_get();
+ __glibcxx_requires_cond(_M_sbuf
+ && !traits_type::eq_int_type(_M_c,traits_type::eof()),
_M_message(__gnu_debug::__msg_inc_istreambuf)
._M_iterator(*this));
istreambuf_iterator __old = *this;
if (_M_sbuf)
{
- __old._M_c = _M_sbuf->sbumpc();
+ _M_sbuf->sbumpc();
_M_c = traits_type::eof();
}
return __old;
@@ -177,18 +187,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_get() const
{
const int_type __eof = traits_type::eof();
- int_type __ret = __eof;
- if (_M_sbuf)
- {
- if (!traits_type::eq_int_type(_M_c, __eof))
- __ret = _M_c;
- else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
- __eof))
- _M_c = __ret;
- else
- _M_sbuf = 0;
- }
- return __ret;
+ if (_M_sbuf && traits_type::eq_int_type(_M_c, __eof))
+ _M_c = _M_sbuf->sgetc();
+ return _M_c;
}
bool
@@ -339,7 +340,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename __is_iterator_type::streambuf_type streambuf_type;
typedef typename traits_type::int_type int_type;
- if (__first._M_sbuf && !__last._M_sbuf)
+ if (__first._M_sbuf && (__last == istreambuf_iterator<_CharT>()))
{
streambuf_type* __sb = __first._M_sbuf;
int_type __c = __sb->sgetc();
@@ -374,7 +375,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename __is_iterator_type::streambuf_type streambuf_type;
typedef typename traits_type::int_type int_type;
- if (__first._M_sbuf && !__last._M_sbuf)
+ if (__first._M_sbuf && (__last == istreambuf_iterator<_CharT>()))
{
const int_type __ival = traits_type::to_int_type(__val);
streambuf_type* __sb = __first._M_sbuf;
@@ -395,11 +396,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
else
__c = __sb->snextc();
}
-
- if (!traits_type::eq_int_type(__c, traits_type::eof()))
- __first._M_c = __c;
- else
- __first._M_sbuf = 0;
+ __first._M_c = __c;
}
return __first;
}
diff --git a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc
new file mode 100644
index 0000000..803ede4
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/3.cc
@@ -0,0 +1,61 @@
+// { dg-options "-std=gnu++17" }
+
+// Copyright (C) 2017 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <algorithm>
+#include <sstream>
+#include <iterator>
+#include <cstring>
+#include <testsuite_hooks.h>
+
+void test03()
+{
+ using namespace std;
+ bool test __attribute__((unused)) = true;
+
+ std::stringstream s;
+ char b[] = "c2ee3d09-43b3-466d-b490-db35999a22cf";
+ char r[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ char q[] = "3c4852d6-d47b-4f46-b05e-b5edc1aa440e";
+ // 012345678901234567890123456789012345
+ // 0 1 2 3
+ s << b;
+ VERIFY( !s.fail() );
+
+ istreambuf_iterator<char> i(s);
+ copy_n(i, 36, r);
+ ++i; // EOF reached
+ VERIFY(i == std::istreambuf_iterator<char>());
+
+ VERIFY(memcmp(b, r, 36) == 0);
+
+ s << q;
+ VERIFY(!s.fail());
+
+ copy_n(i, 36, r);
+ ++i; // EOF reached
+ VERIFY(i == std::istreambuf_iterator<char>());
+
+ VERIFY(memcmp(q, r, 36) == 0);
+}
+
+int main()
+{
+ test03();
+ return 0;
+}
--
2.10.1
More information about the Libstdc++
mailing list