1  
//
1  
//
2  
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/capy
7  
// Official repository: https://github.com/cppalliance/capy
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
10  
#ifndef BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
11  
#define BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
11  
#define BOOST_CAPY_BUFFERS_MAKE_BUFFER_HPP
12  

12  

13  
#include <boost/capy/detail/config.hpp>
13  
#include <boost/capy/detail/config.hpp>
14  
#include <boost/capy/buffers.hpp>
14  
#include <boost/capy/buffers.hpp>
15  
#include <array>
15  
#include <array>
16  
#include <cstdlib>
16  
#include <cstdlib>
17  
#include <iterator>
17  
#include <iterator>
18  
#include <ranges>
18  
#include <ranges>
19  
#include <span>
19  
#include <span>
20  
#include <string>
20  
#include <string>
21  
#include <string_view>
21  
#include <string_view>
22  
#include <type_traits>
22  
#include <type_traits>
23  
#include <vector>
23  
#include <vector>
24  

24  

25  
BOOST_CAPY_MSVC_WARNING_PUSH
25  
BOOST_CAPY_MSVC_WARNING_PUSH
26  
BOOST_CAPY_MSVC_WARNING_DISABLE(4459)
26  
BOOST_CAPY_MSVC_WARNING_DISABLE(4459)
27  

27  

28  
namespace boost {
28  
namespace boost {
29  
namespace capy {
29  
namespace capy {
30  

30  

31  
/** Return a buffer.
31  
/** Return a buffer.
32  
*/
32  
*/
33  
[[nodiscard]] inline
33  
[[nodiscard]] inline
34  
mutable_buffer
34  
mutable_buffer
35  
make_buffer(
35  
make_buffer(
36  
    mutable_buffer const& b) noexcept
36  
    mutable_buffer const& b) noexcept
37  
{
37  
{
38  
    return b;
38  
    return b;
39  
}
39  
}
40  

40  

41  
/** Return a buffer with a maximum size.
41  
/** Return a buffer with a maximum size.
42  
*/
42  
*/
43  
[[nodiscard]] inline
43  
[[nodiscard]] inline
44  
mutable_buffer
44  
mutable_buffer
45  
make_buffer(
45  
make_buffer(
46  
    mutable_buffer const& b,
46  
    mutable_buffer const& b,
47  
    std::size_t max_size) noexcept
47  
    std::size_t max_size) noexcept
48  
{
48  
{
49  
    return mutable_buffer(
49  
    return mutable_buffer(
50  
        b.data(),
50  
        b.data(),
51  
        b.size() < max_size ? b.size() : max_size);
51  
        b.size() < max_size ? b.size() : max_size);
52  
}
52  
}
53  

53  

54  
/** Return a buffer.
54  
/** Return a buffer.
55  
*/
55  
*/
56  
[[nodiscard]] inline
56  
[[nodiscard]] inline
57  
mutable_buffer
57  
mutable_buffer
58  
make_buffer(
58  
make_buffer(
59  
    void* data,
59  
    void* data,
60  
    std::size_t size) noexcept
60  
    std::size_t size) noexcept
61  
{
61  
{
62  
    return mutable_buffer(data, size);
62  
    return mutable_buffer(data, size);
63  
}
63  
}
64  

64  

65  
/** Return a buffer with a maximum size.
65  
/** Return a buffer with a maximum size.
66  
*/
66  
*/
67  
[[nodiscard]] inline
67  
[[nodiscard]] inline
68  
mutable_buffer
68  
mutable_buffer
69  
make_buffer(
69  
make_buffer(
70  
    void* data,
70  
    void* data,
71  
    std::size_t size,
71  
    std::size_t size,
72  
    std::size_t max_size) noexcept
72  
    std::size_t max_size) noexcept
73  
{
73  
{
74  
    return mutable_buffer(
74  
    return mutable_buffer(
75  
        data,
75  
        data,
76  
        size < max_size ? size : max_size);
76  
        size < max_size ? size : max_size);
77  
}
77  
}
78  

78  

79  
/** Return a buffer.
79  
/** Return a buffer.
80  
*/
80  
*/
81  
[[nodiscard]] inline
81  
[[nodiscard]] inline
82  
const_buffer
82  
const_buffer
83  
make_buffer(
83  
make_buffer(
84  
    const_buffer const& b) noexcept
84  
    const_buffer const& b) noexcept
85  
{
85  
{
86  
    return b;
86  
    return b;
87  
}
87  
}
88  

88  

89  
/** Return a buffer with a maximum size.
89  
/** Return a buffer with a maximum size.
90  
*/
90  
*/
91  
[[nodiscard]] inline
91  
[[nodiscard]] inline
92  
const_buffer
92  
const_buffer
93  
make_buffer(
93  
make_buffer(
94  
    const_buffer const& b,
94  
    const_buffer const& b,
95  
    std::size_t max_size) noexcept
95  
    std::size_t max_size) noexcept
96  
{
96  
{
97  
    return const_buffer(
97  
    return const_buffer(
98  
        b.data(),
98  
        b.data(),
99  
        b.size() < max_size ? b.size() : max_size);
99  
        b.size() < max_size ? b.size() : max_size);
100  
}
100  
}
101  

101  

102  
/** Return a buffer.
102  
/** Return a buffer.
103  
*/
103  
*/
104  
[[nodiscard]] inline
104  
[[nodiscard]] inline
105  
const_buffer
105  
const_buffer
106  
make_buffer(
106  
make_buffer(
107  
    void const* data,
107  
    void const* data,
108  
    std::size_t size) noexcept
108  
    std::size_t size) noexcept
109  
{
109  
{
110  
    return const_buffer(data, size);
110  
    return const_buffer(data, size);
111  
}
111  
}
112  

112  

113  
/** Return a buffer with a maximum size.
113  
/** Return a buffer with a maximum size.
114  
*/
114  
*/
115  
[[nodiscard]] inline
115  
[[nodiscard]] inline
116  
const_buffer
116  
const_buffer
117  
make_buffer(
117  
make_buffer(
118  
    void const* data,
118  
    void const* data,
119  
    std::size_t size,
119  
    std::size_t size,
120  
    std::size_t max_size) noexcept
120  
    std::size_t max_size) noexcept
121  
{
121  
{
122  
    return const_buffer(
122  
    return const_buffer(
123  
        data,
123  
        data,
124  
        size < max_size ? size : max_size);
124  
        size < max_size ? size : max_size);
125  
}
125  
}
126  

126  

127  
/** Return a buffer from a C-style array.
127  
/** Return a buffer from a C-style array.
128  
*/
128  
*/
129  
template<class T, std::size_t N>
129  
template<class T, std::size_t N>
130  
    requires std::is_trivially_copyable_v<T>
130  
    requires std::is_trivially_copyable_v<T>
131  
[[nodiscard]]
131  
[[nodiscard]]
132  
mutable_buffer
132  
mutable_buffer
133  
make_buffer(
133  
make_buffer(
134  
    T (&data)[N]) noexcept
134  
    T (&data)[N]) noexcept
135  
{
135  
{
136  
    return mutable_buffer(
136  
    return mutable_buffer(
137  
        data, N * sizeof(T));
137  
        data, N * sizeof(T));
138  
}
138  
}
139  

139  

140  
/** Return a buffer from a C-style array with a maximum size.
140  
/** Return a buffer from a C-style array with a maximum size.
141  
*/
141  
*/
142  
template<class T, std::size_t N>
142  
template<class T, std::size_t N>
143  
    requires std::is_trivially_copyable_v<T>
143  
    requires std::is_trivially_copyable_v<T>
144  
[[nodiscard]]
144  
[[nodiscard]]
145  
mutable_buffer
145  
mutable_buffer
146  
make_buffer(
146  
make_buffer(
147  
    T (&data)[N],
147  
    T (&data)[N],
148  
    std::size_t max_size) noexcept
148  
    std::size_t max_size) noexcept
149  
{
149  
{
150  
    return mutable_buffer(
150  
    return mutable_buffer(
151  
        data,
151  
        data,
152  
        N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
152  
        N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
153  
}
153  
}
154  

154  

155  
/** Return a buffer from a const C-style array.
155  
/** Return a buffer from a const C-style array.
156  
*/
156  
*/
157  
template<class T, std::size_t N>
157  
template<class T, std::size_t N>
158  
    requires std::is_trivially_copyable_v<T>
158  
    requires std::is_trivially_copyable_v<T>
159  
[[nodiscard]]
159  
[[nodiscard]]
160  
const_buffer
160  
const_buffer
161  
make_buffer(
161  
make_buffer(
162  
    T const (&data)[N]) noexcept
162  
    T const (&data)[N]) noexcept
163  
{
163  
{
164  
    return const_buffer(
164  
    return const_buffer(
165  
        data, N * sizeof(T));
165  
        data, N * sizeof(T));
166  
}
166  
}
167  

167  

168  
/** Return a buffer from a const C-style array with a maximum size.
168  
/** Return a buffer from a const C-style array with a maximum size.
169  
*/
169  
*/
170  
template<class T, std::size_t N>
170  
template<class T, std::size_t N>
171  
    requires std::is_trivially_copyable_v<T>
171  
    requires std::is_trivially_copyable_v<T>
172  
[[nodiscard]]
172  
[[nodiscard]]
173  
const_buffer
173  
const_buffer
174  
make_buffer(
174  
make_buffer(
175  
    T const (&data)[N],
175  
    T const (&data)[N],
176  
    std::size_t max_size) noexcept
176  
    std::size_t max_size) noexcept
177  
{
177  
{
178  
    return const_buffer(
178  
    return const_buffer(
179  
        data,
179  
        data,
180  
        N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
180  
        N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
181  
}
181  
}
182  

182  

183  
// std::array
183  
// std::array
184  

184  

185  
/** Return a buffer from a std::array.
185  
/** Return a buffer from a std::array.
186  
*/
186  
*/
187  
template<class T, std::size_t N>
187  
template<class T, std::size_t N>
188  
    requires std::is_trivially_copyable_v<T>
188  
    requires std::is_trivially_copyable_v<T>
189  
[[nodiscard]]
189  
[[nodiscard]]
190  
mutable_buffer
190  
mutable_buffer
191  
make_buffer(
191  
make_buffer(
192  
    std::array<T, N>& data) noexcept
192  
    std::array<T, N>& data) noexcept
193  
{
193  
{
194  
    return mutable_buffer(
194  
    return mutable_buffer(
195  
        data.data(), data.size() * sizeof(T));
195  
        data.data(), data.size() * sizeof(T));
196  
}
196  
}
197  

197  

198  
/** Return a buffer from a std::array with a maximum size.
198  
/** Return a buffer from a std::array with a maximum size.
199  
*/
199  
*/
200  
template<class T, std::size_t N>
200  
template<class T, std::size_t N>
201  
    requires std::is_trivially_copyable_v<T>
201  
    requires std::is_trivially_copyable_v<T>
202  
[[nodiscard]]
202  
[[nodiscard]]
203  
mutable_buffer
203  
mutable_buffer
204  
make_buffer(
204  
make_buffer(
205  
    std::array<T, N>& data,
205  
    std::array<T, N>& data,
206  
    std::size_t max_size) noexcept
206  
    std::size_t max_size) noexcept
207  
{
207  
{
208  
    return mutable_buffer(
208  
    return mutable_buffer(
209  
        data.data(),
209  
        data.data(),
210  
        data.size() * sizeof(T) < max_size
210  
        data.size() * sizeof(T) < max_size
211  
            ? data.size() * sizeof(T) : max_size);
211  
            ? data.size() * sizeof(T) : max_size);
212  
}
212  
}
213  

213  

214  
/** Return a buffer from a const std::array.
214  
/** Return a buffer from a const std::array.
215  
*/
215  
*/
216  
template<class T, std::size_t N>
216  
template<class T, std::size_t N>
217  
    requires std::is_trivially_copyable_v<T>
217  
    requires std::is_trivially_copyable_v<T>
218  
[[nodiscard]]
218  
[[nodiscard]]
219  
const_buffer
219  
const_buffer
220  
make_buffer(
220  
make_buffer(
221  
    std::array<T, N> const& data) noexcept
221  
    std::array<T, N> const& data) noexcept
222  
{
222  
{
223  
    return const_buffer(
223  
    return const_buffer(
224  
        data.data(), data.size() * sizeof(T));
224  
        data.data(), data.size() * sizeof(T));
225  
}
225  
}
226  

226  

227  
/** Return a buffer from a const std::array with a maximum size.
227  
/** Return a buffer from a const std::array with a maximum size.
228  
*/
228  
*/
229  
template<class T, std::size_t N>
229  
template<class T, std::size_t N>
230  
    requires std::is_trivially_copyable_v<T>
230  
    requires std::is_trivially_copyable_v<T>
231  
[[nodiscard]]
231  
[[nodiscard]]
232  
const_buffer
232  
const_buffer
233  
make_buffer(
233  
make_buffer(
234  
    std::array<T, N> const& data,
234  
    std::array<T, N> const& data,
235  
    std::size_t max_size) noexcept
235  
    std::size_t max_size) noexcept
236  
{
236  
{
237  
    return const_buffer(
237  
    return const_buffer(
238  
        data.data(),
238  
        data.data(),
239  
        data.size() * sizeof(T) < max_size
239  
        data.size() * sizeof(T) < max_size
240  
            ? data.size() * sizeof(T) : max_size);
240  
            ? data.size() * sizeof(T) : max_size);
241  
}
241  
}
242  

242  

243  
// std::vector
243  
// std::vector
244  

244  

245  
/** Return a buffer from a std::vector.
245  
/** Return a buffer from a std::vector.
246  
*/
246  
*/
247  
template<class T, class Allocator>
247  
template<class T, class Allocator>
248  
    requires std::is_trivially_copyable_v<T>
248  
    requires std::is_trivially_copyable_v<T>
249  
[[nodiscard]]
249  
[[nodiscard]]
250  
mutable_buffer
250  
mutable_buffer
251  
make_buffer(
251  
make_buffer(
252  
    std::vector<T, Allocator>& data) noexcept
252  
    std::vector<T, Allocator>& data) noexcept
253  
{
253  
{
254  
    return mutable_buffer(
254  
    return mutable_buffer(
255  
        data.size() ? data.data() : nullptr,
255  
        data.size() ? data.data() : nullptr,
256  
        data.size() * sizeof(T));
256  
        data.size() * sizeof(T));
257  
}
257  
}
258  

258  

259  
/** Return a buffer from a std::vector with a maximum size.
259  
/** Return a buffer from a std::vector with a maximum size.
260  
*/
260  
*/
261  
template<class T, class Allocator>
261  
template<class T, class Allocator>
262  
    requires std::is_trivially_copyable_v<T>
262  
    requires std::is_trivially_copyable_v<T>
263  
[[nodiscard]]
263  
[[nodiscard]]
264  
mutable_buffer
264  
mutable_buffer
265  
make_buffer(
265  
make_buffer(
266  
    std::vector<T, Allocator>& data,
266  
    std::vector<T, Allocator>& data,
267  
    std::size_t max_size) noexcept
267  
    std::size_t max_size) noexcept
268  
{
268  
{
269  
    return mutable_buffer(
269  
    return mutable_buffer(
270  
        data.size() ? data.data() : nullptr,
270  
        data.size() ? data.data() : nullptr,
271  
        data.size() * sizeof(T) < max_size
271  
        data.size() * sizeof(T) < max_size
272  
            ? data.size() * sizeof(T) : max_size);
272  
            ? data.size() * sizeof(T) : max_size);
273  
}
273  
}
274  

274  

275  
/** Return a buffer from a const std::vector.
275  
/** Return a buffer from a const std::vector.
276  
*/
276  
*/
277  
template<class T, class Allocator>
277  
template<class T, class Allocator>
278  
    requires std::is_trivially_copyable_v<T>
278  
    requires std::is_trivially_copyable_v<T>
279  
[[nodiscard]]
279  
[[nodiscard]]
280  
const_buffer
280  
const_buffer
281  
make_buffer(
281  
make_buffer(
282  
    std::vector<T, Allocator> const& data) noexcept
282  
    std::vector<T, Allocator> const& data) noexcept
283  
{
283  
{
284  
    return const_buffer(
284  
    return const_buffer(
285  
        data.size() ? data.data() : nullptr,
285  
        data.size() ? data.data() : nullptr,
286  
        data.size() * sizeof(T));
286  
        data.size() * sizeof(T));
287  
}
287  
}
288  

288  

289  
/** Return a buffer from a const std::vector with a maximum size.
289  
/** Return a buffer from a const std::vector with a maximum size.
290  
*/
290  
*/
291  
template<class T, class Allocator>
291  
template<class T, class Allocator>
292  
    requires std::is_trivially_copyable_v<T>
292  
    requires std::is_trivially_copyable_v<T>
293  
[[nodiscard]]
293  
[[nodiscard]]
294  
const_buffer
294  
const_buffer
295  
make_buffer(
295  
make_buffer(
296  
    std::vector<T, Allocator> const& data,
296  
    std::vector<T, Allocator> const& data,
297  
    std::size_t max_size) noexcept
297  
    std::size_t max_size) noexcept
298  
{
298  
{
299  
    return const_buffer(
299  
    return const_buffer(
300  
        data.size() ? data.data() : nullptr,
300  
        data.size() ? data.data() : nullptr,
301  
        data.size() * sizeof(T) < max_size
301  
        data.size() * sizeof(T) < max_size
302  
            ? data.size() * sizeof(T) : max_size);
302  
            ? data.size() * sizeof(T) : max_size);
303  
}
303  
}
304  

304  

305  
// std::basic_string
305  
// std::basic_string
306  

306  

307  
/** Return a buffer from a std::basic_string.
307  
/** Return a buffer from a std::basic_string.
308  
*/
308  
*/
309  
template<class CharT, class Traits, class Allocator>
309  
template<class CharT, class Traits, class Allocator>
310  
[[nodiscard]]
310  
[[nodiscard]]
311  
mutable_buffer
311  
mutable_buffer
312  
make_buffer(
312  
make_buffer(
313  
    std::basic_string<CharT, Traits, Allocator>& data) noexcept
313  
    std::basic_string<CharT, Traits, Allocator>& data) noexcept
314  
{
314  
{
315  
    return mutable_buffer(
315  
    return mutable_buffer(
316  
        data.size() ? &data[0] : nullptr,
316  
        data.size() ? &data[0] : nullptr,
317  
        data.size() * sizeof(CharT));
317  
        data.size() * sizeof(CharT));
318  
}
318  
}
319  

319  

320  
/** Return a buffer from a std::basic_string with a maximum size.
320  
/** Return a buffer from a std::basic_string with a maximum size.
321  
*/
321  
*/
322  
template<class CharT, class Traits, class Allocator>
322  
template<class CharT, class Traits, class Allocator>
323  
[[nodiscard]]
323  
[[nodiscard]]
324  
mutable_buffer
324  
mutable_buffer
325  
make_buffer(
325  
make_buffer(
326  
    std::basic_string<CharT, Traits, Allocator>& data,
326  
    std::basic_string<CharT, Traits, Allocator>& data,
327  
    std::size_t max_size) noexcept
327  
    std::size_t max_size) noexcept
328  
{
328  
{
329  
    return mutable_buffer(
329  
    return mutable_buffer(
330  
        data.size() ? &data[0] : nullptr,
330  
        data.size() ? &data[0] : nullptr,
331  
        data.size() * sizeof(CharT) < max_size
331  
        data.size() * sizeof(CharT) < max_size
332  
            ? data.size() * sizeof(CharT) : max_size);
332  
            ? data.size() * sizeof(CharT) : max_size);
333  
}
333  
}
334  

334  

335  
/** Return a buffer from a const std::basic_string.
335  
/** Return a buffer from a const std::basic_string.
336  
*/
336  
*/
337  
template<class CharT, class Traits, class Allocator>
337  
template<class CharT, class Traits, class Allocator>
338  
[[nodiscard]]
338  
[[nodiscard]]
339  
const_buffer
339  
const_buffer
340  
make_buffer(
340  
make_buffer(
341  
    std::basic_string<CharT, Traits, Allocator> const& data) noexcept
341  
    std::basic_string<CharT, Traits, Allocator> const& data) noexcept
342  
{
342  
{
343  
    return const_buffer(
343  
    return const_buffer(
344  
        data.data(),
344  
        data.data(),
345  
        data.size() * sizeof(CharT));
345  
        data.size() * sizeof(CharT));
346  
}
346  
}
347  

347  

348  
/** Return a buffer from a const std::basic_string with a maximum size.
348  
/** Return a buffer from a const std::basic_string with a maximum size.
349  
*/
349  
*/
350  
template<class CharT, class Traits, class Allocator>
350  
template<class CharT, class Traits, class Allocator>
351  
[[nodiscard]]
351  
[[nodiscard]]
352  
const_buffer
352  
const_buffer
353  
make_buffer(
353  
make_buffer(
354  
    std::basic_string<CharT, Traits, Allocator> const& data,
354  
    std::basic_string<CharT, Traits, Allocator> const& data,
355  
    std::size_t max_size) noexcept
355  
    std::size_t max_size) noexcept
356  
{
356  
{
357  
    return const_buffer(
357  
    return const_buffer(
358  
        data.data(),
358  
        data.data(),
359  
        data.size() * sizeof(CharT) < max_size
359  
        data.size() * sizeof(CharT) < max_size
360  
            ? data.size() * sizeof(CharT) : max_size);
360  
            ? data.size() * sizeof(CharT) : max_size);
361  
}
361  
}
362  

362  

363  
// std::basic_string_view
363  
// std::basic_string_view
364  

364  

365  
/** Return a buffer from a std::basic_string_view.
365  
/** Return a buffer from a std::basic_string_view.
366  
*/
366  
*/
367  
template<class CharT, class Traits>
367  
template<class CharT, class Traits>
368  
[[nodiscard]]
368  
[[nodiscard]]
369  
const_buffer
369  
const_buffer
370  
make_buffer(
370  
make_buffer(
371  
    std::basic_string_view<CharT, Traits> data) noexcept
371  
    std::basic_string_view<CharT, Traits> data) noexcept
372  
{
372  
{
373  
    return const_buffer(
373  
    return const_buffer(
374  
        data.size() ? data.data() : nullptr,
374  
        data.size() ? data.data() : nullptr,
375  
        data.size() * sizeof(CharT));
375  
        data.size() * sizeof(CharT));
376  
}
376  
}
377  

377  

378  
/** Return a buffer from a std::basic_string_view with a maximum size.
378  
/** Return a buffer from a std::basic_string_view with a maximum size.
379  
*/
379  
*/
380  
template<class CharT, class Traits>
380  
template<class CharT, class Traits>
381  
[[nodiscard]]
381  
[[nodiscard]]
382  
const_buffer
382  
const_buffer
383  
make_buffer(
383  
make_buffer(
384  
    std::basic_string_view<CharT, Traits> data,
384  
    std::basic_string_view<CharT, Traits> data,
385  
    std::size_t max_size) noexcept
385  
    std::size_t max_size) noexcept
386  
{
386  
{
387  
    return const_buffer(
387  
    return const_buffer(
388  
        data.size() ? data.data() : nullptr,
388  
        data.size() ? data.data() : nullptr,
389  
        data.size() * sizeof(CharT) < max_size
389  
        data.size() * sizeof(CharT) < max_size
390  
            ? data.size() * sizeof(CharT) : max_size);
390  
            ? data.size() * sizeof(CharT) : max_size);
391  
}
391  
}
392  

392  

393  
// std::span
393  
// std::span
394  

394  

395  
/** Return a buffer from a mutable std::span.
395  
/** Return a buffer from a mutable std::span.
396  
*/
396  
*/
397  
template<class T, std::size_t Extent>
397  
template<class T, std::size_t Extent>
398  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
398  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
399  
[[nodiscard]]
399  
[[nodiscard]]
400  
mutable_buffer
400  
mutable_buffer
401  
make_buffer(
401  
make_buffer(
402  
    std::span<T, Extent> data) noexcept
402  
    std::span<T, Extent> data) noexcept
403  
{
403  
{
404  
    return mutable_buffer(data.data(), data.size());
404  
    return mutable_buffer(data.data(), data.size());
405  
}
405  
}
406  

406  

407  
/** Return a buffer from a mutable std::span with a maximum size.
407  
/** Return a buffer from a mutable std::span with a maximum size.
408  
*/
408  
*/
409  
template<class T, std::size_t Extent>
409  
template<class T, std::size_t Extent>
410  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
410  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
411  
[[nodiscard]]
411  
[[nodiscard]]
412  
mutable_buffer
412  
mutable_buffer
413  
make_buffer(
413  
make_buffer(
414  
    std::span<T, Extent> data,
414  
    std::span<T, Extent> data,
415  
    std::size_t max_size) noexcept
415  
    std::size_t max_size) noexcept
416  
{
416  
{
417  
    return mutable_buffer(
417  
    return mutable_buffer(
418  
        data.data(),
418  
        data.data(),
419  
        data.size() < max_size ? data.size() : max_size);
419  
        data.size() < max_size ? data.size() : max_size);
420  
}
420  
}
421  

421  

422  
/** Return a buffer from a const std::span.
422  
/** Return a buffer from a const std::span.
423  
*/
423  
*/
424  
template<class T, std::size_t Extent>
424  
template<class T, std::size_t Extent>
425  
    requires (sizeof(T) == 1)
425  
    requires (sizeof(T) == 1)
426  
[[nodiscard]]
426  
[[nodiscard]]
427  
const_buffer
427  
const_buffer
428  
make_buffer(
428  
make_buffer(
429  
    std::span<T const, Extent> data) noexcept
429  
    std::span<T const, Extent> data) noexcept
430  
{
430  
{
431  
    return const_buffer(data.data(), data.size());
431  
    return const_buffer(data.data(), data.size());
432  
}
432  
}
433  

433  

434  
/** Return a buffer from a const std::span with a maximum size.
434  
/** Return a buffer from a const std::span with a maximum size.
435  
*/
435  
*/
436  
template<class T, std::size_t Extent>
436  
template<class T, std::size_t Extent>
437  
    requires (sizeof(T) == 1)
437  
    requires (sizeof(T) == 1)
438  
[[nodiscard]]
438  
[[nodiscard]]
439  
const_buffer
439  
const_buffer
440  
make_buffer(
440  
make_buffer(
441  
    std::span<T const, Extent> data,
441  
    std::span<T const, Extent> data,
442  
    std::size_t max_size) noexcept
442  
    std::size_t max_size) noexcept
443  
{
443  
{
444  
    return const_buffer(
444  
    return const_buffer(
445  
        data.data(),
445  
        data.data(),
446  
        data.size() < max_size ? data.size() : max_size);
446  
        data.size() < max_size ? data.size() : max_size);
447  
}
447  
}
448  

448  

449  
// Contiguous ranges
449  
// Contiguous ranges
450  

450  

451  
namespace detail {
451  
namespace detail {
452  

452  

453  
template<class T>
453  
template<class T>
454  
concept non_buffer_contiguous_range =
454  
concept non_buffer_contiguous_range =
455  
    std::ranges::contiguous_range<T> &&
455  
    std::ranges::contiguous_range<T> &&
456  
    std::ranges::sized_range<T> &&
456  
    std::ranges::sized_range<T> &&
457  
    !std::convertible_to<T, const_buffer> &&
457  
    !std::convertible_to<T, const_buffer> &&
458  
    !std::convertible_to<T, mutable_buffer> &&
458  
    !std::convertible_to<T, mutable_buffer> &&
459  
    std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
459  
    std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
460  

460  

461  
template<class T>
461  
template<class T>
462  
concept mutable_contiguous_range =
462  
concept mutable_contiguous_range =
463  
    non_buffer_contiguous_range<T> &&
463  
    non_buffer_contiguous_range<T> &&
464  
    !std::is_const_v<std::remove_reference_t<
464  
    !std::is_const_v<std::remove_reference_t<
465  
        std::ranges::range_reference_t<T>>>;
465  
        std::ranges::range_reference_t<T>>>;
466  

466  

467  
template<class T>
467  
template<class T>
468  
concept const_contiguous_range =
468  
concept const_contiguous_range =
469  
    non_buffer_contiguous_range<T> &&
469  
    non_buffer_contiguous_range<T> &&
470  
    std::is_const_v<std::remove_reference_t<
470  
    std::is_const_v<std::remove_reference_t<
471  
        std::ranges::range_reference_t<T>>>;
471  
        std::ranges::range_reference_t<T>>>;
472  

472  

473  
} // detail
473  
} // detail
474  

474  

475  
/** Return a buffer from a mutable contiguous range.
475  
/** Return a buffer from a mutable contiguous range.
476  
*/
476  
*/
477  
template<detail::mutable_contiguous_range T>
477  
template<detail::mutable_contiguous_range T>
478  
[[nodiscard]]
478  
[[nodiscard]]
479  
mutable_buffer
479  
mutable_buffer
480  
make_buffer(T& data) noexcept
480  
make_buffer(T& data) noexcept
481  
{
481  
{
482  
    return mutable_buffer(
482  
    return mutable_buffer(
483  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
483  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
484  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
484  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
485  
}
485  
}
486  

486  

487  
/** Return a buffer from a mutable contiguous range with a maximum size.
487  
/** Return a buffer from a mutable contiguous range with a maximum size.
488  
*/
488  
*/
489  
template<detail::mutable_contiguous_range T>
489  
template<detail::mutable_contiguous_range T>
490  
[[nodiscard]]
490  
[[nodiscard]]
491  
mutable_buffer
491  
mutable_buffer
492  
make_buffer(
492  
make_buffer(
493  
    T& data,
493  
    T& data,
494  
    std::size_t max_size) noexcept
494  
    std::size_t max_size) noexcept
495  
{
495  
{
496  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
496  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
497  
    return mutable_buffer(
497  
    return mutable_buffer(
498  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
498  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
499  
        n < max_size ? n : max_size);
499  
        n < max_size ? n : max_size);
500  
}
500  
}
501  

501  

502  
/** Return a buffer from a const contiguous range.
502  
/** Return a buffer from a const contiguous range.
503  
*/
503  
*/
504  
template<detail::non_buffer_contiguous_range T>
504  
template<detail::non_buffer_contiguous_range T>
505  
[[nodiscard]]
505  
[[nodiscard]]
506  
const_buffer
506  
const_buffer
507  
make_buffer(T const& data) noexcept
507  
make_buffer(T const& data) noexcept
508  
{
508  
{
509  
    return const_buffer(
509  
    return const_buffer(
510  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
510  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
511  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
511  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
512  
}
512  
}
513  

513  

514  
/** Return a buffer from a const contiguous range with a maximum size.
514  
/** Return a buffer from a const contiguous range with a maximum size.
515  
*/
515  
*/
516  
template<detail::non_buffer_contiguous_range T>
516  
template<detail::non_buffer_contiguous_range T>
517  
[[nodiscard]]
517  
[[nodiscard]]
518  
const_buffer
518  
const_buffer
519  
make_buffer(
519  
make_buffer(
520  
    T const& data,
520  
    T const& data,
521  
    std::size_t max_size) noexcept
521  
    std::size_t max_size) noexcept
522  
{
522  
{
523  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
523  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
524  
    return const_buffer(
524  
    return const_buffer(
525  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
525  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
526  
        n < max_size ? n : max_size);
526  
        n < max_size ? n : max_size);
527  
}
527  
}
528  

528  

529  
} // capy
529  
} // capy
530  
} // boost
530  
} // boost
531  

531  

532  
BOOST_CAPY_MSVC_WARNING_POP
532  
BOOST_CAPY_MSVC_WARNING_POP
533  

533  

534  
#endif
534  
#endif