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