LCOV - code coverage report
Current view: top level - capy/buffers - consuming_buffers.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 16 16
Test Date: 2026-08-14 20:51:18 Functions: 63.6 % 33 21 12

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       3                 : // Copyright (c) 2026 Michael Vandeberg
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/capy
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP
      12                 : #define BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP
      13                 : 
      14                 : #include <boost/capy/detail/config.hpp>
      15                 : #include <boost/capy/buffers.hpp>
      16                 : #include <boost/capy/detail/slice_of.hpp>
      17                 : 
      18                 : #include <cstddef>
      19                 : #include <utility>
      20                 : 
      21                 : namespace boost {
      22                 : namespace capy {
      23                 : 
      24                 : /** A cursor that drives consumption of a buffer sequence.
      25                 : 
      26                 :     `consuming_buffers` is the dedicated driver for `read_some`/`write_some`
      27                 :     loops. It presents the not-yet-consumed bytes of a buffer sequence via
      28                 :     `data()`, and `consume(n)` advances past `n` transferred bytes **in
      29                 :     place**.
      30                 : 
      31                 :     It is deliberately **not** itself a buffer sequence — it hands out the
      32                 :     remaining bytes through `data()` (returning a `slice_of` view). It
      33                 :     **borrows** the underlying sequence (iterators + a consumed-byte offset).
      34                 :     The sequence must outlive the cursor. That is the natural case when the
      35                 :     cursor is a local of a composed operation that took its buffers by value.
      36                 : 
      37                 :     @par Example
      38                 :     @code
      39                 :     consuming_buffers consuming(buffers);
      40                 :     std::size_t total = 0, want = buffer_size(buffers);
      41                 :     while (total < want)
      42                 :     {
      43                 :         auto [ec, n] = co_await stream.read_some(consuming.data());
      44                 :         consuming.consume(n);
      45                 :         total += n;
      46                 :         if (ec && total < want) co_return {ec, total};
      47                 :     }
      48                 :     @endcode
      49                 : 
      50                 :     @see buffer_slice, slice_of
      51                 : */
      52                 : template<class Seq>
      53                 :     requires MutableBufferSequence<Seq> || ConstBufferSequence<Seq>
      54                 : class consuming_buffers
      55                 : {
      56                 : public:
      57                 :     /// Names the buffer type the underlying sequence `Seq` yields.
      58                 :     using buffer_type = capy::buffer_type<Seq>;
      59                 : 
      60                 : private:
      61                 :     using iterator_type =
      62                 :         decltype(capy::begin(std::declval<Seq const&>()));
      63                 : 
      64                 :     iterator_type first_{};
      65                 :     iterator_type last_{};
      66                 :     std::size_t   front_skip_ = 0;  // bytes consumed from *first_
      67                 : 
      68                 : public:
      69                 :     /** Construct a cursor over `s`.
      70                 : 
      71                 :         @param s The sequence to consume. Must outlive the cursor.
      72                 :     */
      73 HIT         315 :     explicit consuming_buffers(Seq const& s) noexcept
      74             315 :         : first_(capy::begin(s))
      75             315 :         , last_(capy::end(s))
      76                 :     {
      77             315 :     }
      78                 : 
      79                 :     /** Reject construction from a temporary (the view would dangle).
      80                 : 
      81                 :         @param s The sequence that would be consumed.
      82                 :     */
      83                 :     consuming_buffers(Seq const&& s) = delete;
      84                 : 
      85                 :     /** Return the remaining (unconsumed) bytes as a buffer sequence.
      86                 : 
      87                 :         @return The bytes not yet consumed, as a buffer sequence.
      88                 :     */
      89                 :     detail::slice_of<Seq>
      90             362 :     data() const noexcept
      91                 :     {
      92             362 :         return detail::slice_of<Seq>(first_, last_, front_skip_, 0);
      93                 :     }
      94                 : 
      95                 :     /** Discard `n` bytes from the front, in place.
      96                 : 
      97                 :         Advances past `min(n, remaining)` bytes.
      98                 : 
      99                 :         @param n The number of bytes consumed.
     100                 :     */
     101                 :     void
     102             272 :     consume(std::size_t n) noexcept
     103                 :     {
     104             415 :         while (n > 0 && first_ != last_)
     105                 :         {
     106             214 :             std::size_t const sz    = buffer_type(*first_).size();
     107             214 :             std::size_t const avail = sz - front_skip_;
     108             214 :             if (n < avail)
     109                 :             {
     110              71 :                 front_skip_ += n;
     111              71 :                 return;
     112                 :             }
     113             143 :             n -= avail;
     114             143 :             ++first_;
     115             143 :             front_skip_ = 0;
     116                 :         }
     117                 :     }
     118                 : };
     119                 : 
     120                 : /** Deduce the sequence type from the constructor argument.
     121                 : 
     122                 :     @tparam Seq The buffer sequence type.
     123                 : */
     124                 : template<class Seq>
     125                 : consuming_buffers(Seq const&) -> consuming_buffers<Seq>;
     126                 : 
     127                 : } // namespace capy
     128                 : } // namespace boost
     129                 : 
     130                 : #endif
        

Generated by: LCOV version 2.3