public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
@ 2020-05-07  7:12 François Dumont
  2020-05-15  5:17 ` François Dumont
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: François Dumont @ 2020-05-07  7:12 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1805 bytes --]

     This patch purpose is to make sure that existing 
std::copy/std::copy_n overloads for char* will also be used for 
std::deque<char> iterators when dealing with istreambuf_iterator. It 
also make sure that it still works when _GLIBCXX_DEBUG is activated.

     * include/bits/stl_algo.h (__copy_n_a): Move to ...
     * include/bits/stl_algobase.h (__copy_n_a): ...here. Add __strict
     parameter.
     (__niter_base(const _Safe_iterator<_Ite, _Seq,
     random_access_iterator_tag>&)): New declaration.
     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
     _Deque_iterator<>)): New declaration.
     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
     New declaration.
     * include/bits/deque.tcc
     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
     _Deque_iterator<>)): Add definition.
     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
     Add definition.
     * include/bits/streambuf_iterator.h
     (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*, bool)): Adapt
     definition.
     * include/debug/safe_iterator.tcc (__niter_base): Add definition.
     * testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc (test03):
     New.
     * testsuite/25_algorithms/copy/streambuf_iterators/char/debug/
     deque_neg.cc: New.
     * testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc:
     New.
     * testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc: New.
     * testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc: New.

Already tested for a while on Linux x64 normal and debug modes but I am 
currently rebuilding everything and will commit only once all succeeded 
again.

Ok ?

François


[-- Attachment #2: deque_streambuf_ite.patch --]
[-- Type: text/x-patch, Size: 16095 bytes --]

diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index e773f32b256..45207066c48 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -1065,6 +1065,57 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
       return __result;
     }
 
+#if __cplusplus >= 201103L
+  template<bool _IsMove, typename _CharT>
+    __enable_if_t<__is_char<_CharT>::__value,
+		  _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>>
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __first,
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __last,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result)
+    {
+      if (__first == __last)
+	return __result;
+
+      for (;;)
+	{
+	  const auto __len = __result._M_last - __result._M_cur;
+	  const auto __nb
+	    = std::__copy_n_a(__first, __len, __result._M_cur, false)
+	    - __result._M_cur;
+	  __result += __nb;
+
+	  if (__nb != __len)
+	    break;
+	}
+
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    __enable_if_t<__is_char<_CharT>::__value,
+		  _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>>
+    __copy_n_a(
+      istreambuf_iterator<_CharT, char_traits<_CharT>> __it, _Size __size,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result,
+      bool __strict)
+    {
+      if (__size == 0)
+	return __result;
+
+      do
+	{
+	  const auto __len = std::min<_Size>(__result._M_last - __result._M_cur,
+					     __size);
+	  std::__copy_n_a(__it, __len, __result._M_cur, __strict);
+	  __result += __len;
+	  __size -= __len;
+	}
+      while (__size != 0);
+      return __result;
+    }
+#endif
+
   template<bool _IsMove,
 	   typename _Tp, typename _Ref, typename _Ptr, typename _OI>
     _OI
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 932ece55529..70d8232aece 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -705,31 +705,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __result;
     }
 
-  template<typename _InputIterator, typename _Size, typename _OutputIterator>
-    _GLIBCXX20_CONSTEXPR
-    _OutputIterator
-    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
-    {
-      if (__n > 0)
-	{
-	  while (true)
-	    {
-	      *__result = *__first;
-	      ++__result;
-	      if (--__n > 0)
-		++__first;
-	      else
-		break;
-	    }
-	}
-      return __result;
-    }
- 
-  template<typename _CharT, typename _Size>
-    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
-	       _Size, _CharT*);
-
   template<typename _InputIterator, typename _Size, typename _OutputIterator>
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
@@ -738,7 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       return std::__niter_wrap(__result,
 			       __copy_n_a(__first, __n,
-					  std::__niter_base(__result)));
+					  std::__niter_base(__result), true));
     }
 
   template<typename _RandomAccessIterator, typename _Size,
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index e52368c62a7..fb6b3ba6ae8 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -314,6 +314,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
     { return __it; }
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>&);
+
   // Reverse the __niter_base transformation to get a
   // __normal_iterator back again (this assumes that __normal_iterator
   // is only used to wrap random access iterators, like pointers).
@@ -466,6 +471,16 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
     __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >,
 		   istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*);
 
+#if __cplusplus >= 201103L
+  template<bool _IsMove, typename _CharT>
+    __enable_if_t<__is_char<_CharT>::__value,
+		  _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>>
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>);
+#endif
+
   template<bool _IsMove, typename _II, typename _OI>
     _GLIBCXX20_CONSTEXPR
     inline _OI
@@ -539,6 +554,41 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 		  const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&,
 		  const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&);
 
+#if __cplusplus >= 201103L
+  template<typename _InputIterator, typename _Size, typename _OutputIterator>
+    _GLIBCXX20_CONSTEXPR
+    _OutputIterator
+    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result,
+	       bool)
+    {
+      if (__n > 0)
+	{
+	  while (true)
+	    {
+	      *__result = *__first;
+	      ++__result;
+	      if (--__n > 0)
+		++__first;
+	      else
+		break;
+	    }
+	}
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
+	       _Size, _CharT*, bool);
+
+  template<typename _CharT, typename _Size>
+    __enable_if_t<__is_char<_CharT>::__value,
+		  _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>>
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>, _Size,
+	       _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>,
+	       bool);
+#endif
+
   /**
    *  @brief Copies the range [first,last) into result.
    *  @ingroup mutating_algorithms
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index d3f1610fc8d..7cdccbef960 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -85,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201103L
       template<typename _CharT2, typename _Size>
 	friend __enable_if_t<__is_char<_CharT2>::__value, _CharT2*>
-	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*);
+	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*, bool);
 #endif
 
       template<typename _CharT2>
@@ -399,7 +399,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201103L
   template<typename _CharT, typename _Size>
     __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result)
+    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result,
+	       bool __strict __attribute__((__unused__)))
     {
       if (__n == 0)
 	return __result;
@@ -409,7 +410,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			      ._M_iterator(__it));
       _CharT* __beg = __result;
       __result += __it._M_sbuf->sgetn(__beg, __n);
-      __glibcxx_requires_cond(__result - __beg == __n,
+      __glibcxx_requires_cond(!__strict || __result - __beg == __n,
 			      _M_message(__gnu_debug::__msg_inc_istreambuf)
 			      ._M_iterator(__it));
       return __result;
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index f90bbf3d125..ca4e2d52d1d 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -234,6 +234,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>& __it)
+    { return __it.base(); }
+
   template<bool _IsMove,
 	   typename _Ite, typename _Seq, typename _Cat, typename _OI>
     _OI
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
index fe04e9342e7..bc23497ff0e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <cstring>
 #include <vector>
+#include <deque>
 
 #include <testsuite_hooks.h>
 
@@ -76,9 +77,34 @@ void test02()
   VERIFY( !memcmp(buffer.data(), buffer_ref, 16500) );
 }
 
+void test03()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  std::deque<char> buffer(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  in_iterator_type end;
+  copy(beg, end, buffer.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( std::equal(buffer.begin(), buffer.end(), buffer_ref) );
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
new file mode 100644
index 00000000000..26627e37440
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <sstream>
+#include <deque>
+#include <algorithm>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  const char data1[] = "Drei Phantasien nach Friedrich Holderlin";
+  const string str1(data1);
+  istringstream iss1(str1);
+  in_iterator_type beg1(iss1);
+  in_iterator_type end1;
+  deque<char> d(sizeof(data1) - 2, '0');
+
+  copy(beg1, end1, d.begin());
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
new file mode 100644
index 00000000000..ede641820b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-fileio "" }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(17000, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 17000, dq.begin());
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
new file mode 100644
index 00000000000..5e1a0c2b75b
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <cstring>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500],
+       buffer[16501];
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, buffer);
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( !memcmp(buffer, buffer_ref, 16500) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
new file mode 100644
index 00000000000..ace73701b90
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, dq.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( equal(dq.begin(), dq.end(), buffer_ref) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-07  7:12 [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator François Dumont
@ 2020-05-15  5:17 ` François Dumont
  2020-05-19 19:12 ` François Dumont
  2020-05-21 12:17 ` Jonathan Wakely
  2 siblings, 0 replies; 11+ messages in thread
From: François Dumont @ 2020-05-15  5:17 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Now fully tested, ok to commit ?


On 07/05/20 9:12 am, François Dumont wrote:
>     This patch purpose is to make sure that existing 
> std::copy/std::copy_n overloads for char* will also be used for 
> std::deque<char> iterators when dealing with istreambuf_iterator. It 
> also make sure that it still works when _GLIBCXX_DEBUG is activated.
>
>     * include/bits/stl_algo.h (__copy_n_a): Move ...
>     * include/bits/stl_algobase.h (__copy_n_a): ...here. Add __strict
>     parameter.
>     (__niter_base(const _Safe_iterator<_Ite, _Seq,
>     random_access_iterator_tag>&)): New declaration.
>     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>     _Deque_iterator<>)): New declaration.
>     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>     New declaration.
>     * include/bits/deque.tcc
>     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>     _Deque_iterator<>)): Add definition.
>     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>     Add definition.
>     * include/bits/streambuf_iterator.h
>     (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*, bool)): Adapt
>     definition.
>     * include/debug/safe_iterator.tcc (__niter_base): Add definition.
>     * testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc 
> (test03):
>     New.
>     * testsuite/25_algorithms/copy/streambuf_iterators/char/debug/
>     deque_neg.cc: New.
>     * testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc:
>     New.
>     * testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc: New.
>     * testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc: New.
>
> Already tested for a while on Linux x64 normal and debug modes but I 
> am currently rebuilding everything and will commit only once all 
> succeeded again.
>
> Ok ?
>
> François
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-07  7:12 [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator François Dumont
  2020-05-15  5:17 ` François Dumont
@ 2020-05-19 19:12 ` François Dumont
  2020-05-21 12:17 ` Jonathan Wakely
  2 siblings, 0 replies; 11+ messages in thread
From: François Dumont @ 2020-05-19 19:12 UTC (permalink / raw)
  To: libstdc++, gcc-patches

No chance to review this ?


On 07/05/20 9:12 am, François Dumont wrote:
>     This patch purpose is to make sure that existing 
> std::copy/std::copy_n overloads for char* will also be used for 
> std::deque<char> iterators when dealing with istreambuf_iterator. It 
> also make sure that it still works when _GLIBCXX_DEBUG is activated.
>
>     * include/bits/stl_algo.h (__copy_n_a): Move to ...
>     * include/bits/stl_algobase.h (__copy_n_a): ...here. Add __strict
>     parameter.
>     (__niter_base(const _Safe_iterator<_Ite, _Seq,
>     random_access_iterator_tag>&)): New declaration.
>     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>     _Deque_iterator<>)): New declaration.
>     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>     New declaration.
>     * include/bits/deque.tcc
>     (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>     _Deque_iterator<>)): Add definition.
>     (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>     Add definition.
>     * include/bits/streambuf_iterator.h
>     (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*, bool)): Adapt
>     definition.
>     * include/debug/safe_iterator.tcc (__niter_base): Add definition.
>     * testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc 
> (test03):
>     New.
>     * testsuite/25_algorithms/copy/streambuf_iterators/char/debug/
>     deque_neg.cc: New.
>     * testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc:
>     New.
>     * testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc: New.
>     * testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc: New.
>
> Already tested for a while on Linux x64 normal and debug modes but I 
> am currently rebuilding everything and will commit only once all 
> succeeded again.
>
> Ok ?
>
> François
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-07  7:12 [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator François Dumont
  2020-05-15  5:17 ` François Dumont
  2020-05-19 19:12 ` François Dumont
@ 2020-05-21 12:17 ` Jonathan Wakely
  2020-05-22 20:57   ` François Dumont
  2 siblings, 1 reply; 11+ messages in thread
From: Jonathan Wakely @ 2020-05-21 12:17 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 07/05/20 09:12 +0200, François Dumont via Libstdc++ wrote:
>    This patch purpose is to make sure that existing 
>std::copy/std::copy_n overloads for char* will also be used for 
>std::deque<char> iterators when dealing with istreambuf_iterator. It 
>also make sure that it still works when _GLIBCXX_DEBUG is activated.
>
>    * include/bits/stl_algo.h (__copy_n_a): Move to ...
>    * include/bits/stl_algobase.h (__copy_n_a): ...here. Add __strict
>    parameter.
>    (__niter_base(const _Safe_iterator<_Ite, _Seq,
>    random_access_iterator_tag>&)): New declaration.
>    (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>    _Deque_iterator<>)): New declaration.
>    (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>    New declaration.
>    * include/bits/deque.tcc
>    (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
>    _Deque_iterator<>)): Add definition.
>    (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
>    Add definition.
>    * include/bits/streambuf_iterator.h
>    (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*, bool)): Adapt
>    definition.
>    * include/debug/safe_iterator.tcc (__niter_base): Add definition.
>    * testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc (test03):
>    New.
>    * testsuite/25_algorithms/copy/streambuf_iterators/char/debug/
>    deque_neg.cc: New.
>    * testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc:
>    New.
>    * testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc: New.
>    * testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc: New.
>
>Already tested for a while on Linux x64 normal and debug modes but I 
>am currently rebuilding everything and will commit only once all 
>succeeded again.
>
>Ok ?
>
>François
>

>diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
>index e773f32b256..45207066c48 100644
>--- a/libstdc++-v3/include/bits/deque.tcc
>+++ b/libstdc++-v3/include/bits/deque.tcc
>@@ -1065,6 +1065,57 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
>       return __result;
>     }
> 
>+#if __cplusplus >= 201103L

Why is the optimization not done for C++03 mode?

It looks like the uses of 'auto' can be reaplced easily, and
__enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-21 12:17 ` Jonathan Wakely
@ 2020-05-22 20:57   ` François Dumont
  2020-05-23 14:02     ` François Dumont
  2020-05-23 16:37     ` Jonathan Wakely
  0 siblings, 2 replies; 11+ messages in thread
From: François Dumont @ 2020-05-22 20:57 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 717 bytes --]

On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>
> Why is the optimization not done for C++03 mode?
>
I did it this way because the new std::copy overload rely on std::copy_n 
implementation details which is a C++11 algo.


> It looks like the uses of 'auto' can be reaplced easily, and
> __enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
>
But yes, we can indeed provide those implementation details in pre-C++11.

This is what I've done in this new version.

Tested under Linux x86_64 in default c++ mode.

I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even if I 
do see the option in build logs. I remember you adivised a different 
approach, can you tell me again ?

François


[-- Attachment #2: deque_streambuf_ite.patch --]
[-- Type: text/x-patch, Size: 16708 bytes --]

diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index e773f32b256..66ecd9da2f3 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -1065,6 +1065,57 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
       return __result;
     }
 
+  template<bool _IsMove, typename _CharT>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __first,
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __last,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result)
+    {
+      if (__first == __last)
+	return __result;
+
+      for (;;)
+	{
+	  const std::ptrdiff_t __len = __result._M_last - __result._M_cur;
+	  const std::ptrdiff_t __nb
+	    = std::__copy_n_a(__first, __len, __result._M_cur, false)
+	    - __result._M_cur;
+	  __result += __nb;
+
+	  if (__nb != __len)
+	    break;
+	}
+
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_n_a(
+      istreambuf_iterator<_CharT, char_traits<_CharT>> __it, _Size __size,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result,
+      bool __strict)
+    {
+      if (__size == 0)
+	return __result;
+
+      do
+	{
+	  const _Size __len
+	    = std::min<_Size>(__result._M_last - __result._M_cur, __size);
+	  std::__copy_n_a(__it, __len, __result._M_cur, __strict);
+	  __result += __len;
+	  __size -= __len;
+	}
+      while (__size != 0);
+      return __result;
+    }
+
   template<bool _IsMove,
 	   typename _Tp, typename _Ref, typename _Ptr, typename _OI>
     _OI
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 932ece55529..70d8232aece 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -705,31 +705,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __result;
     }
 
-  template<typename _InputIterator, typename _Size, typename _OutputIterator>
-    _GLIBCXX20_CONSTEXPR
-    _OutputIterator
-    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
-    {
-      if (__n > 0)
-	{
-	  while (true)
-	    {
-	      *__result = *__first;
-	      ++__result;
-	      if (--__n > 0)
-		++__first;
-	      else
-		break;
-	    }
-	}
-      return __result;
-    }
- 
-  template<typename _CharT, typename _Size>
-    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
-	       _Size, _CharT*);
-
   template<typename _InputIterator, typename _Size, typename _OutputIterator>
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
@@ -738,7 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       return std::__niter_wrap(__result,
 			       __copy_n_a(__first, __n,
-					  std::__niter_base(__result)));
+					  std::__niter_base(__result), true));
     }
 
   template<typename _RandomAccessIterator, typename _Size,
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d577ef0953b..ecc50a10c9d 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -314,6 +314,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
     { return __it; }
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>&);
+
   // Reverse the __niter_base transformation to get a
   // __normal_iterator back again (this assumes that __normal_iterator
   // is only used to wrap random access iterators, like pointers).
@@ -466,6 +471,15 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
     __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >,
 		   istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*);
 
+  template<bool _IsMove, typename _CharT>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>);
+
   template<bool _IsMove, typename _II, typename _OI>
     _GLIBCXX20_CONSTEXPR
     inline _OI
@@ -539,6 +553,41 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 		  const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&,
 		  const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&);
 
+  template<typename _InputIterator, typename _Size, typename _OutputIterator>
+    _GLIBCXX20_CONSTEXPR
+    _OutputIterator
+    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result,
+	       bool)
+    {
+      if (__n > 0)
+	{
+	  while (true)
+	    {
+	      *__result = *__first;
+	      ++__result;
+	      if (--__n > 0)
+		++__first;
+	      else
+		break;
+	    }
+	}
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value, _CharT*>::__type
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	       _Size, _CharT*, bool);
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >, _Size,
+	       _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>,
+	       bool);
+
   /**
    *  @brief Copies the range [first,last) into result.
    *  @ingroup mutating_algorithms
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index d3f1610fc8d..184c82cd5bf 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -82,11 +82,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__copy_move_a2(istreambuf_iterator<_CharT2>,
 		       istreambuf_iterator<_CharT2>, _CharT2*);
 
-#if __cplusplus >= 201103L
       template<typename _CharT2, typename _Size>
-	friend __enable_if_t<__is_char<_CharT2>::__value, _CharT2*>
-	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*);
-#endif
+	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
+					       _CharT2*>::__type
+	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*, bool);
 
       template<typename _CharT2>
 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
@@ -396,10 +395,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __result;
     }
 
-#if __cplusplus >= 201103L
   template<typename _CharT, typename _Size>
-    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result)
+    typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
+				    _CharT*>::__type
+    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result,
+	       bool __strict __attribute__((__unused__)))
     {
       if (__n == 0)
 	return __result;
@@ -409,12 +409,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			      ._M_iterator(__it));
       _CharT* __beg = __result;
       __result += __it._M_sbuf->sgetn(__beg, __n);
-      __glibcxx_requires_cond(__result - __beg == __n,
+      __glibcxx_requires_cond(!__strict || __result - __beg == __n,
 			      _M_message(__gnu_debug::__msg_inc_istreambuf)
 			      ._M_iterator(__it));
       return __result;
     }
-#endif // C++11
 
   template<typename _CharT>
     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index f90bbf3d125..ca4e2d52d1d 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -234,6 +234,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>& __it)
+    { return __it.base(); }
+
   template<bool _IsMove,
 	   typename _Ite, typename _Seq, typename _Cat, typename _OI>
     _OI
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
index fe04e9342e7..bc23497ff0e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <cstring>
 #include <vector>
+#include <deque>
 
 #include <testsuite_hooks.h>
 
@@ -76,9 +77,34 @@ void test02()
   VERIFY( !memcmp(buffer.data(), buffer_ref, 16500) );
 }
 
+void test03()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  std::deque<char> buffer(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  in_iterator_type end;
+  copy(beg, end, buffer.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( std::equal(buffer.begin(), buffer.end(), buffer_ref) );
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
new file mode 100644
index 00000000000..26627e37440
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <sstream>
+#include <deque>
+#include <algorithm>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  const char data1[] = "Drei Phantasien nach Friedrich Holderlin";
+  const string str1(data1);
+  istringstream iss1(str1);
+  in_iterator_type beg1(iss1);
+  in_iterator_type end1;
+  deque<char> d(sizeof(data1) - 2, '0');
+
+  copy(beg1, end1, d.begin());
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
new file mode 100644
index 00000000000..ede641820b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-fileio "" }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(17000, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 17000, dq.begin());
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
new file mode 100644
index 00000000000..5e1a0c2b75b
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <cstring>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500],
+       buffer[16501];
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, buffer);
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( !memcmp(buffer, buffer_ref, 16500) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
new file mode 100644
index 00000000000..ace73701b90
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, dq.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( equal(dq.begin(), dq.end(), buffer_ref) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-22 20:57   ` François Dumont
@ 2020-05-23 14:02     ` François Dumont
  2020-05-23 16:37     ` Jonathan Wakely
  1 sibling, 0 replies; 11+ messages in thread
From: François Dumont @ 2020-05-23 14:02 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On 22/05/20 10:57 pm, François Dumont wrote:
> On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>>
>> Why is the optimization not done for C++03 mode?
>>
> I did it this way because the new std::copy overload rely on 
> std::copy_n implementation details which is a C++11 algo.
>
>
>> It looks like the uses of 'auto' can be reaplced easily, and
>> __enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
>>
> But yes, we can indeed provide those implementation details in pre-C++11.
>
> This is what I've done in this new version.


Note that I expose all __copy_n_a overloads in stl_algobase.h and not 
only the overload needed for the std::copy. Let me know if you prefer to 
limit it.


>
> Tested under Linux x86_64 in default c++ mode.
>
> I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even if 
> I do see the option in build logs. I remember you adivised a different 
> approach, can you tell me again ?
>
> François
>
I forgot to mention that "doesn't seem to work" above means that all 
C++11 or higher tests are reported as FAIL in this case. I was expecting 
an UNSUPPORTED.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-22 20:57   ` François Dumont
  2020-05-23 14:02     ` François Dumont
@ 2020-05-23 16:37     ` Jonathan Wakely
  2020-05-24 13:43       ` François Dumont
  1 sibling, 1 reply; 11+ messages in thread
From: Jonathan Wakely @ 2020-05-23 16:37 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 22/05/20 22:57 +0200, François Dumont via Libstdc++ wrote:
>On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>>
>>Why is the optimization not done for C++03 mode?
>>
>I did it this way because the new std::copy overload rely on 
>std::copy_n implementation details which is a C++11 algo.
>
>
>>It looks like the uses of 'auto' can be reaplced easily, and
>>__enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
>>
>But yes, we can indeed provide those implementation details in pre-C++11.
>
>This is what I've done in this new version.
>
>Tested under Linux x86_64 in default c++ mode.
>
>I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even if 
>I do see the option in build logs. I remember you adivised a different 
>approach, can you tell me again ?

See the documentation:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-23 16:37     ` Jonathan Wakely
@ 2020-05-24 13:43       ` François Dumont
  2020-05-26 11:45         ` François Dumont
  2020-06-02 20:15         ` Jonathan Wakely
  0 siblings, 2 replies; 11+ messages in thread
From: François Dumont @ 2020-05-24 13:43 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1238 bytes --]

Now tested in C++98 mode, there was indeed a small problem.

I even wonder if I shouldn't have extend the std::copy overload to any 
call with deque iterator as the output so that it is transform into an 
output to pointer.

Ok to commit ?

François

On 23/05/20 6:37 pm, Jonathan Wakely wrote:
> On 22/05/20 22:57 +0200, François Dumont via Libstdc++ wrote:
>> On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>>>
>>> Why is the optimization not done for C++03 mode?
>>>
>> I did it this way because the new std::copy overload rely on 
>> std::copy_n implementation details which is a C++11 algo.
>>
>>
>>> It looks like the uses of 'auto' can be reaplced easily, and
>>> __enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
>>>
>> But yes, we can indeed provide those implementation details in 
>> pre-C++11.
>>
>> This is what I've done in this new version.
>>
>> Tested under Linux x86_64 in default c++ mode.
>>
>> I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even 
>> if I do see the option in build logs. I remember you adivised a 
>> different approach, can you tell me again ?
>
> See the documentation:
> https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations 
>
>
>


[-- Attachment #2: deque_streambuf_ite.patch --]
[-- Type: text/x-patch, Size: 16709 bytes --]

diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index e773f32b256..d7dbe64f3e1 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -1065,6 +1065,57 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
       return __result;
     }
 
+  template<bool _IsMove, typename _CharT>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __first,
+	istreambuf_iterator<_CharT, char_traits<_CharT> > __last,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result)
+    {
+      if (__first == __last)
+	return __result;
+
+      for (;;)
+	{
+	  const std::ptrdiff_t __len = __result._M_last - __result._M_cur;
+	  const std::ptrdiff_t __nb
+	    = std::__copy_n_a(__first, __len, __result._M_cur, false)
+	    - __result._M_cur;
+	  __result += __nb;
+
+	  if (__nb != __len)
+	    break;
+	}
+
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_n_a(
+      istreambuf_iterator<_CharT, char_traits<_CharT> > __it, _Size __size,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result,
+      bool __strict)
+    {
+      if (__size == 0)
+	return __result;
+
+      do
+	{
+	  const _Size __len
+	    = std::min<_Size>(__result._M_last - __result._M_cur, __size);
+	  std::__copy_n_a(__it, __len, __result._M_cur, __strict);
+	  __result += __len;
+	  __size -= __len;
+	}
+      while (__size != 0);
+      return __result;
+    }
+
   template<bool _IsMove,
 	   typename _Tp, typename _Ref, typename _Ptr, typename _OI>
     _OI
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 932ece55529..70d8232aece 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -705,31 +705,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __result;
     }
 
-  template<typename _InputIterator, typename _Size, typename _OutputIterator>
-    _GLIBCXX20_CONSTEXPR
-    _OutputIterator
-    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
-    {
-      if (__n > 0)
-	{
-	  while (true)
-	    {
-	      *__result = *__first;
-	      ++__result;
-	      if (--__n > 0)
-		++__first;
-	      else
-		break;
-	    }
-	}
-      return __result;
-    }
- 
-  template<typename _CharT, typename _Size>
-    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
-	       _Size, _CharT*);
-
   template<typename _InputIterator, typename _Size, typename _OutputIterator>
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
@@ -738,7 +713,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       return std::__niter_wrap(__result,
 			       __copy_n_a(__first, __n,
-					  std::__niter_base(__result)));
+					  std::__niter_base(__result), true));
     }
 
   template<typename _RandomAccessIterator, typename _Size,
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d577ef0953b..ecc50a10c9d 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -314,6 +314,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
     { return __it; }
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>&);
+
   // Reverse the __niter_base transformation to get a
   // __normal_iterator back again (this assumes that __normal_iterator
   // is only used to wrap random access iterators, like pointers).
@@ -466,6 +471,15 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
     __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >,
 		   istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*);
 
+  template<bool _IsMove, typename _CharT>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_move_a2(
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	_GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>);
+
   template<bool _IsMove, typename _II, typename _OI>
     _GLIBCXX20_CONSTEXPR
     inline _OI
@@ -539,6 +553,41 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 		  const ::__gnu_debug::_Safe_iterator<_IIte, _ISeq, _ICat>&,
 		  const ::__gnu_debug::_Safe_iterator<_OIte, _OSeq, _OCat>&);
 
+  template<typename _InputIterator, typename _Size, typename _OutputIterator>
+    _GLIBCXX20_CONSTEXPR
+    _OutputIterator
+    __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result,
+	       bool)
+    {
+      if (__n > 0)
+	{
+	  while (true)
+	    {
+	      *__result = *__first;
+	      ++__result;
+	      if (--__n > 0)
+		++__first;
+	      else
+		break;
+	    }
+	}
+      return __result;
+    }
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value, _CharT*>::__type
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >,
+	       _Size, _CharT*, bool);
+
+  template<typename _CharT, typename _Size>
+    typename __gnu_cxx::__enable_if<
+      __is_char<_CharT>::__value,
+      _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type
+    __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT> >, _Size,
+	       _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*>,
+	       bool);
+
   /**
    *  @brief Copies the range [first,last) into result.
    *  @ingroup mutating_algorithms
diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h
index d3f1610fc8d..184c82cd5bf 100644
--- a/libstdc++-v3/include/bits/streambuf_iterator.h
+++ b/libstdc++-v3/include/bits/streambuf_iterator.h
@@ -82,11 +82,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__copy_move_a2(istreambuf_iterator<_CharT2>,
 		       istreambuf_iterator<_CharT2>, _CharT2*);
 
-#if __cplusplus >= 201103L
       template<typename _CharT2, typename _Size>
-	friend __enable_if_t<__is_char<_CharT2>::__value, _CharT2*>
-	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*);
-#endif
+	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
+					       _CharT2*>::__type
+	__copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*, bool);
 
       template<typename _CharT2>
 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
@@ -396,10 +395,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __result;
     }
 
-#if __cplusplus >= 201103L
   template<typename _CharT, typename _Size>
-    __enable_if_t<__is_char<_CharT>::__value, _CharT*>
-    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result)
+    typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
+				    _CharT*>::__type
+    __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result,
+	       bool __strict __attribute__((__unused__)))
     {
       if (__n == 0)
 	return __result;
@@ -409,12 +409,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			      ._M_iterator(__it));
       _CharT* __beg = __result;
       __result += __it._M_sbuf->sgetn(__beg, __n);
-      __glibcxx_requires_cond(__result - __beg == __n,
+      __glibcxx_requires_cond(!__strict || __result - __beg == __n,
 			      _M_message(__gnu_debug::__msg_inc_istreambuf)
 			      ._M_iterator(__it));
       return __result;
     }
-#endif // C++11
 
   template<typename _CharT>
     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index f90bbf3d125..ca4e2d52d1d 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -234,6 +234,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+  template<typename _Ite, typename _Seq>
+    _Ite
+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+		 std::random_access_iterator_tag>& __it)
+    { return __it.base(); }
+
   template<bool _IsMove,
 	   typename _Ite, typename _Seq, typename _Cat, typename _OI>
     _OI
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
index fe04e9342e7..bc23497ff0e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <cstring>
 #include <vector>
+#include <deque>
 
 #include <testsuite_hooks.h>
 
@@ -76,9 +77,34 @@ void test02()
   VERIFY( !memcmp(buffer.data(), buffer_ref, 16500) );
 }
 
+void test03()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  std::deque<char> buffer(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  in_iterator_type end;
+  copy(beg, end, buffer.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( std::equal(buffer.begin(), buffer.end(), buffer_ref) );
+}
+
 int main()
 {
   test01();
   test02();
+  test03();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
new file mode 100644
index 00000000000..26627e37440
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <sstream>
+#include <deque>
+#include <algorithm>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  const char data1[] = "Drei Phantasien nach Friedrich Holderlin";
+  const string str1(data1);
+  istringstream iss1(str1);
+  in_iterator_type beg1(iss1);
+  in_iterator_type end1;
+  deque<char> d(sizeof(data1) - 2, '0');
+
+  copy(beg1, end1, d.begin());
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
new file mode 100644
index 00000000000..ede641820b5
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-fileio "" }
+// { dg-require-debug-mode "" }
+
+#include <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(17000, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 17000, dq.begin());
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
new file mode 100644
index 00000000000..5e1a0c2b75b
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <cstring>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500],
+       buffer[16501];
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, buffer);
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( !memcmp(buffer, buffer_ref, 16500) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
new file mode 100644
index 00000000000..ace73701b90
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++11 } }
+// { dg-require-fileio "" }
+
+// Copyright (C) 2020 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 <iterator>
+#include <fstream>
+#include <algorithm>
+#include <deque>
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std;
+
+  typedef istreambuf_iterator<char> in_iterator_type;
+
+  ifstream fbuf_ref("istream_unformatted-1.txt"),
+	   fbuf("istream_unformatted-1.txt");
+
+  char buffer_ref[16500];
+  deque<char> dq(16500, 'a');
+
+  fbuf_ref.read(buffer_ref, 16500);
+
+  in_iterator_type beg(fbuf);
+  copy_n(beg, 16500, dq.begin());
+
+  VERIFY( fbuf_ref.good() );
+  VERIFY( fbuf.good() );
+
+  VERIFY( equal(dq.begin(), dq.end(), buffer_ref) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-24 13:43       ` François Dumont
@ 2020-05-26 11:45         ` François Dumont
  2020-06-02 14:20           ` François Dumont
  2020-06-02 20:15         ` Jonathan Wakely
  1 sibling, 1 reply; 11+ messages in thread
From: François Dumont @ 2020-05-26 11:45 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On 24/05/20 3:43 pm, François Dumont wrote:
> Now tested in C++98 mode, there was indeed a small problem.
>
> I even wonder if I shouldn't have extend the std::copy overload to any 
> call with deque iterator as the output so that it is transform into an 
> output to pointer.


Ignore this remark, I had a look and we already have an overload that 
does that. It is limited to RA iterators and is just fine.


>
> Ok to commit ?
>
> François
>
> On 23/05/20 6:37 pm, Jonathan Wakely wrote:
>> On 22/05/20 22:57 +0200, François Dumont via Libstdc++ wrote:
>>> On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>>>>
>>>> Why is the optimization not done for C++03 mode?
>>>>
>>> I did it this way because the new std::copy overload rely on 
>>> std::copy_n implementation details which is a C++11 algo.
>>>
>>>
>>>> It looks like the uses of 'auto' can be reaplced easily, and
>>>> __enable_if_t<> can be replaced with __gnu_cxx::__enable_if<>::__type.
>>>>
>>> But yes, we can indeed provide those implementation details in 
>>> pre-C++11.
>>>
>>> This is what I've done in this new version.
>>>
>>> Tested under Linux x86_64 in default c++ mode.
>>>
>>> I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even 
>>> if I do see the option in build logs. I remember you adivised a 
>>> different approach, can you tell me again ?
>>
>> See the documentation:
>> https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations 
>>
>>
>>
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-26 11:45         ` François Dumont
@ 2020-06-02 14:20           ` François Dumont
  0 siblings, 0 replies; 11+ messages in thread
From: François Dumont @ 2020-06-02 14:20 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

Hi

Any feedback regarding this patch ?

François


On 26/05/20 1:45 pm, François Dumont wrote:
> On 24/05/20 3:43 pm, François Dumont wrote:
>> Now tested in C++98 mode, there was indeed a small problem.
>>
>> I even wonder if I shouldn't have extend the std::copy overload to 
>> any call with deque iterator as the output so that it is transform 
>> into an output to pointer.
>
>
> Ignore this remark, I had a look and we already have an overload that 
> does that. It is limited to RA iterators and is just fine.
>
>
>>
>> Ok to commit ?
>>
>> François
>>
>> On 23/05/20 6:37 pm, Jonathan Wakely wrote:
>>> On 22/05/20 22:57 +0200, François Dumont via Libstdc++ wrote:
>>>> On 21/05/20 2:17 pm, Jonathan Wakely wrote:
>>>>>
>>>>> Why is the optimization not done for C++03 mode?
>>>>>
>>>> I did it this way because the new std::copy overload rely on 
>>>> std::copy_n implementation details which is a C++11 algo.
>>>>
>>>>
>>>>> It looks like the uses of 'auto' can be reaplced easily, and
>>>>> __enable_if_t<> can be replaced with 
>>>>> __gnu_cxx::__enable_if<>::__type.
>>>>>
>>>> But yes, we can indeed provide those implementation details in 
>>>> pre-C++11.
>>>>
>>>> This is what I've done in this new version.
>>>>
>>>> Tested under Linux x86_64 in default c++ mode.
>>>>
>>>> I tried to use CXXFLAGS=-std=c++03 but it doesn't seem to work even 
>>>> if I do see the option in build logs. I remember you adivised a 
>>>> different approach, can you tell me again ?
>>>
>>> See the documentation:
>>> https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations 
>>>
>>>
>>>
>>
>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator
  2020-05-24 13:43       ` François Dumont
  2020-05-26 11:45         ` François Dumont
@ 2020-06-02 20:15         ` Jonathan Wakely
  1 sibling, 0 replies; 11+ messages in thread
From: Jonathan Wakely @ 2020-06-02 20:15 UTC (permalink / raw)
  To: François Dumont; +Cc: libstdc++, gcc-patches

On 24/05/20 15:43 +0200, François Dumont via Libstdc++ wrote:
>Now tested in C++98 mode, there was indeed a small problem.
>
>I even wonder if I shouldn't have extend the std::copy overload to any 
>call with deque iterator as the output so that it is transform into an 
>output to pointer.
>
>Ok to commit ?



>--- a/libstdc++-v3/include/debug/safe_iterator.tcc
>+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
>@@ -234,6 +234,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
> {
> _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 
>+  template<typename _Ite, typename _Seq>
>+    _Ite
>+    __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
>+		 std::random_access_iterator_tag>& __it)
>+    { return __it.base(); }
>+

I was going to ask if there's a reason this uses "_Ite" and not
"_Iter", but I see we already have several uses of that.

Thy all seem to be introduced by you though :-)

We definitely have a lot more "_Iter" uses though:

$ git grep -w _Ite -- include/ | wc -l
46
$ git grep -w _Iter -- include/ | wc -l
835

When I see "Ite" it looks to me as though it should rhyme with "sight"
or "white", rather than "Iter" which rhymes with "bitter" (and so is
the start of "iterator").

Leave it as _Ite for now, I might go through and change every _Ite to
_Iter later.


OK for master, thanks.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-06-02 20:15 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-07  7:12 [PATCH] Extend std::copy/std::copy_n char* overload to deque iterator François Dumont
2020-05-15  5:17 ` François Dumont
2020-05-19 19:12 ` François Dumont
2020-05-21 12:17 ` Jonathan Wakely
2020-05-22 20:57   ` François Dumont
2020-05-23 14:02     ` François Dumont
2020-05-23 16:37     ` Jonathan Wakely
2020-05-24 13:43       ` François Dumont
2020-05-26 11:45         ` François Dumont
2020-06-02 14:20           ` François Dumont
2020-06-02 20:15         ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).