streambuf_iterator.h 15 KB

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