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  
//------------------------------------------------
185  
//------------------------------------------------
186  
// std::array
186  
// std::array
187  
//------------------------------------------------
187  
//------------------------------------------------
188  

188  

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

201  

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

217  

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

230  

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

246  

247  
//------------------------------------------------
247  
//------------------------------------------------
248  
// std::vector
248  
// std::vector
249  
//------------------------------------------------
249  
//------------------------------------------------
250  

250  

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

264  

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

280  

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

294  

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

310  

311  
//------------------------------------------------
311  
//------------------------------------------------
312  
// std::basic_string
312  
// std::basic_string
313  
//------------------------------------------------
313  
//------------------------------------------------
314  

314  

315  
/** Return a buffer from a std::basic_string.
315  
/** Return a buffer from a std::basic_string.
316  
*/
316  
*/
317  
template<class CharT, class Traits, class Allocator>
317  
template<class CharT, class Traits, class Allocator>
318  
[[nodiscard]]
318  
[[nodiscard]]
319  
mutable_buffer
319  
mutable_buffer
320  
make_buffer(
320  
make_buffer(
321  
    std::basic_string<CharT, Traits, Allocator>& data) noexcept
321  
    std::basic_string<CharT, Traits, Allocator>& data) noexcept
322  
{
322  
{
323  
    return mutable_buffer(
323  
    return mutable_buffer(
324  
        data.size() ? &data[0] : nullptr,
324  
        data.size() ? &data[0] : nullptr,
325  
        data.size() * sizeof(CharT));
325  
        data.size() * sizeof(CharT));
326  
}
326  
}
327  

327  

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

342  

343  
/** Return a buffer from a const std::basic_string.
343  
/** Return a buffer from a const std::basic_string.
344  
*/
344  
*/
345  
template<class CharT, class Traits, class Allocator>
345  
template<class CharT, class Traits, class Allocator>
346  
[[nodiscard]]
346  
[[nodiscard]]
347  
const_buffer
347  
const_buffer
348  
make_buffer(
348  
make_buffer(
349  
    std::basic_string<CharT, Traits, Allocator> const& data) noexcept
349  
    std::basic_string<CharT, Traits, Allocator> const& data) noexcept
350  
{
350  
{
351  
    return const_buffer(
351  
    return const_buffer(
352  
        data.data(),
352  
        data.data(),
353  
        data.size() * sizeof(CharT));
353  
        data.size() * sizeof(CharT));
354  
}
354  
}
355  

355  

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

370  

371  
//------------------------------------------------
371  
//------------------------------------------------
372  
// std::basic_string_view
372  
// std::basic_string_view
373  
//------------------------------------------------
373  
//------------------------------------------------
374  

374  

375  
/** Return a buffer from a std::basic_string_view.
375  
/** Return a buffer from a std::basic_string_view.
376  
*/
376  
*/
377  
template<class CharT, class Traits>
377  
template<class CharT, class Traits>
378  
[[nodiscard]]
378  
[[nodiscard]]
379  
const_buffer
379  
const_buffer
380  
make_buffer(
380  
make_buffer(
381  
    std::basic_string_view<CharT, Traits> data) noexcept
381  
    std::basic_string_view<CharT, Traits> data) noexcept
382  
{
382  
{
383  
    return const_buffer(
383  
    return const_buffer(
384  
        data.size() ? data.data() : nullptr,
384  
        data.size() ? data.data() : nullptr,
385  
        data.size() * sizeof(CharT));
385  
        data.size() * sizeof(CharT));
386  
}
386  
}
387  

387  

388  
/** Return a buffer from a std::basic_string_view with a maximum size.
388  
/** Return a buffer from a std::basic_string_view with a maximum size.
389  
*/
389  
*/
390  
template<class CharT, class Traits>
390  
template<class CharT, class Traits>
391  
[[nodiscard]]
391  
[[nodiscard]]
392  
const_buffer
392  
const_buffer
393  
make_buffer(
393  
make_buffer(
394  
    std::basic_string_view<CharT, Traits> data,
394  
    std::basic_string_view<CharT, Traits> data,
395  
    std::size_t max_size) noexcept
395  
    std::size_t max_size) noexcept
396  
{
396  
{
397  
    return const_buffer(
397  
    return const_buffer(
398  
        data.size() ? data.data() : nullptr,
398  
        data.size() ? data.data() : nullptr,
399  
        data.size() * sizeof(CharT) < max_size
399  
        data.size() * sizeof(CharT) < max_size
400  
            ? data.size() * sizeof(CharT) : max_size);
400  
            ? data.size() * sizeof(CharT) : max_size);
401  
}
401  
}
402  

402  

403  
//------------------------------------------------
403  
//------------------------------------------------
404  
// std::span
404  
// std::span
405  
//------------------------------------------------
405  
//------------------------------------------------
406  

406  

407  
/** Return a buffer from a mutable std::span.
407  
/** Return a buffer from a mutable std::span.
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) noexcept
414  
    std::span<T, Extent> data) noexcept
415  
{
415  
{
416  
    return mutable_buffer(data.data(), data.size());
416  
    return mutable_buffer(data.data(), data.size());
417  
}
417  
}
418  

418  

419  
/** Return a buffer from a mutable std::span with a maximum size.
419  
/** Return a buffer from a mutable std::span with a maximum size.
420  
*/
420  
*/
421  
template<class T, std::size_t Extent>
421  
template<class T, std::size_t Extent>
422  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
422  
    requires (!std::is_const_v<T> && sizeof(T) == 1)
423  
[[nodiscard]]
423  
[[nodiscard]]
424  
mutable_buffer
424  
mutable_buffer
425  
make_buffer(
425  
make_buffer(
426  
    std::span<T, Extent> data,
426  
    std::span<T, Extent> data,
427  
    std::size_t max_size) noexcept
427  
    std::size_t max_size) noexcept
428  
{
428  
{
429  
    return mutable_buffer(
429  
    return mutable_buffer(
430  
        data.data(),
430  
        data.data(),
431  
        data.size() < max_size ? data.size() : max_size);
431  
        data.size() < max_size ? data.size() : max_size);
432  
}
432  
}
433  

433  

434  
/** Return a buffer from a const std::span.
434  
/** Return a buffer from a const std::span.
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) noexcept
441  
    std::span<T const, Extent> data) noexcept
442  
{
442  
{
443  
    return const_buffer(data.data(), data.size());
443  
    return const_buffer(data.data(), data.size());
444  
}
444  
}
445  

445  

446  
/** Return a buffer from a const std::span with a maximum size.
446  
/** Return a buffer from a const std::span with a maximum size.
447  
*/
447  
*/
448  
template<class T, std::size_t Extent>
448  
template<class T, std::size_t Extent>
449  
    requires (sizeof(T) == 1)
449  
    requires (sizeof(T) == 1)
450  
[[nodiscard]]
450  
[[nodiscard]]
451  
const_buffer
451  
const_buffer
452  
make_buffer(
452  
make_buffer(
453  
    std::span<T const, Extent> data,
453  
    std::span<T const, Extent> data,
454  
    std::size_t max_size) noexcept
454  
    std::size_t max_size) noexcept
455  
{
455  
{
456  
    return const_buffer(
456  
    return const_buffer(
457  
        data.data(),
457  
        data.data(),
458  
        data.size() < max_size ? data.size() : max_size);
458  
        data.size() < max_size ? data.size() : max_size);
459  
}
459  
}
460  

460  

461  
//------------------------------------------------
461  
//------------------------------------------------
462  
// Contiguous ranges
462  
// Contiguous ranges
463  
//------------------------------------------------
463  
//------------------------------------------------
464  

464  

465  
namespace detail {
465  
namespace detail {
466  

466  

467  
template<class T>
467  
template<class T>
468  
concept non_buffer_contiguous_range =
468  
concept non_buffer_contiguous_range =
469  
    std::ranges::contiguous_range<T> &&
469  
    std::ranges::contiguous_range<T> &&
470  
    std::ranges::sized_range<T> &&
470  
    std::ranges::sized_range<T> &&
471  
    !std::convertible_to<T, const_buffer> &&
471  
    !std::convertible_to<T, const_buffer> &&
472  
    !std::convertible_to<T, mutable_buffer> &&
472  
    !std::convertible_to<T, mutable_buffer> &&
473  
    std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
473  
    std::is_trivially_copyable_v<std::ranges::range_value_t<T>>;
474  

474  

475  
template<class T>
475  
template<class T>
476  
concept mutable_contiguous_range =
476  
concept mutable_contiguous_range =
477  
    non_buffer_contiguous_range<T> &&
477  
    non_buffer_contiguous_range<T> &&
478  
    !std::is_const_v<std::remove_reference_t<
478  
    !std::is_const_v<std::remove_reference_t<
479  
        std::ranges::range_reference_t<T>>>;
479  
        std::ranges::range_reference_t<T>>>;
480  

480  

481  
template<class T>
481  
template<class T>
482  
concept const_contiguous_range =
482  
concept const_contiguous_range =
483  
    non_buffer_contiguous_range<T> &&
483  
    non_buffer_contiguous_range<T> &&
484  
    std::is_const_v<std::remove_reference_t<
484  
    std::is_const_v<std::remove_reference_t<
485  
        std::ranges::range_reference_t<T>>>;
485  
        std::ranges::range_reference_t<T>>>;
486  

486  

487  
} // detail
487  
} // detail
488  

488  

489  
/** Return a buffer from a mutable contiguous range.
489  
/** Return a buffer from a mutable contiguous range.
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(T& data) noexcept
494  
make_buffer(T& data) noexcept
495  
{
495  
{
496  
    return mutable_buffer(
496  
    return mutable_buffer(
497  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
497  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
498  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
498  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
499  
}
499  
}
500  

500  

501  
/** Return a buffer from a mutable contiguous range with a maximum size.
501  
/** Return a buffer from a mutable contiguous range with a maximum size.
502  
*/
502  
*/
503  
template<detail::mutable_contiguous_range T>
503  
template<detail::mutable_contiguous_range T>
504  
[[nodiscard]]
504  
[[nodiscard]]
505  
mutable_buffer
505  
mutable_buffer
506  
make_buffer(
506  
make_buffer(
507  
    T& data,
507  
    T& data,
508  
    std::size_t max_size) noexcept
508  
    std::size_t max_size) noexcept
509  
{
509  
{
510  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
510  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
511  
    return mutable_buffer(
511  
    return mutable_buffer(
512  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
512  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
513  
        n < max_size ? n : max_size);
513  
        n < max_size ? n : max_size);
514  
}
514  
}
515  

515  

516  
/** Return a buffer from a const contiguous range.
516  
/** Return a buffer from a const contiguous range.
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(T const& data) noexcept
521  
make_buffer(T const& data) noexcept
522  
{
522  
{
523  
    return const_buffer(
523  
    return const_buffer(
524  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
524  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
525  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
525  
        std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>));
526  
}
526  
}
527  

527  

528  
/** Return a buffer from a const contiguous range with a maximum size.
528  
/** Return a buffer from a const contiguous range with a maximum size.
529  
*/
529  
*/
530  
template<detail::non_buffer_contiguous_range T>
530  
template<detail::non_buffer_contiguous_range T>
531  
[[nodiscard]]
531  
[[nodiscard]]
532  
const_buffer
532  
const_buffer
533  
make_buffer(
533  
make_buffer(
534  
    T const& data,
534  
    T const& data,
535  
    std::size_t max_size) noexcept
535  
    std::size_t max_size) noexcept
536  
{
536  
{
537  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
537  
    auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
538  
    return const_buffer(
538  
    return const_buffer(
539  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
539  
        std::ranges::size(data) ? std::ranges::data(data) : nullptr,
540  
        n < max_size ? n : max_size);
540  
        n < max_size ? n : max_size);
541  
}
541  
}
542  

542  

543  
} // capy
543  
} // capy
544  
} // boost
544  
} // boost
545  

545  

546  
#ifdef _MSC_VER
546  
#ifdef _MSC_VER
547  
#pragma warning(pop)
547  
#pragma warning(pop)
548  
#endif
548  
#endif
549  

549  

550  
#endif
550  
#endif