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