TLA Line data Source code
1 : //
2 : // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/capy
9 : //
10 :
11 : #ifndef BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
12 : #define BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
13 :
14 : #include <boost/capy/detail/config.hpp>
15 : #include <boost/capy/buffers.hpp>
16 : #include <array>
17 : #include <cstdlib>
18 : #include <iterator>
19 : #include <ranges>
20 : #include <span>
21 : #include <string>
22 : #include <string_view>
23 : #include <type_traits>
24 : #include <vector>
25 :
26 : BOOST_CAPY_MSVC_WARNING_PUSH
27 : BOOST_CAPY_MSVC_WARNING_DISABLE(4459)
28 :
29 : namespace boost {
30 : namespace capy {
31 :
32 : /** Return the buffer unchanged.
33 :
34 : @param b The buffer to return.
35 : @return A copy of `b`, referring to the same storage.
36 : */
37 : [[nodiscard]] inline
38 : mutable_buffer
39 HIT 1 : make_buffer(
40 : mutable_buffer const& b) noexcept
41 : {
42 1 : return b;
43 : }
44 :
45 : /** Return the buffer, clamped to a maximum size.
46 :
47 : @param b The buffer to return.
48 : @param max_size The maximum size, in bytes, of the result.
49 : @return A buffer referring to the storage of `b` whose size
50 : is the smaller of `b.size()` and `max_size`.
51 : */
52 : [[nodiscard]] inline
53 : mutable_buffer
54 2 : make_buffer(
55 : mutable_buffer const& b,
56 : std::size_t max_size) noexcept
57 : {
58 5 : return mutable_buffer(
59 : b.data(),
60 5 : b.size() < max_size ? b.size() : max_size);
61 : }
62 :
63 : /** Return a buffer referring to a region of memory.
64 :
65 : @param data A pointer to the start of the region. The region
66 : must outlive the returned buffer.
67 : @param size The size of the region, in bytes.
68 : @return A buffer referring to `[data, data + size)`.
69 : */
70 : [[nodiscard]] inline
71 : mutable_buffer
72 717 : make_buffer(
73 : void* data,
74 : std::size_t size) noexcept
75 : {
76 717 : return mutable_buffer(data, size);
77 : }
78 :
79 : /** Return a buffer referring to a region of memory, clamped to a maximum size.
80 :
81 : @param data A pointer to the start of the region. The region
82 : must outlive the returned buffer.
83 : @param size The size of the region, in bytes.
84 : @param max_size The maximum size, in bytes, of the result.
85 : @return A buffer referring to `data` whose size is the smaller
86 : of `size` and `max_size`.
87 : */
88 : [[nodiscard]] inline
89 : mutable_buffer
90 2 : make_buffer(
91 : void* data,
92 : std::size_t size,
93 : std::size_t max_size) noexcept
94 : {
95 2 : return mutable_buffer(
96 : data,
97 2 : size < max_size ? size : max_size);
98 : }
99 :
100 : /** Return the buffer unchanged.
101 :
102 : @param b The buffer to return.
103 : @return A copy of `b`, referring to the same storage.
104 : */
105 : [[nodiscard]] inline
106 : const_buffer
107 1 : make_buffer(
108 : const_buffer const& b) noexcept
109 : {
110 1 : return b;
111 : }
112 :
113 : /** Return the buffer, clamped to a maximum size.
114 :
115 : @param b The buffer to return.
116 : @param max_size The maximum size, in bytes, of the result.
117 : @return A buffer referring to the storage of `b` whose size
118 : is the smaller of `b.size()` and `max_size`.
119 : */
120 : [[nodiscard]] inline
121 : const_buffer
122 2 : make_buffer(
123 : const_buffer const& b,
124 : std::size_t max_size) noexcept
125 : {
126 5 : return const_buffer(
127 : b.data(),
128 5 : b.size() < max_size ? b.size() : max_size);
129 : }
130 :
131 : /** Return a buffer referring to a region of memory.
132 :
133 : @param data A pointer to the start of the region. The region
134 : must outlive the returned buffer.
135 : @param size The size of the region, in bytes.
136 : @return A buffer referring to `[data, data + size)`.
137 : */
138 : [[nodiscard]] inline
139 : const_buffer
140 1 : make_buffer(
141 : void const* data,
142 : std::size_t size) noexcept
143 : {
144 1 : return const_buffer(data, size);
145 : }
146 :
147 : /** Return a buffer referring to a region of memory, clamped to a maximum size.
148 :
149 : @param data A pointer to the start of the region. The region
150 : must outlive the returned buffer.
151 : @param size The size of the region, in bytes.
152 : @param max_size The maximum size, in bytes, of the result.
153 : @return A buffer referring to `data` whose size is the smaller
154 : of `size` and `max_size`.
155 : */
156 : [[nodiscard]] inline
157 : const_buffer
158 2 : make_buffer(
159 : void const* data,
160 : std::size_t size,
161 : std::size_t max_size) noexcept
162 : {
163 2 : return const_buffer(
164 : data,
165 2 : size < max_size ? size : max_size);
166 : }
167 :
168 : // std::basic_string_view
169 :
170 : /** Return a buffer from a `std::basic_string_view`.
171 :
172 : @param data The view whose characters are referenced. The
173 : underlying storage must outlive the returned buffer.
174 : @return A buffer referring to the view's storage. The size,
175 : in bytes, is `data.size() * sizeof(CharT)`.
176 : */
177 : template<class CharT, class Traits>
178 : [[nodiscard]]
179 : const_buffer
180 58 : make_buffer(
181 : std::basic_string_view<CharT, Traits> data) noexcept
182 : {
183 171 : return const_buffer(
184 114 : data.size() ? data.data() : nullptr,
185 59 : data.size() * sizeof(CharT));
186 : }
187 :
188 : /** Return a buffer from a `std::basic_string_view`, clamped to a maximum size.
189 :
190 : @param data The view whose characters are referenced. The
191 : underlying storage must outlive the returned buffer.
192 : @param max_size The maximum size, in bytes, of the result.
193 : @return A buffer referring to the view's storage whose size is
194 : the smaller of `data.size() * sizeof(CharT)` and `max_size`.
195 : */
196 : template<class CharT, class Traits>
197 : [[nodiscard]]
198 : const_buffer
199 2 : make_buffer(
200 : std::basic_string_view<CharT, Traits> data,
201 : std::size_t max_size) noexcept
202 : {
203 6 : return const_buffer(
204 4 : data.size() ? data.data() : nullptr,
205 2 : data.size() * sizeof(CharT) < max_size
206 3 : ? data.size() * sizeof(CharT) : max_size);
207 : }
208 :
209 : // Contiguous ranges
210 :
211 : namespace detail {
212 :
213 : template<class T>
214 : concept non_buffer_contiguous_range =
215 : std::ranges::contiguous_range<T> &&
216 : std::ranges::sized_range<T> &&
217 : !std::convertible_to<T, const_buffer> &&
218 : !std::convertible_to<T, mutable_buffer> &&
219 : std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
220 :
221 : template<class T>
222 : concept mutable_contiguous_range =
223 : non_buffer_contiguous_range<T> &&
224 : !std::is_const_v<std::remove_reference_t<
225 : std::ranges::range_reference_t<T>>>;
226 :
227 : template<class T>
228 : concept const_contiguous_range =
229 : non_buffer_contiguous_range<T> &&
230 : std::is_const_v<std::remove_reference_t<
231 : std::ranges::range_reference_t<T>>>;
232 :
233 : } // detail
234 :
235 : /** Return a buffer from a mutable contiguous range.
236 :
237 : Accepts any sized, contiguous range of trivially-copyable,
238 : non-const elements, whether passed as an lvalue or a temporary.
239 : That includes `std::vector`, `std::array`, `std::string`,
240 : `std::span`, `boost::span`, and built-in arrays. The returned buffer
241 : refers to the range's storage, which must outlive the buffer.
242 : Its size, in bytes, is `size() * sizeof(element)`.
243 :
244 : @param data The range whose storage is referenced. It must
245 : outlive the returned buffer.
246 :
247 : @return A buffer of size `size() * sizeof(element)` referring to
248 : the range's storage.
249 : */
250 : template<detail::mutable_contiguous_range T>
251 : [[nodiscard]]
252 : mutable_buffer
253 649 : make_buffer(T&& data) noexcept
254 : {
255 1940 : return mutable_buffer(
256 1295 : std::ranges::size(data) ? std::ranges::data(data) : nullptr,
257 653 : std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
258 : }
259 :
260 : /** Return a buffer from a mutable contiguous range, clamped to a maximum size.
261 :
262 : Like the unclamped overload, but the result is no larger than
263 : `max_size` bytes.
264 :
265 : @param data The range whose storage is referenced. It must
266 : outlive the returned buffer.
267 : @param max_size The maximum size, in bytes, of the result.
268 : @return A buffer whose size is the smaller of
269 : `size() * sizeof(element)` and `max_size`.
270 : */
271 : template<detail::mutable_contiguous_range T>
272 : [[nodiscard]]
273 : mutable_buffer
274 42 : make_buffer(
275 : T&& data,
276 : std::size_t max_size) noexcept
277 : {
278 42 : auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
279 89 : return mutable_buffer(
280 84 : std::ranges::size(data) ? std::ranges::data(data) : nullptr,
281 84 : n < max_size ? n : max_size);
282 : }
283 :
284 : /** Return a buffer from a const contiguous range.
285 :
286 : Accepts any sized, contiguous range of trivially-copyable
287 : elements with const access, including const `std::vector`,
288 : `std::array`, `std::string`, `std::span`, `boost::span`, and
289 : string literals. The returned buffer refers to the range's
290 : storage, which must outlive the buffer. Its size, in bytes,
291 : is `size() * sizeof(element)`.
292 :
293 : @param data The range whose storage is referenced. It must
294 : outlive the returned buffer.
295 :
296 : @return A buffer of size `size() * sizeof(element)` referring to
297 : the range's storage.
298 : */
299 : template<detail::non_buffer_contiguous_range T>
300 : [[nodiscard]]
301 : const_buffer
302 65 : make_buffer(T const& data) noexcept
303 : {
304 195 : return const_buffer(
305 130 : std::ranges::size(data) ? std::ranges::data(data) : nullptr,
306 65 : std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
307 : }
308 :
309 : /** Return a buffer from a const contiguous range, clamped to a maximum size.
310 :
311 : Like the unclamped overload, but the result is no larger than
312 : `max_size` bytes.
313 :
314 : @param data The range whose storage is referenced. It must
315 : outlive the returned buffer.
316 : @param max_size The maximum size, in bytes, of the result.
317 : @return A buffer whose size is the smaller of
318 : `size() * sizeof(element)` and `max_size`.
319 : */
320 : template<detail::non_buffer_contiguous_range T>
321 : [[nodiscard]]
322 : const_buffer
323 366 : make_buffer(
324 : T const& data,
325 : std::size_t max_size) noexcept
326 : {
327 366 : auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
328 737 : return const_buffer(
329 732 : std::ranges::size(data) ? std::ranges::data(data) : nullptr,
330 732 : n < max_size ? n : max_size);
331 : }
332 :
333 : } // capy
334 : } // boost
335 :
336 : BOOST_CAPY_MSVC_WARNING_POP
337 :
338 : #endif
|