Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Streambuf iterators
  2.  
  3. // Copyright (C) 1997-2015 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.