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 : #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 HIT 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 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 3903 : make_buffer(
61 : void* data,
62 : std::size_t size) noexcept
63 : {
64 3903 : 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 : 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 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 : 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 656 : make_buffer(
136 : T (&data)[N]) noexcept
137 : {
138 656 : return mutable_buffer(
139 656 : 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 39 : make_buffer(
149 : T (&data)[N],
150 : std::size_t max_size) noexcept
151 : {
152 78 : return mutable_buffer(
153 : data,
154 39 : 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 714 : make_buffer(
177 : T const (&data)[N],
178 : std::size_t max_size) noexcept
179 : {
180 1428 : return const_buffer(
181 : data,
182 714 : 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 2 : make_buffer(
194 : std::array<T, N>& data) noexcept
195 : {
196 4 : return mutable_buffer(
197 3 : 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 2 : make_buffer(
207 : std::array<T, N>& data,
208 : std::size_t max_size) noexcept
209 : {
210 6 : return mutable_buffer(
211 2 : data.data(),
212 2 : data.size() * sizeof(T) < max_size
213 2 : ? 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 1 : make_buffer(
223 : std::array<T, N> const& data) noexcept
224 : {
225 1 : return const_buffer(
226 2 : 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 2 : make_buffer(
236 : std::array<T, N> const& data,
237 : std::size_t max_size) noexcept
238 : {
239 2 : return const_buffer(
240 2 : data.data(),
241 2 : data.size() * sizeof(T) < max_size
242 2 : ? 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 3 : make_buffer(
254 : std::vector<T, Allocator>& data) noexcept
255 : {
256 7 : return mutable_buffer(
257 5 : data.size() ? data.data() : nullptr,
258 4 : 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 2 : make_buffer(
268 : std::vector<T, Allocator>& data,
269 : std::size_t max_size) noexcept
270 : {
271 6 : return mutable_buffer(
272 4 : data.size() ? data.data() : nullptr,
273 2 : data.size() * sizeof(T) < max_size
274 3 : ? 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 1 : make_buffer(
284 : std::vector<T, Allocator> const& data) noexcept
285 : {
286 3 : return const_buffer(
287 2 : data.size() ? data.data() : nullptr,
288 1 : 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 2 : make_buffer(
298 : std::vector<T, Allocator> const& data,
299 : std::size_t max_size) noexcept
300 : {
301 6 : return const_buffer(
302 4 : data.size() ? data.data() : nullptr,
303 2 : data.size() * sizeof(T) < max_size
304 3 : ? 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 168 : make_buffer(
315 : std::basic_string<CharT, Traits, Allocator>& data) noexcept
316 : {
317 502 : return mutable_buffer(
318 335 : data.size() ? &data[0] : nullptr,
319 169 : 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 2 : make_buffer(
328 : std::basic_string<CharT, Traits, Allocator>& data,
329 : std::size_t max_size) noexcept
330 : {
331 6 : return mutable_buffer(
332 4 : data.size() ? &data[0] : nullptr,
333 2 : data.size() * sizeof(CharT) < max_size
334 3 : ? 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 163 : make_buffer(
343 : std::basic_string<CharT, Traits, Allocator> const& data) noexcept
344 : {
345 326 : return const_buffer(
346 163 : data.data(),
347 163 : 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 2 : make_buffer(
356 : std::basic_string<CharT, Traits, Allocator> const& data,
357 : std::size_t max_size) noexcept
358 : {
359 6 : return const_buffer(
360 2 : data.data(),
361 2 : data.size() * sizeof(CharT) < max_size
362 3 : ? 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 49 : make_buffer(
373 : std::basic_string_view<CharT, Traits> data) noexcept
374 : {
375 145 : return const_buffer(
376 97 : data.size() ? data.data() : nullptr,
377 50 : 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 2 : make_buffer(
386 : std::basic_string_view<CharT, Traits> data,
387 : std::size_t max_size) noexcept
388 : {
389 6 : return const_buffer(
390 4 : data.size() ? data.data() : nullptr,
391 2 : data.size() * sizeof(CharT) < max_size
392 3 : ? 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 2 : make_buffer(
404 : std::span<T, Extent> data) noexcept
405 : {
406 2 : 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 2 : make_buffer(
416 : std::span<T, Extent> data,
417 : std::size_t max_size) noexcept
418 : {
419 6 : return mutable_buffer(
420 2 : data.data(),
421 5 : 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 1 : make_buffer(
431 : std::span<T const, Extent> data) noexcept
432 : {
433 1 : 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 2 : make_buffer(
443 : std::span<T const, Extent> data,
444 : std::size_t max_size) noexcept
445 : {
446 6 : return const_buffer(
447 2 : data.data(),
448 5 : 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
|