1// Streambuf iterators 2 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 4// 2006, 2007, 2009, 2010, 2011 5// Free Software Foundation, Inc. 6// 7// This file is part of the GNU ISO C++ Library. This library is free 8// software; you can redistribute it and/or modify it under the 9// terms of the GNU General Public License as published by the 10// Free Software Foundation; either version 3, or (at your option) 11// any later version. 12 13// This library is distributed in the hope that it will be useful, 14// but WITHOUT ANY WARRANTY; without even the implied warranty of 15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16// GNU General Public License for more details. 17 18// Under Section 7 of GPL version 3, you are granted additional 19// permissions described in the GCC Runtime Library Exception, version 20// 3.1, as published by the Free Software Foundation. 21 22// You should have received a copy of the GNU General Public License and 23// a copy of the GCC Runtime Library Exception along with this program; 24// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25// <http://www.gnu.org/licenses/>. 26 27/** @file bits/streambuf_iterator.h 28 * This is an internal header file, included by other library headers. 29 * Do not attempt to use it directly. @headername{iterator} 30 */ 31 32#ifndef _STREAMBUF_ITERATOR_H 33#define _STREAMBUF_ITERATOR_H 1 34 35#pragma GCC system_header 36 37#include <streambuf> 38#include <debug/debug.h> 39 40namespace std _GLIBCXX_VISIBILITY(default) 41{ 42_GLIBCXX_BEGIN_NAMESPACE_VERSION 43 44 /** 45 * @addtogroup iterators 46 * @{ 47 */ 48 49 // 24.5.3 Template class istreambuf_iterator 50 /// Provides input iterator semantics for streambufs. 51 template<typename _CharT, typename _Traits> 52 class istreambuf_iterator 53 : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type, 54 _CharT*, _CharT&> 55 { 56 public: 57 // Types: 58 //@{ 59 /// Public typedefs 60 typedef _CharT char_type; 61 typedef _Traits traits_type; 62 typedef typename _Traits::int_type int_type; 63 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 64 typedef basic_istream<_CharT, _Traits> istream_type; 65 //@} 66 67 template<typename _CharT2> 68 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 69 ostreambuf_iterator<_CharT2> >::__type 70 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 71 ostreambuf_iterator<_CharT2>); 72 73 template<bool _IsMove, typename _CharT2> 74 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 75 _CharT2*>::__type 76 __copy_move_a2(istreambuf_iterator<_CharT2>, 77 istreambuf_iterator<_CharT2>, _CharT2*); 78 79 template<typename _CharT2> 80 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 81 istreambuf_iterator<_CharT2> >::__type 82 find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 83 const _CharT2&); 84 85 private: 86 // 24.5.3 istreambuf_iterator 87 // p 1 88 // If the end of stream is reached (streambuf_type::sgetc() 89 // returns traits_type::eof()), the iterator becomes equal to 90 // the "end of stream" iterator value. 91 // NB: This implementation assumes the "end of stream" value 92 // is EOF, or -1. 93 mutable streambuf_type* _M_sbuf; 94 mutable int_type _M_c; 95 96 public: 97 /// Construct end of input stream iterator. 98 _GLIBCXX_CONSTEXPR istreambuf_iterator() throw() 99 : _M_sbuf(0), _M_c(traits_type::eof()) { } 100 101 /// Construct start of input stream iterator. 102 istreambuf_iterator(istream_type& __s) throw() 103 : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { } 104 105 /// Construct start of streambuf iterator. 106 istreambuf_iterator(streambuf_type* __s) throw() 107 : _M_sbuf(__s), _M_c(traits_type::eof()) { } 108 109 /// Return the current character pointed to by iterator. This returns 110 /// streambuf.sgetc(). It cannot be assigned. NB: The result of 111 /// operator*() on an end of stream is undefined. 112 char_type 113 operator*() const 114 { 115#ifdef _GLIBCXX_DEBUG_PEDANTIC 116 // Dereferencing a past-the-end istreambuf_iterator is a 117 // libstdc++ extension 118 __glibcxx_requires_cond(!_M_at_eof(), 119 _M_message(__gnu_debug::__msg_deref_istreambuf) 120 ._M_iterator(*this)); 121#endif 122 return traits_type::to_char_type(_M_get()); 123 } 124 125 /// Advance the iterator. Calls streambuf.sbumpc(). 126 istreambuf_iterator& 127 operator++() 128 { 129 __glibcxx_requires_cond(!_M_at_eof(), 130 _M_message(__gnu_debug::__msg_inc_istreambuf) 131 ._M_iterator(*this)); 132 if (_M_sbuf) 133 { 134 _M_sbuf->sbumpc(); 135 _M_c = traits_type::eof(); 136 } 137 return *this; 138 } 139 140 /// Advance the iterator. Calls streambuf.sbumpc(). 141 istreambuf_iterator 142 operator++(int) 143 { 144 __glibcxx_requires_cond(!_M_at_eof(), 145 _M_message(__gnu_debug::__msg_inc_istreambuf) 146 ._M_iterator(*this)); 147 148 istreambuf_iterator __old = *this; 149 if (_M_sbuf) 150 { 151 __old._M_c = _M_sbuf->sbumpc(); 152 _M_c = traits_type::eof(); 153 } 154 return __old; 155 } 156 157 // _GLIBCXX_RESOLVE_LIB_DEFECTS 158 // 110 istreambuf_iterator::equal not const 159 // NB: there is also number 111 (NAD, Future) pending on this function. 160 /// Return true both iterators are end or both are not end. 161 bool 162 equal(const istreambuf_iterator& __b) const 163 { return _M_at_eof() == __b._M_at_eof(); } 164 165 private: 166 int_type 167 _M_get() const 168 { 169 const int_type __eof = traits_type::eof(); 170 int_type __ret = __eof; 171 if (_M_sbuf) 172 { 173 if (!traits_type::eq_int_type(_M_c, __eof)) 174 __ret = _M_c; 175 else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()), 176 __eof)) 177 _M_c = __ret; 178 else 179 _M_sbuf = 0; 180 } 181 return __ret; 182 } 183 184 bool 185 _M_at_eof() const 186 { 187 const int_type __eof = traits_type::eof(); 188 return traits_type::eq_int_type(_M_get(), __eof); 189 } 190 }; 191 192 template<typename _CharT, typename _Traits> 193 inline bool 194 operator==(const istreambuf_iterator<_CharT, _Traits>& __a, 195 const istreambuf_iterator<_CharT, _Traits>& __b) 196 { return __a.equal(__b); } 197 198 template<typename _CharT, typename _Traits> 199 inline bool 200 operator!=(const istreambuf_iterator<_CharT, _Traits>& __a, 201 const istreambuf_iterator<_CharT, _Traits>& __b) 202 { return !__a.equal(__b); } 203 204 /// Provides output iterator semantics for streambufs. 205 template<typename _CharT, typename _Traits> 206 class ostreambuf_iterator 207 : public iterator<output_iterator_tag, void, void, void, void> 208 { 209 public: 210 // Types: 211 //@{ 212 /// Public typedefs 213 typedef _CharT char_type; 214 typedef _Traits traits_type; 215 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 216 typedef basic_ostream<_CharT, _Traits> ostream_type; 217 //@} 218 219 template<typename _CharT2> 220 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 221 ostreambuf_iterator<_CharT2> >::__type 222 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 223 ostreambuf_iterator<_CharT2>); 224 225 private: 226 streambuf_type* _M_sbuf; 227 bool _M_failed; 228 229 public: 230 /// Construct output iterator from ostream. 231 ostreambuf_iterator(ostream_type& __s) throw () 232 : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } 233 234 /// Construct output iterator from streambuf. 235 ostreambuf_iterator(streambuf_type* __s) throw () 236 : _M_sbuf(__s), _M_failed(!_M_sbuf) { } 237 238 /// Write character to streambuf. Calls streambuf.sputc(). 239 ostreambuf_iterator& 240 operator=(_CharT __c) 241 { 242 if (!_M_failed && 243 _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof())) 244 _M_failed = true; 245 return *this; 246 } 247 248 /// Return *this. 249 ostreambuf_iterator& 250 operator*() 251 { return *this; } 252 253 /// Return *this. 254 ostreambuf_iterator& 255 operator++(int) 256 { return *this; } 257 258 /// Return *this. 259 ostreambuf_iterator& 260 operator++() 261 { return *this; } 262 263 /// Return true if previous operator=() failed. 264 bool 265 failed() const throw() 266 { return _M_failed; } 267 268 ostreambuf_iterator& 269 _M_put(const _CharT* __ws, streamsize __len) 270 { 271 if (__builtin_expect(!_M_failed, true) 272 && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len, 273 false)) 274 _M_failed = true; 275 return *this; 276 } 277 }; 278 279 // Overloads for streambuf iterators. 280 template<typename _CharT> 281 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 282 ostreambuf_iterator<_CharT> >::__type 283 copy(istreambuf_iterator<_CharT> __first, 284 istreambuf_iterator<_CharT> __last, 285 ostreambuf_iterator<_CharT> __result) 286 { 287 if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed) 288 { 289 bool __ineof; 290 __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof); 291 if (!__ineof) 292 __result._M_failed = true; 293 } 294 return __result; 295 } 296 297 template<bool _IsMove, typename _CharT> 298 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 299 ostreambuf_iterator<_CharT> >::__type 300 __copy_move_a2(_CharT* __first, _CharT* __last, 301 ostreambuf_iterator<_CharT> __result) 302 { 303 const streamsize __num = __last - __first; 304 if (__num > 0) 305 __result._M_put(__first, __num); 306 return __result; 307 } 308 309 template<bool _IsMove, typename _CharT> 310 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 311 ostreambuf_iterator<_CharT> >::__type 312 __copy_move_a2(const _CharT* __first, const _CharT* __last, 313 ostreambuf_iterator<_CharT> __result) 314 { 315 const streamsize __num = __last - __first; 316 if (__num > 0) 317 __result._M_put(__first, __num); 318 return __result; 319 } 320 321 template<bool _IsMove, typename _CharT> 322 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 323 _CharT*>::__type 324 __copy_move_a2(istreambuf_iterator<_CharT> __first, 325 istreambuf_iterator<_CharT> __last, _CharT* __result) 326 { 327 typedef istreambuf_iterator<_CharT> __is_iterator_type; 328 typedef typename __is_iterator_type::traits_type traits_type; 329 typedef typename __is_iterator_type::streambuf_type streambuf_type; 330 typedef typename traits_type::int_type int_type; 331 332 if (__first._M_sbuf && !__last._M_sbuf) 333 { 334 streambuf_type* __sb = __first._M_sbuf; 335 int_type __c = __sb->sgetc(); 336 while (!traits_type::eq_int_type(__c, traits_type::eof())) 337 { 338 const streamsize __n = __sb->egptr() - __sb->gptr(); 339 if (__n > 1) 340 { 341 traits_type::copy(__result, __sb->gptr(), __n); 342 __sb->__safe_gbump(__n); 343 __result += __n; 344 __c = __sb->underflow(); 345 } 346 else 347 { 348 *__result++ = traits_type::to_char_type(__c); 349 __c = __sb->snextc(); 350 } 351 } 352 } 353 return __result; 354 } 355 356 template<typename _CharT> 357 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 358 istreambuf_iterator<_CharT> >::__type 359 find(istreambuf_iterator<_CharT> __first, 360 istreambuf_iterator<_CharT> __last, const _CharT& __val) 361 { 362 typedef istreambuf_iterator<_CharT> __is_iterator_type; 363 typedef typename __is_iterator_type::traits_type traits_type; 364 typedef typename __is_iterator_type::streambuf_type streambuf_type; 365 typedef typename traits_type::int_type int_type; 366 367 if (__first._M_sbuf && !__last._M_sbuf) 368 { 369 const int_type __ival = traits_type::to_int_type(__val); 370 streambuf_type* __sb = __first._M_sbuf; 371 int_type __c = __sb->sgetc(); 372 while (!traits_type::eq_int_type(__c, traits_type::eof()) 373 && !traits_type::eq_int_type(__c, __ival)) 374 { 375 streamsize __n = __sb->egptr() - __sb->gptr(); 376 if (__n > 1) 377 { 378 const _CharT* __p = traits_type::find(__sb->gptr(), 379 __n, __val); 380 if (__p) 381 __n = __p - __sb->gptr(); 382 __sb->__safe_gbump(__n); 383 __c = __sb->sgetc(); 384 } 385 else 386 __c = __sb->snextc(); 387 } 388 389 if (!traits_type::eq_int_type(__c, traits_type::eof())) 390 __first._M_c = __c; 391 else 392 __first._M_sbuf = 0; 393 } 394 return __first; 395 } 396 397// @} group iterators 398 399_GLIBCXX_END_NAMESPACE_VERSION 400} // namespace 401 402#endif 403