Coverage Report

Created: 2023-02-22 06:14

/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