GCC Code Coverage Report


Directory: ./
File: libs/buffers/include/boost/buffers/dynamic_buffer.hpp
Date: 2025-12-06 02:12:43
Exec Total Coverage
Lines: 31 38 81.6%
Functions: 9 12 75.0%
Branches: 4 5 80.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.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/buffers
8 //
9
10 #ifndef BOOST_BUFFERS_DYNAMIC_BUFFER_HPP
11 #define BOOST_BUFFERS_DYNAMIC_BUFFER_HPP
12
13 #include <boost/buffers/detail/config.hpp>
14 #include <boost/buffers/buffer.hpp>
15 #include <boost/core/span.hpp>
16 #include <cstdlib>
17
18 namespace boost {
19 namespace buffers {
20
21 /** Determine if T is a DynamicBuffer
22 */
23 template<
24 class T,
25 class = void>
26 struct is_dynamic_buffer : std::false_type {};
27
28 template<class T>
29 struct is_dynamic_buffer<
30 T, detail::void_t<decltype(
31 std::declval<std::size_t&>() = std::declval<T const&>().size(),
32 std::declval<std::size_t&>() = std::declval<T const&>().max_size(),
33 std::declval<std::size_t&>() = std::declval<T const&>().capacity(),
34 std::declval<T&>().commit(std::declval<std::size_t>()),
35 std::declval<T&>().consume(std::declval<std::size_t>())
36 )
37 ,typename std::enable_if<
38 is_const_buffer_sequence<typename T::const_buffers_type>::value &&
39 is_mutable_buffer_sequence<typename T::mutable_buffers_type>::value
40 >::type
41 ,typename std::enable_if<
42 std::is_same<decltype(
43 std::declval<T const&>().data()),
44 typename T::const_buffers_type>::value
45 && std::is_same<decltype(
46 std::declval<T&>().prepare(
47 std::declval<std::size_t>())),
48 typename T::mutable_buffers_type>::value
49 >::type
50 > > : std::true_type
51 {
52 };
53
54 /** An abstract, type-erased dynamic buffer.
55 */
56 struct BOOST_SYMBOL_VISIBLE
57 any_dynamic_buffer
58 {
59 using const_buffers_type = span<const_buffer const>;
60 using mutable_buffers_type = span<mutable_buffer const>;
61
62 8192 virtual ~any_dynamic_buffer() = default;
63 virtual std::size_t size() const = 0;
64 virtual std::size_t max_size() const = 0;
65 virtual std::size_t capacity() const = 0;
66 virtual const_buffers_type data() const = 0;
67 virtual mutable_buffers_type prepare(std::size_t) = 0;
68 virtual void commit(std::size_t) = 0;
69 virtual void consume(std::size_t) = 0;
70 };
71
72 //-----------------------------------------------
73
74 /** A type-erased dynamic buffer.
75 */
76 template<
77 class DynamicBuffer,
78 std::size_t N = 8>
79 class any_dynamic_buffer_impl
80 : public any_dynamic_buffer
81 {
82 DynamicBuffer b_;
83 const_buffer data_[N];
84 mutable_buffer out_[N];
85 std::size_t data_len_ = 0;
86 std::size_t out_len_ = 0;
87
88 template<class ConstBufferSequence, class BufferType>
89 static
90 std::size_t
91 69760 unroll(
92 ConstBufferSequence const& bs,
93 BufferType* dest,
94 std::size_t len)
95 {
96 69760 std::size_t i = 0;
97 69760 auto const end_ = end(bs);
98
2/2
✓ Branch 1 taken 69760 times.
✓ Branch 2 taken 34880 times.
209280 for(auto it = begin(bs); it != end_; ++it)
99 {
100 139520 dest[i++] = *it;
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69760 times.
139520 if(i == len)
102 break;
103 }
104 69760 return i;
105 }
106
107 public:
108 template<class DynamicBuffer_>
109 explicit
110 4096 any_dynamic_buffer_impl(
111 DynamicBuffer_&& b)
112 4096 : b_(std::forward<DynamicBuffer_>(b))
113 {
114 4096 }
115
116 DynamicBuffer&
117 buffer() noexcept
118 {
119 return b_;
120 }
121
122 DynamicBuffer const&
123 buffer() const noexcept
124 {
125 return b_;
126 }
127
128 std::size_t
129 size() const override
130 {
131 return b_.size();
132 }
133
134 std::size_t
135 max_size() const override
136 {
137 return b_.max_size();
138 }
139
140 std::size_t
141 capacity() const override
142 {
143 return b_.capacity();
144 }
145
146 const_buffers_type
147 12288 data() const override
148 {
149 24576 return const_buffers_type(
150 12288 data_, data_len_);
151 }
152
153 auto
154 11792 prepare(
155 std::size_t n) ->
156 mutable_buffers_type override
157 {
158 11792 out_len_ = unroll(
159
1/1
✓ Branch 1 taken 11792 times.
11792 b_.prepare(n), out_, N);
160 23584 return mutable_buffers_type(
161 11792 out_, out_len_);
162 }
163
164 void
165 11792 commit(
166 std::size_t n) override
167 {
168 11792 b_.commit(n);
169 11792 data_len_ = unroll(
170 11792 b_.data(), data_, N);
171 11792 }
172
173 void
174 11296 consume(
175 std::size_t n) override
176 {
177 11296 b_.consume(n);
178 11296 data_len_ = unroll(
179 11296 b_.data(), data_, N);
180 11296 }
181 };
182
183 template<
184 class DynamicBuffer
185 , class = typename std::enable_if<
186 is_dynamic_buffer<
187 typename std::decay<DynamicBuffer>::type
188 >::value>::type
189 >
190 auto
191 4096 make_any(DynamicBuffer&& b) ->
192 any_dynamic_buffer_impl<typename
193 std::decay<DynamicBuffer>::type>
194 {
195 return any_dynamic_buffer_impl<typename
196 std::decay<DynamicBuffer>::type>(
197 4096 std::forward<DynamicBuffer>(b));
198 }
199
200 } // buffers
201 } // boost
202
203 #endif
204