This is the mail archive of the libstdc++@gcc.gnu.org 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]
Other format: [Raw text]

Re: std::advance istreambuf_iterator overload


On 09/11/17 22:12 +0100, François Dumont wrote:
Hi

    Working on istreambuf_iterator I realized that this iterator would really benefit from an std::advance overload so here it is.


    Tested under Linux x86_64 normal and debug modes, ok to commit ?

François


diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index 0a6c7f9..b60626a 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -417,6 +421,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
      return __last;
    }

+  template<typename _CharT, typename _Distance>
+    inline _GLIBCXX17_CONSTEXPR void

This function can never be constexpr.

+    advance(istreambuf_iterator<_CharT>& __i, _Distance __n)
+    {
+      if (__n == 0)
+	return;
+
+      __glibcxx_assert(__n > 0);
+      __glibcxx_requires_cond(!__i._M_at_eof(),
+			      _M_message(__gnu_debug::__msg_inc_istreambuf)
+			      ._M_iterator(__i));
+
+      typedef istreambuf_iterator<_CharT>		   __is_iterator_type;
+      typedef typename __is_iterator_type::traits_type	   traits_type;
+      typedef typename __is_iterator_type::streambuf_type  streambuf_type;
+      typedef typename traits_type::int_type		   int_type;
+      const int_type __eof = traits_type::eof();
+
+      streambuf_type* __sb = __i._M_sbuf;

This function relies on private members of istreambuf_iterator which
may not be present in a user-defined specialization of
istreambuf_iterator.

I think realistically you can only do this optimization for
istreambuf_iterator<char> and istreambuf_iterator<wchar_t>. Look at
how the std::copy and std::find overloads are contrained with
__is_char.

+      int_type __c = __sb->sgetc();
+      while (__n && !traits_type::eq_int_type(__c, __eof))

Can we use __n > 0 as the condition? Would it give better behaviour
for negative values in non-debug mode?

+	{
+	  streamsize __size = __sb->egptr() - __sb->gptr();
+	  if (__size > __n)
+	    {
+	      __sb->__safe_gbump(__n);
+	      __n = 0;
+	    }
+	  else if (__size > 1)
+	    {
+	      __sb->__safe_gbump(__size);
+	      __n -= __size;
+	      __c = __sb->underflow();
+	    }
+	  else
+	    {
+	      --__n;
+	      __c = __sb->snextc();
+	    }

It seems like it should be possible to optimize this loop, but I don't
see an obvious way to improve it.

+	}
+
+      __glibcxx_requires_cond(__n == 0,
+			      _M_message(__gnu_debug::__msg_inc_istreambuf)
+			      ._M_iterator(__i));
+      __i._M_c = __eof;
+      if (traits_type::eq_int_type(__c, __eof))
+	__i._M_sbuf = 0;
+    }
+


diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc b/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc
new file mode 100644
index 0000000..7c3f882
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/advance/istreambuf_iterators/char/1.cc

Thanks for the comprehensive tests, they look great.



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