Botan 3.0.0
Crypto and TLS for C&
stl_util.h
Go to the documentation of this file.
1/*
2* STL Utility Functions
3* (C) 1999-2007 Jack Lloyd
4* (C) 2015 Simon Warta (Kullo GmbH)
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#ifndef BOTAN_STL_UTIL_H_
10#define BOTAN_STL_UTIL_H_
11
12#include <vector>
13#include <variant>
14#include <string>
15#include <map>
16#include <set>
17#include <span>
18#include <tuple>
19
20#include <botan/secmem.h>
21
22namespace Botan {
23
24inline std::vector<uint8_t> to_byte_vector(std::string_view s)
25 {
26 return std::vector<uint8_t>(s.cbegin(), s.cend());
27 }
28
29inline std::string to_string(const secure_vector<uint8_t> &bytes)
30 {
31 return std::string(bytes.cbegin(), bytes.cend());
32 }
33
34/**
35* Return the keys of a map as a std::set
36*/
37template<typename K, typename V>
38std::set<K> map_keys_as_set(const std::map<K, V>& kv)
39 {
40 std::set<K> s;
41 for(auto&& i : kv)
42 {
43 s.insert(i.first);
44 }
45 return s;
46 }
47
48/**
49* Return the keys of a multimap as a std::set
50*/
51template<typename K, typename V>
52std::set<K> map_keys_as_set(const std::multimap<K, V>& kv)
53 {
54 std::set<K> s;
55 for(auto&& i : kv)
56 {
57 s.insert(i.first);
58 }
59 return s;
60 }
61
62/*
63* Searching through a std::map
64* @param mapping the map to search
65* @param key is what to look for
66* @param null_result is the value to return if key is not in mapping
67* @return mapping[key] or null_result
68*/
69template<typename K, typename V>
70inline V search_map(const std::map<K, V>& mapping,
71 const K& key,
72 const V& null_result = V())
73 {
74 auto i = mapping.find(key);
75 if(i == mapping.end())
76 return null_result;
77 return i->second;
78 }
79
80template<typename K, typename V, typename R>
81inline R search_map(const std::map<K, V>& mapping, const K& key,
82 const R& null_result, const R& found_result)
83 {
84 auto i = mapping.find(key);
85 if(i == mapping.end())
86 return null_result;
87 return found_result;
88 }
89
90/*
91* Insert a key/value pair into a multimap
92*/
93template<typename K, typename V>
94void multimap_insert(std::multimap<K, V>& multimap,
95 const K& key, const V& value)
96 {
97 multimap.insert(std::make_pair(key, value));
98 }
99
100/**
101* Existence check for values
102*/
103template<typename T, typename OT>
104bool value_exists(const std::vector<T>& vec,
105 const OT& val)
106 {
107 for(size_t i = 0; i != vec.size(); ++i)
108 if(vec[i] == val)
109 return true;
110 return false;
111 }
112
113template<typename T, typename Pred>
114void map_remove_if(Pred pred, T& assoc)
115 {
116 auto i = assoc.begin();
117 while(i != assoc.end())
118 {
119 if(pred(i->first))
120 assoc.erase(i++);
121 else
122 i++;
123 }
124 }
125
126/**
127 * Helper class to ease unmarshalling of concatenated fixed-length values
128 */
130 {
131 public:
132 BufferSlicer(std::span<const uint8_t> buffer) : m_remaining(buffer)
133 {}
134
135 template <typename ContainerT>
136 auto take_as(const size_t count)
137 {
138 const auto result = take(count);
139 return ContainerT(result.begin(), result.end());
140 }
141
142 auto take_vector(const size_t count) { return take_as<std::vector<uint8_t>>(count); }
143 auto take_secure_vector(const size_t count) { return take_as<secure_vector<uint8_t>>(count); }
144
145 std::span<const uint8_t> take(const size_t count)
146 {
147 BOTAN_STATE_CHECK(remaining() >= count);
148 auto result = m_remaining.first(count);
149 m_remaining = m_remaining.subspan(count);
150 return result;
151 }
152
153 void copy_into(std::span<uint8_t> sink)
154 {
155 const auto data = take(sink.size());
156 std::copy(data.begin(), data.end(), sink.begin());
157 }
158
159 void skip(const size_t count) { take(count); }
160
161 size_t remaining() const { return m_remaining.size(); }
162 bool empty() const { return m_remaining.empty(); }
163
164 private:
165 std::span<const uint8_t> m_remaining;
166 };
167
168/**
169 * Concatenate an arbitrary number of buffers.
170 * @return the concatenation of \p buffers as the container type of the first buffer
171 */
172template <typename... Ts>
173decltype(auto) concat(Ts&& ...buffers)
174 {
175 static_assert(sizeof...(buffers) > 0, "concat requires at least one buffer");
176
177 using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>;
178 result_t result;
179 result.reserve((buffers.size() + ...));
180 (result.insert(result.end(), buffers.begin(), buffers.end()), ...);
181 return result;
182 }
183
184/**
185 * Concatenate an arbitrary number of buffers and define the output buffer
186 * type as a mandatory template parameter.
187 * @return the concatenation of \p buffers as the user-defined container type
188 */
189template <typename ResultT, typename... Ts>
190ResultT concat_as(Ts&& ...buffers)
191 {
192 return concat(ResultT(), std::forward<Ts>(buffers)...);
193 }
194
195template<typename... Alts, typename... Ts>
196constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
197 return (std::holds_alternative<Alts>(v) || ...);
198}
199
200template<typename GeneralVariantT, typename SpecialT>
201constexpr bool is_generalizable_to(const SpecialT&) noexcept
202 {
203 return std::is_constructible_v<GeneralVariantT, SpecialT>;
204 }
205
206template<typename GeneralVariantT, typename... SpecialTs>
207constexpr bool is_generalizable_to(const std::variant<SpecialTs...>&) noexcept
208 {
209 return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
210 }
211
212/**
213 * @brief Converts a given variant into another variant-ish whose type states
214 * are a super set of the given variant.
215 *
216 * This is useful to convert restricted variant types into more general
217 * variants types.
218 */
219template<typename GeneralVariantT, typename SpecialT>
220constexpr GeneralVariantT generalize_to(SpecialT&& specific) noexcept
221 {
222 static_assert(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>,
223 "Desired general type must be implicitly constructible by the specific type");
224 return std::forward<SpecialT>(specific);
225 }
226
227/**
228 * @brief Converts a given variant into another variant-ish whose type states
229 * are a super set of the given variant.
230 *
231 * This is useful to convert restricted variant types into more general
232 * variants types.
233 */
234template<typename GeneralVariantT, typename... SpecialTs>
235constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) noexcept
236 {
237 static_assert(is_generalizable_to<GeneralVariantT>(specific),
238 "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
239 return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
240 }
241
242// This is a helper utility to emulate pattern matching with std::visit.
243// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
244template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
245// explicit deduction guide (not needed as of C++20)
246template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
247
248}
249
250#endif
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:48
auto take_secure_vector(const size_t count)
Definition: stl_util.h:143
size_t remaining() const
Definition: stl_util.h:161
void skip(const size_t count)
Definition: stl_util.h:159
auto take_vector(const size_t count)
Definition: stl_util.h:142
void copy_into(std::span< uint8_t > sink)
Definition: stl_util.h:153
BufferSlicer(std::span< const uint8_t > buffer)
Definition: stl_util.h:132
auto take_as(const size_t count)
Definition: stl_util.h:136
bool empty() const
Definition: stl_util.h:162
std::span< const uint8_t > take(const size_t count)
Definition: stl_util.h:145
int(* final)(unsigned char *, CTX *)
FE_25519 T
Definition: ge.cpp:36
Definition: alg_id.cpp:12
constexpr GeneralVariantT generalize_to(SpecialT &&specific) noexcept
Converts a given variant into another variant-ish whose type states are a super set of the given vari...
Definition: stl_util.h:220
void map_remove_if(Pred pred, T &assoc)
Definition: stl_util.h:114
std::vector< uint8_t > to_byte_vector(std::string_view s)
Definition: stl_util.h:24
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition: stl_util.h:196
std::set< K > map_keys_as_set(const std::map< K, V > &kv)
Definition: stl_util.h:38
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
Definition: stl_util.h:70
void multimap_insert(std::multimap< K, V > &multimap, const K &key, const V &value)
Definition: stl_util.h:94
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition: stl_util.h:104
constexpr bool is_generalizable_to(const SpecialT &) noexcept
Definition: stl_util.h:201
decltype(auto) concat(Ts &&...buffers)
Definition: stl_util.h:173
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition: exceptn.cpp:12
ResultT concat_as(Ts &&...buffers)
Definition: stl_util.h:190
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64