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