1 // Streambuf iterators 2 3 // Copyright (C) 1997-2013 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/streambuf_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 _STREAMBUF_ITERATOR_H 31 #define _STREAMBUF_ITERATOR_H 1 32 33 #pragma GCC system_header 34 35 #include <streambuf> 36 #include <debug/debug.h> 37 38 namespace std _GLIBCXX_VISIBILITY(default) 39 { 40 _GLIBCXX_BEGIN_NAMESPACE_VERSION 41 42 /** 43 * @addtogroup iterators 44 * @{ 45 */ 46 47 // 24.5.3 Template class istreambuf_iterator 48 /// Provides input iterator semantics for streambufs. 49 template<typename _CharT, typename _Traits> 50 class istreambuf_iterator 51 : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type, 52 _CharT*, 53 #if __cplusplus >= 201103L 54 // LWG 445. 55 _CharT> 56 #else 57 _CharT&> 58 #endif 59 { 60 public: 61 // Types: 62 //@{ 63 /// Public typedefs 64 typedef _CharT char_type; 65 typedef _Traits traits_type; 66 typedef typename _Traits::int_type int_type; 67 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 68 typedef basic_istream<_CharT, _Traits> istream_type; 69 //@} 70 71 template<typename _CharT2> 72 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 73 ostreambuf_iterator<_CharT2> >::__type 74 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 75 ostreambuf_iterator<_CharT2>); 76 77 template<bool _IsMove, typename _CharT2> 78 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 79 _CharT2*>::__type 80 __copy_move_a2(istreambuf_iterator<_CharT2>, 81 istreambuf_iterator<_CharT2>, _CharT2*); 82 83 template<typename _CharT2> 84 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 85 istreambuf_iterator<_CharT2> >::__type 86 find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 87 const _CharT2&); 88 89 private: 90 // 24.5.3 istreambuf_iterator 91 // p 1 92 // If the end of stream is reached (streambuf_type::sgetc() 93 // returns traits_type::eof()), the iterator becomes equal to 94 // the "end of stream" iterator value. 95 // NB: This implementation assumes the "end of stream" value 96 // is EOF, or -1. 97 mutable streambuf_type* _M_sbuf; 98 mutable int_type _M_c; 99 100 public: 101 /// Construct end of input stream iterator. 102 _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT 103 : _M_sbuf(0), _M_c(traits_type::eof()) { } 104 105 #if __cplusplus >= 201103L 106 istreambuf_iterator(const istreambuf_iterator&) noexcept = default; 107 108 ~istreambuf_iterator() = default; 109 #endif 110 111 /// Construct start of input stream iterator. 112 istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT 113 : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { } 114 115 /// Construct start of streambuf iterator. 116 istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT 117 : _M_sbuf(__s), _M_c(traits_type::eof()) { } 118 119 /// Return the current character pointed to by iterator. This returns 120 /// streambuf.sgetc(). It cannot be assigned. NB: The result of 121 /// operator*() on an end of stream is undefined. 122 char_type 123 operator*() const 124 { 125 #ifdef _GLIBCXX_DEBUG_PEDANTIC 126 // Dereferencing a past-the-end istreambuf_iterator is a 127 // libstdc++ extension 128 __glibcxx_requires_cond(!_M_at_eof(), 129 _M_message(__gnu_debug::__msg_deref_istreambuf) 130 ._M_iterator(*this)); 131 #endif 132 return traits_type::to_char_type(_M_get()); 133 } 134 135 /// Advance the iterator. Calls streambuf.sbumpc(). 136 istreambuf_iterator& 137 operator++() 138 { 139 __glibcxx_requires_cond(!_M_at_eof(), 140 _M_message(__gnu_debug::__msg_inc_istreambuf) 141 ._M_iterator(*this)); 142 if (_M_sbuf) 143 { 144 _M_sbuf->sbumpc(); 145 _M_c = traits_type::eof(); 146 } 147 return *this; 148 } 149 150 /// Advance the iterator. Calls streambuf.sbumpc(). 151 istreambuf_iterator 152 operator++(int) 153 { 154 __glibcxx_requires_cond(!_M_at_eof(), 155 _M_message(__gnu_debug::__msg_inc_istreambuf) 156 ._M_iterator(*this)); 157 158 istreambuf_iterator __old = *this; 159 if (_M_sbuf) 160 { 161 __old._M_c = _M_sbuf->sbumpc(); 162 _M_c = traits_type::eof(); 163 } 164 return __old; 165 } 166 167 // _GLIBCXX_RESOLVE_LIB_DEFECTS 168 // 110 istreambuf_iterator::equal not const 169 // NB: there is also number 111 (NAD, Future) pending on this function. 170 /// Return true both iterators are end or both are not end. 171 bool 172 equal(const istreambuf_iterator& __b) const 173 { return _M_at_eof() == __b._M_at_eof(); } 174 175 private: 176 int_type 177 _M_get() const 178 { 179 const int_type __eof = traits_type::eof(); 180 int_type __ret = __eof; 181 if (_M_sbuf) 182 { 183 if (!traits_type::eq_int_type(_M_c, __eof)) 184 __ret = _M_c; 185 else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()), 186 __eof)) 187 _M_c = __ret; 188 else 189 _M_sbuf = 0; 190 } 191 return __ret; 192 } 193 194 bool 195 _M_at_eof() const 196 { 197 const int_type __eof = traits_type::eof(); 198 return traits_type::eq_int_type(_M_get(), __eof); 199 } 200 }; 201 202 template<typename _CharT, typename _Traits> 203 inline bool 204 operator==(const istreambuf_iterator<_CharT, _Traits>& __a, 205 const istreambuf_iterator<_CharT, _Traits>& __b) 206 { return __a.equal(__b); } 207 208 template<typename _CharT, typename _Traits> 209 inline bool 210 operator!=(const istreambuf_iterator<_CharT, _Traits>& __a, 211 const istreambuf_iterator<_CharT, _Traits>& __b) 212 { return !__a.equal(__b); } 213 214 /// Provides output iterator semantics for streambufs. 215 template<typename _CharT, typename _Traits> 216 class ostreambuf_iterator 217 : public iterator<output_iterator_tag, void, void, void, void> 218 { 219 public: 220 // Types: 221 //@{ 222 /// Public typedefs 223 typedef _CharT char_type; 224 typedef _Traits traits_type; 225 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 226 typedef basic_ostream<_CharT, _Traits> ostream_type; 227 //@} 228 229 template<typename _CharT2> 230 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 231 ostreambuf_iterator<_CharT2> >::__type 232 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 233 ostreambuf_iterator<_CharT2>); 234 235 private: 236 streambuf_type* _M_sbuf; 237 bool _M_failed; 238 239 public: 240 /// Construct output iterator from ostream. 241 ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT 242 : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } 243 244 /// Construct output iterator from streambuf. 245 ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT 246 : _M_sbuf(__s), _M_failed(!_M_sbuf) { } 247 248 /// Write character to streambuf. Calls streambuf.sputc(). 249 ostreambuf_iterator& 250 operator=(_CharT __c) 251 { 252 if (!_M_failed && 253 _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof())) 254 _M_failed = true; 255 return *this; 256 } 257 258 /// Return *this. 259 ostreambuf_iterator& 260 operator*() 261 { return *this; } 262 263 /// Return *this. 264 ostreambuf_iterator& 265 operator++(int) 266 { return *this; } 267 268 /// Return *this. 269 ostreambuf_iterator& 270 operator++() 271 { return *this; } 272 273 /// Return true if previous operator=() failed. 274 bool 275 failed() const _GLIBCXX_USE_NOEXCEPT 276 { return _M_failed; } 277 278 ostreambuf_iterator& 279 _M_put(const _CharT* __ws, streamsize __len) 280 { 281 if (__builtin_expect(!_M_failed, true) 282 && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len, 283 false)) 284 _M_failed = true; 285 return *this; 286 } 287 }; 288 289 // Overloads for streambuf iterators. 290 template<typename _CharT> 291 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 292 ostreambuf_iterator<_CharT> >::__type 293 copy(istreambuf_iterator<_CharT> __first, 294 istreambuf_iterator<_CharT> __last, 295 ostreambuf_iterator<_CharT> __result) 296 { 297 if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed) 298 { 299 bool __ineof; 300 __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof); 301 if (!__ineof) 302 __result._M_failed = true; 303 } 304 return __result; 305 } 306 307 template<bool _IsMove, typename _CharT> 308 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 309 ostreambuf_iterator<_CharT> >::__type 310 __copy_move_a2(_CharT* __first, _CharT* __last, 311 ostreambuf_iterator<_CharT> __result) 312 { 313 const streamsize __num = __last - __first; 314 if (__num > 0) 315 __result._M_put(__first, __num); 316 return __result; 317 } 318 319 template<bool _IsMove, typename _CharT> 320 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 321 ostreambuf_iterator<_CharT> >::__type 322 __copy_move_a2(const _CharT* __first, const _CharT* __last, 323 ostreambuf_iterator<_CharT> __result) 324 { 325 const streamsize __num = __last - __first; 326 if (__num > 0) 327 __result._M_put(__first, __num); 328 return __result; 329 } 330 331 template<bool _IsMove, typename _CharT> 332 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 333 _CharT*>::__type 334 __copy_move_a2(istreambuf_iterator<_CharT> __first, 335 istreambuf_iterator<_CharT> __last, _CharT* __result) 336 { 337 typedef istreambuf_iterator<_CharT> __is_iterator_type; 338 typedef typename __is_iterator_type::traits_type traits_type; 339 typedef typename __is_iterator_type::streambuf_type streambuf_type; 340 typedef typename traits_type::int_type int_type; 341 342 if (__first._M_sbuf && !__last._M_sbuf) 343 { 344 streambuf_type* __sb = __first._M_sbuf; 345 int_type __c = __sb->sgetc(); 346 while (!traits_type::eq_int_type(__c, traits_type::eof())) 347 { 348 const streamsize __n = __sb->egptr() - __sb->gptr(); 349 if (__n > 1) 350 { 351 traits_type::copy(__result, __sb->gptr(), __n); 352 __sb->__safe_gbump(__n); 353 __result += __n; 354 __c = __sb->underflow(); 355 } 356 else 357 { 358 *__result++ = traits_type::to_char_type(__c); 359 __c = __sb->snextc(); 360 } 361 } 362 } 363 return __result; 364 } 365 366 template<typename _CharT> 367 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 368 istreambuf_iterator<_CharT> >::__type 369 find(istreambuf_iterator<_CharT> __first, 370 istreambuf_iterator<_CharT> __last, const _CharT& __val) 371 { 372 typedef istreambuf_iterator<_CharT> __is_iterator_type; 373 typedef typename __is_iterator_type::traits_type traits_type; 374 typedef typename __is_iterator_type::streambuf_type streambuf_type; 375 typedef typename traits_type::int_type int_type; 376 377 if (__first._M_sbuf && !__last._M_sbuf) 378 { 379 const int_type __ival = traits_type::to_int_type(__val); 380 streambuf_type* __sb = __first._M_sbuf; 381 int_type __c = __sb->sgetc(); 382 while (!traits_type::eq_int_type(__c, traits_type::eof()) 383 && !traits_type::eq_int_type(__c, __ival)) 384 { 385 streamsize __n = __sb->egptr() - __sb->gptr(); 386 if (__n > 1) 387 { 388 const _CharT* __p = traits_type::find(__sb->gptr(), 389 __n, __val); 390 if (__p) 391 __n = __p - __sb->gptr(); 392 __sb->__safe_gbump(__n); 393 __c = __sb->sgetc(); 394 } 395 else 396 __c = __sb->snextc(); 397 } 398 399 if (!traits_type::eq_int_type(__c, traits_type::eof())) 400 __first._M_c = __c; 401 else 402 __first._M_sbuf = 0; 403 } 404 return __first; 405 } 406 407 // @} group iterators 408 409 _GLIBCXX_END_NAMESPACE_VERSION 410 } // namespace 411 412 #endif 413