libs/capy/include/boost/capy/buffers/make_buffer.hpp

100.0% Lines (105/105) 100.0% Functions (46/46) 81.8% Branches (36/44)
libs/capy/include/boost/capy/buffers/make_buffer.hpp
Line Branch Hits Source Code
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/capy
8 //
9
10 #ifndef BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
11 #define BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15 #include <array>
16 #include <cstdlib>
17 #include <iterator>
18 #include <ranges>
19 #include <span>
20 #include <string>
21 #include <string_view>
22 #include <type_traits>
23 #include <vector>
24
25 #ifdef _MSC_VER
26 #pragma warning(push)
27 #pragma warning(disable: 4459)
28 #endif
29
30 namespace boost {
31 namespace capy {
32
33 /** Return a buffer.
34 */
35 [[nodiscard]] inline
36 mutable_buffer
37 1 make_buffer(
38 mutable_buffer const& b) noexcept
39 {
40 1 return b;
41 }
42
43 /** Return a buffer with a maximum size.
44 */
45 [[nodiscard]] inline
46 mutable_buffer
47 2 make_buffer(
48 mutable_buffer const& b,
49 std::size_t max_size) noexcept
50 {
51
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
5 return mutable_buffer(
52 b.data(),
53 5 b.size() < max_size ? b.size() : max_size);
54 }
55
56 /** Return a buffer.
57 */
58 [[nodiscard]] inline
59 mutable_buffer
60 3524 make_buffer(
61 void* data,
62 std::size_t size) noexcept
63 {
64 3524 return mutable_buffer(data, size);
65 }
66
67 /** Return a buffer with a maximum size.
68 */
69 [[nodiscard]] inline
70 mutable_buffer
71 2 make_buffer(
72 void* data,
73 std::size_t size,
74 std::size_t max_size) noexcept
75 {
76
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 return mutable_buffer(
77 data,
78 2 size < max_size ? size : max_size);
79 }
80
81 /** Return a buffer.
82 */
83 [[nodiscard]] inline
84 const_buffer
85 1 make_buffer(
86 const_buffer const& b) noexcept
87 {
88 1 return b;
89 }
90
91 /** Return a buffer with a maximum size.
92 */
93 [[nodiscard]] inline
94 const_buffer
95 2 make_buffer(
96 const_buffer const& b,
97 std::size_t max_size) noexcept
98 {
99
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
5 return const_buffer(
100 b.data(),
101 5 b.size() < max_size ? b.size() : max_size);
102 }
103
104 /** Return a buffer.
105 */
106 [[nodiscard]] inline
107 const_buffer
108 1 make_buffer(
109 void const* data,
110 std::size_t size) noexcept
111 {
112 1 return const_buffer(data, size);
113 }
114
115 /** Return a buffer with a maximum size.
116 */
117 [[nodiscard]] inline
118 const_buffer
119 2 make_buffer(
120 void const* data,
121 std::size_t size,
122 std::size_t max_size) noexcept
123 {
124
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 return const_buffer(
125 data,
126 2 size < max_size ? size : max_size);
127 }
128
129 /** Return a buffer from a C-style array.
130 */
131 template<class T, std::size_t N>
132 requires std::is_trivially_copyable_v<T>
133 [[nodiscard]]
134 mutable_buffer
135 112 make_buffer(
136 T (&data)[N]) noexcept
137 {
138 112 return mutable_buffer(
139 112 data, N * sizeof(T));
140 }
141
142 /** Return a buffer from a C-style array with a maximum size.
143 */
144 template<class T, std::size_t N>
145 requires std::is_trivially_copyable_v<T>
146 [[nodiscard]]
147 mutable_buffer
148 9 make_buffer(
149 T (&data)[N],
150 std::size_t max_size) noexcept
151 {
152 18 return mutable_buffer(
153 data,
154 9 N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
155 }
156
157 /** Return a buffer from a const C-style array.
158 */
159 template<class T, std::size_t N>
160 requires std::is_trivially_copyable_v<T>
161 [[nodiscard]]
162 const_buffer
163 1 make_buffer(
164 T const (&data)[N]) noexcept
165 {
166 1 return const_buffer(
167 1 data, N * sizeof(T));
168 }
169
170 /** Return a buffer from a const C-style array with a maximum size.
171 */
172 template<class T, std::size_t N>
173 requires std::is_trivially_copyable_v<T>
174 [[nodiscard]]
175 const_buffer
176 115 make_buffer(
177 T const (&data)[N],
178 std::size_t max_size) noexcept
179 {
180 230 return const_buffer(
181 data,
182 115 N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
183 }
184
185 //------------------------------------------------
186 // std::array
187 //------------------------------------------------
188
189 /** Return a buffer from a std::array.
190 */
191 template<class T, std::size_t N>
192 requires std::is_trivially_copyable_v<T>
193 [[nodiscard]]
194 mutable_buffer
195 2 make_buffer(
196 std::array<T, N>& data) noexcept
197 {
198 4 return mutable_buffer(
199 3 data.data(), data.size() * sizeof(T));
200 }
201
202 /** Return a buffer from a std::array with a maximum size.
203 */
204 template<class T, std::size_t N>
205 requires std::is_trivially_copyable_v<T>
206 [[nodiscard]]
207 mutable_buffer
208 2 make_buffer(
209 std::array<T, N>& data,
210 std::size_t max_size) noexcept
211 {
212 6 return mutable_buffer(
213 2 data.data(),
214 2 data.size() * sizeof(T) < max_size
215 2 ? data.size() * sizeof(T) : max_size);
216 }
217
218 /** Return a buffer from a const std::array.
219 */
220 template<class T, std::size_t N>
221 requires std::is_trivially_copyable_v<T>
222 [[nodiscard]]
223 const_buffer
224 1 make_buffer(
225 std::array<T, N> const& data) noexcept
226 {
227 1 return const_buffer(
228 2 data.data(), data.size() * sizeof(T));
229 }
230
231 /** Return a buffer from a const std::array with a maximum size.
232 */
233 template<class T, std::size_t N>
234 requires std::is_trivially_copyable_v<T>
235 [[nodiscard]]
236 const_buffer
237 2 make_buffer(
238 std::array<T, N> const& data,
239 std::size_t max_size) noexcept
240 {
241 2 return const_buffer(
242 2 data.data(),
243 2 data.size() * sizeof(T) < max_size
244 2 ? data.size() * sizeof(T) : max_size);
245 }
246
247 //------------------------------------------------
248 // std::vector
249 //------------------------------------------------
250
251 /** Return a buffer from a std::vector.
252 */
253 template<class T, class Allocator>
254 requires std::is_trivially_copyable_v<T>
255 [[nodiscard]]
256 mutable_buffer
257 3 make_buffer(
258 std::vector<T, Allocator>& data) noexcept
259 {
260
3/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
7 return mutable_buffer(
261 5 data.size() ? data.data() : nullptr,
262 4 data.size() * sizeof(T));
263 }
264
265 /** Return a buffer from a std::vector with a maximum size.
266 */
267 template<class T, class Allocator>
268 requires std::is_trivially_copyable_v<T>
269 [[nodiscard]]
270 mutable_buffer
271 2 make_buffer(
272 std::vector<T, Allocator>& data,
273 std::size_t max_size) noexcept
274 {
275
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 return mutable_buffer(
276 4 data.size() ? data.data() : nullptr,
277 2 data.size() * sizeof(T) < max_size
278 3 ? data.size() * sizeof(T) : max_size);
279 }
280
281 /** Return a buffer from a const std::vector.
282 */
283 template<class T, class Allocator>
284 requires std::is_trivially_copyable_v<T>
285 [[nodiscard]]
286 const_buffer
287 1 make_buffer(
288 std::vector<T, Allocator> const& data) noexcept
289 {
290
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
3 return const_buffer(
291 2 data.size() ? data.data() : nullptr,
292 1 data.size() * sizeof(T));
293 }
294
295 /** Return a buffer from a const std::vector with a maximum size.
296 */
297 template<class T, class Allocator>
298 requires std::is_trivially_copyable_v<T>
299 [[nodiscard]]
300 const_buffer
301 2 make_buffer(
302 std::vector<T, Allocator> const& data,
303 std::size_t max_size) noexcept
304 {
305
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 return const_buffer(
306 4 data.size() ? data.data() : nullptr,
307 2 data.size() * sizeof(T) < max_size
308 3 ? data.size() * sizeof(T) : max_size);
309 }
310
311 //------------------------------------------------
312 // std::basic_string
313 //------------------------------------------------
314
315 /** Return a buffer from a std::basic_string.
316 */
317 template<class CharT, class Traits, class Allocator>
318 [[nodiscard]]
319 mutable_buffer
320 17 make_buffer(
321 std::basic_string<CharT, Traits, Allocator>& data) noexcept
322 {
323
3/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1 time.
49 return mutable_buffer(
324 33 data.size() ? &data[0] : nullptr,
325 18 data.size() * sizeof(CharT));
326 }
327
328 /** Return a buffer from a std::basic_string with a maximum size.
329 */
330 template<class CharT, class Traits, class Allocator>
331 [[nodiscard]]
332 mutable_buffer
333 2 make_buffer(
334 std::basic_string<CharT, Traits, Allocator>& data,
335 std::size_t max_size) noexcept
336 {
337
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 return mutable_buffer(
338 4 data.size() ? &data[0] : nullptr,
339 2 data.size() * sizeof(CharT) < max_size
340 3 ? data.size() * sizeof(CharT) : max_size);
341 }
342
343 /** Return a buffer from a const std::basic_string.
344 */
345 template<class CharT, class Traits, class Allocator>
346 [[nodiscard]]
347 const_buffer
348 163 make_buffer(
349 std::basic_string<CharT, Traits, Allocator> const& data) noexcept
350 {
351 326 return const_buffer(
352 163 data.data(),
353 163 data.size() * sizeof(CharT));
354 }
355
356 /** Return a buffer from a const std::basic_string with a maximum size.
357 */
358 template<class CharT, class Traits, class Allocator>
359 [[nodiscard]]
360 const_buffer
361 2 make_buffer(
362 std::basic_string<CharT, Traits, Allocator> const& data,
363 std::size_t max_size) noexcept
364 {
365
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
6 return const_buffer(
366 2 data.data(),
367 2 data.size() * sizeof(CharT) < max_size
368 3 ? data.size() * sizeof(CharT) : max_size);
369 }
370
371 //------------------------------------------------
372 // std::basic_string_view
373 //------------------------------------------------
374
375 /** Return a buffer from a std::basic_string_view.
376 */
377 template<class CharT, class Traits>
378 [[nodiscard]]
379 const_buffer
380 7 make_buffer(
381 std::basic_string_view<CharT, Traits> data) noexcept
382 {
383
3/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 time.
19 return const_buffer(
384 13 data.size() ? data.data() : nullptr,
385 8 data.size() * sizeof(CharT));
386 }
387
388 /** Return a buffer from a std::basic_string_view with a maximum size.
389 */
390 template<class CharT, class Traits>
391 [[nodiscard]]
392 const_buffer
393 2 make_buffer(
394 std::basic_string_view<CharT, Traits> data,
395 std::size_t max_size) noexcept
396 {
397
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 return const_buffer(
398 4 data.size() ? data.data() : nullptr,
399 2 data.size() * sizeof(CharT) < max_size
400 3 ? data.size() * sizeof(CharT) : max_size);
401 }
402
403 //------------------------------------------------
404 // std::span
405 //------------------------------------------------
406
407 /** Return a buffer from a mutable std::span.
408 */
409 template<class T, std::size_t Extent>
410 requires (!std::is_const_v<T> && sizeof(T) == 1)
411 [[nodiscard]]
412 mutable_buffer
413 2 make_buffer(
414 std::span<T, Extent> data) noexcept
415 {
416 2 return mutable_buffer(data.data(), data.size());
417 }
418
419 /** Return a buffer from a mutable std::span with a maximum size.
420 */
421 template<class T, std::size_t Extent>
422 requires (!std::is_const_v<T> && sizeof(T) == 1)
423 [[nodiscard]]
424 mutable_buffer
425 2 make_buffer(
426 std::span<T, Extent> data,
427 std::size_t max_size) noexcept
428 {
429
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
6 return mutable_buffer(
430 2 data.data(),
431 5 data.size() < max_size ? data.size() : max_size);
432 }
433
434 /** Return a buffer from a const std::span.
435 */
436 template<class T, std::size_t Extent>
437 requires (sizeof(T) == 1)
438 [[nodiscard]]
439 const_buffer
440 1 make_buffer(
441 std::span<T const, Extent> data) noexcept
442 {
443 1 return const_buffer(data.data(), data.size());
444 }
445
446 /** Return a buffer from a const std::span with a maximum size.
447 */
448 template<class T, std::size_t Extent>
449 requires (sizeof(T) == 1)
450 [[nodiscard]]
451 const_buffer
452 2 make_buffer(
453 std::span<T const, Extent> data,
454 std::size_t max_size) noexcept
455 {
456
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
6 return const_buffer(
457 2 data.data(),
458 5 data.size() < max_size ? data.size() : max_size);
459 }
460
461 //------------------------------------------------
462 // Contiguous ranges
463 //------------------------------------------------
464
465 namespace detail {
466
467 template<class T>
468 concept non_buffer_contiguous_range =
469 std::ranges::contiguous_range<T> &&
470 std::ranges::sized_range<T> &&
471 !std::convertible_to<T, const_buffer> &&
472 !std::convertible_to<T, mutable_buffer> &&
473 std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
474
475 template<class T>
476 concept mutable_contiguous_range =
477 non_buffer_contiguous_range<T> &&
478 !std::is_const_v<std::remove_reference_t<
479 std::ranges::range_reference_t<T>>>;
480
481 template<class T>
482 concept const_contiguous_range =
483 non_buffer_contiguous_range<T> &&
484 std::is_const_v<std::remove_reference_t<
485 std::ranges::range_reference_t<T>>>;
486
487 } // detail
488
489 /** Return a buffer from a mutable contiguous range.
490 */
491 template<detail::mutable_contiguous_range T>
492 [[nodiscard]]
493 mutable_buffer
494 make_buffer(T& data) noexcept
495 {
496 return mutable_buffer(
497 std::ranges::size(data) ? std::ranges::data(data) : nullptr,
498 std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
499 }
500
501 /** Return a buffer from a mutable contiguous range with a maximum size.
502 */
503 template<detail::mutable_contiguous_range T>
504 [[nodiscard]]
505 mutable_buffer
506 make_buffer(
507 T& data,
508 std::size_t max_size) noexcept
509 {
510 auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
511 return mutable_buffer(
512 std::ranges::size(data) ? std::ranges::data(data) : nullptr,
513 n < max_size ? n : max_size);
514 }
515
516 /** Return a buffer from a const contiguous range.
517 */
518 template<detail::non_buffer_contiguous_range T>
519 [[nodiscard]]
520 const_buffer
521 make_buffer(T const& data) noexcept
522 {
523 return const_buffer(
524 std::ranges::size(data) ? std::ranges::data(data) : nullptr,
525 std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
526 }
527
528 /** Return a buffer from a const contiguous range with a maximum size.
529 */
530 template<detail::non_buffer_contiguous_range T>
531 [[nodiscard]]
532 const_buffer
533 make_buffer(
534 T const& data,
535 std::size_t max_size) noexcept
536 {
537 auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
538 return const_buffer(
539 std::ranges::size(data) ? std::ranges::data(data) : nullptr,
540 n < max_size ? n : max_size);
541 }
542
543 } // capy
544 } // boost
545
546 #ifdef _MSC_VER
547 #pragma warning(pop)
548 #endif
549
550 #endif
551