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