libstdc++
|
00001 // Streambuf iterators 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 00004 // 2006, 2007, 2009, 2010, 2011 00005 // Free Software Foundation, Inc. 00006 // 00007 // This file is part of the GNU ISO C++ Library. This library is free 00008 // software; you can redistribute it and/or modify it under the 00009 // terms of the GNU General Public License as published by the 00010 // Free Software Foundation; either version 3, or (at your option) 00011 // any later version. 00012 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 00018 // Under Section 7 of GPL version 3, you are granted additional 00019 // permissions described in the GCC Runtime Library Exception, version 00020 // 3.1, as published by the Free Software Foundation. 00021 00022 // You should have received a copy of the GNU General Public License and 00023 // a copy of the GCC Runtime Library Exception along with this program; 00024 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00025 // <http://www.gnu.org/licenses/>. 00026 00027 /** @file bits/streambuf_iterator.h 00028 * This is an internal header file, included by other library headers. 00029 * Do not attempt to use it directly. @headername{iterator} 00030 */ 00031 00032 #ifndef _STREAMBUF_ITERATOR_H 00033 #define _STREAMBUF_ITERATOR_H 1 00034 00035 #pragma GCC system_header 00036 00037 #include <streambuf> 00038 #include <debug/debug.h> 00039 00040 namespace std _GLIBCXX_VISIBILITY(default) 00041 { 00042 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00043 00044 /** 00045 * @addtogroup iterators 00046 * @{ 00047 */ 00048 00049 // 24.5.3 Template class istreambuf_iterator 00050 /// Provides input iterator semantics for streambufs. 00051 template<typename _CharT, typename _Traits> 00052 class istreambuf_iterator 00053 : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type, 00054 _CharT*, 00055 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00056 // LWG 445. 00057 _CharT> 00058 #else 00059 _CharT&> 00060 #endif 00061 { 00062 public: 00063 // Types: 00064 //@{ 00065 /// Public typedefs 00066 typedef _CharT char_type; 00067 typedef _Traits traits_type; 00068 typedef typename _Traits::int_type int_type; 00069 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 00070 typedef basic_istream<_CharT, _Traits> istream_type; 00071 //@} 00072 00073 template<typename _CharT2> 00074 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 00075 ostreambuf_iterator<_CharT2> >::__type 00076 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 00077 ostreambuf_iterator<_CharT2>); 00078 00079 template<bool _IsMove, typename _CharT2> 00080 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 00081 _CharT2*>::__type 00082 __copy_move_a2(istreambuf_iterator<_CharT2>, 00083 istreambuf_iterator<_CharT2>, _CharT2*); 00084 00085 template<typename _CharT2> 00086 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 00087 istreambuf_iterator<_CharT2> >::__type 00088 find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 00089 const _CharT2&); 00090 00091 private: 00092 // 24.5.3 istreambuf_iterator 00093 // p 1 00094 // If the end of stream is reached (streambuf_type::sgetc() 00095 // returns traits_type::eof()), the iterator becomes equal to 00096 // the "end of stream" iterator value. 00097 // NB: This implementation assumes the "end of stream" value 00098 // is EOF, or -1. 00099 mutable streambuf_type* _M_sbuf; 00100 mutable int_type _M_c; 00101 00102 public: 00103 /// Construct end of input stream iterator. 00104 _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT 00105 : _M_sbuf(0), _M_c(traits_type::eof()) { } 00106 00107 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00108 istreambuf_iterator(const istreambuf_iterator&) noexcept = default; 00109 00110 ~istreambuf_iterator() = default; 00111 #endif 00112 00113 /// Construct start of input stream iterator. 00114 istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT 00115 : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { } 00116 00117 /// Construct start of streambuf iterator. 00118 istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT 00119 : _M_sbuf(__s), _M_c(traits_type::eof()) { } 00120 00121 /// Return the current character pointed to by iterator. This returns 00122 /// streambuf.sgetc(). It cannot be assigned. NB: The result of 00123 /// operator*() on an end of stream is undefined. 00124 char_type 00125 operator*() const 00126 { 00127 #ifdef _GLIBCXX_DEBUG_PEDANTIC 00128 // Dereferencing a past-the-end istreambuf_iterator is a 00129 // libstdc++ extension 00130 __glibcxx_requires_cond(!_M_at_eof(), 00131 _M_message(__gnu_debug::__msg_deref_istreambuf) 00132 ._M_iterator(*this)); 00133 #endif 00134 return traits_type::to_char_type(_M_get()); 00135 } 00136 00137 /// Advance the iterator. Calls streambuf.sbumpc(). 00138 istreambuf_iterator& 00139 operator++() 00140 { 00141 __glibcxx_requires_cond(!_M_at_eof(), 00142 _M_message(__gnu_debug::__msg_inc_istreambuf) 00143 ._M_iterator(*this)); 00144 if (_M_sbuf) 00145 { 00146 _M_sbuf->sbumpc(); 00147 _M_c = traits_type::eof(); 00148 } 00149 return *this; 00150 } 00151 00152 /// Advance the iterator. Calls streambuf.sbumpc(). 00153 istreambuf_iterator 00154 operator++(int) 00155 { 00156 __glibcxx_requires_cond(!_M_at_eof(), 00157 _M_message(__gnu_debug::__msg_inc_istreambuf) 00158 ._M_iterator(*this)); 00159 00160 istreambuf_iterator __old = *this; 00161 if (_M_sbuf) 00162 { 00163 __old._M_c = _M_sbuf->sbumpc(); 00164 _M_c = traits_type::eof(); 00165 } 00166 return __old; 00167 } 00168 00169 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00170 // 110 istreambuf_iterator::equal not const 00171 // NB: there is also number 111 (NAD, Future) pending on this function. 00172 /// Return true both iterators are end or both are not end. 00173 bool 00174 equal(const istreambuf_iterator& __b) const 00175 { return _M_at_eof() == __b._M_at_eof(); } 00176 00177 private: 00178 int_type 00179 _M_get() const 00180 { 00181 const int_type __eof = traits_type::eof(); 00182 int_type __ret = __eof; 00183 if (_M_sbuf) 00184 { 00185 if (!traits_type::eq_int_type(_M_c, __eof)) 00186 __ret = _M_c; 00187 else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()), 00188 __eof)) 00189 _M_c = __ret; 00190 else 00191 _M_sbuf = 0; 00192 } 00193 return __ret; 00194 } 00195 00196 bool 00197 _M_at_eof() const 00198 { 00199 const int_type __eof = traits_type::eof(); 00200 return traits_type::eq_int_type(_M_get(), __eof); 00201 } 00202 }; 00203 00204 template<typename _CharT, typename _Traits> 00205 inline bool 00206 operator==(const istreambuf_iterator<_CharT, _Traits>& __a, 00207 const istreambuf_iterator<_CharT, _Traits>& __b) 00208 { return __a.equal(__b); } 00209 00210 template<typename _CharT, typename _Traits> 00211 inline bool 00212 operator!=(const istreambuf_iterator<_CharT, _Traits>& __a, 00213 const istreambuf_iterator<_CharT, _Traits>& __b) 00214 { return !__a.equal(__b); } 00215 00216 /// Provides output iterator semantics for streambufs. 00217 template<typename _CharT, typename _Traits> 00218 class ostreambuf_iterator 00219 : public iterator<output_iterator_tag, void, void, void, void> 00220 { 00221 public: 00222 // Types: 00223 //@{ 00224 /// Public typedefs 00225 typedef _CharT char_type; 00226 typedef _Traits traits_type; 00227 typedef basic_streambuf<_CharT, _Traits> streambuf_type; 00228 typedef basic_ostream<_CharT, _Traits> ostream_type; 00229 //@} 00230 00231 template<typename _CharT2> 00232 friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 00233 ostreambuf_iterator<_CharT2> >::__type 00234 copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>, 00235 ostreambuf_iterator<_CharT2>); 00236 00237 private: 00238 streambuf_type* _M_sbuf; 00239 bool _M_failed; 00240 00241 public: 00242 /// Construct output iterator from ostream. 00243 ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT 00244 : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } 00245 00246 /// Construct output iterator from streambuf. 00247 ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT 00248 : _M_sbuf(__s), _M_failed(!_M_sbuf) { } 00249 00250 /// Write character to streambuf. Calls streambuf.sputc(). 00251 ostreambuf_iterator& 00252 operator=(_CharT __c) 00253 { 00254 if (!_M_failed && 00255 _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof())) 00256 _M_failed = true; 00257 return *this; 00258 } 00259 00260 /// Return *this. 00261 ostreambuf_iterator& 00262 operator*() 00263 { return *this; } 00264 00265 /// Return *this. 00266 ostreambuf_iterator& 00267 operator++(int) 00268 { return *this; } 00269 00270 /// Return *this. 00271 ostreambuf_iterator& 00272 operator++() 00273 { return *this; } 00274 00275 /// Return true if previous operator=() failed. 00276 bool 00277 failed() const _GLIBCXX_USE_NOEXCEPT 00278 { return _M_failed; } 00279 00280 ostreambuf_iterator& 00281 _M_put(const _CharT* __ws, streamsize __len) 00282 { 00283 if (__builtin_expect(!_M_failed, true) 00284 && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len, 00285 false)) 00286 _M_failed = true; 00287 return *this; 00288 } 00289 }; 00290 00291 // Overloads for streambuf iterators. 00292 template<typename _CharT> 00293 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 00294 ostreambuf_iterator<_CharT> >::__type 00295 copy(istreambuf_iterator<_CharT> __first, 00296 istreambuf_iterator<_CharT> __last, 00297 ostreambuf_iterator<_CharT> __result) 00298 { 00299 if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed) 00300 { 00301 bool __ineof; 00302 __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof); 00303 if (!__ineof) 00304 __result._M_failed = true; 00305 } 00306 return __result; 00307 } 00308 00309 template<bool _IsMove, typename _CharT> 00310 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 00311 ostreambuf_iterator<_CharT> >::__type 00312 __copy_move_a2(_CharT* __first, _CharT* __last, 00313 ostreambuf_iterator<_CharT> __result) 00314 { 00315 const streamsize __num = __last - __first; 00316 if (__num > 0) 00317 __result._M_put(__first, __num); 00318 return __result; 00319 } 00320 00321 template<bool _IsMove, typename _CharT> 00322 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 00323 ostreambuf_iterator<_CharT> >::__type 00324 __copy_move_a2(const _CharT* __first, const _CharT* __last, 00325 ostreambuf_iterator<_CharT> __result) 00326 { 00327 const streamsize __num = __last - __first; 00328 if (__num > 0) 00329 __result._M_put(__first, __num); 00330 return __result; 00331 } 00332 00333 template<bool _IsMove, typename _CharT> 00334 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 00335 _CharT*>::__type 00336 __copy_move_a2(istreambuf_iterator<_CharT> __first, 00337 istreambuf_iterator<_CharT> __last, _CharT* __result) 00338 { 00339 typedef istreambuf_iterator<_CharT> __is_iterator_type; 00340 typedef typename __is_iterator_type::traits_type traits_type; 00341 typedef typename __is_iterator_type::streambuf_type streambuf_type; 00342 typedef typename traits_type::int_type int_type; 00343 00344 if (__first._M_sbuf && !__last._M_sbuf) 00345 { 00346 streambuf_type* __sb = __first._M_sbuf; 00347 int_type __c = __sb->sgetc(); 00348 while (!traits_type::eq_int_type(__c, traits_type::eof())) 00349 { 00350 const streamsize __n = __sb->egptr() - __sb->gptr(); 00351 if (__n > 1) 00352 { 00353 traits_type::copy(__result, __sb->gptr(), __n); 00354 __sb->__safe_gbump(__n); 00355 __result += __n; 00356 __c = __sb->underflow(); 00357 } 00358 else 00359 { 00360 *__result++ = traits_type::to_char_type(__c); 00361 __c = __sb->snextc(); 00362 } 00363 } 00364 } 00365 return __result; 00366 } 00367 00368 template<typename _CharT> 00369 typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 00370 istreambuf_iterator<_CharT> >::__type 00371 find(istreambuf_iterator<_CharT> __first, 00372 istreambuf_iterator<_CharT> __last, const _CharT& __val) 00373 { 00374 typedef istreambuf_iterator<_CharT> __is_iterator_type; 00375 typedef typename __is_iterator_type::traits_type traits_type; 00376 typedef typename __is_iterator_type::streambuf_type streambuf_type; 00377 typedef typename traits_type::int_type int_type; 00378 00379 if (__first._M_sbuf && !__last._M_sbuf) 00380 { 00381 const int_type __ival = traits_type::to_int_type(__val); 00382 streambuf_type* __sb = __first._M_sbuf; 00383 int_type __c = __sb->sgetc(); 00384 while (!traits_type::eq_int_type(__c, traits_type::eof()) 00385 && !traits_type::eq_int_type(__c, __ival)) 00386 { 00387 streamsize __n = __sb->egptr() - __sb->gptr(); 00388 if (__n > 1) 00389 { 00390 const _CharT* __p = traits_type::find(__sb->gptr(), 00391 __n, __val); 00392 if (__p) 00393 __n = __p - __sb->gptr(); 00394 __sb->__safe_gbump(__n); 00395 __c = __sb->sgetc(); 00396 } 00397 else 00398 __c = __sb->snextc(); 00399 } 00400 00401 if (!traits_type::eq_int_type(__c, traits_type::eof())) 00402 __first._M_c = __c; 00403 else 00404 __first._M_sbuf = 0; 00405 } 00406 return __first; 00407 } 00408 00409 // @} group iterators 00410 00411 _GLIBCXX_END_NAMESPACE_VERSION 00412 } // namespace 00413 00414 #endif