diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 478f012def8..ec651e2cc45 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -771,6 +771,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _OutputIterator __result, random_access_iterator_tag) { return std::copy(__first, __first + __n, __result); } + template + typename enable_if<__is_char<_CharT>::__value, + _OutputIterator>::type + copy_n(istreambuf_iterator<_CharT, char_traits<_CharT> >, + _Size __n, _OutputIterator __result); + /** * @brief Copies the range [first,first+n) into [result,result+n). * @ingroup mutating_algorithms diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 2f4ff494a3a..c682fa91bde 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -80,6 +80,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __copy_move_a2(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, _CharT2*); +#if __cplusplus >= 201103L + template + friend typename enable_if<__is_char<_CharT2>::__value, + _OutputIterator>::type + copy_n(istreambuf_iterator<_CharT2>, _Size, _OutputIterator); +#endif + template friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, istreambuf_iterator<_CharT2> >::__type @@ -367,6 +374,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __result; } +#if __cplusplus >= 201103L + template + typename enable_if<__is_char<_CharT>::__value, _OutputIterator>::type + copy_n(istreambuf_iterator<_CharT> __it, _Size __n, + _OutputIterator __result) + { + if (__n == 0) + return __result; + + __glibcxx_assert(__n > 0); + __glibcxx_requires_cond(!__it._M_at_eof(), + _M_message(__gnu_debug::__msg_inc_istreambuf) + ._M_iterator(__it)); + + using traits_type = typename istreambuf_iterator<_CharT>::traits_type; + const auto __eof = traits_type::eof(); + + auto __sb = __it._M_sbuf; + while (__n > 0) + { + streamsize __size = __sb->egptr() - __sb->gptr(); + if (__size == 0) + { + if (traits_type::eq_int_type(__sb->underflow(), __eof)) + { + __glibcxx_requires_cond(__n == 0, + _M_message(__gnu_debug::__msg_inc_istreambuf) + ._M_iterator(__it)); + break; + } + + __size = __sb->egptr() - __sb->gptr(); + } + + streamsize __xsize = std::min(__size, __n); + __result = std::copy(__sb->gptr(), __sb->gptr() + __xsize, __result); + __sb->__safe_gbump(__xsize); + __n -= __xsize; + } + + return __result; + } +#endif + template typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, istreambuf_iterator<_CharT> >::__type diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf index d9ca981d704..4f62ebf4d95 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -155,6 +155,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __copy_move_a2(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, _CharT2*); +#if __cplusplus >= 201103L + template + friend typename enable_if<__is_char<_CharT2>::__value, + _OutputIterator>::type + copy_n(istreambuf_iterator<_CharT2>, _Size, _OutputIterator); +#endif + template friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, istreambuf_iterator<_CharT2> >::__type diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator.cc new file mode 100644 index 00000000000..ebd769cf7c0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2019 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 +// . + +// { dg-do run { target c++11 } } + +#include +#include +#include + +#include + +void test01() +{ + std::stringstream ss("12345"); + + std::string ostr(5, '0'); + typedef std::istreambuf_iterator istrb_ite; + std::copy_n(istrb_ite(ss), 0, ostr.begin()); + VERIFY( ostr.front() == '0' ); + + std::copy_n(istrb_ite(ss), 2, ostr.begin()); + VERIFY( ostr == "12000" ); + + std::copy_n(istrb_ite(ss), 3, ostr.begin() + 2); + VERIFY( ostr == "12345" ); +} + +void test02() +{ + std::stringstream ss("12345"); + + std::string ostr(5, '0'); + typedef std::istreambuf_iterator istrb_ite; + + istrb_ite ibfit(ss); + std::copy_n(ibfit, 3, std::copy_n(ibfit, 2, ostr.begin())); + VERIFY( ostr == "12345" ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator_neg.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator_neg.cc new file mode 100644 index 00000000000..42bc5b64306 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/istreambuf_iterator_neg.cc @@ -0,0 +1,40 @@ +// Copyright (C) 2019 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 +// . + +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode { } } + +#include +#include +#include + +#include + +void test01() +{ + std::stringstream ss("12345"); + + std::string ostr(10, '0'); + typedef std::istreambuf_iterator istrb_ite; + std::copy_n(istrb_ite(ss), 10, ostr.begin()); +} + +int main() +{ + test01(); + return 0; +}