Botan 3.5.0
Crypto and TLS for C&
Botan::detail Namespace Reference

Classes

struct  AutoDetect
 
class  Strong_Adapter
 
class  Strong_Adapter< T >
 
class  Strong_Base
 
struct  unwrap_type
 
struct  unwrap_type< T >
 

Concepts

concept  int_or_strong_type
 
concept  unsigned_integralish
 

Typedefs

template<int_or_strong_type T>
using unwrap_type_t = typename unwrap_type<T>::type
 

Enumerations

enum class  Endianness : bool { Big , Little }
 

Functions

template<ranges::spanable_range OutR, ranges::spanable_range... Rs>
requires (concepts::reservable_container<OutR> || ranges::statically_spanable_range<OutR>)
constexpr OutR concatenate (Rs &&... ranges)
 
template<Endianness endianness, unsigned_integralish T>
size_t copy_out_any_word_aligned_portion (std::span< uint8_t > &out, std::span< const T > &in)
 
constexpr uint16_t ct_int_div_kyber_q (uint32_t a)
 
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)
 
template<int_or_strong_type T>
constexpr auto unwrap (T t) -> unwrap_type_t< T >
 
template<int_or_strong_type T>
constexpr auto wrap (unwrap_type_t< T > t) -> T
 

Variables

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

Typedef Documentation

◆ unwrap_type_t

template<int_or_strong_type T>
using Botan::detail::unwrap_type_t = typename unwrap_type<T>::type

Definition at line 72 of file int_utils.h.

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

◆ concatenate()

template<ranges::spanable_range OutR, ranges::spanable_range... Rs>
requires (concepts::reservable_container<OutR> || ranges::statically_spanable_range<OutR>)
OutR Botan::detail::concatenate ( Rs &&... ranges)
constexpr

Helper function that performs range size-checks as required given the selected output and input range types. If all lengths are known at compile time, this check will be performed at compile time as well. It will then instantiate an output range and concatenate the input ranges' contents.

Definition at line 204 of file stl_util.h.

206{
207 OutR result;
208
209 // Prepare and validate the output range and construct a lambda that does the
210 // actual filling of the result buffer.
211 // (if no input ranges are given, GCC claims that fill_fn is unused)
212 [[maybe_unused]] auto fill_fn = [&] {
214 // dynamically allocate the correct result byte length
215 const size_t total_size = (ranges.size() + ... + 0);
216 result.reserve(total_size);
217
218 // fill the result buffer using a back-inserter
219 return [&result](auto&& range) {
220 std::copy(std::ranges::begin(range), std::ranges::end(range), std::back_inserter(unpack(result)));
221 };
222 } else {
223 if constexpr((ranges::statically_spanable_range<Rs> && ... && true)) {
224 // all input ranges have a static extent, so check the total size at compile time
225 // (work around an issue in MSVC that warns `total_size` is unused)
226 [[maybe_unused]] constexpr size_t total_size = (decltype(std::span{ranges})::extent + ... + 0);
227 static_assert(result.size() == total_size, "size of result buffer does not match the sum of input buffers");
228 } else {
229 // at least one input range has a dynamic extent, so check the total size at runtime
230 const size_t total_size = (ranges.size() + ... + 0);
231 BOTAN_ARG_CHECK(result.size() == total_size,
232 "result buffer has static extent that does not match the sum of input buffers");
233 }
234
235 // fill the result buffer and hold the current output-iterator position
236 return [itr = std::ranges::begin(result)](auto&& range) mutable {
237 std::copy(std::ranges::begin(range), std::ranges::end(range), itr);
238 std::advance(itr, std::ranges::size(range));
239 };
240 }
241 }();
242
243 // perform the actual concatenation
244 (fill_fn(std::forward<Rs>(ranges)), ...);
245
246 return result;
247}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
constexpr decltype(auto) unpack(T &t)

References BOTAN_ARG_CHECK, and Botan::unpack().

Referenced by Botan::concat().

◆ 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 )
inline

Definition at line 714 of file loadstor.h.

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

References BOTAN_ASSERT_NOMSG, store_any(), and T.

Referenced by Botan::copy_out_be(), and Botan::copy_out_le().

◆ ct_int_div_kyber_q()

uint16_t Botan::detail::ct_int_div_kyber_q ( uint32_t a)
inlineconstexpr

Constant time implementation for computing an unsigned integer division with KyberConstants::Q = 3329.

It enforces the optimization of various compilers, replacing the division operation with multiplication and shifts.

This implementation is only valid for integers <= 2**20

Returns
(a / KyberConstants::Q)

Definition at line 45 of file kyber_structures.h.

45 {
46 BOTAN_DEBUG_ASSERT(a < (1 << 18));
47
48 /*
49 Constants based on "Hacker's Delight" (Second Edition) by Henry
50 S. Warren, Jr. Chapter 10-9 "Unsigned Division by Divisors >= 1"
51 */
52 const uint64_t m = 161271;
53 const size_t p = 29;
54 return static_cast<uint16_t>((a * m) >> p);
55}
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98

References BOTAN_DEBUG_ASSERT.

Referenced by Botan::Polynomial::to_message().

◆ fallback_load_any()

template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
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 181 of file loadstor.h.

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

References Big, and Little.

Referenced by load_any().

◆ fallback_store_any()

template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
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 203 of file loadstor.h.

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

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

Referenced by store_any().

◆ is_native()

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 135 of file loadstor.h.

135 {
136#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
137 return endianness == Endianness::Big;
138#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
139 return endianness == Endianness::Little;
140#else
141 return false;
142#endif
143}

References Big, and Little.

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

◆ is_opposite()

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 149 of file loadstor.h.

149 {
150#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
151 return endianness == Endianness::Little;
152#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
153 return endianness == Endianness::Big;
154#else
155 return false;
156#endif
157}

References Big, and Little.

Referenced by load_any(), and store_any().

◆ load_any() [1/8]

template<Endianness endianness, unsigned_integralish OutT>
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 417 of file loadstor.h.

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

References load_any().

◆ 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...>)))
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 432 of file loadstor.h.

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

References load_any().

◆ 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...>))
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 295 of file loadstor.h.

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

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

◆ load_any() [4/8]

template<Endianness endianness, std::unsigned_integral OutT, ranges::contiguous_range< uint8_t > InR>
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 244 of file loadstor.h.

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

References Botan::ranges::assert_exact_byte_length(), fallback_load_any(), is_native(), is_opposite(), native_endianness_is_unknown(), Botan::reverse_bytes(), and Botan::typecast_copy().

Referenced by load_any(), load_any(), load_any(), load_any(), load_any(), load_any(), Botan::load_be(), and Botan::load_le().

◆ 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>>)
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 282 of file loadstor.h.

282 {
283 using underlying_type = std::underlying_type_t<OutT>;
284 return static_cast<OutT>(load_any<endianness, underlying_type>(std::forward<InR>(in_range)));
285}

References load_any().

◆ 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>))
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 360 of file loadstor.h.

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

References BOTAN_ARG_CHECK, and load_any().

◆ 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>>))
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 318 of file loadstor.h.

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

References Botan::ranges::assert_equal_byte_lengths(), is_native(), load_any(), 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>)
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 446 of file loadstor.h.

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

References load_any(), and T.

◆ native_endianness_is_unknown()

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

Definition at line 160 of file loadstor.h.

160 {
161#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) || defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
162 return false;
163#else
164 return true;
165#endif
166}

Referenced by load_any(), and store_any().

◆ 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>)
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 625 of file loadstor.h.

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

References store_any().

◆ store_any() [2/9]

template<Endianness endianness, std::unsigned_integral InT, ranges::contiguous_output_range< uint8_t > OutR>
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 487 of file loadstor.h.

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

References Botan::ranges::assert_exact_byte_length(), fallback_store_any(), is_native(), is_opposite(), native_endianness_is_unknown(), Botan::reverse_bytes(), and Botan::typecast_copy().

Referenced by copy_out_any_word_aligned_portion(), store_any(), store_any(), store_any(), store_any(), store_any(), store_any(), store_any(), store_any(), Botan::store_be(), and Botan::store_le().

◆ 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>>)
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 527 of file loadstor.h.

527 {
528 using underlying_type = std::underlying_type_t<InT>;
529 // TODO: C++23: use std::to_underlying(in) instead
530 store_any<endianness, underlying_type>(static_cast<underlying_type>(in), std::forward<OutR>(out_range));
531}

References store_any().

◆ 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>>)
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 565 of file loadstor.h.

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

References Botan::ranges::assert_equal_byte_lengths(), is_native(), store_any(), 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...>))
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 544 of file loadstor.h.

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

References Botan::ranges::assert_exact_byte_length(), store_any(), 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>
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 608 of file loadstor.h.

608 {
609 store_any<endianness, T>(in, std::forward<OutR>(out_range));
610}

References store_any().

◆ store_any() [7/9]

template<Endianness endianness, typename InT , unsigned_integralish T>
requires (std::same_as<AutoDetect, InT> || std::same_as<T, InT>)
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 673 of file loadstor.h.

673 {
674 // asserts that *out points to enough bytes to write into
675 store_any<endianness, InT>(in, std::span<uint8_t, sizeof(T)>(out, sizeof(T)));
676}

References store_any(), and T.

◆ store_any() [8/9]

template<Endianness endianness, typename OutR , unsigned_integralish... Ts>
requires all_same_v<Ts...>
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 658 of file loadstor.h.

658 {
659 return store_any<endianness, OutR>(std::array{ins...});
660}

References store_any().

◆ 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...>
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 685 of file loadstor.h.

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

References store_any().

◆ unwrap()

template<int_or_strong_type T>
auto Botan::detail::unwrap ( T t) -> unwrap_type_t<T>
constexpr

Definition at line 75 of file int_utils.h.

75 {
76 if constexpr(std::integral<T>) {
77 return t;
78 } else {
79 return t.get();
80 }
81}

Referenced by Botan::checked_cast_to_or_throw().

◆ wrap()

template<int_or_strong_type T>
auto Botan::detail::wrap ( unwrap_type_t< T > t) -> T
constexpr

Definition at line 84 of file int_utils.h.

84 {
85 if constexpr(std::integral<T>) {
86 return t;
87 } else {
88 return T(t);
89 }
90}

References T.

Referenced by Botan::checked_cast_to_or_throw().

Variable Documentation

◆ has_capability

template<typename CapabilityT , typename... Tags>
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.