xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/stream_iterator.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 // Stream iterators
2 
3 // Copyright (C) 2001-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/stream_iterator.h
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{iterator}
28  */
29 
30 #ifndef _STREAM_ITERATOR_H
31 #define _STREAM_ITERATOR_H 1
32 
33 #pragma GCC system_header
34 
35 #include <debug/debug.h>
36 
_GLIBCXX_VISIBILITY(default)37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
40 
41   /**
42    * @addtogroup iterators
43    * @{
44    */
45 
46 // Ignore warnings about std::iterator.
47 #pragma GCC diagnostic push
48 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
49 
50   /// Provides input iterator semantics for streams.
51   template<typename _Tp, typename _CharT = char,
52            typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t>
53     class istream_iterator
54     : public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&>
55     {
56     public:
57       typedef _CharT                         char_type;
58       typedef _Traits                        traits_type;
59       typedef basic_istream<_CharT, _Traits> istream_type;
60 
61     private:
62       istream_type*	_M_stream;
63       _Tp		_M_value;
64       // This bool becomes false at end-of-stream. It should be sufficient to
65       // check _M_stream != nullptr instead, but historically we did not set
66       // _M_stream to null when reaching the end, so we need to keep this flag.
67       bool		_M_ok;
68 
69     public:
70       ///  Construct end of input stream iterator.
71       _GLIBCXX_CONSTEXPR istream_iterator()
72       _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Tp>::value)
73       : _M_stream(0), _M_value(), _M_ok(false) {}
74 
75       ///  Construct start of input stream iterator.
76       istream_iterator(istream_type& __s)
77       : _M_stream(std::__addressof(__s)), _M_ok(true)
78       { _M_read(); }
79 
80       _GLIBCXX_CONSTEXPR
81       istream_iterator(const istream_iterator& __obj)
82       _GLIBCXX_NOEXCEPT_IF(is_nothrow_copy_constructible<_Tp>::value)
83       : _M_stream(__obj._M_stream), _M_value(__obj._M_value),
84         _M_ok(__obj._M_ok)
85       { }
86 
87 #if __cplusplus > 201703L && __cpp_lib_concepts
88       constexpr
89       istream_iterator(default_sentinel_t)
90       noexcept(is_nothrow_default_constructible_v<_Tp>)
91       : istream_iterator() { }
92 #endif
93 
94 #if __cplusplus >= 201103L
95       istream_iterator& operator=(const istream_iterator&) = default;
96       ~istream_iterator() = default;
97 #endif
98 
99       _GLIBCXX_NODISCARD
100       const _Tp&
101       operator*() const _GLIBCXX_NOEXCEPT
102       {
103 	__glibcxx_requires_cond(_M_ok,
104 				_M_message(__gnu_debug::__msg_deref_istream)
105 				._M_iterator(*this));
106 	return _M_value;
107       }
108 
109       _GLIBCXX_NODISCARD
110       const _Tp*
111       operator->() const _GLIBCXX_NOEXCEPT
112       { return std::__addressof((operator*())); }
113 
114       istream_iterator&
115       operator++()
116       {
117 	__glibcxx_requires_cond(_M_ok,
118 				_M_message(__gnu_debug::__msg_inc_istream)
119 				._M_iterator(*this));
120 	_M_read();
121 	return *this;
122       }
123 
124       istream_iterator
125       operator++(int)
126       {
127 	__glibcxx_requires_cond(_M_ok,
128 				_M_message(__gnu_debug::__msg_inc_istream)
129 				._M_iterator(*this));
130 	istream_iterator __tmp = *this;
131 	_M_read();
132 	return __tmp;
133       }
134 
135     private:
136       bool
137       _M_equal(const istream_iterator& __x) const _GLIBCXX_NOEXCEPT
138       {
139 	// Ideally this would just return _M_stream == __x._M_stream,
140 	// but code compiled with old versions never sets _M_stream to null.
141 	return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream);
142       }
143 
144       void
145       _M_read()
146       {
147         if (_M_stream && !(*_M_stream >> _M_value))
148           {
149             _M_stream = 0;
150             _M_ok = false;
151           }
152       }
153 
154       /// Return true if the iterators refer to the same stream,
155       /// or are both at end-of-stream.
156       _GLIBCXX_NODISCARD
157       friend bool
158       operator==(const istream_iterator& __x, const istream_iterator& __y)
159       _GLIBCXX_NOEXCEPT
160       { return __x._M_equal(__y); }
161 
162 #if __cpp_impl_three_way_comparison < 201907L
163       /// Return true if the iterators refer to different streams,
164       /// or if one is at end-of-stream and the other is not.
165       _GLIBCXX_NODISCARD
166       friend bool
167       operator!=(const istream_iterator& __x, const istream_iterator& __y)
168       _GLIBCXX_NOEXCEPT
169       { return !__x._M_equal(__y); }
170 #endif
171 
172 #if __cplusplus > 201703L && __cpp_lib_concepts
173       [[nodiscard]]
174       friend bool
175       operator==(const istream_iterator& __i, default_sentinel_t) noexcept
176       { return !__i._M_stream; }
177 #endif
178     };
179 
180   /**
181    *  @brief  Provides output iterator semantics for streams.
182    *
183    *  This class provides an iterator to write to an ostream.  The type Tp is
184    *  the only type written by this iterator and there must be an
185    *  operator<<(Tp) defined.
186    *
187    *  @tparam  _Tp  The type to write to the ostream.
188    *  @tparam  _CharT  The ostream char_type.
189    *  @tparam  _Traits  The ostream char_traits.
190   */
191   template<typename _Tp, typename _CharT = char,
192            typename _Traits = char_traits<_CharT> >
193     class ostream_iterator
194     : public iterator<output_iterator_tag, void, void, void, void>
195     {
196     public:
197       ///@{
198       /// Public typedef
199 #if __cplusplus > 201703L
200       using difference_type = ptrdiff_t;
201 #endif
202       typedef _CharT                         char_type;
203       typedef _Traits                        traits_type;
204       typedef basic_ostream<_CharT, _Traits> ostream_type;
205       ///@}
206 
207     private:
208       ostream_type*	_M_stream;
209       const _CharT*	_M_string;
210 
211     public:
212       /// Construct from an ostream.
213       ostream_iterator(ostream_type& __s) _GLIBCXX_NOEXCEPT
214       : _M_stream(std::__addressof(__s)), _M_string(0) {}
215 
216       /**
217        *  Construct from an ostream.
218        *
219        *  The delimiter string @a c is written to the stream after every Tp
220        *  written to the stream.  The delimiter is not copied, and thus must
221        *  not be destroyed while this iterator is in use.
222        *
223        *  @param  __s  Underlying ostream to write to.
224        *  @param  __c  CharT delimiter string to insert.
225       */
226       ostream_iterator(ostream_type& __s, const _CharT* __c) _GLIBCXX_NOEXCEPT
227       : _M_stream(std::__addressof(__s)), _M_string(__c)  { }
228 
229       /// Copy constructor.
230       ostream_iterator(const ostream_iterator& __obj) _GLIBCXX_NOEXCEPT
231       : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }
232 
233 #if __cplusplus >= 201103L
234       ostream_iterator& operator=(const ostream_iterator&) = default;
235 #endif
236 
237       /// Writes @a value to underlying ostream using operator<<.  If
238       /// constructed with delimiter string, writes delimiter to ostream.
239       ostream_iterator&
240       operator=(const _Tp& __value)
241       {
242 	__glibcxx_requires_cond(_M_stream != 0,
243 				_M_message(__gnu_debug::__msg_output_ostream)
244 				._M_iterator(*this));
245 	*_M_stream << __value;
246 	if (_M_string)
247           *_M_stream << _M_string;
248 	return *this;
249       }
250 
251       _GLIBCXX_NODISCARD
252       ostream_iterator&
253       operator*() _GLIBCXX_NOEXCEPT
254       { return *this; }
255 
256       ostream_iterator&
257       operator++() _GLIBCXX_NOEXCEPT
258       { return *this; }
259 
260       ostream_iterator&
261       operator++(int) _GLIBCXX_NOEXCEPT
262       { return *this; }
263     };
264 #pragma GCC diagnostic pop
265 
266   /// @} group iterators
267 
268 _GLIBCXX_END_NAMESPACE_VERSION
269 } // namespace
270 
271 #endif
272