[gcc(refs/users/guojiufu/heads/personal-branch)] libstdc++: Specialize copy/copy_n for istreambuf_iterator and deque iterators

Jiu Fu Guo guojiufu@gcc.gnu.org
Wed Jun 10 03:38:11 GMT 2020


https://gcc.gnu.org/g:4e05c918d28e3fa66f5baaf556f6886447c68c9a

commit 4e05c918d28e3fa66f5baaf556f6886447c68c9a
Author: François Dumont <fdumont@gcc.gnu.org>
Date:   Wed Jan 22 18:21:28 2020 +0100

    libstdc++: Specialize copy/copy_n for istreambuf_iterator and deque iterators
    
    Add __copy_n_a overloads for std::deque iterators to replace with C memmove
    when possible. Expose std::copy_n implementation details in pre-C++11 modes
    and use it for std::copy overloads.
    
    libstdc++-v3/ChangeLog
    
            * include/bits/stl_algo.h (__copy_n_a): Move to ...
            * include/bits/stl_algobase.h (__copy_n_a): ...here. Add __strict
            parameter.
            (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
            Declare.
            (__niter_base(const _Safe_iterator<_Ite, _Seq,
            random_access_iterator_tag>&)): Declare.
            (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
            _Deque_iterator<>)): Declare.
            * include/bits/deque.tcc
            (__copy_move_a2(istreambuf_iterator<>, istreambuf_iterator<>,
            _Deque_iterator<>)): New.
            (__copy_n_a(istreambuf_iterator<>, _Size, _Deque_iterator<>, bool)):
            New.
            * include/bits/streambuf_iterator.h
            (__copy_n_a(istreambuf_iterator<>, _Size, _CharT*, bool)): Adapt.
            * include/debug/safe_iterator.tcc (__niter_base): New.
            * testsuite/25_algorithms/copy/streambuf_iterators/char/4.cc
            (test03): New.
            * testsuite/25_algorithms/copy/streambuf_iterators/char/debug/deque_neg.cc:
            New test.
            * testsuite/25_algorithms/copy_n/debug/istreambuf_ite_deque_neg.cc:
            New test.
            * testsuite/25_algorithms/copy_n/istreambuf_iterator/2.cc: New test.
            * testsuite/25_algorithms/copy_n/istreambuf_iterator/deque.cc:
            New test.

Diff:
---
 libstdc++-v3/include/bits/deque.tcc                | 51 ++++++++++++++++++++
 libstdc++-v3/include/bits/stl_algo.h               | 27 +----------
 libstdc++-v3/include/bits/stl_algobase.h           | 49 +++++++++++++++++++
 libstdc++-v3/include/bits/streambuf_iterator.h     | 17 ++++---
 libstdc++-v3/include/debug/safe_iterator.tcc       |  6 +++
 .../copy/streambuf_iterators/char/4.cc             | 26 ++++++++++
 .../streambuf_iterators/char/debug/deque_neg.cc    | 46 ++++++++++++++++++
 .../copy_n/debug/istreambuf_ite_deque_neg.cc       | 50 +++++++++++++++++++
 .../25_algorithms/copy_n/istreambuf_iterator/2.cc  | 56 ++++++++++++++++++++++
 .../copy_n/istreambuf_iterator/deque.cc            | 56 ++++++++++++++++++++++
 10 files changed, 349 insertions(+), 35 deletions(-)

diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc
index b4943e8ea77..1d32a1691c7 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 b743c87cb80..fd6edd0d5f4 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 0a0e29923b8..0163d8f902d 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 312a88911ee..888ac803ae5 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;
+}


More information about the Libstdc++-cvs mailing list