include/boost/capy/detail/buffer_array.hpp

98.9% Lines (86/87) 100.0% List of functions (67/67)
buffer_array.hpp
f(x) Functions (67)
Function Calls Lines Blocks
boost::capy::detail::buffer_array<2ul, false>::buffer_array() :66 1x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::buffer_array() :66 1x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array() :66 2x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array() :66 2x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array(boost::capy::detail::buffer_array<16ul, false> const&) :73 141x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array(boost::capy::detail::buffer_array<16ul, true> const&) :73 117x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array(boost::capy::detail::buffer_array<4ul, false> const&) :73 17x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array(boost::capy::detail::buffer_array<4ul, true> const&) :73 17x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array(boost::capy::mutable_buffer const&) :85 69x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array(boost::capy::const_buffer const&) :85 50x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array(boost::capy::mutable_buffer const&) :85 5x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array(boost::capy::const_buffer const&) :85 6x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array<std::array<boost::capy::mutable_buffer, 2ul> >(std::array<boost::capy::mutable_buffer, 2ul> const&) :109 12x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array<std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >(std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> const&) :109 6x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array<std::span<boost::capy::mutable_buffer, 18446744073709551615ul> >(std::span<boost::capy::mutable_buffer, 18446744073709551615ul> const&) :109 52x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::buffer_array<std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >(std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > const&) :109 6x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array<std::array<boost::capy::const_buffer, 2ul> >(std::array<boost::capy::const_buffer, 2ul> const&) :109 6x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >(std::span<boost::capy::const_buffer const, 18446744073709551615ul> const&) :109 8x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array<std::span<boost::capy::const_buffer, 18446744073709551615ul> >(std::span<boost::capy::const_buffer, 18446744073709551615ul> const&) :109 51x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::buffer_array<std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >(std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > const&) :109 6x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::buffer_array<std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >(std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > const&) :109 2x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::buffer_array<std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >(std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > const&) :109 2x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array<std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >(std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > const&) :109 17x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array<std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >(std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > const&) :109 17x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::buffer_array<std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >(std::in_place_t, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > const&) :138 1x 92.3% 94.0% boost::capy::detail::buffer_array<2ul, true>::buffer_array<std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >(std::in_place_t, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > const&) :138 1x 92.3% 94.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array<std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >(std::in_place_t, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > const&) :138 1x 92.3% 89.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array<std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >(std::in_place_t, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > const&) :138 1x 92.3% 89.0% boost::capy::detail::buffer_array<2ul, false>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > > >(__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >) :167 1x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > > >(__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >) :167 1x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > > >(__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >) :167 3x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > > >(__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >) :167 3x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > > >(std::in_place_t, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >) :194 1x 90.9% 93.0% boost::capy::detail::buffer_array<2ul, true>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > > >(std::in_place_t, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >) :194 1x 90.9% 93.0% boost::capy::detail::buffer_array<4ul, false>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > > >(std::in_place_t, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::mutable_buffer*, std::vector<boost::capy::mutable_buffer, std::allocator<boost::capy::mutable_buffer> > >) :194 1x 90.9% 93.0% boost::capy::detail::buffer_array<4ul, true>::buffer_array<__gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > > >(std::in_place_t, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >, __gnu_cxx::__normal_iterator<boost::capy::const_buffer*, std::vector<boost::capy::const_buffer, std::allocator<boost::capy::const_buffer> > >) :194 1x 90.9% 93.0% boost::capy::detail::buffer_array<16ul, false>::~buffer_array() :213 286x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::~buffer_array() :213 238x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::~buffer_array() :213 4x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::~buffer_array() :213 4x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::~buffer_array() :213 46x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::~buffer_array() :213 47x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::operator=(boost::capy::detail::buffer_array<2ul, false> const&) :222 1x 88.9% 90.0% boost::capy::detail::buffer_array<2ul, true>::operator=(boost::capy::detail::buffer_array<2ul, true> const&) :222 1x 88.9% 90.0% boost::capy::detail::buffer_array<4ul, false>::operator=(boost::capy::detail::buffer_array<4ul, false> const&) :222 1x 88.9% 90.0% boost::capy::detail::buffer_array<4ul, true>::operator=(boost::capy::detail::buffer_array<4ul, true> const&) :222 1x 88.9% 90.0% boost::capy::detail::buffer_array<4ul, false>::begin() :239 64x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::begin() :239 66x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::begin() const :247 3x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::begin() const :247 3x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::begin() const :247 1217x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::begin() const :247 1218x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::end() :255 64x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::end() :255 65x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::end() const :263 3x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::end() const :263 3x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::end() const :263 1217x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::end() const :263 1218x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::to_span() :271 195x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::to_span() :271 155x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, false>::to_span() :271 3x 100.0% 100.0% boost::capy::detail::buffer_array<2ul, true>::to_span() :271 3x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::to_span() :271 11x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, true>::to_span() :271 12x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, false>::to_span() const :279 54x 100.0% 100.0% boost::capy::detail::buffer_array<16ul, true>::to_span() const :279 121x 100.0% 100.0% boost::capy::detail::buffer_array<4ul, false>::operator std::span<boost::capy::mutable_buffer, 18446744073709551615ul>() :286 1x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 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/capy
8 //
9
10 #ifndef BOOST_CAPY_DETAIL_BUFFER_ARRAY_HPP
11 #define BOOST_CAPY_DETAIL_BUFFER_ARRAY_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/detail/except.hpp>
15 #include <boost/capy/buffers.hpp>
16
17 #include <cstddef>
18 #include <new>
19 #include <span>
20 #include <utility>
21
22 namespace boost {
23 namespace capy {
24 namespace detail {
25
26 /** A buffer sequence holding up to N buffers.
27
28 This class template stores a fixed-capacity array of buffer
29 descriptors, where the actual count can vary from 0 to N.
30 It provides efficient storage for small buffer sequences
31 without dynamic allocation.
32
33 @par Example
34 @code
35 void process(ConstBufferSequence auto const& buffers)
36 {
37 detail::const_buffer_array<4> bufs(buffers);
38 // use bufs.begin(), bufs.end(), bufs.to_span()
39 }
40 @endcode
41
42 @tparam N Maximum number of buffers the array can hold.
43 @tparam IsConst If true, holds const_buffer; otherwise mutable_buffer.
44 */
45 template<std::size_t N, bool IsConst>
46 class buffer_array
47 {
48 public:
49 /** The type of buffer stored in the array.
50 */
51 using value_type = std::conditional_t<IsConst, const_buffer, mutable_buffer>;
52
53 private:
54 std::size_t n_ = 0;
55 std::size_t size_ = 0;
56 union {
57 int dummy_;
58 value_type arr_[N];
59 };
60
61 public:
62 /** Construct a default instance.
63
64 Constructs an empty buffer array.
65 */
66 6x buffer_array() noexcept
67 6x : dummy_(0)
68 {
69 6x }
70
71 /** Construct a copy.
72 */
73 292x buffer_array(buffer_array const& other) noexcept
74 292x : n_(other.n_)
75 292x , size_(other.size_)
76 {
77 811x for(std::size_t i = 0; i < n_; ++i)
78 519x ::new(&arr_[i]) value_type(other.arr_[i]);
79 292x }
80
81 /** Construct from a single buffer.
82
83 @param b The buffer to store.
84 */
85 130x buffer_array(value_type const& b) noexcept
86 130x : dummy_(0)
87 {
88 130x if(b.size() != 0)
89 {
90 122x ::new(&arr_[0]) value_type(b);
91 122x n_ = 1;
92 122x size_ = b.size();
93 }
94 130x }
95
96 /** Construct from a buffer sequence.
97
98 Copies up to N buffer descriptors from the source
99 sequence into the internal array. If the sequence
100 contains more than N non-empty buffers, excess
101 buffers are silently ignored.
102
103 @param bs The buffer sequence to copy from.
104 */
105 template<class BS>
106 requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
107 && (!std::same_as<std::remove_cvref_t<BS>, buffer_array>)
108 && (!std::same_as<std::remove_cvref_t<BS>, value_type>)
109 185x buffer_array(BS const& bs) noexcept
110 185x : dummy_(0)
111 {
112 185x auto it = capy::begin(bs);
113 185x auto const last = capy::end(bs);
114 618x while(it != last && n_ < N)
115 {
116 433x value_type b(*it);
117 433x if(b.size() != 0)
118 {
119 427x ::new(&arr_[n_++]) value_type(b);
120 427x size_ += b.size();
121 }
122 433x ++it;
123 }
124 185x }
125
126 /** Construct from a buffer sequence with overflow checking.
127
128 Copies buffer descriptors from the source sequence
129 into the internal array.
130
131 @param bs The buffer sequence to copy from.
132
133 @throws std::length_error if the sequence contains
134 more than N non-empty buffers.
135 */
136 template<class BS>
137 requires (IsConst ? ConstBufferSequence<BS> : MutableBufferSequence<BS>)
138 4x buffer_array(std::in_place_t, BS const& bs)
139 4x : dummy_(0)
140 {
141 4x auto it = capy::begin(bs);
142 4x auto const last = capy::end(bs);
143 14x while(it != last)
144 {
145 12x value_type b(*it);
146 12x if(b.size() != 0)
147 {
148 12x if(n_ >= N)
149 2x detail::throw_length_error();
150 10x ::new(&arr_[n_++]) value_type(b);
151 10x size_ += b.size();
152 }
153 10x ++it;
154 }
155 2x }
156
157 /** Construct from an iterator range.
158
159 Copies up to N non-empty buffer descriptors from the
160 range `[first, last)`. If the range contains more than
161 N non-empty buffers, excess buffers are silently ignored.
162
163 @param first Iterator to the first buffer descriptor.
164 @param last Iterator past the last buffer descriptor.
165 */
166 template<class Iterator>
167 8x buffer_array(Iterator first, Iterator last) noexcept
168 8x : dummy_(0)
169 {
170 26x while(first != last && n_ < N)
171 {
172 18x value_type b(*first);
173 18x if(b.size() != 0)
174 {
175 14x ::new(&arr_[n_++]) value_type(b);
176 14x size_ += b.size();
177 }
178 18x ++first;
179 }
180 8x }
181
182 /** Construct from an iterator range with overflow checking.
183
184 Copies all non-empty buffer descriptors from the range
185 `[first, last)` into the internal array.
186
187 @param first Iterator to the first buffer descriptor.
188 @param last Iterator past the last buffer descriptor.
189
190 @throws std::length_error if the range contains more
191 than N non-empty buffers.
192 */
193 template<class Iterator>
194 4x buffer_array(std::in_place_t, Iterator first, Iterator last)
195 4x : dummy_(0)
196 {
197 14x while(first != last)
198 {
199 12x value_type b(*first);
200 12x if(b.size() != 0)
201 {
202 12x if(n_ >= N)
203 2x detail::throw_length_error();
204 10x ::new(&arr_[n_++]) value_type(b);
205 10x size_ += b.size();
206 }
207 10x ++first;
208 }
209 2x }
210
211 /** Destructor.
212 */
213 625x ~buffer_array()
214 {
215 1725x while(n_--)
216 1100x arr_[n_].~value_type();
217 625x }
218
219 /** Assign by copying.
220 */
221 buffer_array&
222 4x operator=(buffer_array const& other) noexcept
223 {
224 4x if(this != &other)
225 {
226 4x while(n_--)
227 arr_[n_].~value_type();
228 4x n_ = other.n_;
229 4x size_ = other.size_;
230 10x for(std::size_t i = 0; i < n_; ++i)
231 6x ::new(&arr_[i]) value_type(other.arr_[i]);
232 }
233 4x return *this;
234 }
235
236 /** Return an iterator to the beginning.
237 */
238 value_type*
239 130x begin() noexcept
240 {
241 130x return arr_;
242 }
243
244 /** Return an iterator to the beginning.
245 */
246 value_type const*
247 2441x begin() const noexcept
248 {
249 2441x return arr_;
250 }
251
252 /** Return an iterator to the end.
253 */
254 value_type*
255 129x end() noexcept
256 {
257 129x return arr_ + n_;
258 }
259
260 /** Return an iterator to the end.
261 */
262 value_type const*
263 2441x end() const noexcept
264 {
265 2441x return arr_ + n_;
266 }
267
268 /** Return a span of the buffers.
269 */
270 std::span<value_type>
271 379x to_span() noexcept
272 {
273 379x return { arr_, n_ };
274 }
275
276 /** Return a span of the buffers.
277 */
278 std::span<value_type const>
279 175x to_span() const noexcept
280 {
281 175x return { arr_, n_ };
282 }
283
284 /** Conversion to mutable span.
285 */
286 1x operator std::span<value_type>() noexcept
287 {
288 1x return { arr_, n_ };
289 }
290
291 /** Conversion to const span.
292 */
293 operator std::span<value_type const>() const noexcept
294 {
295 return { arr_, n_ };
296 }
297
298 /** Return the total byte count in O(1).
299 */
300 std::size_t
301 byte_size() const noexcept
302 {
303 return size_;
304 }
305 };
306
307 /** Alias for buffer_array holding const_buffer.
308
309 @tparam N Maximum number of buffers.
310 */
311 template<std::size_t N>
312 using const_buffer_array = buffer_array<N, true>;
313
314 /** Alias for buffer_array holding mutable_buffer.
315
316 @tparam N Maximum number of buffers.
317 */
318 template<std::size_t N>
319 using mutable_buffer_array = buffer_array<N, false>;
320
321 } // namespace detail
322 } // namespace capy
323 } // namespace boost
324
325 #endif
326