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 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 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 : 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 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 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 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 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 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 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 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 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 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 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 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 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
|