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