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-07-22 18:54:45 Functions: 71.4 % 21 15 6

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

Generated by: LCOV version 2.3