/src/botan/build/include/botan/internal/stl_util.h
Line | Count | Source (jump to first uncovered line) |
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 <tuple> |
18 | | |
19 | | #include <botan/secmem.h> |
20 | | |
21 | | namespace Botan { |
22 | | |
23 | | inline std::vector<uint8_t> to_byte_vector(const std::string& s) |
24 | 0 | { |
25 | 0 | return std::vector<uint8_t>(s.cbegin(), s.cend()); |
26 | 0 | } |
27 | | |
28 | | inline std::string to_string(const secure_vector<uint8_t> &bytes) |
29 | 0 | { |
30 | 0 | return std::string(bytes.cbegin(), bytes.cend()); |
31 | 0 | } |
32 | | |
33 | | /** |
34 | | * Return the keys of a map as a std::set |
35 | | */ |
36 | | template<typename K, typename V> |
37 | | std::set<K> map_keys_as_set(const std::map<K, V>& kv) |
38 | | { |
39 | | std::set<K> s; |
40 | | for(auto&& i : kv) |
41 | | { |
42 | | s.insert(i.first); |
43 | | } |
44 | | return s; |
45 | | } |
46 | | |
47 | | /** |
48 | | * Return the keys of a multimap as a std::set |
49 | | */ |
50 | | template<typename K, typename V> |
51 | | std::set<K> map_keys_as_set(const std::multimap<K, V>& kv) |
52 | | { |
53 | | std::set<K> s; |
54 | | for(auto&& i : kv) |
55 | | { |
56 | | s.insert(i.first); |
57 | | } |
58 | | return s; |
59 | | } |
60 | | |
61 | | /* |
62 | | * Searching through a std::map |
63 | | * @param mapping the map to search |
64 | | * @param key is what to look for |
65 | | * @param null_result is the value to return if key is not in mapping |
66 | | * @return mapping[key] or null_result |
67 | | */ |
68 | | template<typename K, typename V> |
69 | | inline V search_map(const std::map<K, V>& mapping, |
70 | | const K& key, |
71 | | const V& null_result = V()) |
72 | | { |
73 | | auto i = mapping.find(key); |
74 | | if(i == mapping.end()) |
75 | | return null_result; |
76 | | return i->second; |
77 | | } |
78 | | |
79 | | template<typename K, typename V, typename R> |
80 | | inline R search_map(const std::map<K, V>& mapping, const K& key, |
81 | | const R& null_result, const R& found_result) |
82 | | { |
83 | | auto i = mapping.find(key); |
84 | | if(i == mapping.end()) |
85 | | return null_result; |
86 | | return found_result; |
87 | | } |
88 | | |
89 | | /* |
90 | | * Insert a key/value pair into a multimap |
91 | | */ |
92 | | template<typename K, typename V> |
93 | | void multimap_insert(std::multimap<K, V>& multimap, |
94 | | const K& key, const V& value) |
95 | | { |
96 | | multimap.insert(std::make_pair(key, value)); |
97 | | } |
98 | | |
99 | | /** |
100 | | * Existence check for values |
101 | | */ |
102 | | template<typename T> |
103 | | bool value_exists(const std::vector<T>& vec, |
104 | | const T& val) |
105 | | { |
106 | | for(size_t i = 0; i != vec.size(); ++i) |
107 | | if(vec[i] == val) |
108 | | return true; |
109 | | return false; |
110 | | } |
111 | | |
112 | | template<typename T, typename Pred> |
113 | | void map_remove_if(Pred pred, T& assoc) |
114 | | { |
115 | | auto i = assoc.begin(); |
116 | | while(i != assoc.end()) |
117 | | { |
118 | | if(pred(i->first)) |
119 | | assoc.erase(i++); |
120 | | else |
121 | | i++; |
122 | | } |
123 | | } |
124 | | |
125 | | /** |
126 | | * Concatenate an arbitrary number of buffers. |
127 | | * @return the concatenation of \p buffers as the container type of the first buffer |
128 | | */ |
129 | | template <typename... Ts> |
130 | | decltype(auto) concat(Ts&& ...buffers) |
131 | | { |
132 | | static_assert(sizeof...(buffers) > 0, "concat requires at least one buffer"); |
133 | | |
134 | | using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>; |
135 | | result_t result; |
136 | | result.reserve((buffers.size() + ...)); |
137 | | (result.insert(result.end(), buffers.begin(), buffers.end()), ...); |
138 | | return result; |
139 | | } |
140 | | |
141 | | /** |
142 | | * Concatenate an arbitrary number of buffers and define the output buffer |
143 | | * type as a mandatory template parameter. |
144 | | * @return the concatenation of \p buffers as the user-defined container type |
145 | | */ |
146 | | template <typename ResultT, typename... Ts> |
147 | | ResultT concat_as(Ts&& ...buffers) |
148 | | { |
149 | | return concat(ResultT(), std::forward<Ts>(buffers)...); |
150 | | } |
151 | | |
152 | | template<typename... Alts, typename... Ts> |
153 | | constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept { |
154 | | return (std::holds_alternative<Alts>(v) || ...); |
155 | | } |
156 | | |
157 | | template<typename GeneralVariantT, typename SpecialT> |
158 | | constexpr bool is_generalizable_to(const SpecialT&) noexcept |
159 | | { |
160 | | return std::is_constructible_v<GeneralVariantT, SpecialT>; |
161 | | } |
162 | | |
163 | | template<typename GeneralVariantT, typename... SpecialTs> |
164 | | constexpr bool is_generalizable_to(const std::variant<SpecialTs...>&) noexcept |
165 | | { |
166 | | return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...); |
167 | | } |
168 | | |
169 | | /** |
170 | | * @brief Converts a given variant into another variant-ish whose type states |
171 | | * are a super set of the given variant. |
172 | | * |
173 | | * This is useful to convert restricted variant types into more general |
174 | | * variants types. |
175 | | */ |
176 | | template<typename GeneralVariantT, typename SpecialT> |
177 | | constexpr GeneralVariantT generalize_to(SpecialT&& specific) noexcept |
178 | | { |
179 | | static_assert(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>, |
180 | | "Desired general type must be implicitly constructible by the specific type"); |
181 | | return std::forward<SpecialT>(specific); |
182 | | } |
183 | | |
184 | | /** |
185 | | * @brief Converts a given variant into another variant-ish whose type states |
186 | | * are a super set of the given variant. |
187 | | * |
188 | | * This is useful to convert restricted variant types into more general |
189 | | * variants types. |
190 | | */ |
191 | | template<typename GeneralVariantT, typename... SpecialTs> |
192 | | constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) noexcept |
193 | | { |
194 | | static_assert(is_generalizable_to<GeneralVariantT>(specific), |
195 | | "Desired general type must be implicitly constructible by all types of the specialized std::variant<>"); |
196 | | return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific)); |
197 | | } |
198 | | |
199 | | // This is a helper utility to emulate pattern matching with std::visit. |
200 | | // See https://en.cppreference.com/w/cpp/utility/variant/visit for more info. |
201 | | template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; |
202 | | // explicit deduction guide (not needed as of C++20) |
203 | | template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; |
204 | | |
205 | | } |
206 | | |
207 | | #endif |