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