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 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