/src/botan/build/include/internal/botan/internal/bitvector.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * An abstraction for an arbitrarily large bitvector that can |
3 | | * optionally use the secure_allocator. All bitwise accesses and all |
4 | | * constructors are implemented in constant time. Otherwise, only methods |
5 | | * with the "ct_" pre-fix run in constant time. |
6 | | * |
7 | | * (C) 2023-2024 Jack Lloyd |
8 | | * (C) 2023-2024 René Meusel, Rohde & Schwarz Cybersecurity |
9 | | * |
10 | | * Botan is released under the Simplified BSD License (see license.txt) |
11 | | */ |
12 | | |
13 | | #ifndef BOTAN_BIT_VECTOR_H_ |
14 | | #define BOTAN_BIT_VECTOR_H_ |
15 | | |
16 | | #include <botan/concepts.h> |
17 | | #include <botan/exceptn.h> |
18 | | #include <botan/mem_ops.h> |
19 | | #include <botan/secmem.h> |
20 | | #include <botan/strong_type.h> |
21 | | #include <botan/internal/bit_ops.h> |
22 | | #include <botan/internal/ct_utils.h> |
23 | | #include <botan/internal/loadstor.h> |
24 | | #include <botan/internal/stl_util.h> |
25 | | |
26 | | #include <memory> |
27 | | #include <optional> |
28 | | #include <span> |
29 | | #include <sstream> |
30 | | #include <string> |
31 | | #include <utility> |
32 | | #include <vector> |
33 | | |
34 | | namespace Botan { |
35 | | |
36 | | template <template <typename> typename AllocatorT> |
37 | | class bitvector_base; |
38 | | |
39 | | template <typename T> |
40 | | struct is_bitvector : std::false_type {}; |
41 | | |
42 | | template <template <typename> typename T> |
43 | | struct is_bitvector<bitvector_base<T>> : std::true_type {}; |
44 | | |
45 | | template <typename T> |
46 | | constexpr static bool is_bitvector_v = is_bitvector<T>::value; |
47 | | |
48 | | template <typename T> |
49 | | concept bitvectorish = is_bitvector_v<strong_type_wrapped_type<T>>; |
50 | | |
51 | | namespace detail { |
52 | | |
53 | | template <typename T0, typename... Ts> |
54 | | struct first_type { |
55 | | using type = T0; |
56 | | }; |
57 | | |
58 | | // get the first type from a parameter pack |
59 | | // TODO: C++26 will bring Parameter Pack indexing: |
60 | | // using first_t = Ts...[0]; |
61 | | template <typename... Ts> |
62 | | requires(sizeof...(Ts) > 0) |
63 | | using first_t = typename first_type<Ts...>::type; |
64 | | |
65 | | // get the first object from a parameter pack |
66 | | // TODO: C++26 will bring Parameter Pack indexing: |
67 | | // auto first = s...[0]; |
68 | | template <typename T0, typename... Ts> |
69 | 0 | constexpr static first_t<T0, Ts...> first(T0&& t, Ts&&...) { |
70 | 0 | return std::forward<T0>(t); |
71 | 0 | } Unexecuted instantiation: cmce_decaps.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&) Unexecuted instantiation: cmce_decaps.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&) Unexecuted instantiation: cmce_decaps.cpp:Botan::detail::first_type<std::__1::span<unsigned long const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned long const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_decaps.cpp:Botan::detail::first_type<std::__1::span<unsigned int const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned int const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_decaps.cpp:Botan::detail::first_type<std::__1::span<unsigned short const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned short const, 18446744073709551615ul>&>(std::__1::span<unsigned short const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned long const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned long const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned int const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned int const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned short const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned short const, 18446744073709551615ul>&>(std::__1::span<unsigned short const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_keys_internal.cpp:Botan::detail::first_type<std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&>(std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned long, 18446744073709551615ul>&, std::__1::span<unsigned long const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned int, 18446744073709551615ul>&, std::__1::span<unsigned int const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&>(std::__1::span<unsigned short, 18446744073709551615ul>&, std::__1::span<unsigned short const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>::type Botan::detail::first<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned long const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned long const, 18446744073709551615ul>&>(std::__1::span<unsigned long const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned int const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned int const, 18446744073709551615ul>&>(std::__1::span<unsigned int const, 18446744073709551615ul>&) Unexecuted instantiation: cmce_matrix.cpp:Botan::detail::first_type<std::__1::span<unsigned short const, 18446744073709551615ul>&>::type Botan::detail::first<std::__1::span<unsigned short const, 18446744073709551615ul>&>(std::__1::span<unsigned short const, 18446744073709551615ul>&) |
72 | | |
73 | | template <typename OutT, typename> |
74 | | using as = OutT; |
75 | | |
76 | | template <typename FnT, std::unsigned_integral BlockT, typename... ParamTs> |
77 | | using blockwise_processing_callback_return_type = std::invoke_result_t<FnT, as<BlockT, ParamTs>...>; |
78 | | |
79 | | template <typename FnT, typename BlockT, typename... ParamTs> |
80 | | concept is_blockwise_processing_callback_return_type = |
81 | | std::unsigned_integral<BlockT> && |
82 | | (std::same_as<BlockT, blockwise_processing_callback_return_type<FnT, BlockT, ParamTs...>> || |
83 | | std::same_as<bool, blockwise_processing_callback_return_type<FnT, BlockT, ParamTs...>> || |
84 | | std::same_as<void, blockwise_processing_callback_return_type<FnT, BlockT, ParamTs...>>); |
85 | | |
86 | | template <typename FnT, typename... ParamTs> |
87 | | concept blockwise_processing_callback_without_mask = |
88 | | is_blockwise_processing_callback_return_type<FnT, uint8_t, ParamTs...> && |
89 | | is_blockwise_processing_callback_return_type<FnT, uint16_t, ParamTs...> && |
90 | | is_blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs...> && |
91 | | is_blockwise_processing_callback_return_type<FnT, uint64_t, ParamTs...>; |
92 | | |
93 | | template <typename FnT, typename... ParamTs> |
94 | | concept blockwise_processing_callback_with_mask = |
95 | | is_blockwise_processing_callback_return_type<FnT, uint8_t, ParamTs..., uint8_t /* mask */> && |
96 | | is_blockwise_processing_callback_return_type<FnT, uint16_t, ParamTs..., uint16_t /* mask */> && |
97 | | is_blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs..., uint32_t /* mask */> && |
98 | | is_blockwise_processing_callback_return_type<FnT, uint64_t, ParamTs..., uint64_t /* mask */>; |
99 | | |
100 | | /** |
101 | | * Defines the callback constraints for the BitRangeOperator. For further |
102 | | * details, see bitvector_base::range_operation(). |
103 | | */ |
104 | | template <typename FnT, typename... ParamTs> |
105 | | concept blockwise_processing_callback = blockwise_processing_callback_with_mask<FnT, ParamTs...> || |
106 | | blockwise_processing_callback_without_mask<FnT, ParamTs...>; |
107 | | |
108 | | template <typename FnT, typename... ParamTs> |
109 | | concept manipulating_blockwise_processing_callback = |
110 | | (blockwise_processing_callback_without_mask<FnT, ParamTs...> && |
111 | | std::same_as<uint32_t, blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs...>>) || |
112 | | (blockwise_processing_callback_with_mask<FnT, ParamTs...> && |
113 | | std::same_as<uint32_t, blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs..., first_t<ParamTs...>>>); |
114 | | |
115 | | template <typename FnT, typename... ParamTs> |
116 | | concept predicate_blockwise_processing_callback = |
117 | | (blockwise_processing_callback_without_mask<FnT, ParamTs...> && |
118 | | std::same_as<bool, blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs...>>) || |
119 | | (blockwise_processing_callback_with_mask<FnT, ParamTs...> && |
120 | | std::same_as<bool, blockwise_processing_callback_return_type<FnT, uint32_t, ParamTs..., first_t<ParamTs...>>>); |
121 | | |
122 | | template <typename T> |
123 | | class bitvector_iterator { |
124 | | private: |
125 | | using size_type = typename T::size_type; |
126 | | |
127 | | public: |
128 | | using difference_type = std::make_signed_t<size_type>; |
129 | | using value_type = std::remove_const_t<decltype(std::declval<T>().at(0))>; |
130 | | using pointer = value_type*; |
131 | | using reference = value_type&; |
132 | | |
133 | | // TODO: technically, this could be a random access iterator |
134 | | using iterator_category = std::bidirectional_iterator_tag; |
135 | | |
136 | | public: |
137 | | bitvector_iterator() = default; |
138 | | ~bitvector_iterator() = default; |
139 | | |
140 | | bitvector_iterator(T* bitvector, size_t offset) : m_bitvector(bitvector) { update(offset); } |
141 | | |
142 | | bitvector_iterator(const bitvector_iterator& other) noexcept : m_bitvector(other.m_bitvector) { |
143 | | update(other.m_offset); |
144 | | } |
145 | | |
146 | | bitvector_iterator(bitvector_iterator&& other) noexcept : m_bitvector(other.m_bitvector) { |
147 | | update(other.m_offset); |
148 | | } |
149 | | |
150 | | bitvector_iterator& operator=(const bitvector_iterator& other) noexcept { |
151 | | if(this != &other) { |
152 | | m_bitvector = other.m_bitvector; |
153 | | update(other.m_offset); |
154 | | } |
155 | | return *this; |
156 | | } |
157 | | |
158 | | bitvector_iterator& operator=(bitvector_iterator&& other) noexcept { |
159 | | m_bitvector = other.m_bitvector; |
160 | | update(other.m_offset); |
161 | | return *this; |
162 | | } |
163 | | |
164 | | bitvector_iterator& operator++() noexcept { |
165 | | update(signed_offset() + 1); |
166 | | return *this; |
167 | | } |
168 | | |
169 | | bitvector_iterator operator++(int) noexcept { |
170 | | auto copy = *this; |
171 | | update(signed_offset() + 1); |
172 | | return copy; |
173 | | } |
174 | | |
175 | | bitvector_iterator& operator--() noexcept { |
176 | | update(signed_offset() - 1); |
177 | | return *this; |
178 | | } |
179 | | |
180 | | bitvector_iterator operator--(int) noexcept { |
181 | | auto copy = *this; |
182 | | update(signed_offset() - 1); |
183 | | return copy; |
184 | | } |
185 | | |
186 | | std::partial_ordering operator<=>(const bitvector_iterator& other) const noexcept { |
187 | | if(m_bitvector == other.m_bitvector) { |
188 | | return m_offset <=> other.m_offset; |
189 | | } else { |
190 | | return std::partial_ordering::unordered; |
191 | | } |
192 | | } |
193 | | |
194 | | bool operator==(const bitvector_iterator& other) const noexcept { |
195 | | return m_bitvector == other.m_bitvector && m_offset == other.m_offset; |
196 | | } |
197 | | |
198 | | reference operator*() const { return m_bitref.value(); } |
199 | | |
200 | | pointer operator->() const { return &(m_bitref.value()); } |
201 | | |
202 | | private: |
203 | 0 | void update(size_type new_offset) { |
204 | 0 | m_offset = new_offset; |
205 | 0 | if(m_offset < m_bitvector->size()) { |
206 | 0 | m_bitref.emplace((*m_bitvector)[m_offset]); |
207 | 0 | } else { |
208 | 0 | // end() iterator |
209 | 0 | m_bitref.reset(); |
210 | 0 | } |
211 | 0 | } Unexecuted instantiation: Botan::detail::bitvector_iterator<Botan::bitvector_base<Botan::secure_allocator> >::update(unsigned long) Unexecuted instantiation: Botan::detail::bitvector_iterator<Botan::bitvector_base<Botan::secure_allocator> const>::update(unsigned long) |
212 | | |
213 | | difference_type signed_offset() const { return static_cast<difference_type>(m_offset); } |
214 | | |
215 | | private: |
216 | | T* m_bitvector; |
217 | | size_type m_offset; |
218 | | mutable std::optional<value_type> m_bitref; |
219 | | }; |
220 | | |
221 | | } // namespace detail |
222 | | |
223 | | /** |
224 | | * An arbitrarily large bitvector with typical bit manipulation and convenient |
225 | | * bitwise access methods. Don't use `bitvector_base` directly, but the type |
226 | | * aliases:: |
227 | | * |
228 | | * * bitvector - with a standard allocator |
229 | | * * secure_bitvector - with a secure allocator that auto-scrubs the memory |
230 | | */ |
231 | | template <template <typename> typename AllocatorT> |
232 | | class bitvector_base final { |
233 | | public: |
234 | | using block_type = uint8_t; |
235 | | using size_type = size_t; |
236 | | using allocator_type = AllocatorT<block_type>; |
237 | | using value_type = block_type; |
238 | | using iterator = detail::bitvector_iterator<bitvector_base<AllocatorT>>; |
239 | | using const_iterator = detail::bitvector_iterator<const bitvector_base<AllocatorT>>; |
240 | | |
241 | | static constexpr size_type block_size_bytes = sizeof(block_type); |
242 | | static constexpr size_type block_size_bits = block_size_bytes * 8; |
243 | | static constexpr bool uses_secure_allocator = std::is_same_v<allocator_type, secure_allocator<block_type>>; |
244 | | |
245 | | private: |
246 | | template <template <typename> typename FriendAllocatorT> |
247 | | friend class bitvector_base; |
248 | | |
249 | | static constexpr block_type one = block_type(1); |
250 | | |
251 | | static constexpr size_type block_offset_shift = size_type(3) + ceil_log2(block_size_bytes); |
252 | | static constexpr size_type block_index_mask = (one << block_offset_shift) - 1; |
253 | | |
254 | 0 | static constexpr size_type block_index(size_type pos) { return pos >> block_offset_shift; } |
255 | | |
256 | 0 | static constexpr size_type block_offset(size_type pos) { return pos & block_index_mask; } |
257 | | |
258 | | private: |
259 | | /** |
260 | | * Internal helper to wrap a single bit in the bitvector and provide |
261 | | * certain convenience access methods. |
262 | | */ |
263 | | template <typename BlockT> |
264 | | requires std::same_as<block_type, std::remove_cv_t<BlockT>> |
265 | | class bitref_base { |
266 | | private: |
267 | | friend class bitvector_base<AllocatorT>; |
268 | | |
269 | | constexpr bitref_base(std::span<BlockT> blocks, size_type pos) noexcept : |
270 | 0 | m_block(blocks[block_index(pos)]), m_mask(one << block_offset(pos)) {} Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char const>::bitref_base(std::__1::span<unsigned char const, 18446744073709551615ul>, unsigned long) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char>::bitref_base(std::__1::span<unsigned char, 18446744073709551615ul>, unsigned long) |
271 | | |
272 | | public: |
273 | | bitref_base() = delete; |
274 | | bitref_base(const bitref_base&) noexcept = default; |
275 | | bitref_base(bitref_base&&) noexcept = default; |
276 | | bitref_base& operator=(const bitref_base&) = delete; |
277 | | bitref_base& operator=(bitref_base&&) = delete; |
278 | | |
279 | | ~bitref_base() = default; |
280 | | |
281 | | public: |
282 | 0 | constexpr operator bool() const noexcept { return is_set(); } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char const>::operator bool() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char>::operator bool() const |
283 | | |
284 | 0 | constexpr bool is_set() const noexcept { return (m_block & m_mask) > 0; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char const>::is_set() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitref_base<unsigned char>::is_set() const |
285 | | |
286 | | template <std::integral T> |
287 | 0 | constexpr T as() const noexcept { |
288 | 0 | return static_cast<T>(is_set()); |
289 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE11bitref_baseIKhE2asITkNSt3__18integralEhEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE11bitref_baseIhE2asITkNSt3__18integralEmEET_v |
290 | | |
291 | 0 | constexpr CT::Choice as_choice() const noexcept { |
292 | 0 | return CT::Choice::from_int(static_cast<BlockT>(m_block & m_mask)); |
293 | 0 | } |
294 | | |
295 | | protected: |
296 | | BlockT& m_block; // NOLINT(*-non-private-member-variables-in-classes) |
297 | | BlockT m_mask; // NOLINT(*-non-private-member-variables-in-classes) |
298 | | }; |
299 | | |
300 | | public: |
301 | | /** |
302 | | * Wraps a constant reference into the bitvector. Bit can be accessed |
303 | | * but not modified. |
304 | | */ |
305 | | template <typename BlockT> |
306 | | class bitref final : public bitref_base<BlockT> { |
307 | | public: |
308 | | using bitref_base<BlockT>::bitref_base; |
309 | | }; |
310 | | |
311 | | /** |
312 | | * Wraps a modifiable reference into the bitvector. Bit may be accessed |
313 | | * and modified (e.g. flipped or XOR'ed). |
314 | | * |
315 | | * Constant-time operations are used for the bit manipulations. The |
316 | | * location of the bit in the bit vector may be leaked, though. |
317 | | */ |
318 | | template <typename BlockT> |
319 | | requires(!std::is_const_v<BlockT>) |
320 | | class bitref<BlockT> : public bitref_base<BlockT> { |
321 | | public: |
322 | | using bitref_base<BlockT>::bitref_base; |
323 | | |
324 | | ~bitref() = default; |
325 | | bitref(const bitref&) noexcept = default; |
326 | | bitref(bitref&&) noexcept = default; |
327 | | |
328 | | constexpr bitref& set() noexcept { |
329 | | this->m_block |= this->m_mask; |
330 | | return *this; |
331 | | } |
332 | | |
333 | | constexpr bitref& unset() noexcept { |
334 | | this->m_block &= ~this->m_mask; |
335 | | return *this; |
336 | | } |
337 | | |
338 | | constexpr bitref& flip() noexcept { |
339 | | this->m_block ^= this->m_mask; |
340 | | return *this; |
341 | | } |
342 | | |
343 | | // NOLINTBEGIN |
344 | | |
345 | 0 | constexpr bitref& operator=(bool bit) noexcept { |
346 | 0 | this->m_block = |
347 | 0 | CT::Mask<BlockT>::expand(bit).select(this->m_mask | this->m_block, this->m_block & ~this->m_mask); |
348 | 0 | return *this; |
349 | 0 | } |
350 | | |
351 | | constexpr bitref& operator=(const bitref& bit) noexcept { return *this = bit.is_set(); } |
352 | | |
353 | | constexpr bitref& operator=(bitref&& bit) noexcept { return *this = bit.is_set(); } |
354 | | |
355 | | // NOLINTEND |
356 | | |
357 | | constexpr bitref& operator&=(bool other) noexcept { |
358 | | this->m_block &= ~CT::Mask<BlockT>::expand(other).if_not_set_return(this->m_mask); |
359 | | return *this; |
360 | | } |
361 | | |
362 | | constexpr bitref& operator|=(bool other) noexcept { |
363 | | this->m_block |= CT::Mask<BlockT>::expand(other).if_set_return(this->m_mask); |
364 | | return *this; |
365 | | } |
366 | | |
367 | 0 | constexpr bitref& operator^=(bool other) noexcept { |
368 | 0 | this->m_block ^= CT::Mask<BlockT>::expand(other).if_set_return(this->m_mask); |
369 | 0 | return *this; |
370 | 0 | } |
371 | | }; |
372 | | |
373 | | public: |
374 | 0 | bitvector_base() : m_bits(0) {} |
375 | | |
376 | 0 | bitvector_base(size_type bits) : m_bits(bits), m_blocks(ceil_toblocks(bits)) {} |
377 | | |
378 | | /** |
379 | | * Initialize the bitvector from a byte-array. Bits are taken byte-wise |
380 | | * from least significant to most significant. Example:: |
381 | | * |
382 | | * bitvector[0] -> LSB(Byte[0]) |
383 | | * bitvector[1] -> LSB+1(Byte[0]) |
384 | | * ... |
385 | | * bitvector[8] -> LSB(Byte[1]) |
386 | | * |
387 | | * @param bytes The byte vector to be loaded |
388 | | * @param bits The number of bits to be loaded. This must not be more |
389 | | * than the number of bytes in @p bytes. |
390 | | */ |
391 | 0 | bitvector_base(std::span<const uint8_t> bytes, std::optional<size_type> bits = std::nullopt) { |
392 | 0 | from_bytes(bytes, bits); |
393 | 0 | } |
394 | | |
395 | | bitvector_base(std::initializer_list<block_type> blocks, std::optional<size_type> bits = std::nullopt) : |
396 | 0 | m_bits(bits.value_or(blocks.size() * block_size_bits)), m_blocks(blocks.begin(), blocks.end()) {} Unexecuted instantiation: Botan::bitvector_base<std::__1::allocator>::bitvector_base(std::initializer_list<unsigned char>, std::__1::optional<unsigned long>) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::bitvector_base(std::initializer_list<unsigned char>, std::__1::optional<unsigned long>) |
397 | | |
398 | | bool empty() const { return m_bits == 0; } |
399 | | |
400 | 0 | size_type size() const { return m_bits; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::size() const Unexecuted instantiation: Botan::bitvector_base<std::__1::allocator>::size() const |
401 | | |
402 | | /** |
403 | | * @returns true iff the number of 1-bits in this is odd, false otherwise (constant time) |
404 | | */ |
405 | 0 | CT::Choice has_odd_hamming_weight() const { |
406 | 0 | uint64_t acc = 0; |
407 | 0 | full_range_operation([&](std::unsigned_integral auto block) { acc ^= block; }, *this); Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::has_odd_hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::has_odd_hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned int>(unsigned int) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::has_odd_hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned short>(unsigned short) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::has_odd_hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const |
408 | |
|
409 | 0 | for(size_t i = (sizeof(acc) * 8) >> 1; i > 0; i >>= 1) { |
410 | 0 | acc ^= acc >> i; |
411 | 0 | } |
412 | |
|
413 | 0 | return CT::Choice::from_int(acc & one); |
414 | 0 | } |
415 | | |
416 | | /** |
417 | | * Counts the number of 1-bits in the bitvector in constant time. |
418 | | * @returns the "population count" (or hamming weight) of the bitvector |
419 | | */ |
420 | 0 | size_type hamming_weight() const { |
421 | 0 | size_type acc = 0; |
422 | 0 | full_range_operation([&](std::unsigned_integral auto block) { acc += ct_popcount(block); }, *this); Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned long>(unsigned long) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned int>(unsigned int) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned short>(unsigned short) const Unexecuted instantiation: auto Botan::bitvector_base<Botan::secure_allocator>::hamming_weight() const::{lambda(auto:1)#1}::operator()<unsigned char>(unsigned char) const |
423 | 0 | return acc; |
424 | 0 | } |
425 | | |
426 | | /** |
427 | | * @returns copies this bitvector into a new bitvector of type @p OutT |
428 | | */ |
429 | | template <bitvectorish OutT> |
430 | 0 | OutT as() const { |
431 | 0 | return subvector<OutT>(0, size()); |
432 | 0 | } |
433 | | |
434 | | /** |
435 | | * @returns true if @p other contains the same bit pattern as this |
436 | | */ |
437 | | template <bitvectorish OtherT> |
438 | | bool equals_vartime(const OtherT& other) const noexcept { |
439 | | return size() == other.size() && |
440 | | full_range_operation([]<std::unsigned_integral BlockT>(BlockT lhs, BlockT rhs) { return lhs == rhs; }, |
441 | | *this, |
442 | | unwrap_strong_type(other)); |
443 | | } |
444 | | |
445 | | /** |
446 | | * @returns true if @p other contains the same bit pattern as this |
447 | | */ |
448 | | template <bitvectorish OtherT> |
449 | 0 | bool equals(const OtherT& other) const noexcept { |
450 | 0 | return (*this ^ other).none(); |
451 | 0 | } |
452 | | |
453 | | /// @name Serialization |
454 | | /// @{ |
455 | | |
456 | | /** |
457 | | * Re-initialize the bitvector with the given bytes. See the respective |
458 | | * constructor for details. This should be used only when trying to save |
459 | | * allocations. Otherwise, use the constructor. |
460 | | * |
461 | | * @param bytes the byte range to load bits from |
462 | | * @param bits (optional) if not all @p bytes should be loaded in full |
463 | | */ |
464 | 0 | void from_bytes(std::span<const uint8_t> bytes, std::optional<size_type> bits = std::nullopt) { |
465 | 0 | m_bits = bits.value_or(bytes.size_bytes() * 8); |
466 | 0 | BOTAN_ARG_CHECK(m_bits <= bytes.size_bytes() * 8, "not enough data to load so many bits"); |
467 | 0 | resize(m_bits); |
468 | | |
469 | | // load as much aligned data as possible |
470 | 0 | const auto verbatim_blocks = m_bits / block_size_bits; |
471 | 0 | const auto verbatim_bytes = verbatim_blocks * block_size_bytes; |
472 | 0 | if(verbatim_blocks > 0) { |
473 | 0 | typecast_copy(std::span{m_blocks}.first(verbatim_blocks), bytes.first(verbatim_bytes)); |
474 | 0 | } |
475 | | |
476 | | // load remaining unaligned data |
477 | 0 | for(size_type i = verbatim_bytes * 8; i < m_bits; ++i) { |
478 | 0 | ref(i) = ((bytes[i >> 3] & (uint8_t(1) << (i & 7))) != 0); |
479 | 0 | } |
480 | 0 | } |
481 | | |
482 | | /** |
483 | | * Renders the bitvector into a byte array. By default, this will use |
484 | | * `std::vector<uint8_t>` or `Botan::secure_vector<uint8_t>`, depending on |
485 | | * the allocator used by the bitvector. The rendering is compatible with |
486 | | * the bit layout explained in the respective constructor. |
487 | | */ |
488 | | template <concepts::resizable_byte_buffer OutT = |
489 | | std::conditional_t<uses_secure_allocator, secure_vector<uint8_t>, std::vector<uint8_t>>> |
490 | 0 | OutT to_bytes() const { |
491 | 0 | OutT out(ceil_tobytes(m_bits)); |
492 | 0 | to_bytes(out); |
493 | 0 | return out; |
494 | 0 | } |
495 | | |
496 | | /** |
497 | | * Renders the bitvector into a properly sized byte range. |
498 | | * |
499 | | * @param out a byte range that has a length of at least `ceil_tobytes(size())`. |
500 | | */ |
501 | 0 | void to_bytes(std::span<uint8_t> out) const { |
502 | 0 | const auto bytes_needed = ceil_tobytes(m_bits); |
503 | 0 | BOTAN_ARG_CHECK(bytes_needed <= out.size_bytes(), "Not enough space to render bitvector"); |
504 | | |
505 | | // copy as much aligned data as possible |
506 | 0 | const auto verbatim_blocks = m_bits / block_size_bits; |
507 | 0 | const auto verbatim_bytes = verbatim_blocks * block_size_bytes; |
508 | 0 | if(verbatim_blocks > 0) { |
509 | 0 | typecast_copy(out.first(verbatim_bytes), std::span{m_blocks}.first(verbatim_blocks)); |
510 | 0 | } |
511 | | |
512 | | // copy remaining unaligned data |
513 | 0 | clear_mem(out.subspan(verbatim_bytes)); |
514 | 0 | for(size_type i = verbatim_bytes * 8; i < m_bits; ++i) { |
515 | 0 | out[i >> 3] |= ref(i).template as<uint8_t>() << (i & 7); |
516 | 0 | } |
517 | 0 | } |
518 | | |
519 | | /** |
520 | | * Renders this bitvector into a sequence of "0"s and "1"s. |
521 | | * This is meant for debugging purposes and is not efficient. |
522 | | */ |
523 | | std::string to_string() const { |
524 | | std::stringstream ss; |
525 | | for(size_type i = 0; i < size(); ++i) { |
526 | | ss << ref(i); |
527 | | } |
528 | | return ss.str(); |
529 | | } |
530 | | |
531 | | /// @} |
532 | | |
533 | | /// @name Capacity Accessors and Modifiers |
534 | | /// @{ |
535 | | |
536 | | size_type capacity() const { return m_blocks.capacity() * block_size_bits; } |
537 | | |
538 | 0 | void reserve(size_type bits) { m_blocks.reserve(ceil_toblocks(bits)); } |
539 | | |
540 | 0 | void resize(size_type bits) { |
541 | 0 | const auto new_number_of_blocks = ceil_toblocks(bits); |
542 | 0 | if(new_number_of_blocks != m_blocks.size()) { |
543 | 0 | m_blocks.resize(new_number_of_blocks); |
544 | 0 | } |
545 | |
|
546 | 0 | m_bits = bits; |
547 | 0 | zero_unused_bits(); |
548 | 0 | } |
549 | | |
550 | 0 | void push_back(bool bit) { |
551 | 0 | const auto i = size(); |
552 | 0 | resize(i + 1); |
553 | 0 | ref(i) = bit; |
554 | 0 | } |
555 | | |
556 | | void pop_back() { |
557 | | if(!empty()) { |
558 | | resize(size() - 1); |
559 | | } |
560 | | } |
561 | | |
562 | | /// @} |
563 | | |
564 | | /// @name Bitwise and Global Accessors and Modifiers |
565 | | /// @{ |
566 | | |
567 | 0 | auto at(size_type pos) { |
568 | 0 | check_offset(pos); |
569 | 0 | return ref(pos); |
570 | 0 | } |
571 | | |
572 | | // TODO C++23: deducing this |
573 | 0 | auto at(size_type pos) const { |
574 | 0 | check_offset(pos); |
575 | 0 | return ref(pos); |
576 | 0 | } |
577 | | |
578 | | auto front() { return ref(0); } |
579 | | |
580 | | // TODO C++23: deducing this |
581 | | auto front() const { return ref(0); } |
582 | | |
583 | | auto back() { return ref(size() - 1); } |
584 | | |
585 | | // TODO C++23: deducing this |
586 | | auto back() const { return ref(size() - 1); } |
587 | | |
588 | | /** |
589 | | * Sets the bit at position @p pos. |
590 | | * @throws Botan::Invalid_Argument if @p pos is out of range |
591 | | */ |
592 | | bitvector_base& set(size_type pos) { |
593 | | check_offset(pos); |
594 | | ref(pos).set(); |
595 | | return *this; |
596 | | } |
597 | | |
598 | | /** |
599 | | * Sets all currently allocated bits. |
600 | | */ |
601 | | bitvector_base& set() { |
602 | | full_range_operation( |
603 | | [](std::unsigned_integral auto block) -> decltype(block) { return static_cast<decltype(block)>(~0); }, |
604 | | *this); |
605 | | zero_unused_bits(); |
606 | | return *this; |
607 | | } |
608 | | |
609 | | /** |
610 | | * Unsets the bit at position @p pos. |
611 | | * @throws Botan::Invalid_Argument if @p pos is out of range |
612 | | */ |
613 | | bitvector_base& unset(size_type pos) { |
614 | | check_offset(pos); |
615 | | ref(pos).unset(); |
616 | | return *this; |
617 | | } |
618 | | |
619 | | /** |
620 | | * Unsets all currently allocated bits. |
621 | | */ |
622 | | bitvector_base& unset() { |
623 | | full_range_operation( |
624 | | [](std::unsigned_integral auto block) -> decltype(block) { return static_cast<decltype(block)>(0); }, |
625 | | *this); |
626 | | return *this; |
627 | | } |
628 | | |
629 | | /** |
630 | | * Flips the bit at position @p pos. |
631 | | * @throws Botan::Invalid_Argument if @p pos is out of range |
632 | | */ |
633 | | bitvector_base& flip(size_type pos) { |
634 | | check_offset(pos); |
635 | | ref(pos).flip(); |
636 | | return *this; |
637 | | } |
638 | | |
639 | | /** |
640 | | * Flips all currently allocated bits. |
641 | | */ |
642 | | bitvector_base& flip() { |
643 | | full_range_operation([](std::unsigned_integral auto block) -> decltype(block) { return ~block; }, *this); |
644 | | zero_unused_bits(); |
645 | | return *this; |
646 | | } |
647 | | |
648 | | /** |
649 | | * @returns true iff no bit is set |
650 | | */ |
651 | | bool none_vartime() const { |
652 | | return full_range_operation([](std::unsigned_integral auto block) { return block == 0; }, *this); |
653 | | } |
654 | | |
655 | | /** |
656 | | * @returns true iff no bit is set in constant time |
657 | | */ |
658 | 0 | bool none() const { return hamming_weight() == 0; } |
659 | | |
660 | | /** |
661 | | * @returns true iff at least one bit is set |
662 | | */ |
663 | | bool any_vartime() const { return !none_vartime(); } |
664 | | |
665 | | /** |
666 | | * @returns true iff at least one bit is set in constant time |
667 | | */ |
668 | | bool any() const { return !none(); } |
669 | | |
670 | | /** |
671 | | * @returns true iff all bits are set |
672 | | */ |
673 | | bool all_vartime() const { |
674 | | return full_range_operation( |
675 | | []<std::unsigned_integral BlockT>(BlockT block, BlockT mask) { return block == mask; }, *this); |
676 | | } |
677 | | |
678 | | /** |
679 | | * @returns true iff all bits are set in constant time |
680 | | */ |
681 | | bool all() const { return hamming_weight() == m_bits; } |
682 | | |
683 | 0 | auto operator[](size_type pos) { return ref(pos); } |
684 | | |
685 | | // TODO C++23: deducing this |
686 | 0 | auto operator[](size_type pos) const { return ref(pos); } |
687 | | |
688 | | /// @} |
689 | | |
690 | | /// @name Subvectors |
691 | | /// @{ |
692 | | |
693 | | /** |
694 | | * Creates a new bitvector with a subsection of this bitvector starting at |
695 | | * @p pos copying exactly @p length bits. |
696 | | */ |
697 | | template <bitvectorish OutT = bitvector_base<AllocatorT>> |
698 | 0 | auto subvector(size_type pos, std::optional<size_type> length = std::nullopt) const { |
699 | 0 | size_type bitlen = length.value_or(size() - pos); |
700 | 0 | BOTAN_ARG_CHECK(pos + bitlen <= size(), "Not enough bits to copy"); |
701 | |
|
702 | 0 | OutT newvector(bitlen); |
703 | | |
704 | | // Handle bitvectors that are wrapped in strong types |
705 | 0 | auto& newvector_unwrapped = unwrap_strong_type(newvector); |
706 | |
|
707 | 0 | if(bitlen > 0) { |
708 | 0 | if(pos % 8 == 0) { |
709 | 0 | copy_mem( |
710 | 0 | newvector_unwrapped.m_blocks, |
711 | 0 | std::span{m_blocks}.subspan(block_index(pos), block_index(pos + bitlen - 1) - block_index(pos) + 1)); |
712 | 0 | } else { |
713 | 0 | BitRangeOperator<const bitvector_base<AllocatorT>, BitRangeAlignment::no_alignment> from_op( |
714 | 0 | *this, pos, bitlen); |
715 | 0 | BitRangeOperator<strong_type_wrapped_type<OutT>> to_op( |
716 | 0 | unwrap_strong_type(newvector_unwrapped), 0, bitlen); |
717 | 0 | range_operation([](auto /* to */, auto from) { return from; }, to_op, from_op); Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEENKUlT_T0_E_clImmEEDaS7_S8_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEENKUlT_T0_E_clIjjEEDaS7_S8_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEENKUlT_T0_E_clIttEEDaS7_S8_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEENKUlT_T0_E_clIhhEEDaS7_S8_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEENKUlT_T0_E_clImmEEDaSA_SB_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEENKUlT_T0_E_clIjjEEDaSA_SB_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEENKUlT_T0_E_clIttEEDaSA_SB_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEENKUlT_T0_E_clIhhEEDaSA_SB_ |
718 | 0 | } |
719 | |
|
720 | 0 | newvector_unwrapped.zero_unused_bits(); |
721 | 0 | } |
722 | |
|
723 | 0 | return newvector; |
724 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEE Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEE |
725 | | |
726 | | /** |
727 | | * Extracts a subvector of bits as an unsigned integral type @p OutT |
728 | | * starting from bit @p pos and copying exactly sizeof(OutT)*8 bits. |
729 | | * |
730 | | * Hint: The bits are in big-endian order, i.e. the least significant bit |
731 | | * is the 0th bit and the most significant bit it the n-th. Hence, |
732 | | * addressing the bits with bitwise operations is done like so: |
733 | | * bool bit = (out_int >> pos) & 1; |
734 | | */ |
735 | | template <typename OutT> |
736 | | requires(std::unsigned_integral<strong_type_wrapped_type<OutT>> && |
737 | | !std::same_as<bool, strong_type_wrapped_type<OutT>>) |
738 | 0 | OutT subvector(size_type pos) const { |
739 | 0 | using result_t = strong_type_wrapped_type<OutT>; |
740 | 0 | constexpr size_t bits = sizeof(result_t) * 8; |
741 | 0 | BOTAN_ARG_CHECK(pos + bits <= size(), "Not enough bits to copy"); |
742 | 0 | result_t out = 0; |
743 | |
|
744 | 0 | if(pos % 8 == 0) { |
745 | 0 | out = load_le<result_t>(std::span{m_blocks}.subspan(block_index(pos)).template first<sizeof(result_t)>()); |
746 | 0 | } else { |
747 | 0 | BitRangeOperator<const bitvector_base<AllocatorT>, BitRangeAlignment::no_alignment> op(*this, pos, bits); |
748 | 0 | range_operation( |
749 | 0 | [&](std::unsigned_integral auto integer) { |
750 | 0 | if constexpr(std::same_as<result_t, decltype(integer)>) { |
751 | 0 | out = integer; |
752 | 0 | } |
753 | 0 | }, Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS9_EEET_mENKUlSA_E_clImEEDaSA_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS9_EEET_mENKUlSA_E_clIjEEDaSA_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS9_EEET_mENKUlSA_E_clItEEDaSA_ Unexecuted instantiation: _ZZNK5Botan14bitvector_baseINS_16secure_allocatorEE9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS9_EEET_mENKUlSA_E_clIhEEDaSA_ |
754 | 0 | op); |
755 | 0 | } |
756 | |
|
757 | 0 | return wrap_strong_type<OutT>(out); |
758 | 0 | } |
759 | | |
760 | | /** |
761 | | * Replaces a subvector of bits with the bits of another bitvector @p value |
762 | | * starting at bit @p pos. The number of bits to replace is determined by |
763 | | * the size of @p value. |
764 | | * |
765 | | * @note This is currently supported for byte-aligned @p pos only. |
766 | | * |
767 | | * @throws Not_Implemented when called with @p pos not divisible by 8. |
768 | | * |
769 | | * @param pos the position to start replacing bits |
770 | | * @param value the bitvector to copy bits from |
771 | | */ |
772 | | template <typename InT> |
773 | | requires(std::unsigned_integral<strong_type_wrapped_type<InT>> && !std::same_as<bool, InT>) |
774 | 0 | void subvector_replace(size_type pos, InT value) { |
775 | 0 | using in_t = strong_type_wrapped_type<InT>; |
776 | 0 | constexpr size_t bits = sizeof(in_t) * 8; |
777 | 0 | BOTAN_ARG_CHECK(pos + bits <= size(), "Not enough bits to replace"); |
778 | |
|
779 | 0 | if(pos % 8 == 0) { |
780 | 0 | store_le(std::span{m_blocks}.subspan(block_index(pos)).template first<sizeof(in_t)>(), |
781 | 0 | unwrap_strong_type(value)); |
782 | 0 | } else { |
783 | 0 | BitRangeOperator<bitvector_base<AllocatorT>, BitRangeAlignment::no_alignment> op(*this, pos, bits); |
784 | 0 | range_operation( |
785 | 0 | [&]<std::unsigned_integral BlockT>(BlockT block) -> BlockT { |
786 | 0 | if constexpr(std::same_as<in_t, BlockT>) { |
787 | 0 | return unwrap_strong_type(value); |
788 | 0 | } else { |
789 | | // This should never be reached. BOTAN_ASSERT_UNREACHABLE() |
790 | | // caused warning "unreachable code" on MSVC, though. You |
791 | | // don't say! |
792 | | // |
793 | | // Returning the given block back, is the most reasonable |
794 | | // thing to do in this case, though. |
795 | 0 | return block; |
796 | 0 | } |
797 | 0 | }, Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEE17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS6_EEEvmT_ENKUlTkNSt3__117unsigned_integralESA_E_clImEESA_SA_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEE17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS6_EEEvmT_ENKUlTkNSt3__117unsigned_integralESA_E_clIjEESA_SA_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEE17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS6_EEEvmT_ENKUlTkNSt3__117unsigned_integralESA_E_clItEESA_SA_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEE17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS6_EEEvmT_ENKUlTkNSt3__117unsigned_integralESA_E_clIhEESA_SA_ |
798 | 0 | op); |
799 | 0 | } |
800 | 0 | } |
801 | | |
802 | | /// @} |
803 | | |
804 | | /// @name Operators |
805 | | /// |
806 | | /// @{ |
807 | | |
808 | | auto operator~() { |
809 | | auto newbv = *this; |
810 | | newbv.flip(); |
811 | | return newbv; |
812 | | } |
813 | | |
814 | | template <bitvectorish OtherT> |
815 | | auto& operator|=(const OtherT& other) { |
816 | | full_range_operation([]<std::unsigned_integral BlockT>(BlockT lhs, BlockT rhs) -> BlockT { return lhs | rhs; }, |
817 | | *this, |
818 | | unwrap_strong_type(other)); |
819 | | return *this; |
820 | | } |
821 | | |
822 | | template <bitvectorish OtherT> |
823 | 0 | auto& operator&=(const OtherT& other) { |
824 | 0 | full_range_operation([]<std::unsigned_integral BlockT>(BlockT lhs, BlockT rhs) -> BlockT { return lhs & rhs; }, Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEaNITkNS_12bitvectorishES2_EERDaRKT_ENKUlTkNSt3__117unsigned_integralES5_S5_E_clImEES5_S5_S5_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEaNITkNS_12bitvectorishES2_EERDaRKT_ENKUlTkNSt3__117unsigned_integralES5_S5_E_clIjEES5_S5_S5_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEaNITkNS_12bitvectorishES2_EERDaRKT_ENKUlTkNSt3__117unsigned_integralES5_S5_E_clItEES5_S5_S5_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEaNITkNS_12bitvectorishES2_EERDaRKT_ENKUlTkNSt3__117unsigned_integralES5_S5_E_clIhEES5_S5_S5_ |
825 | 0 | *this, |
826 | 0 | unwrap_strong_type(other)); |
827 | 0 | return *this; |
828 | 0 | } |
829 | | |
830 | | template <bitvectorish OtherT> |
831 | 0 | auto& operator^=(const OtherT& other) { |
832 | 0 | full_range_operation([]<std::unsigned_integral BlockT>(BlockT lhs, BlockT rhs) -> BlockT { return lhs ^ rhs; }, Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEeOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_ENKUlTkNS4_17unsigned_integralES8_S8_E_clImEES8_S8_S8_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEeOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_ENKUlTkNS4_17unsigned_integralES8_S8_E_clIjEES8_S8_S8_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEeOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_ENKUlTkNS4_17unsigned_integralES8_S8_E_clItEES8_S8_S8_ Unexecuted instantiation: _ZZN5Botan14bitvector_baseINS_16secure_allocatorEEeOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_ENKUlTkNS4_17unsigned_integralES8_S8_E_clIhEES8_S8_S8_ |
833 | 0 | *this, |
834 | 0 | unwrap_strong_type(other)); |
835 | 0 | return *this; |
836 | 0 | } |
837 | | |
838 | | /// @} |
839 | | |
840 | | /// @name Constant Time Operations |
841 | | /// |
842 | | /// @{ |
843 | | |
844 | | /** |
845 | | * Implements:: |
846 | | * |
847 | | * if(condition) { |
848 | | * *this ^= other; |
849 | | * } |
850 | | * |
851 | | * omitting runtime dependence on any of the parameters. |
852 | | */ |
853 | | template <bitvectorish OtherT> |
854 | 0 | void ct_conditional_xor(CT::Choice condition, const OtherT& other) { |
855 | 0 | BOTAN_ASSERT_NOMSG(m_bits == other.m_bits); |
856 | 0 | BOTAN_ASSERT_NOMSG(m_blocks.size() == other.m_blocks.size()); |
857 | |
|
858 | 0 | auto maybe_xor = overloaded{ |
859 | 0 | [m = CT::Mask<uint64_t>::from_choice(condition)](uint64_t lhs, uint64_t rhs) -> uint64_t { |
860 | 0 | return lhs ^ m.if_set_return(rhs); |
861 | 0 | }, |
862 | 0 | [m = CT::Mask<uint32_t>::from_choice(condition)](uint32_t lhs, uint32_t rhs) -> uint32_t { |
863 | 0 | return lhs ^ m.if_set_return(rhs); |
864 | 0 | }, |
865 | 0 | [m = CT::Mask<uint16_t>::from_choice(condition)](uint16_t lhs, uint16_t rhs) -> uint16_t { |
866 | 0 | return lhs ^ m.if_set_return(rhs); |
867 | 0 | }, |
868 | 0 | [m = CT::Mask<uint8_t>::from_choice(condition)](uint8_t lhs, uint8_t rhs) -> uint8_t { |
869 | 0 | return lhs ^ m.if_set_return(rhs); |
870 | 0 | }, |
871 | 0 | }; |
872 | |
|
873 | 0 | full_range_operation(maybe_xor, *this, unwrap_strong_type(other)); |
874 | 0 | } |
875 | | |
876 | 0 | constexpr void _const_time_poison() const { CT::poison(m_blocks); } |
877 | | |
878 | 0 | constexpr void _const_time_unpoison() const { CT::unpoison(m_blocks); } |
879 | | |
880 | | /// @} |
881 | | |
882 | | /// @name Iterators |
883 | | /// |
884 | | /// @{ |
885 | | |
886 | 0 | iterator begin() noexcept { return iterator(this, 0); } |
887 | | |
888 | 0 | const_iterator begin() const noexcept { return const_iterator(this, 0); } |
889 | | |
890 | | const_iterator cbegin() const noexcept { return const_iterator(this, 0); } |
891 | | |
892 | 0 | iterator end() noexcept { return iterator(this, size()); } |
893 | | |
894 | 0 | const_iterator end() const noexcept { return const_iterator(this, size()); } |
895 | | |
896 | | const_iterator cend() noexcept { return const_iterator(this, size()); } |
897 | | |
898 | | /// @} |
899 | | |
900 | | private: |
901 | 0 | void check_offset(size_type pos) const { |
902 | | // BOTAN_ASSERT_NOMSG(!CT::is_poisoned(&m_bits, sizeof(m_bits))); |
903 | | // BOTAN_ASSERT_NOMSG(!CT::is_poisoned(&pos, sizeof(pos))); |
904 | 0 | BOTAN_ARG_CHECK(pos < m_bits, "Out of range"); |
905 | 0 | } |
906 | | |
907 | 0 | void zero_unused_bits() { |
908 | 0 | const auto first_unused_bit = size(); |
909 | | |
910 | | // Zero out any unused bits in the last block |
911 | 0 | if(first_unused_bit % block_size_bits != 0) { |
912 | 0 | const block_type mask = (one << block_offset(first_unused_bit)) - one; |
913 | 0 | m_blocks[block_index(first_unused_bit)] &= mask; |
914 | 0 | } |
915 | 0 | } |
916 | | |
917 | 0 | static constexpr size_type ceil_toblocks(size_type bits) { |
918 | 0 | return (bits + block_size_bits - 1) / block_size_bits; |
919 | 0 | } |
920 | | |
921 | 0 | auto ref(size_type pos) const { return bitref<const block_type>(m_blocks, pos); } |
922 | | |
923 | 0 | auto ref(size_type pos) { return bitref<block_type>(m_blocks, pos); } |
924 | | |
925 | | private: |
926 | | enum class BitRangeAlignment { byte_aligned, no_alignment }; |
927 | | |
928 | | /** |
929 | | * Helper construction to implement bit range operations on the bitvector. |
930 | | * It basically implements an iterator to read and write blocks of bits |
931 | | * from the underlying bitvector. Where "blocks of bits" are unsigned |
932 | | * integers of varying bit lengths. |
933 | | * |
934 | | * If the iteration starts at a byte boundary in the underlying bitvector, |
935 | | * this applies certain optimizations (i.e. loading blocks of bits straight |
936 | | * from the underlying byte buffer). The optimizations are enabled at |
937 | | * compile time (with the template parameter `alignment`). |
938 | | */ |
939 | | template <typename BitvectorT, auto alignment = BitRangeAlignment::byte_aligned> |
940 | | requires is_bitvector_v<std::remove_cvref_t<BitvectorT>> |
941 | | class BitRangeOperator { |
942 | | private: |
943 | 0 | constexpr static bool is_const() { return std::is_const_v<BitvectorT>; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_const() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_const() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_const() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::is_const() |
944 | | |
945 | | struct UnalignedDataHelper { |
946 | | const uint8_t padding_bits; |
947 | | const uint8_t bits_to_byte_alignment; |
948 | | }; |
949 | | |
950 | | public: |
951 | | BitRangeOperator(BitvectorT& source, size_type start_bitoffset, size_type bitlength) : |
952 | 0 | m_source(source), |
953 | 0 | m_start_bitoffset(start_bitoffset), |
954 | 0 | m_bitlength(bitlength), |
955 | 0 | m_unaligned_helper({.padding_bits = static_cast<uint8_t>(start_bitoffset % 8), |
956 | 0 | .bits_to_byte_alignment = static_cast<uint8_t>(8 - (start_bitoffset % 8))}), |
957 | 0 | m_read_bitpos(start_bitoffset), |
958 | 0 | m_write_bitpos(start_bitoffset) { |
959 | 0 | BOTAN_ASSERT(is_byte_aligned() == (m_start_bitoffset % 8 == 0), "byte alignment guarantee"); |
960 | 0 | BOTAN_ASSERT(m_source.size() >= m_start_bitoffset + m_bitlength, "enough bytes in underlying source"); |
961 | 0 | } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator> const&, unsigned long, unsigned long) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator>&, unsigned long, unsigned long) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator> const&, unsigned long, unsigned long) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<std::__1::allocator> const&, unsigned long, unsigned long) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator>&, unsigned long, unsigned long) |
962 | | |
963 | 0 | BitRangeOperator(BitvectorT& source) : BitRangeOperator(source, 0, source.size()) {} Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator> const&) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<Botan::secure_allocator>&) Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::BitRangeOperator(Botan::bitvector_base<std::__1::allocator> const&) |
964 | | |
965 | 0 | static constexpr bool is_byte_aligned() { return alignment == BitRangeAlignment::byte_aligned; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::is_byte_aligned() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_byte_aligned() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_byte_aligned() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::is_byte_aligned() Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::is_byte_aligned() |
966 | | |
967 | | /** |
968 | | * @returns the overall number of bits to be iterated with this operator |
969 | | */ |
970 | 0 | size_type size() const { return m_bitlength; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::size() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::size() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::size() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::size() const |
971 | | |
972 | | /** |
973 | | * @returns the number of bits not yet read from this operator |
974 | | */ |
975 | 0 | size_type bits_to_read() const { return m_bitlength - m_read_bitpos + m_start_bitoffset; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::bits_to_read() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::bits_to_read() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::bits_to_read() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::bits_to_read() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::bits_to_read() const |
976 | | |
977 | | /** |
978 | | * @returns the number of bits still to be written into this operator |
979 | | */ |
980 | 0 | size_type bits_to_write() const { return m_bitlength - m_write_bitpos + m_start_bitoffset; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::bits_to_write() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::bits_to_write() const |
981 | | |
982 | | /** |
983 | | * Loads the next block of bits from the underlying bitvector. No |
984 | | * bounds checks are performed. The caller can define the size of |
985 | | * the resulting unsigned integer block. |
986 | | */ |
987 | | template <std::unsigned_integral BlockT> |
988 | 0 | BlockT load_next() const { |
989 | 0 | constexpr size_type block_size = sizeof(BlockT); |
990 | 0 | constexpr size_type block_bits = block_size * 8; |
991 | 0 | const auto bits_remaining = bits_to_read(); |
992 | |
|
993 | 0 | BlockT result_block = 0; |
994 | 0 | if constexpr(is_byte_aligned()) { |
995 | 0 | result_block = load_le(m_source.as_byte_span().subspan(read_bytepos()).template first<block_size>()); |
996 | 0 | } else { |
997 | 0 | const size_type byte_pos = read_bytepos(); |
998 | 0 | const size_type bits_to_collect = std::min(block_bits, bits_to_read()); |
999 | |
|
1000 | 0 | const uint8_t first_byte = m_source.as_byte_span()[byte_pos]; |
1001 | | |
1002 | | // Initialize the left-most bits from the first byte. |
1003 | 0 | result_block = BlockT(first_byte) >> m_unaligned_helper.padding_bits; |
1004 | | |
1005 | | // If more bits are needed, we pull them from the remaining bytes. |
1006 | 0 | if(m_unaligned_helper.bits_to_byte_alignment < bits_to_collect) { |
1007 | 0 | const BlockT block = |
1008 | 0 | load_le(m_source.as_byte_span().subspan(byte_pos + 1).template first<block_size>()); |
1009 | 0 | result_block |= block << m_unaligned_helper.bits_to_byte_alignment; |
1010 | 0 | } |
1011 | 0 | } |
1012 | |
|
1013 | 0 | m_read_bitpos += std::min(block_bits, bits_remaining); |
1014 | 0 | return result_block; |
1015 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE9load_nextITkNSt3__117unsigned_integralEmEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEmEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE9load_nextITkNSt3__117unsigned_integralEjEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEjEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE9load_nextITkNSt3__117unsigned_integralEtEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEtEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE9load_nextITkNSt3__117unsigned_integralEhEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEhEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE9load_nextITkNSt3__117unsigned_integralEhEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE9load_nextITkNS4_17unsigned_integralEhEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEmEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEjEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEtEET_v Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE9load_nextITkNSt3__117unsigned_integralEhEET_v |
1016 | | |
1017 | | /** |
1018 | | * Stores the next block of bits into the underlying bitvector. |
1019 | | * No bounds checks are performed. Storing bit blocks that are not |
1020 | | * aligned at a byte-boundary in the underlying bitvector is |
1021 | | * currently not implemented. |
1022 | | */ |
1023 | | template <std::unsigned_integral BlockT> |
1024 | | requires(!is_const()) |
1025 | 0 | void store_next(BlockT block) { |
1026 | 0 | constexpr size_type block_size = sizeof(BlockT); |
1027 | 0 | constexpr size_type block_bits = block_size * 8; |
1028 | |
|
1029 | 0 | if constexpr(is_byte_aligned()) { |
1030 | 0 | auto sink = m_source.as_byte_span().subspan(write_bytepos()).template first<block_size>(); |
1031 | 0 | store_le(sink, block); |
1032 | 0 | } else { |
1033 | 0 | const size_type byte_pos = write_bytepos(); |
1034 | 0 | const size_type bits_to_store = std::min(block_bits, bits_to_write()); |
1035 | |
|
1036 | 0 | uint8_t& first_byte = m_source.as_byte_span()[byte_pos]; |
1037 | | |
1038 | | // Set the left-most bits in the first byte, leaving all others unchanged |
1039 | 0 | first_byte = (first_byte & uint8_t(0xFF >> m_unaligned_helper.bits_to_byte_alignment)) | |
1040 | 0 | uint8_t(block << m_unaligned_helper.padding_bits); |
1041 | | |
1042 | | // If more bits are provided, we store them in the remaining bytes. |
1043 | 0 | if(m_unaligned_helper.bits_to_byte_alignment < bits_to_store) { |
1044 | 0 | const auto remaining_bytes = |
1045 | 0 | m_source.as_byte_span().subspan(byte_pos + 1).template first<block_size>(); |
1046 | 0 | const BlockT padding_mask = ~(BlockT(-1) >> m_unaligned_helper.bits_to_byte_alignment); |
1047 | 0 | const BlockT new_bytes = |
1048 | 0 | (load_le(remaining_bytes) & padding_mask) | block >> m_unaligned_helper.bits_to_byte_alignment; |
1049 | 0 | store_le(remaining_bytes, new_bytes); |
1050 | 0 | } |
1051 | 0 | } |
1052 | |
|
1053 | 0 | m_write_bitpos += std::min(block_bits, bits_to_write()); |
1054 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE10store_nextITkNSt3__117unsigned_integralEmQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE10store_nextITkNSt3__117unsigned_integralEjQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE10store_nextITkNSt3__117unsigned_integralEtQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE10store_nextITkNSt3__117unsigned_integralEhQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE10store_nextITkNSt3__117unsigned_integralEmQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE10store_nextITkNSt3__117unsigned_integralEjQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE10store_nextITkNSt3__117unsigned_integralEtQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EE10store_nextITkNSt3__117unsigned_integralEhQntclL_ZNS_14bitvector_base16BitRangeOperator8is_constEvEEEEvT_ |
1055 | | |
1056 | | template <std::unsigned_integral BlockT> |
1057 | | requires(is_byte_aligned() && !is_const()) |
1058 | 0 | std::span<BlockT> span(size_type blocks) const { |
1059 | 0 | BOTAN_DEBUG_ASSERT(blocks == 0 || is_memory_aligned_to<BlockT>()); |
1060 | 0 | BOTAN_DEBUG_ASSERT(read_bytepos() % sizeof(BlockT) == 0); |
1061 | | // Intermittently casting to void* to avoid a compiler warning |
1062 | 0 | void* ptr = reinterpret_cast<void*>(m_source.as_byte_span().data() + read_bytepos()); |
1063 | 0 | return {reinterpret_cast<BlockT*>(ptr), blocks}; |
1064 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEmQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEntclL_ZNS9_8is_constEvEEEENS7_4spanIT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEjQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEntclL_ZNS9_8is_constEvEEEENS7_4spanIT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEtQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEntclL_ZNS9_8is_constEvEEEENS7_4spanIT_Lm18446744073709551615EEEm |
1065 | | |
1066 | | template <std::unsigned_integral BlockT> |
1067 | | requires(is_byte_aligned() && is_const()) |
1068 | 0 | std::span<const BlockT> span(size_type blocks) const { |
1069 | 0 | BOTAN_DEBUG_ASSERT(blocks == 0 || is_memory_aligned_to<BlockT>()); |
1070 | 0 | BOTAN_DEBUG_ASSERT(read_bytepos() % sizeof(BlockT) == 0); |
1071 | | // Intermittently casting to void* to avoid a compiler warning |
1072 | 0 | const void* ptr = reinterpret_cast<const void*>(m_source.as_byte_span().data() + read_bytepos()); |
1073 | 0 | return {reinterpret_cast<const BlockT*>(ptr), blocks}; |
1074 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEmQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSA_8is_constEvEEEENS8_4spanIKT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEjQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSA_8is_constEvEEEENS8_4spanIKT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE4spanITkNSt3__117unsigned_integralEtQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSA_8is_constEvEEEENS8_4spanIKT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE4spanITkNS4_17unsigned_integralEmQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSC_8is_constEvEEEENS4_4spanIKT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE4spanITkNS4_17unsigned_integralEjQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSC_8is_constEvEEEENS4_4spanIKT_Lm18446744073709551615EEEm Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE4spanITkNS4_17unsigned_integralEtQaaclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEclL_ZNSC_8is_constEvEEEENS4_4spanIKT_Lm18446744073709551615EEEm |
1075 | | |
1076 | | void advance(size_type bytes) |
1077 | | requires(is_byte_aligned()) |
1078 | 0 | { |
1079 | 0 | m_read_bitpos += bytes * 8; |
1080 | 0 | m_write_bitpos += bytes * 8; |
1081 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE7advanceEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE7advanceEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE7advanceEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEE |
1082 | | |
1083 | | template <std::unsigned_integral BlockT> |
1084 | | requires(is_byte_aligned()) |
1085 | 0 | size_t is_memory_aligned_to() const { |
1086 | 0 | const void* cptr = m_source.as_byte_span().data() + read_bytepos(); |
1087 | 0 | const void* ptr_before = cptr; |
1088 | | |
1089 | | // std::align takes `ptr` as a reference (!), i.e. `void*&` and |
1090 | | // uses it as an out-param. Though, `cptr` is const because this |
1091 | | // method is const-qualified, hence the const_cast<>. |
1092 | 0 | void* ptr = const_cast<void*>(cptr); |
1093 | 0 | size_t size = sizeof(BlockT); |
1094 | 0 | return ptr_before != nullptr && std::align(alignof(BlockT), size, ptr, size) == ptr_before; |
1095 | 0 | } Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EE20is_memory_aligned_toITkNSt3__117unsigned_integralEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEEEmv Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EE20is_memory_aligned_toITkNSt3__117unsigned_integralEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEEEmv Unexecuted instantiation: _ZNK5Botan14bitvector_baseINS_16secure_allocatorEE16BitRangeOperatorIKNS0_INSt3__19allocatorEEELNS2_17BitRangeAlignmentE0EE20is_memory_aligned_toITkNS4_17unsigned_integralEmQclL_ZNS_14bitvector_base16BitRangeOperator15is_byte_alignedEvEEEEmv |
1096 | | |
1097 | | private: |
1098 | 0 | size_type read_bytepos() const { return m_read_bitpos / 8; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::read_bytepos() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::read_bytepos() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::read_bytepos() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::read_bytepos() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::read_bytepos() const |
1099 | | |
1100 | 0 | size_type write_bytepos() const { return m_write_bitpos / 8; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>::write_bytepos() const Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>::write_bytepos() const |
1101 | | |
1102 | | private: |
1103 | | BitvectorT& m_source; |
1104 | | size_type m_start_bitoffset; |
1105 | | size_type m_bitlength; |
1106 | | |
1107 | | UnalignedDataHelper m_unaligned_helper; |
1108 | | |
1109 | | mutable size_type m_read_bitpos; |
1110 | | mutable size_type m_write_bitpos; |
1111 | | }; |
1112 | | |
1113 | | /** |
1114 | | * Helper struct for the low-level handling of blockwise operations |
1115 | | * |
1116 | | * This has two main code paths: Optimized for byte-aligned ranges that |
1117 | | * can simply be taken from memory as-is. And a generic implementation |
1118 | | * that must assemble blocks from unaligned bits before processing. |
1119 | | */ |
1120 | | template <typename FnT, typename... ParamTs> |
1121 | | requires detail::blockwise_processing_callback<FnT, ParamTs...> |
1122 | | class blockwise_processing_callback_trait { |
1123 | | public: |
1124 | | constexpr static bool needs_mask = detail::blockwise_processing_callback_with_mask<FnT, ParamTs...>; |
1125 | | constexpr static bool is_manipulator = detail::manipulating_blockwise_processing_callback<FnT, ParamTs...>; |
1126 | | constexpr static bool is_predicate = detail::predicate_blockwise_processing_callback<FnT, ParamTs...>; |
1127 | | static_assert(!is_manipulator || !is_predicate, "cannot be manipulator and predicate at the same time"); |
1128 | | |
1129 | | /** |
1130 | | * Applies @p fn to the blocks provided in @p blocks by simply reading from |
1131 | | * memory without re-arranging any bits across byte-boundaries. |
1132 | | */ |
1133 | | template <std::unsigned_integral... BlockTs> |
1134 | | requires(all_same_v<std::remove_cv_t<BlockTs>...> && sizeof...(BlockTs) == sizeof...(ParamTs)) |
1135 | 0 | constexpr static bool apply_on_full_blocks(FnT fn, std::span<BlockTs>... blocks) { |
1136 | 0 | constexpr size_type bits = sizeof(detail::first_t<BlockTs...>) * 8; |
1137 | 0 | const size_type iterations = detail::first(blocks...).size(); |
1138 | 0 | for(size_type i = 0; i < iterations; ++i) { |
1139 | | if constexpr(is_predicate) { |
1140 | | if(!apply(fn, bits, blocks[i]...)) { |
1141 | | return false; |
1142 | | } |
1143 | 0 | } else if constexpr(is_manipulator) { |
1144 | 0 | detail::first(blocks...)[i] = apply(fn, bits, blocks[i]...); |
1145 | 0 | } else { |
1146 | 0 | apply(fn, bits, blocks[i]...); |
1147 | 0 | } |
1148 | 0 | } |
1149 | 0 | return true; |
1150 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKmEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKjEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKtEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE20apply_on_full_blocksITpTkNS5_17unsigned_integralEJmKmEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSC_DpNS5_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE20apply_on_full_blocksITpTkNS5_17unsigned_integralEJjKjEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSC_DpNS5_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE20apply_on_full_blocksITpTkNS5_17unsigned_integralEJtKtEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSC_DpNS5_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJmKmEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSF_DpNSN_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJjKjEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSF_DpNSN_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJtKtEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSF_DpNSN_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE20apply_on_full_blocksITpTkNS9_17unsigned_integralEJmKmEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSA_DpNS9_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE20apply_on_full_blocksITpTkNS9_17unsigned_integralEJjKjEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSA_DpNS9_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE20apply_on_full_blocksITpTkNS9_17unsigned_integralEJtKtEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbSA_DpNS9_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKmEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKjEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE20apply_on_full_blocksITpTkNSt3__117unsigned_integralEJKtEQaa10all_same_vIDpu11__remove_cvITL1__EEeqsZTL1__sZTL0_0_EEbS5_DpNSC_4spanIT_Lm18446744073709551615EEE |
1151 | | |
1152 | | /** |
1153 | | * Applies @p fn to as many blocks as @p ops provide for the given type. |
1154 | | */ |
1155 | | template <std::unsigned_integral BlockT, typename... BitRangeOperatorTs> |
1156 | | requires(sizeof...(BitRangeOperatorTs) == sizeof...(ParamTs)) |
1157 | 0 | constexpr static bool apply_on_unaligned_blocks(FnT fn, BitRangeOperatorTs&... ops) { |
1158 | 0 | constexpr size_type block_bits = sizeof(BlockT) * 8; |
1159 | 0 | auto bits = detail::first(ops...).bits_to_read(); |
1160 | 0 | if(bits == 0) { |
1161 | 0 | return true; |
1162 | 0 | } |
1163 | | |
1164 | 0 | bits += block_bits; // avoid unsigned integer underflow in the following loop |
1165 | 0 | while(bits > block_bits * 2 - 8) { |
1166 | 0 | bits -= block_bits; |
1167 | | if constexpr(is_predicate) { |
1168 | | if(!apply(fn, bits, ops.template load_next<BlockT>()...)) { |
1169 | | return false; |
1170 | | } |
1171 | 0 | } else if constexpr(is_manipulator) { |
1172 | 0 | detail::first(ops...).store_next(apply(fn, bits, ops.template load_next<BlockT>()...)); |
1173 | 0 | } else { |
1174 | 0 | apply(fn, bits, ops.template load_next<BlockT>()...); |
1175 | 0 | } |
1176 | 0 | } |
1177 | 0 | return true; |
1178 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE25apply_on_unaligned_blocksITkNS5_17unsigned_integralEmJSD_SF_EQeqsZTL1_0_sZTL0_0_EEbSA_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE25apply_on_unaligned_blocksITkNS5_17unsigned_integralEjJSD_SF_EQeqsZTL1_0_sZTL0_0_EEbSA_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE25apply_on_unaligned_blocksITkNS5_17unsigned_integralEtJSD_SF_EQeqsZTL1_0_sZTL0_0_EEbSA_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE25apply_on_unaligned_blocksITkNS5_17unsigned_integralEhJSD_SF_EQeqsZTL1_0_sZTL0_0_EEbSA_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEhJS9_EQeqsZTL1_0_sZTL0_0_EEbS5_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE25apply_on_unaligned_blocksITkNS5_17unsigned_integralEhJSF_SH_EQeqsZTL1_0_sZTL0_0_EEbSC_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEmJSG_EQeqsZTL1_0_sZTL0_0_EEbSC_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEjJSG_EQeqsZTL1_0_sZTL0_0_EEbSC_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEtJSG_EQeqsZTL1_0_sZTL0_0_EEbSC_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEhJSG_EQeqsZTL1_0_sZTL0_0_EEbSC_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSC_17unsigned_integralEmJSG_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSC_17unsigned_integralEjJSG_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSC_17unsigned_integralEtJSG_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE25apply_on_unaligned_blocksITkNSC_17unsigned_integralEhJSG_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEhJSI_SK_EQeqsZTL1_0_sZTL0_0_EEbSF_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE25apply_on_unaligned_blocksITkNS8_17unsigned_integralEmJSG_SI_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE25apply_on_unaligned_blocksITkNS8_17unsigned_integralEjJSG_SI_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE25apply_on_unaligned_blocksITkNS8_17unsigned_integralEtJSG_SI_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE25apply_on_unaligned_blocksITkNS8_17unsigned_integralEhJSG_SI_EQeqsZTL1_0_sZTL0_0_EEbSD_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE25apply_on_unaligned_blocksITkNS9_17unsigned_integralEhJSD_SF_EQeqsZTL1_0_sZTL0_0_EEbSA_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE25apply_on_unaligned_blocksITkNSt3__117unsigned_integralEhJS9_EQeqsZTL1_0_sZTL0_0_EEbS5_DpRT0_ |
1179 | | |
1180 | | private: |
1181 | | template <std::unsigned_integral... BlockTs> |
1182 | | requires(all_same_v<BlockTs...>) |
1183 | 0 | constexpr static auto apply(FnT fn, size_type bits, BlockTs... blocks) { |
1184 | | if constexpr(needs_mask) { |
1185 | | return fn(blocks..., make_mask<detail::first_t<BlockTs...>>(bits)); |
1186 | 0 | } else { |
1187 | 0 | return fn(blocks...); |
1188 | 0 | } |
1189 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE5applyITpTkNS5_17unsigned_integralEJmmEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE5applyITpTkNS5_17unsigned_integralEJjjEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE5applyITpTkNS5_17unsigned_integralEJttEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEE5applyITpTkNS5_17unsigned_integralEJhhEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJmEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJjEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJtEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJhEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE5applyITpTkNS5_17unsigned_integralEJmmEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE5applyITpTkNS5_17unsigned_integralEJjjEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE5applyITpTkNS5_17unsigned_integralEJttEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEE5applyITpTkNS5_17unsigned_integralEJhhEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSt3__117unsigned_integralEJmEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSt3__117unsigned_integralEJjEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSt3__117unsigned_integralEJtEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSt3__117unsigned_integralEJhEQ10all_same_vIDpTL1__EEEDaSC_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSC_17unsigned_integralEJmEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSC_17unsigned_integralEJjEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSC_17unsigned_integralEJtEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEE5applyITpTkNSC_17unsigned_integralEJhEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE5applyITpTkNSt3__117unsigned_integralEJmmEQ10all_same_vIDpTL1__EEEDaSF_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE5applyITpTkNSt3__117unsigned_integralEJjjEQ10all_same_vIDpTL1__EEEDaSF_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE5applyITpTkNSt3__117unsigned_integralEJttEQ10all_same_vIDpTL1__EEEDaSF_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEE5applyITpTkNSt3__117unsigned_integralEJhhEQ10all_same_vIDpTL1__EEEDaSF_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE5applyITpTkNS8_17unsigned_integralEJmmEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE5applyITpTkNS8_17unsigned_integralEJjjEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE5applyITpTkNS8_17unsigned_integralEJttEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEE5applyITpTkNS8_17unsigned_integralEJhhEQ10all_same_vIDpTL1__EEEDaSD_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE5applyITpTkNS9_17unsigned_integralEJmmEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE5applyITpTkNS9_17unsigned_integralEJjjEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE5applyITpTkNS9_17unsigned_integralEJttEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEE5applyITpTkNS9_17unsigned_integralEJhhEQ10all_same_vIDpTL1__EEEDaSA_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJmEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJjEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJtEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35blockwise_processing_callback_traitIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEE5applyITpTkNSt3__117unsigned_integralEJhEQ10all_same_vIDpTL1__EEEDaS5_mDpT_ |
1190 | | }; |
1191 | | |
1192 | | /** |
1193 | | * Helper function of `full_range_operation` and `range_operation` that |
1194 | | * calls @p fn on a given aligned unsigned integer block as long as the |
1195 | | * underlying bit range contains enough bits to fill the block fully. |
1196 | | * |
1197 | | * This uses bare memory access to gain a speed up for aligned data. |
1198 | | */ |
1199 | | template <std::unsigned_integral BlockT, typename FnT, typename... BitRangeOperatorTs> |
1200 | | requires(detail::blockwise_processing_callback<FnT, BitRangeOperatorTs...> && |
1201 | | sizeof...(BitRangeOperatorTs) > 0) |
1202 | 0 | static bool _process_in_fully_aligned_blocks_of(FnT fn, BitRangeOperatorTs&... ops) { |
1203 | 0 | constexpr size_type block_bytes = sizeof(BlockT); |
1204 | 0 | constexpr size_type block_bits = block_bytes * 8; |
1205 | 0 | const size_type blocks = detail::first(ops...).bits_to_read() / block_bits; |
1206 | |
|
1207 | 0 | using callback_trait = blockwise_processing_callback_trait<FnT, BitRangeOperatorTs...>; |
1208 | 0 | const auto result = callback_trait::apply_on_full_blocks(fn, ops.template span<BlockT>(blocks)...); |
1209 | 0 | (ops.advance(block_bytes * blocks), ...); |
1210 | 0 | return result; |
1211 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEmZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEjZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEtZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEmZNS2_eOITkNS_12bitvectorishENS0_INS4_9allocatorEEEEERDaRKT_EUlTkNS4_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEjZNS2_eOITkNS_12bitvectorishENS0_INS4_9allocatorEEEEERDaRKT_EUlTkNS4_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEtZNS2_eOITkNS_12bitvectorishENS0_INS4_9allocatorEEEEERDaRKT_EUlTkNS4_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEmNS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUljjE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlttE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSH_IKS2_LSI_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEjNS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUljjE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlttE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSH_IKS2_LSI_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEtNS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUljjE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlttE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSH_IKS2_LSI_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEmZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNS4_17unsigned_integralES7_S7_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEjZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNS4_17unsigned_integralES7_S7_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEtZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNS4_17unsigned_integralES7_S7_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEmZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEjZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE35_process_in_fully_aligned_blocks_ofITkNSt3__117unsigned_integralEtZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EgtsZTL0_1_Li0EEEbT0_DpRT1_ |
1212 | | |
1213 | | /** |
1214 | | * Helper function of `full_range_operation` and `range_operation` that |
1215 | | * calls @p fn on a given unsigned integer block size as long as the |
1216 | | * underlying bit range contains enough bits to fill the block. |
1217 | | */ |
1218 | | template <std::unsigned_integral BlockT, typename FnT, typename... BitRangeOperatorTs> |
1219 | | requires(detail::blockwise_processing_callback<FnT, BitRangeOperatorTs...>) |
1220 | 0 | static bool _process_in_unaligned_blocks_of(FnT fn, BitRangeOperatorTs&... ops) { |
1221 | 0 | using callback_trait = blockwise_processing_callback_trait<FnT, BitRangeOperatorTs...>; |
1222 | 0 | return callback_trait::template apply_on_unaligned_blocks<BlockT>(fn, ops...); |
1223 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEmZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbS9_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEjZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbS9_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEtZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbS9_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbS9_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNS2_eOITkNS_12bitvectorishENS0_INS4_9allocatorEEEEERDaRKT_EUlTkNS4_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEmZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSB_EEET_mEUlSC_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEjZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSB_EEET_mEUlSC_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEtZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSB_EEET_mEUlSC_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSB_EEET_mEUlSC_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEmZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS8_EEEvmT_EUlTkNS4_17unsigned_integralESC_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEjZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS8_EEEvmT_EUlTkNS4_17unsigned_integralESC_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEtZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS8_EEEvmT_EUlTkNS4_17unsigned_integralESC_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS8_EEEvmT_EUlTkNS4_17unsigned_integralESC_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhNS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUljjE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlttE_ZNS6_ITkNS_12bitvectorishES2_EEvS8_SB_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSH_IKS2_LSI_0EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEmZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbSC_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEjZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbSC_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEtZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbSC_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNS4_8optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbSC_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNS4_17unsigned_integralES7_S7_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE31_process_in_unaligned_blocks_ofITkNSt3__117unsigned_integralEhZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQsr6detailE29blockwise_processing_callbackITL0_0_DpTL0_1_EEEbT0_DpRT1_ |
1224 | | |
1225 | | /** |
1226 | | * Apply @p fn to all bits in the ranges defined by @p ops. If more than |
1227 | | * one range operator is passed to @p ops, @p fn receives corresponding |
1228 | | * blocks of bits from each operator. Therefore, all @p ops have to define |
1229 | | * the exact same length of their underlying ranges. |
1230 | | * |
1231 | | * @p fn may return a bit block that will be stored into the _first_ bit |
1232 | | * range passed into @p ops. If @p fn returns a boolean, and its value is |
1233 | | * `false`, the range operation is cancelled and `false` is returned. |
1234 | | * |
1235 | | * The implementation ensures to pull bits in the largest bit blocks |
1236 | | * possible and reverts to smaller bit blocks only when needed. |
1237 | | */ |
1238 | | template <typename FnT, typename... BitRangeOperatorTs> |
1239 | | requires(detail::blockwise_processing_callback<FnT, BitRangeOperatorTs...> && |
1240 | | sizeof...(BitRangeOperatorTs) > 0) |
1241 | 0 | static bool range_operation(FnT fn, BitRangeOperatorTs... ops) { |
1242 | 0 | BOTAN_ASSERT(has_equal_lengths(ops...), "all BitRangeOperators have the same length"); |
1243 | |
|
1244 | 0 | if constexpr((BitRangeOperatorTs::is_byte_aligned() && ...)) { |
1245 | | // Note: At the moment we can assume that this will always be used |
1246 | | // on the _entire_ bitvector. Therefore, we can safely assume |
1247 | | // that the bitvectors' underlying buffers are properly aligned. |
1248 | | // If this assumption changes, we need to add further handling |
1249 | | // to process a byte padding at the beginning of the bitvector |
1250 | | // until a memory alignment boundary is reached. |
1251 | 0 | const bool alignment = (ops.template is_memory_aligned_to<uint64_t>() && ...); |
1252 | 0 | BOTAN_ASSERT_NOMSG(alignment); |
1253 | |
|
1254 | 0 | return _process_in_fully_aligned_blocks_of<uint64_t>(fn, ops...) && |
1255 | 0 | _process_in_fully_aligned_blocks_of<uint32_t>(fn, ops...) && |
1256 | 0 | _process_in_fully_aligned_blocks_of<uint16_t>(fn, ops...) && |
1257 | 0 | _process_in_unaligned_blocks_of<uint8_t>(fn, ops...); |
1258 | 0 | } else { |
1259 | 0 | return _process_in_unaligned_blocks_of<uint64_t>(fn, ops...) && |
1260 | 0 | _process_in_unaligned_blocks_of<uint32_t>(fn, ops...) && |
1261 | 0 | _process_in_unaligned_blocks_of<uint16_t>(fn, ops...) && |
1262 | 0 | _process_in_unaligned_blocks_of<uint8_t>(fn, ops...); |
1263 | 0 | } |
1264 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNKS2_9subvectorITkNS_12bitvectorishES2_EEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_1EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS8_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNKS2_14hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS4_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSD_IKS7_LSE_0EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS9_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNKS2_9subvectorImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbSA_EEET_mEUlSB_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE1EEEEQaasr6detailE29blockwise_processing_callbackIS7_DpTL0_0_EgtsZTL0_0_Li0EEEbSB_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNS2_17subvector_replaceImQaasr3stdE17unsigned_integralINS_6detail19wrapped_type_helperIu14__remove_cvrefITL0__EE4typeEEntsr3stdE7same_asIbS7_EEEvmT_EUlTkNSt3__117unsigned_integralESB_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE1EEEEQaasr6detailE29blockwise_processing_callbackIS7_DpTL0_0_EgtsZTL0_0_Li0EEEbSB_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationINS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSG_IKS2_LSH_0EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS8_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNKS2_9subvectorITkNS_12bitvectorishENS_6StrongIS2_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEEEUlT_T0_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSE_IKS2_LSF_1EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbSB_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JNS2_16BitRangeOperatorIS2_LNS2_17BitRangeAlignmentE0EEENSB_IKS2_LSC_0EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS6_DpT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE15range_operationIZNKS2_22has_odd_hamming_weightEvEUlT_E_JNS2_16BitRangeOperatorIKS2_LNS2_17BitRangeAlignmentE0EEEEQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EgtsZTL0_0_Li0EEEbS4_DpT0_ |
1265 | | |
1266 | | /** |
1267 | | * Apply @p fn to all bit blocks in the bitvector(s). |
1268 | | */ |
1269 | | template <typename FnT, typename... BitvectorTs> |
1270 | | requires(detail::blockwise_processing_callback<FnT, BitvectorTs...> && |
1271 | | (is_bitvector_v<std::remove_cvref_t<BitvectorTs>> && ... && true)) |
1272 | 0 | static bool full_range_operation(FnT&& fn, BitvectorTs&... bitvecs) { |
1273 | 0 | BOTAN_ASSERT(has_equal_lengths(bitvecs...), "all bitvectors have the same length"); |
1274 | 0 | return range_operation(std::forward<FnT>(fn), BitRangeOperator<BitvectorTs>(bitvecs)...); |
1275 | 0 | } Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE20full_range_operationIZNKS2_14hamming_weightEvEUlT_E_JKS2_EQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EfRaa14is_bitvector_vIu14__remove_cvrefIS8_EELb1EEEbOS4_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE20full_range_operationIZNS2_eOITkNS_12bitvectorishENS0_INSt3__19allocatorEEEEERDaRKT_EUlTkNS5_17unsigned_integralES9_S9_E_JS2_KS7_EQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EfRaa14is_bitvector_vIu14__remove_cvrefISF_EELb1EEEbOS9_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE20full_range_operationIRNS_10overloadedIJZNS2_18ct_conditional_xorITkNS_12bitvectorishES2_EEvNS_2CT6ChoiceERKT_EUlmmE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUljjE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlttE_ZNS5_ITkNS_12bitvectorishES2_EEvS7_SA_EUlhhE_EEEJS2_KS2_EQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EfRaa14is_bitvector_vIu14__remove_cvrefISJ_EELb1EEEbOS8_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE20full_range_operationIZNS2_aNITkNS_12bitvectorishES2_EERDaRKT_EUlTkNSt3__117unsigned_integralES6_S6_E_JS2_KS2_EQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EfRaa14is_bitvector_vIu14__remove_cvrefISD_EELb1EEEbOS6_DpRT0_ Unexecuted instantiation: _ZN5Botan14bitvector_baseINS_16secure_allocatorEE20full_range_operationIZNKS2_22has_odd_hamming_weightEvEUlT_E_JKS2_EQaasr6detailE29blockwise_processing_callbackITL0__DpTL0_0_EfRaa14is_bitvector_vIu14__remove_cvrefIS8_EELb1EEEbOS4_DpRT0_ |
1276 | | |
1277 | | template <typename SomeT, typename... SomeTs> |
1278 | 0 | static bool has_equal_lengths(const SomeT& v, const SomeTs&... vs) { |
1279 | 0 | return ((v.size() == vs.size()) && ... && true); |
1280 | 0 | } Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1> >(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>>(Botan::bitvector_base<Botan::secure_allocator> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>, Botan::bitvector_base<std::__1::allocator> >(Botan::bitvector_base<Botan::secure_allocator> const&, Botan::bitvector_base<std::__1::allocator> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> >(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<std::__1::allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1>>(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)1> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>, Botan::bitvector_base<Botan::secure_allocator> >(Botan::bitvector_base<Botan::secure_allocator> const&, Botan::bitvector_base<Botan::secure_allocator> const&) Unexecuted instantiation: bool Botan::bitvector_base<Botan::secure_allocator>::has_equal_lengths<Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0>, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> >(Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator>, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&, Botan::bitvector_base<Botan::secure_allocator>::BitRangeOperator<Botan::bitvector_base<Botan::secure_allocator> const, (Botan::bitvector_base<Botan::secure_allocator>::BitRangeAlignment)0> const&) |
1281 | | |
1282 | | template <std::unsigned_integral T> |
1283 | | static constexpr T make_mask(size_type bits) { |
1284 | | const bool max = bits >= sizeof(T) * 8; |
1285 | | bits &= T(max - 1); |
1286 | | return (T(!max) << bits) - 1; |
1287 | | } |
1288 | | |
1289 | 0 | auto as_byte_span() { return std::span{m_blocks.data(), m_blocks.size() * sizeof(block_type)}; } |
1290 | | |
1291 | 0 | auto as_byte_span() const { return std::span{m_blocks.data(), m_blocks.size() * sizeof(block_type)}; } Unexecuted instantiation: Botan::bitvector_base<Botan::secure_allocator>::as_byte_span() const Unexecuted instantiation: Botan::bitvector_base<std::__1::allocator>::as_byte_span() const |
1292 | | |
1293 | | private: |
1294 | | size_type m_bits; |
1295 | | std::vector<block_type, allocator_type> m_blocks; |
1296 | | }; |
1297 | | |
1298 | | using secure_bitvector = bitvector_base<secure_allocator>; |
1299 | | using bitvector = bitvector_base<std::allocator>; |
1300 | | |
1301 | | namespace detail { |
1302 | | |
1303 | | /** |
1304 | | * If one of the allocators is a Botan::secure_allocator, this will always |
1305 | | * prefer it. Otherwise, the allocator of @p lhs will be used as a default. |
1306 | | */ |
1307 | | template <bitvectorish T1, bitvectorish T2> |
1308 | 0 | constexpr auto copy_lhs_allocator_aware(const T1& lhs, const T2&) { |
1309 | 0 | constexpr bool needs_secure_allocator = |
1310 | 0 | strong_type_wrapped_type<T1>::uses_secure_allocator || strong_type_wrapped_type<T2>::uses_secure_allocator; |
1311 | |
|
1312 | 0 | if constexpr(needs_secure_allocator) { |
1313 | 0 | return lhs.template as<secure_bitvector>(); |
1314 | | } else { |
1315 | | return lhs.template as<bitvector>(); |
1316 | | } |
1317 | 0 | } |
1318 | | |
1319 | | } // namespace detail |
1320 | | |
1321 | | template <bitvectorish T1, bitvectorish T2> |
1322 | | auto operator|(const T1& lhs, const T2& rhs) { |
1323 | | auto res = detail::copy_lhs_allocator_aware(lhs, rhs); |
1324 | | res |= rhs; |
1325 | | return res; |
1326 | | } |
1327 | | |
1328 | | template <bitvectorish T1, bitvectorish T2> |
1329 | | auto operator&(const T1& lhs, const T2& rhs) { |
1330 | | auto res = detail::copy_lhs_allocator_aware(lhs, rhs); |
1331 | | res &= rhs; |
1332 | | return res; |
1333 | | } |
1334 | | |
1335 | | template <bitvectorish T1, bitvectorish T2> |
1336 | 0 | auto operator^(const T1& lhs, const T2& rhs) { |
1337 | 0 | auto res = detail::copy_lhs_allocator_aware(lhs, rhs); |
1338 | 0 | res ^= rhs; |
1339 | 0 | return res; |
1340 | 0 | } |
1341 | | |
1342 | | template <bitvectorish T1, bitvectorish T2> |
1343 | | bool operator==(const T1& lhs, const T2& rhs) { |
1344 | | return lhs.equals_vartime(rhs); |
1345 | | } |
1346 | | |
1347 | | template <bitvectorish T1, bitvectorish T2> |
1348 | | bool operator!=(const T1& lhs, const T2& rhs) { |
1349 | | return lhs.equals_vartime(rhs); |
1350 | | } |
1351 | | |
1352 | | namespace detail { |
1353 | | |
1354 | | /** |
1355 | | * A Strong<> adapter for arbitrarily large bitvectors |
1356 | | */ |
1357 | | template <concepts::container T> |
1358 | | requires is_bitvector_v<T> |
1359 | | class Strong_Adapter<T> : public Container_Strong_Adapter_Base<T> { |
1360 | | public: |
1361 | | using size_type = typename T::size_type; |
1362 | | |
1363 | | public: |
1364 | | using Container_Strong_Adapter_Base<T>::Container_Strong_Adapter_Base; |
1365 | | |
1366 | 0 | auto at(size_type i) const { return this->get().at(i); } |
1367 | | |
1368 | 0 | auto at(size_type i) { return this->get().at(i); } |
1369 | | |
1370 | | auto set(size_type i) { return this->get().set(i); } |
1371 | | |
1372 | | auto unset(size_type i) { return this->get().unset(i); } |
1373 | | |
1374 | | auto flip(size_type i) { return this->get().flip(i); } |
1375 | | |
1376 | | auto flip() { return this->get().flip(); } |
1377 | | |
1378 | | template <typename OutT> |
1379 | 0 | auto as() const { |
1380 | 0 | return this->get().template as<OutT>(); |
1381 | 0 | } |
1382 | | |
1383 | | template <bitvectorish OutT = T> |
1384 | 0 | auto subvector(size_type pos, std::optional<size_type> length = std::nullopt) const { |
1385 | 0 | return this->get().template subvector<OutT>(pos, length); |
1386 | 0 | } Unexecuted instantiation: _ZNK5Botan6detail14Strong_AdapterINS_14bitvector_baseINS_16secure_allocatorEEEE9subvectorITkNS_12bitvectorishENS_6StrongIS4_NS_13CmceCodeWord_EJEEEEEDamNSt3__18optionalImEE Unexecuted instantiation: _ZNK5Botan6detail14Strong_AdapterINS_14bitvector_baseINS_16secure_allocatorEEEE9subvectorITkNS_12bitvectorishES4_EEDamNSt3__18optionalImEE |
1387 | | |
1388 | | template <typename OutT> |
1389 | | requires(std::unsigned_integral<strong_type_wrapped_type<OutT>> && |
1390 | | !std::same_as<bool, strong_type_wrapped_type<OutT>>) |
1391 | 0 | auto subvector(size_type pos) const { |
1392 | 0 | return this->get().template subvector<OutT>(pos); |
1393 | 0 | } |
1394 | | |
1395 | | template <typename InT> |
1396 | | requires(std::unsigned_integral<strong_type_wrapped_type<InT>> && !std::same_as<bool, InT>) |
1397 | 0 | void subvector_replace(size_type pos, InT value) { |
1398 | 0 | return this->get().subvector_replace(pos, value); |
1399 | 0 | } |
1400 | | |
1401 | | template <bitvectorish OtherT> |
1402 | 0 | auto equals(const OtherT& other) const { |
1403 | 0 | return this->get().equals(other); |
1404 | 0 | } |
1405 | | |
1406 | 0 | auto push_back(bool b) { return this->get().push_back(b); } |
1407 | | |
1408 | | auto pop_back() { return this->get().pop_back(); } |
1409 | | |
1410 | | auto front() const { return this->get().front(); } |
1411 | | |
1412 | | auto front() { return this->get().front(); } |
1413 | | |
1414 | | auto back() const { return this->get().back(); } |
1415 | | |
1416 | | auto back() { return this->get().back(); } |
1417 | | |
1418 | | auto any_vartime() const { return this->get().any_vartime(); } |
1419 | | |
1420 | | auto all_vartime() const { return this->get().all_vartime(); } |
1421 | | |
1422 | | auto none_vartime() const { return this->get().none_vartime(); } |
1423 | | |
1424 | | auto has_odd_hamming_weight() const { return this->get().has_odd_hamming_weight(); } |
1425 | | |
1426 | 0 | auto hamming_weight() const { return this->get().hamming_weight(); } |
1427 | | |
1428 | | auto from_bytes(std::span<const uint8_t> bytes, std::optional<size_type> bits = std::nullopt) { |
1429 | | return this->get().from_bytes(bytes, bits); |
1430 | | } |
1431 | | |
1432 | | template <typename OutT = T> |
1433 | | auto to_bytes() const { |
1434 | | return this->get().template to_bytes<OutT>(); |
1435 | | } |
1436 | | |
1437 | 0 | auto to_bytes(std::span<uint8_t> out) const { return this->get().to_bytes(out); } |
1438 | | |
1439 | | auto to_string() const { return this->get().to_string(); } |
1440 | | |
1441 | | auto capacity() const { return this->get().capacity(); } |
1442 | | |
1443 | | auto reserve(size_type n) { return this->get().reserve(n); } |
1444 | | |
1445 | 0 | constexpr void _const_time_poison() const { this->get()._const_time_poison(); } |
1446 | | |
1447 | 0 | constexpr void _const_time_unpoison() const { this->get()._const_time_unpoison(); } |
1448 | | }; |
1449 | | |
1450 | | } // namespace detail |
1451 | | |
1452 | | } // namespace Botan |
1453 | | |
1454 | | #endif |