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  
#ifdef _MSC_VER
25  
#ifdef _MSC_VER
26  
#pragma warning(push)
26  
#pragma warning(push)
27  
#pragma warning(disable: 4459)
27  
#pragma warning(disable: 4459)
28  
#endif
28  
#endif
29  

29  

30  
namespace boost {
30  
namespace boost {
31  
namespace capy {
31  
namespace capy {
32  

32  

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

42  

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

55  

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

66  

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

80  

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

90  

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

103  

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

114  

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

128  

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

141  

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

156  

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

169  

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

184  

185  
// std::array
185  
// std::array
186  

186  

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

199  

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

215  

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

228  

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

244  

245  
// std::vector
245  
// std::vector
246  

246  

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

260  

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

276  

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

290  

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

306  

307  
// std::basic_string
307  
// std::basic_string
308  

308  

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

321  

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

336  

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

349  

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

364  

365  
// std::basic_string_view
365  
// std::basic_string_view
366  

366  

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

379  

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

394  

395  
// std::span
395  
// std::span
396  

396  

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

408  

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

423  

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

435  

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

450  

451  
// Contiguous ranges
451  
// Contiguous ranges
452  

452  

453  
namespace detail {
453  
namespace detail {
454  

454  

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

462  

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

468  

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

474  

475  
} // detail
475  
} // detail
476  

476  

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

488  

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

503  

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

515  

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

530  

531  
} // capy
531  
} // capy
532  
} // boost
532  
} // boost
533  

533  

534  
#ifdef _MSC_VER
534  
#ifdef _MSC_VER
535  
#pragma warning(pop)
535  
#pragma warning(pop)
536  
#endif
536  
#endif
537  

537  

538  
#endif
538  
#endif