include/boost/capy/buffers/make_buffer.hpp

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