Botan 3.4.0
Crypto and TLS for C&
Classes | Concepts | Enumerations | Functions | Variables
Botan::detail Namespace Reference

Classes

struct  AutoDetect
 
class  Strong_Adapter
 
class  Strong_Adapter< T >
 
class  Strong_Base
 

Concepts

concept  unsigned_integralish
 

Enumerations

enum class  Endianness : bool { Big , Little }
 

Functions

template<Endianness endianness, unsigned_integralish T>
size_t copy_out_any_word_aligned_portion (std::span< uint8_t > &out, std::span< const T > &in)
 
template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
constexpr OutT fallback_load_any (InR &&in_range)
 
template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
constexpr void fallback_store_any (InT in, OutR &&out_range)
 
constexpr bool is_native (Endianness endianness)
 
constexpr bool is_opposite (Endianness endianness)
 
template<Endianness endianness, unsigned_integralish OutT>
constexpr OutT load_any (const uint8_t in[], size_t off)
 
template<Endianness endianness, typename OutT , unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0 && all_same_v<Ts...> && ((std::same_as<AutoDetect, OutT> && all_same_v<Ts...>) || (unsigned_integralish<OutT> && all_same_v<OutT, Ts...>)))
constexpr void load_any (const uint8_t in[], Ts &... outs)
 
template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR, unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0) && ((std::same_as<AutoDetect, OutT> && all_same_v<Ts...>) || (unsigned_integralish<OutT> && all_same_v<OutT, Ts...>))
constexpr void load_any (InR &&in, Ts &... outs)
 
template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
constexpr OutT load_any (InR &&in_range)
 
template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR>
requires (std::is_enum_v<OutT> && std::unsigned_integral<std::underlying_type_t<OutT>>)
constexpr OutT load_any (InR &&in_range)
 
template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR>
requires (std::same_as<AutoDetect, OutT> || ((ranges::statically_spanable_range<OutT> || concepts::resizable_container<OutT>)&&unsigned_integralish<typename OutT::value_type>))
constexpr auto load_any (InR &&in_range)
 
template<Endianness endianness, typename OutT , ranges::contiguous_output_range OutR, ranges::contiguous_range< uint8_t > InR>
requires (unsigned_integralish<std::ranges::range_value_t<OutR>> && (std::same_as<AutoDetect, OutT> || std::same_as<OutT, std::ranges::range_value_t<OutR>>))
constexpr void load_any (OutR &&out, InR &&in)
 
template<Endianness endianness, typename OutT , unsigned_integralish T>
requires (std::same_as<AutoDetect, OutT> || std::same_as<T, OutT>)
constexpr void load_any (T out[], const uint8_t in[], size_t count)
 
template<Endianness endianness>
constexpr bool native_endianness_is_unknown ()
 
template<Endianness endianness, typename OutR , ranges::spanable_range InR>
requires (std::same_as<AutoDetect, OutR> || (ranges::statically_spanable_range<OutR> && std::default_initializable<OutR>) || concepts::resizable_byte_buffer<OutR>)
constexpr auto store_any (InR &&in_range)
 
template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
constexpr void store_any (InT in, OutR &&out_range)
 
template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR>
requires (std::is_enum_v<InT> && std::unsigned_integral<std::underlying_type_t<InT>>)
constexpr void store_any (InT in, OutR &&out_range)
 
template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR, ranges::spanable_range InR>
requires (std::same_as<AutoDetect, InT> || std::same_as<InT, std::ranges::range_value_t<InR>>)
constexpr void store_any (OutR &&out, InR &&in)
 
template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR, unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0) && ((std::same_as<AutoDetect, InT> && all_same_v<Ts...>) || (unsigned_integralish<InT> && all_same_v<InT, Ts...>))
constexpr void store_any (OutR &&out, Ts... ins)
 
template<Endianness endianness, typename InT , unsigned_integralish T, ranges::contiguous_output_range< uint8_t > OutR>
requires std::same_as<AutoDetect, InT>
constexpr void store_any (T in, OutR &&out_range)
 
template<Endianness endianness, typename InT , unsigned_integralish T>
requires (std::same_as<AutoDetect, InT> || std::same_as<T, InT>)
constexpr void store_any (T in, uint8_t out[])
 
template<Endianness endianness, typename OutR , unsigned_integralish... Ts>
requires all_same_v<Ts...>
constexpr auto store_any (Ts... ins)
 
template<Endianness endianness, typename InT , unsigned_integralish T0, unsigned_integralish... Ts>
requires (std::same_as<AutoDetect, InT> || std::same_as<T0, InT>) && all_same_v<T0, Ts...>
constexpr void store_any (uint8_t out[], T0 in0, Ts... ins)
 

Variables

template<typename CapabilityT , typename... Tags>
constexpr bool has_capability = (std::is_same_v<CapabilityT, Tags> || ...)
 

Enumeration Type Documentation

◆ Endianness

enum class Botan::detail::Endianness : bool
strong
Enumerator
Big 
Little 

Definition at line 126 of file loadstor.h.

126 : bool {
127 Big,
128 Little,
129};

Function Documentation

◆ copy_out_any_word_aligned_portion()

template<Endianness endianness, unsigned_integralish T>
size_t Botan::detail::copy_out_any_word_aligned_portion ( std::span< uint8_t > & out,
std::span< const T > & in )

Definition at line 718 of file loadstor.h.

718 {
719 const size_t full_words = out.size() / sizeof(T);
720 const size_t full_word_bytes = full_words * sizeof(T);
721 const size_t remaining_bytes = out.size() - full_word_bytes;
722 BOTAN_ASSERT_NOMSG(in.size_bytes() >= full_word_bytes + remaining_bytes);
723
724 // copy full words
725 store_any<endianness, T>(out.first(full_word_bytes), in.first(full_words));
726 out = out.subspan(full_word_bytes);
727 in = in.subspan(full_words);
728
729 return remaining_bytes;
730}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
FE_25519 T
Definition ge.cpp:34

References BOTAN_ASSERT_NOMSG, and T.

◆ fallback_load_any()

template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
constexpr OutT Botan::detail::fallback_load_any ( InR && in_range)
inlineconstexpr

Manually load a word from a range in either big or little endian byte order. This will be used only if the endianness of the target platform is unknown at compile time.

Definition at line 185 of file loadstor.h.

185 {
186 std::span in{in_range};
187 // clang-format off
188 if constexpr(endianness == Endianness::Big) {
189 return [&]<size_t... i>(std::index_sequence<i...>) {
190 return static_cast<OutT>(((static_cast<OutT>(in[i]) << ((sizeof(OutT) - i - 1) * 8)) | ...));
191 } (std::make_index_sequence<sizeof(OutT)>());
192 } else {
193 static_assert(endianness == Endianness::Little);
194 return [&]<size_t... i>(std::index_sequence<i...>) {
195 return static_cast<OutT>(((static_cast<OutT>(in[i]) << (i * 8)) | ...));
196 } (std::make_index_sequence<sizeof(OutT)>());
197 }
198 // clang-format on
199}

References Big, and Little.

◆ fallback_store_any()

template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
constexpr void Botan::detail::fallback_store_any ( InT in,
OutR && out_range )
inlineconstexpr

Manually store a word into a range in either big or little endian byte order. This will be used only if the endianness of the target platform is unknown at compile time.

Definition at line 207 of file loadstor.h.

207 {
208 std::span out{out_range};
209 // clang-format off
210 if constexpr(endianness == Endianness::Big) {
211 [&]<size_t... i>(std::index_sequence<i...>) {
212 ((out[i] = get_byte<i>(in)), ...);
213 } (std::make_index_sequence<sizeof(InT)>());
214 } else {
215 static_assert(endianness == Endianness::Little);
216 [&]<size_t... i>(std::index_sequence<i...>) {
217 ((out[i] = get_byte<sizeof(InT) - i - 1>(in)), ...);
218 } (std::make_index_sequence<sizeof(InT)>());
219 }
220 // clang-format on
221}
constexpr uint8_t get_byte(T input)
Definition loadstor.h:75

References Big, Botan::get_byte(), and Little.

◆ is_native()

constexpr bool Botan::detail::is_native ( Endianness endianness)
constexpr
Warning
This function may return false if the native endianness is unknown
Returns
true iff the native endianness matches the given endianness

Definition at line 139 of file loadstor.h.

139 {
140#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
141 return endianness == Endianness::Big;
142#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
143 return endianness == Endianness::Little;
144#else
145 return false;
146#endif
147}

References Big, and Little.

Referenced by load_any(), load_any(), store_any(), and store_any().

◆ is_opposite()

constexpr bool Botan::detail::is_opposite ( Endianness endianness)
constexpr
Warning
This function may return false if the native endianness is unknown
Returns
true iff the native endianness does not match the given endianness

Definition at line 153 of file loadstor.h.

153 {
154#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
155 return endianness == Endianness::Little;
156#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
157 return endianness == Endianness::Big;
158#else
159 return false;
160#endif
161}

References Big, and Little.

Referenced by load_any(), and store_any().

◆ load_any() [1/8]

template<Endianness endianness, unsigned_integralish OutT>
constexpr OutT Botan::detail::load_any ( const uint8_t in[],
size_t off )
inlineconstexpr

Load a word from in at some offset off

Parameters
ina pointer to some bytes
offan offset into the array
Returns
off'th T of in, as a big-endian value

Definition at line 421 of file loadstor.h.

421 {
422 // asserts that *in points to enough bytes to read at offset off
423 constexpr size_t out_size = sizeof(OutT);
424 return load_any<endianness, OutT>(std::span<const uint8_t, out_size>(in + off * out_size, out_size));
425}

◆ load_any() [2/8]

template<Endianness endianness, typename OutT , unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0 && all_same_v<Ts...> && ((std::same_as<AutoDetect, OutT> && all_same_v<Ts...>) || (unsigned_integralish<OutT> && all_same_v<OutT, Ts...>)))
constexpr void Botan::detail::load_any ( const uint8_t in[],
Ts &... outs )
inlineconstexpr

Load many words from in

Parameters
ina pointer to some bytes
outsa arbitrary-length parameter list of unsigned integers to be loaded

Definition at line 436 of file loadstor.h.

436 {
437 constexpr auto bytes = (sizeof(outs) + ...);
438 // asserts that *in points to the correct amount of memory
439 load_any<endianness, OutT>(std::span<const uint8_t, bytes>(in, bytes), outs...);
440}

◆ load_any() [3/8]

template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR, unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0) && ((std::same_as<AutoDetect, OutT> && all_same_v<Ts...>) || (unsigned_integralish<OutT> && all_same_v<OutT, Ts...>))
constexpr void Botan::detail::load_any ( InR && in,
Ts &... outs )
inlineconstexpr

Load many unsigned integers

Parameters
ina fixed-length span to some bytes
outsa arbitrary-length parameter list of unsigned integers to be loaded

Definition at line 299 of file loadstor.h.

299 {
300 ranges::assert_exact_byte_length<(sizeof(Ts) + ...)>(in);
301 auto load_one = [off = 0]<typename T>(auto i, T& o) mutable {
302 o = load_any<endianness, T>(i.subspan(off).template first<sizeof(T)>());
303 off += sizeof(T);
304 };
305
306 (load_one(std::span{in}, outs), ...);
307}

References Botan::ranges::assert_exact_byte_length(), and T.

◆ load_any() [4/8]

template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
constexpr OutT Botan::detail::load_any ( InR && in_range)
inlineconstexpr

Load a word from a range in either big or little endian byte order

This is the base implementation, all other overloads are just convenience wrappers. It is assumed that the range has the correct size for the word.

Template arguments of all overloads of load_any() share the same semantics:

  1. Endianness Either Endianness::Big or Endianness::Little, that will eventually select the byte order translation mode implemented in this base function.
  2. Output type Either AutoDetect, an unsigned integer or a container holding an unsigned integer type. AutoDetect means that the caller did not explicitly specify the type and expects the type to be inferred from the input.

3+. Argument types Typically, those are input and output ranges of bytes or unsigned integers. Or one or more unsigned integers acting as output parameters.

Parameters
in_rangea fixed-length byte range
Returns
T loaded from in_range, as a big-endian value

Overload for loading into a strong type holding an unsigned integer

Definition at line 248 of file loadstor.h.

248 {
249 ranges::assert_exact_byte_length<sizeof(OutT)>(in_range);
250 std::span in{in_range};
251
252 // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
253 // internally to copy ranges on a byte-by-byte basis, which is not allowed
254 // in a `constexpr` context.
255 if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
256 return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
257 } else {
258 if constexpr(sizeof(OutT) == 1) {
259 return static_cast<OutT>(in[0]);
260 } else if constexpr(is_native(endianness)) {
261 return typecast_copy<OutT>(in);
262 } else if constexpr(is_opposite(endianness)) {
263 return reverse_bytes(typecast_copy<OutT>(in));
264 } else {
265 static_assert(native_endianness_is_unknown<endianness>());
266 return fallback_load_any<endianness, OutT>(std::forward<InR>(in_range));
267 }
268 }
269}
constexpr bool is_opposite(Endianness endianness)
Definition loadstor.h:153
constexpr bool is_native(Endianness endianness)
Definition loadstor.h:139
constexpr uint16_t reverse_bytes(uint16_t x)
Definition bswap.h:21

References is_native(), is_opposite(), and Botan::reverse_bytes().

◆ load_any() [5/8]

template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR>
requires (std::is_enum_v<OutT> && std::unsigned_integral<std::underlying_type_t<OutT>>)
constexpr OutT Botan::detail::load_any ( InR && in_range)
inlineconstexpr

Overload for loading into an enum type that uses an unsigned integer as its underlying type.

Definition at line 286 of file loadstor.h.

286 {
287 using underlying_type = std::underlying_type_t<OutT>;
288 return static_cast<OutT>(load_any<endianness, underlying_type>(std::forward<InR>(in_range)));
289}

◆ load_any() [6/8]

template<Endianness endianness, typename OutT , ranges::contiguous_range< uint8_t > InR>
requires (std::same_as<AutoDetect, OutT> || ((ranges::statically_spanable_range<OutT> || concepts::resizable_container<OutT>)&&unsigned_integralish<typename OutT::value_type>))
constexpr auto Botan::detail::load_any ( InR && in_range)
inlineconstexpr

Load one or more unsigned integers, auto-detect the output type if possible. Otherwise, use the specified integer or integer container type.

Parameters
in_rangea statically-sized range with some bytes
Returns
T loaded from in

Definition at line 364 of file loadstor.h.

364 {
365 auto out = []([[maybe_unused]] const auto& in) {
366 if constexpr(std::same_as<AutoDetect, OutT>) {
368 constexpr size_t extent = decltype(std::span{in})::extent;
369
370 // clang-format off
371 using type =
372 std::conditional_t<extent == 1, uint8_t,
373 std::conditional_t<extent == 2, uint16_t,
374 std::conditional_t<extent == 4, uint32_t,
375 std::conditional_t<extent == 8, uint64_t, void>>>>;
376 // clang-format on
377
378 static_assert(
379 !std::is_void_v<type>,
380 "Cannot determine the output type based on a statically sized bytearray with length other than those: 1, 2, 4, 8");
381
382 return type{};
383 } else {
384 static_assert(
385 !std::same_as<AutoDetect, OutT>,
386 "cannot infer return type from a dynamic range at compile time, please specify it explicitly");
387 }
388 } else if constexpr(concepts::resizable_container<OutT>) {
389 const size_t in_bytes = std::span{in}.size_bytes();
390 constexpr size_t out_elem_bytes = sizeof(typename OutT::value_type);
391 BOTAN_ARG_CHECK(in_bytes % out_elem_bytes == 0,
392 "Input range is not word-aligned with the requested output range");
393 return OutT(in_bytes / out_elem_bytes);
394 } else {
395 return OutT{};
396 }
397 }(in_range);
398
399 using out_type = decltype(out);
400 if constexpr(unsigned_integralish<out_type>) {
401 out = load_any<endianness, out_type>(std::forward<InR>(in_range));
402 } else {
403 static_assert(ranges::contiguous_range<out_type>);
404 using out_range_type = std::ranges::range_value_t<out_type>;
405 load_any<endianness, out_range_type>(out, std::forward<InR>(in_range));
406 }
407 return out;
408}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29

References BOTAN_ARG_CHECK.

◆ load_any() [7/8]

template<Endianness endianness, typename OutT , ranges::contiguous_output_range OutR, ranges::contiguous_range< uint8_t > InR>
requires (unsigned_integralish<std::ranges::range_value_t<OutR>> && (std::same_as<AutoDetect, OutT> || std::same_as<OutT, std::ranges::range_value_t<OutR>>))
constexpr void Botan::detail::load_any ( OutR && out,
InR && in )
inlineconstexpr

Load a variable number of words from in into out. The byte length of the out and in ranges must match.

Parameters
outthe output range of words
inthe input range of bytes

Definition at line 322 of file loadstor.h.

322 {
323 ranges::assert_equal_byte_lengths(out, in);
324
325 auto load_elementwise = [&] {
326 using element_type = std::ranges::range_value_t<OutR>;
327 constexpr size_t bytes_per_element = sizeof(element_type);
328 std::span<const uint8_t> in_s(in);
329 for(auto& out_elem : out) {
330 out_elem = load_any<endianness, element_type>(in_s.template first<bytes_per_element>());
331 in_s = in_s.subspan(bytes_per_element);
332 }
333 };
334
335 // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
336 // internally to copy ranges on a byte-by-byte basis, which is not allowed
337 // in a `constexpr` context.
338 if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
339 load_elementwise();
340 } else {
341 if constexpr(is_native(endianness)) {
342 typecast_copy(out, in);
343 } else {
344 load_elementwise();
345 }
346 }
347}
constexpr void typecast_copy(ToR &&out, FromR &&in)
Definition mem_ops.h:178

References Botan::ranges::assert_equal_byte_lengths(), is_native(), and Botan::typecast_copy().

◆ load_any() [8/8]

template<Endianness endianness, typename OutT , unsigned_integralish T>
requires (std::same_as<AutoDetect, OutT> || std::same_as<T, OutT>)
constexpr void Botan::detail::load_any ( T out[],
const uint8_t in[],
size_t count )
inlineconstexpr

Load a variable number of words from in into out.

Parameters
outthe output array of words
inthe input array of bytes
counthow many words are in in

Definition at line 450 of file loadstor.h.

450 {
451 // asserts that *in and *out point to the correct amount of memory
452 load_any<endianness, OutT>(std::span<T>(out, count), std::span<const uint8_t>(in, count * sizeof(T)));
453}

References T.

◆ native_endianness_is_unknown()

template<Endianness endianness>
constexpr bool Botan::detail::native_endianness_is_unknown ( )
constexpr

Definition at line 164 of file loadstor.h.

164 {
165#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) || defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
166 return false;
167#else
168 return true;
169#endif
170}

◆ store_any() [1/9]

template<Endianness endianness, typename OutR , ranges::spanable_range InR>
requires (std::same_as<AutoDetect, OutR> || (ranges::statically_spanable_range<OutR> && std::default_initializable<OutR>) || concepts::resizable_byte_buffer<OutR>)
constexpr auto Botan::detail::store_any ( InR && in_range)
inlineconstexpr

The caller provided some integer values in a collection but did not provide the output container. Let's create one for them, fill it with one of the overloads above and return it. This will default to a std::array if the caller did not specify the desired output container type.

Parameters
in_rangea range of words that should be stored
Returns
a container of bytes that contains the stored words

Definition at line 629 of file loadstor.h.

629 {
630 auto out = []([[maybe_unused]] const auto& in) {
631 if constexpr(std::same_as<AutoDetect, OutR>) {
633 constexpr size_t bytes = decltype(std::span{in})::extent * sizeof(std::ranges::range_value_t<InR>);
634 return std::array<uint8_t, bytes>();
635 } else {
636 static_assert(
637 !std::same_as<AutoDetect, OutR>,
638 "cannot infer a suitable result container type from the given parameters at compile time, please specify it explicitly");
639 }
640 } else if constexpr(concepts::resizable_byte_buffer<OutR>) {
641 return OutR(std::span{in}.size_bytes());
642 } else {
643 return OutR{};
644 }
645 }(in_range);
646
647 store_any<endianness, std::ranges::range_value_t<InR>>(out, std::forward<InR>(in_range));
648 return out;
649}

◆ store_any() [2/9]

template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
constexpr void Botan::detail::store_any ( InT in,
OutR && out_range )
inlineconstexpr

Store a word in either big or little endian byte order into a range

This is the base implementation, all other overloads are just convenience wrappers. It is assumed that the range has the correct size for the word.

Template arguments of all overloads of store_any() share the same semantics as those of load_any(). See the documentation of this function for more details.

Parameters
inan unsigned integral to be stored
out_rangea byte range to store the word into

Overload for loading into a strong type holding an unsigned integer

Definition at line 491 of file loadstor.h.

491 {
492 ranges::assert_exact_byte_length<sizeof(InT)>(out_range);
493 std::span out{out_range};
494
495 // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
496 // internally to copy ranges on a byte-by-byte basis, which is not allowed
497 // in a `constexpr` context.
498 if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
499 return fallback_store_any<endianness, InT>(in, std::forward<OutR>(out_range));
500 } else {
501 if constexpr(sizeof(InT) == 1) {
502 out[0] = static_cast<uint8_t>(in);
503 } else if constexpr(is_native(endianness)) {
504 typecast_copy(out, in);
505 } else if constexpr(is_opposite(endianness)) {
507 } else {
508 static_assert(native_endianness_is_unknown<endianness>());
509 return fallback_store_any<endianness, InT>(in, std::forward<OutR>(out_range));
510 }
511 }
512}

References is_native(), is_opposite(), Botan::reverse_bytes(), and Botan::typecast_copy().

◆ store_any() [3/9]

template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR>
requires (std::is_enum_v<InT> && std::unsigned_integral<std::underlying_type_t<InT>>)
constexpr void Botan::detail::store_any ( InT in,
OutR && out_range )
inlineconstexpr

Overload for storing an enum type that uses an unsigned integer as its underlying type.

Definition at line 531 of file loadstor.h.

531 {
532 using underlying_type = std::underlying_type_t<InT>;
533 // TODO: C++23: use std::to_underlying(in) instead
534 store_any<endianness, underlying_type>(static_cast<underlying_type>(in), std::forward<OutR>(out_range));
535}

◆ store_any() [4/9]

template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR, ranges::spanable_range InR>
requires (std::same_as<AutoDetect, InT> || std::same_as<InT, std::ranges::range_value_t<InR>>)
constexpr void Botan::detail::store_any ( OutR && out,
InR && in )
inlineconstexpr

Store a variable number of words given in in into out. The byte lengths of in and out must be consistent.

Parameters
outthe output range of bytes
inthe input range of words

Definition at line 569 of file loadstor.h.

569 {
570 ranges::assert_equal_byte_lengths(out, in);
571
572 auto store_elementwise = [&] {
573 using element_type = std::ranges::range_value_t<InR>;
574 constexpr size_t bytes_per_element = sizeof(element_type);
575 std::span<uint8_t> out_s(out);
576 for(auto in_elem : in) {
577 store_any<endianness, element_type>(out_s.template first<bytes_per_element>(), in_elem);
578 out_s = out_s.subspan(bytes_per_element);
579 }
580 };
581
582 // At compile time we cannot use `typecast_copy` as it uses `std::memcpy`
583 // internally to copy ranges on a byte-by-byte basis, which is not allowed
584 // in a `constexpr` context.
585 if(std::is_constant_evaluated()) /* TODO: C++23: if consteval {} */ {
586 store_elementwise();
587 } else {
588 if constexpr(is_native(endianness)) {
589 typecast_copy(out, in);
590 } else {
591 store_elementwise();
592 }
593 }
594}

References Botan::ranges::assert_equal_byte_lengths(), is_native(), and Botan::typecast_copy().

◆ store_any() [5/9]

template<Endianness endianness, typename InT , ranges::contiguous_output_range< uint8_t > OutR, unsigned_integralish... Ts>
requires (sizeof...(Ts) > 0) && ((std::same_as<AutoDetect, InT> && all_same_v<Ts...>) || (unsigned_integralish<InT> && all_same_v<InT, Ts...>))
constexpr void Botan::detail::store_any ( OutR && out,
Ts... ins )
inlineconstexpr

Store many unsigned integers words into a byte range

Parameters
outa sized range of some bytes
insa arbitrary-length parameter list of unsigned integers to be stored

Definition at line 548 of file loadstor.h.

548 {
549 ranges::assert_exact_byte_length<(sizeof(Ts) + ...)>(out);
550 auto store_one = [off = 0]<typename T>(auto o, T i) mutable {
551 store_any<endianness, T>(i, o.subspan(off).template first<sizeof(T)>());
552 off += sizeof(T);
553 };
554
555 (store_one(std::span{out}, ins), ...);
556}

References Botan::ranges::assert_exact_byte_length(), and T.

◆ store_any() [6/9]

template<Endianness endianness, typename InT , unsigned_integralish T, ranges::contiguous_output_range< uint8_t > OutR>
requires std::same_as<AutoDetect, InT>
constexpr void Botan::detail::store_any ( T in,
OutR && out_range )
inlineconstexpr

Infer InT from a single unsigned integer input parameter.

TODO: we might consider dropping this overload (i.e. out-range as second parameter) and make this a "special case" of the overload below, that takes a variadic number of input parameters.

Parameters
inan unsigned integer to be stored
out_rangea range of bytes to store the word into

Definition at line 612 of file loadstor.h.

612 {
613 store_any<endianness, T>(in, std::forward<OutR>(out_range));
614}

◆ store_any() [7/9]

template<Endianness endianness, typename InT , unsigned_integralish T>
requires (std::same_as<AutoDetect, InT> || std::same_as<T, InT>)
constexpr void Botan::detail::store_any ( T in,
uint8_t out[] )
inlineconstexpr

Store a single unsigned integer into a raw pointer

Parameters
inthe input unsigned integer
outthe byte array to write to

Definition at line 677 of file loadstor.h.

677 {
678 // asserts that *out points to enough bytes to write into
679 store_any<endianness, InT>(in, std::span<uint8_t, sizeof(T)>(out, sizeof(T)));
680}

References T.

◆ store_any() [8/9]

template<Endianness endianness, typename OutR , unsigned_integralish... Ts>
requires all_same_v<Ts...>
constexpr auto Botan::detail::store_any ( Ts... ins)
inlineconstexpr

The caller provided some integer values but did not provide the output container. Let's create one for them, fill it with one of the overloads above and return it. This will default to a std::array if the caller did not specify the desired output container type.

Parameters
inssome words that should be stored
Returns
a container of bytes that contains the stored words

Definition at line 662 of file loadstor.h.

662 {
663 return store_any<endianness, OutR>(std::array{ins...});
664}

◆ store_any() [9/9]

template<Endianness endianness, typename InT , unsigned_integralish T0, unsigned_integralish... Ts>
requires (std::same_as<AutoDetect, InT> || std::same_as<T0, InT>) && all_same_v<T0, Ts...>
constexpr void Botan::detail::store_any ( uint8_t out[],
T0 in0,
Ts... ins )
inlineconstexpr

Store many unsigned integers words into a raw pointer

Parameters
insa arbitrary-length parameter list of unsigned integers to be stored
outthe byte array to write to

Definition at line 689 of file loadstor.h.

689 {
690 constexpr auto bytes = sizeof(in0) + (sizeof(ins) + ... + 0);
691 // asserts that *out points to the correct amount of memory
692 store_any<endianness, T0>(std::span<uint8_t, bytes>(out, bytes), in0, ins...);
693}

Variable Documentation

◆ has_capability

template<typename CapabilityT , typename... Tags>
constexpr bool Botan::detail::has_capability = (std::is_same_v<CapabilityT, Tags> || ...)
constexpr

Checks whether the CapabilityT is included in the Tags type pack.

Definition at line 31 of file strong_type.h.