mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 23:25:24 +02:00
This adds required headers to a few internal headers that currently assume their deps will be included first. It's more robust to make them include their own dependencies, so that later refactoring or reuse of those headers in new contexts doesn't break. libstdc++-v3/ChangeLog: * include/bits/stl_algo.h: Include <bits/stl_algobase.h>. * include/bits/stl_tempbuf.h: Include headers for __try and __catch macros, std::pair, and __gnu_cxx::__numeric_traits. * include/bits/stream_iterator.h: Include <iosfwd> and headers for std::addressof and std::iterator. * include/bits/streambuf_iterator.h: Include header for std::iterator. * include/std/iterator: Do not include <iosfwd>.
521 lines
16 KiB
C++
521 lines
16 KiB
C++
// Streambuf iterators
|
|
|
|
// Copyright (C) 1997-2022 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.
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/** @file bits/streambuf_iterator.h
|
|
* This is an internal header file, included by other library headers.
|
|
* Do not attempt to use it directly. @headername{iterator}
|
|
*/
|
|
|
|
#ifndef _STREAMBUF_ITERATOR_H
|
|
#define _STREAMBUF_ITERATOR_H 1
|
|
|
|
#pragma GCC system_header
|
|
|
|
#include <streambuf>
|
|
#include <bits/stl_iterator_base_types.h>
|
|
#include <debug/debug.h>
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
/**
|
|
* @addtogroup iterators
|
|
* @{
|
|
*/
|
|
|
|
// Ignore warnings about std::iterator.
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
// 24.5.3 Template class istreambuf_iterator
|
|
/// Provides input iterator semantics for streambufs.
|
|
template<typename _CharT, typename _Traits>
|
|
class istreambuf_iterator
|
|
: public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
|
|
_CharT*, _CharT>
|
|
{
|
|
public:
|
|
// Types:
|
|
///@{
|
|
/// Public typedefs
|
|
#if __cplusplus < 201103L
|
|
typedef _CharT& reference; // Changed to _CharT by LWG 445
|
|
#elif __cplusplus > 201703L
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3188. istreambuf_iterator::pointer should not be unspecified
|
|
using pointer = void;
|
|
#endif
|
|
|
|
typedef _CharT char_type;
|
|
typedef _Traits traits_type;
|
|
typedef typename _Traits::int_type int_type;
|
|
typedef basic_streambuf<_CharT, _Traits> streambuf_type;
|
|
typedef basic_istream<_CharT, _Traits> istream_type;
|
|
///@}
|
|
|
|
template<typename _CharT2>
|
|
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
|
|
ostreambuf_iterator<_CharT2> >::__type
|
|
copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
|
|
ostreambuf_iterator<_CharT2>);
|
|
|
|
template<bool _IsMove, typename _CharT2>
|
|
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
|
|
_CharT2*>::__type
|
|
__copy_move_a2(istreambuf_iterator<_CharT2>,
|
|
istreambuf_iterator<_CharT2>, _CharT2*);
|
|
|
|
template<typename _CharT2, typename _Size>
|
|
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,
|
|
istreambuf_iterator<_CharT2> >::__type
|
|
find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
|
|
const _CharT2&);
|
|
|
|
template<typename _CharT2, typename _Distance>
|
|
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
|
|
void>::__type
|
|
advance(istreambuf_iterator<_CharT2>&, _Distance);
|
|
|
|
private:
|
|
// 24.5.3 istreambuf_iterator
|
|
// p 1
|
|
// If the end of stream is reached (streambuf_type::sgetc()
|
|
// returns traits_type::eof()), the iterator becomes equal to
|
|
// the "end of stream" iterator value.
|
|
// NB: This implementation assumes the "end of stream" value
|
|
// is EOF, or -1.
|
|
mutable streambuf_type* _M_sbuf;
|
|
int_type _M_c;
|
|
|
|
public:
|
|
/// Construct end of input stream iterator.
|
|
_GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT
|
|
: _M_sbuf(0), _M_c(traits_type::eof()) { }
|
|
|
|
#if __cplusplus > 201703L && __cpp_lib_concepts
|
|
constexpr istreambuf_iterator(default_sentinel_t) noexcept
|
|
: istreambuf_iterator() { }
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
|
|
|
|
~istreambuf_iterator() = default;
|
|
#endif
|
|
|
|
/// Construct start of input stream iterator.
|
|
istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
|
|
: _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
|
|
|
|
/// Construct start of streambuf iterator.
|
|
istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
|
|
: _M_sbuf(__s), _M_c(traits_type::eof()) { }
|
|
|
|
#if __cplusplus >= 201103L
|
|
istreambuf_iterator&
|
|
operator=(const istreambuf_iterator&) noexcept = default;
|
|
#endif
|
|
|
|
/// Return the current character pointed to by iterator. This returns
|
|
/// streambuf.sgetc(). It cannot be assigned. NB: The result of
|
|
/// operator*() on an end of stream is undefined.
|
|
_GLIBCXX_NODISCARD
|
|
char_type
|
|
operator*() const
|
|
{
|
|
int_type __c = _M_get();
|
|
|
|
#ifdef _GLIBCXX_DEBUG_PEDANTIC
|
|
// Dereferencing a past-the-end istreambuf_iterator is a
|
|
// libstdc++ extension
|
|
__glibcxx_requires_cond(!_S_is_eof(__c),
|
|
_M_message(__gnu_debug::__msg_deref_istreambuf)
|
|
._M_iterator(*this));
|
|
#endif
|
|
return traits_type::to_char_type(__c);
|
|
}
|
|
|
|
/// Advance the iterator. Calls streambuf.sbumpc().
|
|
istreambuf_iterator&
|
|
operator++()
|
|
{
|
|
__glibcxx_requires_cond(_M_sbuf &&
|
|
(!_S_is_eof(_M_c) || !_S_is_eof(_M_sbuf->sgetc())),
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(*this));
|
|
|
|
_M_sbuf->sbumpc();
|
|
_M_c = traits_type::eof();
|
|
return *this;
|
|
}
|
|
|
|
/// Advance the iterator. Calls streambuf.sbumpc().
|
|
istreambuf_iterator
|
|
operator++(int)
|
|
{
|
|
__glibcxx_requires_cond(_M_sbuf &&
|
|
(!_S_is_eof(_M_c) || !_S_is_eof(_M_sbuf->sgetc())),
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(*this));
|
|
|
|
istreambuf_iterator __old = *this;
|
|
__old._M_c = _M_sbuf->sbumpc();
|
|
_M_c = traits_type::eof();
|
|
return __old;
|
|
}
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 110 istreambuf_iterator::equal not const
|
|
// NB: there is also number 111 (NAD) relevant to this function.
|
|
/// Return true both iterators are end or both are not end.
|
|
_GLIBCXX_NODISCARD
|
|
bool
|
|
equal(const istreambuf_iterator& __b) const
|
|
{ return _M_at_eof() == __b._M_at_eof(); }
|
|
|
|
private:
|
|
int_type
|
|
_M_get() const
|
|
{
|
|
int_type __ret = _M_c;
|
|
if (_M_sbuf && _S_is_eof(__ret) && _S_is_eof(__ret = _M_sbuf->sgetc()))
|
|
_M_sbuf = 0;
|
|
return __ret;
|
|
}
|
|
|
|
bool
|
|
_M_at_eof() const
|
|
{ return _S_is_eof(_M_get()); }
|
|
|
|
static bool
|
|
_S_is_eof(int_type __c)
|
|
{
|
|
const int_type __eof = traits_type::eof();
|
|
return traits_type::eq_int_type(__c, __eof);
|
|
}
|
|
|
|
#if __cplusplus > 201703L && __cpp_lib_concepts
|
|
[[nodiscard]]
|
|
friend bool
|
|
operator==(const istreambuf_iterator& __i, default_sentinel_t __s)
|
|
{ return __i._M_at_eof(); }
|
|
#endif
|
|
};
|
|
|
|
template<typename _CharT, typename _Traits>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
|
|
const istreambuf_iterator<_CharT, _Traits>& __b)
|
|
{ return __a.equal(__b); }
|
|
|
|
#if __cpp_impl_three_way_comparison < 201907L
|
|
template<typename _CharT, typename _Traits>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
|
|
const istreambuf_iterator<_CharT, _Traits>& __b)
|
|
{ return !__a.equal(__b); }
|
|
#endif
|
|
|
|
/// Provides output iterator semantics for streambufs.
|
|
template<typename _CharT, typename _Traits>
|
|
class ostreambuf_iterator
|
|
: public iterator<output_iterator_tag, void, void, void, void>
|
|
{
|
|
public:
|
|
// Types:
|
|
///@{
|
|
/// Public typedefs
|
|
#if __cplusplus > 201703L
|
|
using difference_type = ptrdiff_t;
|
|
#endif
|
|
typedef _CharT char_type;
|
|
typedef _Traits traits_type;
|
|
typedef basic_streambuf<_CharT, _Traits> streambuf_type;
|
|
typedef basic_ostream<_CharT, _Traits> ostream_type;
|
|
///@}
|
|
|
|
template<typename _CharT2>
|
|
friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
|
|
ostreambuf_iterator<_CharT2> >::__type
|
|
copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
|
|
ostreambuf_iterator<_CharT2>);
|
|
|
|
private:
|
|
streambuf_type* _M_sbuf;
|
|
bool _M_failed;
|
|
|
|
public:
|
|
|
|
#if __cplusplus > 201703L
|
|
constexpr
|
|
ostreambuf_iterator() noexcept
|
|
: _M_sbuf(nullptr), _M_failed(true) { }
|
|
#endif
|
|
|
|
/// Construct output iterator from ostream.
|
|
ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT
|
|
: _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
|
|
|
|
/// Construct output iterator from streambuf.
|
|
ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
|
|
: _M_sbuf(__s), _M_failed(!_M_sbuf) { }
|
|
|
|
/// Write character to streambuf. Calls streambuf.sputc().
|
|
ostreambuf_iterator&
|
|
operator=(_CharT __c)
|
|
{
|
|
if (!_M_failed &&
|
|
_Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
|
|
_M_failed = true;
|
|
return *this;
|
|
}
|
|
|
|
/// Return *this.
|
|
_GLIBCXX_NODISCARD
|
|
ostreambuf_iterator&
|
|
operator*()
|
|
{ return *this; }
|
|
|
|
/// Return *this.
|
|
ostreambuf_iterator&
|
|
operator++(int)
|
|
{ return *this; }
|
|
|
|
/// Return *this.
|
|
ostreambuf_iterator&
|
|
operator++()
|
|
{ return *this; }
|
|
|
|
/// Return true if previous operator=() failed.
|
|
_GLIBCXX_NODISCARD
|
|
bool
|
|
failed() const _GLIBCXX_USE_NOEXCEPT
|
|
{ return _M_failed; }
|
|
|
|
ostreambuf_iterator&
|
|
_M_put(const _CharT* __ws, streamsize __len)
|
|
{
|
|
if (__builtin_expect(!_M_failed, true)
|
|
&& __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
|
|
false))
|
|
_M_failed = true;
|
|
return *this;
|
|
}
|
|
};
|
|
#pragma GCC diagnostic pop
|
|
|
|
// Overloads for streambuf iterators.
|
|
template<typename _CharT>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
ostreambuf_iterator<_CharT> >::__type
|
|
copy(istreambuf_iterator<_CharT> __first,
|
|
istreambuf_iterator<_CharT> __last,
|
|
ostreambuf_iterator<_CharT> __result)
|
|
{
|
|
if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
|
|
{
|
|
bool __ineof;
|
|
__copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
|
|
if (!__ineof)
|
|
__result._M_failed = true;
|
|
}
|
|
return __result;
|
|
}
|
|
|
|
template<bool _IsMove, typename _CharT>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
ostreambuf_iterator<_CharT> >::__type
|
|
__copy_move_a2(_CharT* __first, _CharT* __last,
|
|
ostreambuf_iterator<_CharT> __result)
|
|
{
|
|
const streamsize __num = __last - __first;
|
|
if (__num > 0)
|
|
__result._M_put(__first, __num);
|
|
return __result;
|
|
}
|
|
|
|
template<bool _IsMove, typename _CharT>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
ostreambuf_iterator<_CharT> >::__type
|
|
__copy_move_a2(const _CharT* __first, const _CharT* __last,
|
|
ostreambuf_iterator<_CharT> __result)
|
|
{
|
|
const streamsize __num = __last - __first;
|
|
if (__num > 0)
|
|
__result._M_put(__first, __num);
|
|
return __result;
|
|
}
|
|
|
|
template<bool _IsMove, typename _CharT>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
_CharT*>::__type
|
|
__copy_move_a2(istreambuf_iterator<_CharT> __first,
|
|
istreambuf_iterator<_CharT> __last, _CharT* __result)
|
|
{
|
|
typedef istreambuf_iterator<_CharT> __is_iterator_type;
|
|
typedef typename __is_iterator_type::traits_type traits_type;
|
|
typedef typename __is_iterator_type::streambuf_type streambuf_type;
|
|
typedef typename traits_type::int_type int_type;
|
|
|
|
if (__first._M_sbuf && !__last._M_sbuf)
|
|
{
|
|
streambuf_type* __sb = __first._M_sbuf;
|
|
int_type __c = __sb->sgetc();
|
|
while (!traits_type::eq_int_type(__c, traits_type::eof()))
|
|
{
|
|
const streamsize __n = __sb->egptr() - __sb->gptr();
|
|
if (__n > 1)
|
|
{
|
|
traits_type::copy(__result, __sb->gptr(), __n);
|
|
__sb->__safe_gbump(__n);
|
|
__result += __n;
|
|
__c = __sb->underflow();
|
|
}
|
|
else
|
|
{
|
|
*__result++ = traits_type::to_char_type(__c);
|
|
__c = __sb->snextc();
|
|
}
|
|
}
|
|
}
|
|
return __result;
|
|
}
|
|
|
|
template<typename _CharT, typename _Size>
|
|
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;
|
|
|
|
__glibcxx_requires_cond(__it._M_sbuf,
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(__it));
|
|
_CharT* __beg = __result;
|
|
__result += __it._M_sbuf->sgetn(__beg, __n);
|
|
__glibcxx_requires_cond(!__strict || __result - __beg == __n,
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(__it));
|
|
return __result;
|
|
}
|
|
|
|
template<typename _CharT>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
istreambuf_iterator<_CharT> >::__type
|
|
find(istreambuf_iterator<_CharT> __first,
|
|
istreambuf_iterator<_CharT> __last, const _CharT& __val)
|
|
{
|
|
typedef istreambuf_iterator<_CharT> __is_iterator_type;
|
|
typedef typename __is_iterator_type::traits_type traits_type;
|
|
typedef typename __is_iterator_type::streambuf_type streambuf_type;
|
|
typedef typename traits_type::int_type int_type;
|
|
const int_type __eof = traits_type::eof();
|
|
|
|
if (__first._M_sbuf && !__last._M_sbuf)
|
|
{
|
|
const int_type __ival = traits_type::to_int_type(__val);
|
|
streambuf_type* __sb = __first._M_sbuf;
|
|
int_type __c = __sb->sgetc();
|
|
while (!traits_type::eq_int_type(__c, __eof)
|
|
&& !traits_type::eq_int_type(__c, __ival))
|
|
{
|
|
streamsize __n = __sb->egptr() - __sb->gptr();
|
|
if (__n > 1)
|
|
{
|
|
const _CharT* __p = traits_type::find(__sb->gptr(),
|
|
__n, __val);
|
|
if (__p)
|
|
__n = __p - __sb->gptr();
|
|
__sb->__safe_gbump(__n);
|
|
__c = __sb->sgetc();
|
|
}
|
|
else
|
|
__c = __sb->snextc();
|
|
}
|
|
|
|
__first._M_c = __eof;
|
|
}
|
|
|
|
return __first;
|
|
}
|
|
|
|
template<typename _CharT, typename _Distance>
|
|
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
|
|
void>::__type
|
|
advance(istreambuf_iterator<_CharT>& __i, _Distance __n)
|
|
{
|
|
if (__n == 0)
|
|
return;
|
|
|
|
__glibcxx_assert(__n > 0);
|
|
__glibcxx_requires_cond(!__i._M_at_eof(),
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(__i));
|
|
|
|
typedef istreambuf_iterator<_CharT> __is_iterator_type;
|
|
typedef typename __is_iterator_type::traits_type traits_type;
|
|
typedef typename __is_iterator_type::streambuf_type streambuf_type;
|
|
typedef typename traits_type::int_type int_type;
|
|
const int_type __eof = traits_type::eof();
|
|
|
|
streambuf_type* __sb = __i._M_sbuf;
|
|
while (__n > 0)
|
|
{
|
|
streamsize __size = __sb->egptr() - __sb->gptr();
|
|
if (__size > __n)
|
|
{
|
|
__sb->__safe_gbump(__n);
|
|
break;
|
|
}
|
|
|
|
__sb->__safe_gbump(__size);
|
|
__n -= __size;
|
|
if (traits_type::eq_int_type(__sb->underflow(), __eof))
|
|
{
|
|
__glibcxx_requires_cond(__n == 0,
|
|
_M_message(__gnu_debug::__msg_inc_istreambuf)
|
|
._M_iterator(__i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
__i._M_c = __eof;
|
|
}
|
|
|
|
/// @} group iterators
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace
|
|
|
|
#endif
|