diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index afe967e5f03..1f6613e9ef6 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -257,6 +257,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, ostreambuf_iterator<_CharT2>); + template + friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, + void>::__type + advance(ostreambuf_iterator<_CharT2>&, _Distance); + private: streambuf_type* _M_sbuf; bool _M_failed; @@ -405,7 +410,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, - istreambuf_iterator<_CharT> >::__type + istreambuf_iterator<_CharT> >::__type find(istreambuf_iterator<_CharT> __first, istreambuf_iterator<_CharT> __last, const _CharT& __val) { @@ -475,6 +480,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + void>::__type + advance(ostreambuf_iterator<_CharT>& __i, _Distance __n) + { + if (__n == 0) + return; + + __glibcxx_assert(__n > 0); + __glibcxx_requires_cond(!__i.failed(), + _M_message(__gnu_debug::__msg_advance_oob) + ._M_iterator(__i) + ._M_integer(__n)); + + typedef basic_streambuf<_CharT> __streambuf_t; + typedef typename __streambuf_t::pos_type __pos_t; + __pos_t __cur_pos + = __i._M_sbuf->pubseekoff(0, ios_base::cur, ios_base::out); + __pos_t __new_pos = + __i._M_sbuf->pubseekoff(__n, ios_base::cur, ios_base::out); + + if (__new_pos - __cur_pos != __n) + { + __i._M_failed = true; + __glibcxx_requires_cond(!__i.failed(), + _M_message(__gnu_debug::__msg_advance_oob) + ._M_iterator(__i) + ._M_integer(__n)); + } + } + // @} group iterators _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1.cc b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1.cc new file mode 100644 index 00000000000..dd70cc67c75 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1.cc @@ -0,0 +1,55 @@ +// 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 +// . + +#include +#include +#include + +#include + +void test01() +{ + using namespace std; + + const char data1[] = "Drei Phantasien nach Friedrich Holderlin"; + string str1(data1); + str1[17] = 'i'; + + ostringstream oss1(str1); + ostreambuf_iterator beg1(oss1); + + std::advance(beg1, 17); + *beg1 = 'a'; + + VERIFY( !beg1.failed() ); + VERIFY( oss1.str() == data1 ); + str1 = oss1.str(); + + // -1 for the trailing '\0' + // -1 for the beg1 assignment. + std::advance(beg1, sizeof(data1) - 17 - 1 - 1); + *beg1 = '.'; + + str1 += '.'; + VERIFY( oss1.str() == str1 ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1_neg.cc b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1_neg.cc new file mode 100644 index 00000000000..8d266256ed3 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/1_neg.cc @@ -0,0 +1,40 @@ +// 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 +// . + +// { dg-do run { xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include +#include +#include + +void test01() +{ + using namespace std; + + const char data1[] = "Drei Phantasien nach Friedrich Holderlin"; + ostringstream oss1(data1); + ostreambuf_iterator beg1(oss1); + + advance(beg1, -1); // Error. +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2.cc b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2.cc new file mode 100644 index 00000000000..147ff24b728 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2.cc @@ -0,0 +1,47 @@ +// 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 +// . + +// Debug mode would detect the invalid std::advance call. +// { dg-require-normal-mode "" } + +#include +#include +#include + +#include + +void test01() +{ + using namespace std; + + const char data1[] = "Drei Phantasien nach Friedrich Holderlin"; + + ostringstream oss1(data1); + ostreambuf_iterator beg1(oss1); + + VERIFY( !beg1.failed() ); + + std::advance(beg1, sizeof(data1)); + + VERIFY( beg1.failed() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2_neg.cc b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2_neg.cc new file mode 100644 index 00000000000..ffb2238354a --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/advance/ostreambuf_iterator/char/2_neg.cc @@ -0,0 +1,40 @@ +// 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 +// . + +// { dg-do run { xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include +#include +#include + +void test01() +{ + using namespace std; + + const char data1[] = "Drei Phantasien nach Friedrich Holderlin"; + ostringstream oss1(data1); + ostreambuf_iterator beg1(oss1); + + advance(beg1, sizeof(data1)); // Error. +} + +int main() +{ + test01(); + return 0; +}