GCC Code Coverage Report


Directory: ./
File: libs/capy/include/boost/capy/any_bufref.hpp
Date: 2026-01-20 15:02:00
Exec Total Coverage
Lines: 21 21 100.0%
Functions: 9 9 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
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_ANY_BUFREF_HPP
11 #define BOOST_CAPY_ANY_BUFREF_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15
16 #include <cstddef>
17
18 namespace boost {
19 namespace capy {
20
21 /** A type-erased buffer sequence I/O parameter.
22
23 This class provides a type-erased interface for iterating
24 over buffer sequences without knowing the concrete type.
25 It allows asynchronous operations to efficiently type-erase
26 the buffer sequence parameter, avoiding the need to
27 templatize the implementation.
28
29 @par Example
30 The following shows the minimal form of an awaitable, templated on the
31 buffer sequence type, with only an `await_suspend` method. The example
32 demonstrates that you can construct an `any_bufref` in the parameter
33 list when calling a virtual interface; there is no need to create a
34 separate variable if not desired.
35
36 @code
37 template<class Buffers>
38 struct awaitable
39 {
40 Buffers b;
41
42 void await_suspend( std::coroutine_handle<> )
43 {
44 my_virtual_engine_submit( any_bufref( b ) );
45 }
46 };
47
48 // Example virtual interface accepting any_bufref
49 void my_virtual_engine_submit( any_bufref p )
50 {
51 capy::mutable_buffer temp[8];
52 std::size_t n = p.copy_to( temp, 8 );
53 // ... handle the buffers ...
54 }
55 @endcode
56 */
57 class any_bufref
58 {
59 public:
60 /** Construct from a const buffer sequence.
61
62 @param bs The buffer sequence to adapt.
63 */
64 template<ConstBufferSequence BS>
65 explicit
66 36 any_bufref(BS const& bs) noexcept
67 36 : bs_(&bs)
68 36 , fn_(&copy_impl<BS>)
69 {
70 36 }
71
72 /** Fill an array with buffers from the sequence.
73
74 Copies buffer descriptors from the sequence into the
75 destination array. If the total number of bytes across
76 all copied buffers is zero, returns 0 regardless of
77 how many buffer descriptors were copied.
78
79 @param dest Pointer to array of mutable buffer descriptors.
80 @param n Maximum number of buffers to copy.
81
82 @return The number of buffers actually copied, or 0 if
83 the total byte count is zero.
84 */
85 std::size_t
86 18 copy_to(
87 mutable_buffer* dest,
88 std::size_t n) const noexcept
89 {
90 18 return fn_(bs_, dest, n);
91 }
92
93 private:
94 template<ConstBufferSequence BS>
95 static std::size_t
96 18 copy_impl(
97 void const* p,
98 mutable_buffer* dest,
99 std::size_t n)
100 {
101 18 auto const& bs = *static_cast<BS const*>(p);
102 18 auto it = begin(bs);
103 18 auto const end_it = end(bs);
104
105 18 std::size_t i = 0;
106 18 std::size_t bytes = 0;
107 if constexpr (MutableBufferSequence<BS>)
108 {
109 10 for(; it != end_it && i < n; ++it, ++i)
110 {
111 6 dest[i] = *it;
112 6 bytes += dest[i].size();
113 }
114 }
115 else
116 {
117 40 for(; it != end_it && i < n; ++it, ++i)
118 {
119 26 auto const& buf = *it;
120 52 dest[i] = mutable_buffer(
121 const_cast<char*>(
122 26 static_cast<char const*>(buf.data())),
123 buf.size());
124 26 bytes += buf.size();
125 }
126 }
127 // Return 0 if total bytes is 0 (empty buffer sequence)
128 18 return bytes == 0 ? 0 : i;
129 }
130
131 using fn_t = std::size_t(*)(void const*,
132 mutable_buffer*, std::size_t);
133
134 void const* bs_;
135 fn_t fn_;
136 };
137
138 } // namespace capy
139 } // namespace boost
140
141 #endif
142