• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5080663405

25 May 2023 02:18PM UTC coverage: 91.675% (-0.01%) from 91.688%
5080663405

Pull #3549

github

Pull Request #3549: SPHINCS+

78519 of 85649 relevant lines covered (91.68%)

12135443.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.08
/src/lib/utils/stl_util.h
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
#include <botan/concepts.h>
22
#include <botan/strong_type.h>
23

24
namespace Botan {
25

26
inline std::vector<uint8_t> to_byte_vector(std::string_view s)
631✔
27
   {
28
   return std::vector<uint8_t>(s.cbegin(), s.cend());
631✔
29
   }
30

31
inline std::string to_string(const secure_vector<uint8_t>& bytes)
32
   {
33
   return std::string(bytes.cbegin(), bytes.cend());
34
   }
35

36
/**
37
* Return the keys of a map as a std::set
38
*/
39
template<typename K, typename V>
40
std::set<K> map_keys_as_set(const std::map<K, V>& kv)
×
41
   {
42
   std::set<K> s;
×
43
   for(auto&& i : kv)
×
44
      {
45
      s.insert(i.first);
×
46
      }
47
   return s;
×
48
   }
×
49

50
/**
51
* Return the keys of a multimap as a std::set
52
*/
53
template<typename K, typename V>
54
std::set<K> map_keys_as_set(const std::multimap<K, V>& kv)
×
55
   {
56
   std::set<K> s;
×
57
   for(auto&& i : kv)
×
58
      {
59
      s.insert(i.first);
×
60
      }
61
   return s;
×
62
   }
×
63

64
/*
65
* Searching through a std::map
66
* @param mapping the map to search
67
* @param key is what to look for
68
* @param null_result is the value to return if key is not in mapping
69
* @return mapping[key] or null_result
70
*/
71
template<typename K, typename V>
72
inline V search_map(const std::map<K, V>& mapping,
17✔
73
                    const K& key,
74
                    const V& null_result = V())
75
   {
76
   auto i = mapping.find(key);
17✔
77
   if(i == mapping.end())
17✔
78
      { return null_result; }
17✔
79
   return i->second;
16✔
80
   }
81

82
template<typename K, typename V, typename R>
83
inline R search_map(const std::map<K, V>& mapping, const K& key,
84
                    const R& null_result, const R& found_result)
85
   {
86
   auto i = mapping.find(key);
87
   if(i == mapping.end())
88
      { return null_result; }
89
   return found_result;
90
   }
91

92
/*
93
* Insert a key/value pair into a multimap
94
*/
95
template<typename K, typename V>
96
void multimap_insert(std::multimap<K, V>& multimap,
591,649✔
97
                     const K& key, const V& value)
98
   {
99
   multimap.insert(std::make_pair(key, value));
591,649✔
100
   }
591,649✔
101

102
/**
103
* Existence check for values
104
*/
105
template<typename T, typename OT>
106
bool value_exists(const std::vector<T>& vec,
189,456✔
107
                  const OT& val)
108
   {
109
   for(size_t i = 0; i != vec.size(); ++i)
674,579✔
110
      if(vec[i] == val)
658,891✔
111
         return true;
97,326✔
112
   return false;
113
   }
114

115
template<typename T, typename Pred>
116
void map_remove_if(Pred pred, T& assoc)
2,048✔
117
   {
118
   auto i = assoc.begin();
2,048✔
119
   while(i != assoc.end())
2,048✔
120
      {
121
      if(pred(i->first))
4,096✔
122
         assoc.erase(i++);
2,048✔
123
      else
124
         i++;
6,144✔
125
      }
126
   }
2,048✔
127

128
/**
129
 * Helper class to ease unmarshalling of concatenated fixed-length values
130
 */
131
class BufferSlicer final
132
   {
133
   public:
134
      BufferSlicer(std::span<const uint8_t> buffer) : m_remaining(buffer)
3,535✔
135
         {}
136

137
      template <typename ContainerT>
138
      auto copy_as(const size_t count)
3,289✔
139
         {
140
         const auto result = take(count);
3,289✔
141
         return ContainerT(result.begin(), result.end());
3,289✔
142
         }
143

144
      auto take_vector(const size_t count) { return copy_as<std::vector<uint8_t>>(count); }
2,052✔
145
      auto take_secure_vector(const size_t count) { return copy_as<secure_vector<uint8_t>>(count); }
1,237✔
146

147
      std::span<const uint8_t> take(const size_t count)
21,924✔
148
         {
149
         BOTAN_STATE_CHECK(remaining() >= count);
×
150
         auto result = m_remaining.first(count);
21,924✔
151
         m_remaining = m_remaining.subspan(count);
21,924✔
152
         return result;
21,924✔
153
         }
154

155
      template<concepts::contiguous_strong_type T>
156
      StrongSpan<const T> take(const size_t count)
15,352✔
157
         {
158
         return StrongSpan<const T>(take(count));
15,142✔
159
         }
160

161
      void copy_into(std::span<uint8_t> sink)
162
         {
163
         const auto data = take(sink.size());
164
         std::copy(data.begin(), data.end(), sink.begin());
165
         }
166

167
      void skip(const size_t count) { take(count); }
575✔
168

169
      size_t remaining() const { return m_remaining.size(); }
23,219✔
170
      bool empty() const { return m_remaining.empty(); }
1,541✔
171

172
   private:
173
      std::span<const uint8_t> m_remaining;
174
   };
175

176

177
/**
178
 * @brief Helper class to ease in-place marshalling of concatenated fixed-length
179
 *        values.
180
 *
181
 * The size of the final buffer must be known from the start, reallocations are
182
 * not performed.
183
 */
184
class BufferStuffer
185
   {
186
   public:
187
      BufferStuffer(std::span<uint8_t> buffer)
22,704✔
188
         : m_buffer(buffer) {}
22,704✔
189

190
      /**
191
       * @returns a span for the next @p bytes bytes in the concatenated buffer.
192
       *          Checks that the buffer is not exceded.
193
       */
194
      std::span<uint8_t> next(size_t bytes)
1,102,983✔
195
         {
196
         BOTAN_STATE_CHECK(m_buffer.size() >= bytes);
1,102,983✔
197

198
         auto result = m_buffer.first(bytes);
1,102,983✔
199
         m_buffer = m_buffer.subspan(bytes);
1,102,983✔
200
         return result;
1,102,983✔
201
         }
202

203
      template <concepts::contiguous_strong_type StrongT>
204
      StrongSpan<StrongT> next(size_t bytes)
1,101,179✔
205
         {
206
         return StrongSpan<StrongT>(next(bytes));
1,102,263✔
207
         }
208

209
      void append(std::span<const uint8_t> buffer)
210
         {
211
         auto sink = next(buffer.size());
212
         std::copy(buffer.begin(), buffer.end(), sink.begin());
213
         }
214

215
      bool full() const { return m_buffer.empty(); }
54✔
216
      size_t remaining_capacity() const { return m_buffer.size(); }
178✔
217

218
   private:
219
      std::span<uint8_t> m_buffer;
220
   };
221

222
/**
223
 * Concatenate an arbitrary number of buffers.
224
 * @return the concatenation of \p buffers as the container type of the first buffer
225
 */
226
template <typename... Ts>
227
decltype(auto) concat(Ts&& ...buffers)
3,122,928✔
228
   {
229
   static_assert(sizeof...(buffers) > 0, "concat requires at least one buffer");
230

231
   using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>;
232
   result_t result;
3,122,928✔
233
   result.reserve((buffers.size() + ...));
3,122,928✔
234
   (result.insert(result.end(), buffers.begin(), buffers.end()), ...);
3,122,928✔
235
   return result;
3,122,928✔
236
   }
×
237

238
/**
239
 * Concatenate an arbitrary number of buffers and define the output buffer
240
 * type as a mandatory template parameter.
241
 * @return the concatenation of \p buffers as the user-defined container type
242
 */
243
template <typename ResultT, typename... Ts>
244
ResultT concat_as(Ts&& ...buffers)
3,117,023✔
245
   {
246
   return concat(ResultT(), std::forward<Ts>(buffers)...);
6,234,046✔
247
   }
248

249
template<typename... Alts, typename... Ts>
250
constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
3,624✔
251
    return (std::holds_alternative<Alts>(v) || ...);
3,624✔
252
}
253

254
template<typename GeneralVariantT, typename SpecialT>
255
constexpr bool is_generalizable_to(const SpecialT&) noexcept
256
   {
257
   return std::is_constructible_v<GeneralVariantT, SpecialT>;
258
   }
259

260
template<typename GeneralVariantT, typename... SpecialTs>
261
constexpr bool is_generalizable_to(const std::variant<SpecialTs...>&) noexcept
262
   {
263
   return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
264
   }
265

266
/**
267
 * @brief Converts a given variant into another variant-ish whose type states
268
 *        are a super set of the given variant.
269
 *
270
 * This is useful to convert restricted variant types into more general
271
 * variants types.
272
 */
273
template<typename GeneralVariantT, typename SpecialT>
274
constexpr GeneralVariantT generalize_to(SpecialT&& specific) noexcept
1,369✔
275
   requires (std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
276
   {
277
   return std::forward<SpecialT>(specific);
1,369✔
278
   }
279

280
/**
281
 * @brief Converts a given variant into another variant-ish whose type states
282
 *        are a super set of the given variant.
283
 *
284
 * This is useful to convert restricted variant types into more general
285
 * variants types.
286
 */
287
template<typename GeneralVariantT, typename... SpecialTs>
288
constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) noexcept
3,226✔
289
   {
290
   static_assert(is_generalizable_to<GeneralVariantT>(specific),
291
                 "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
292
   return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
5,083✔
293
   }
294

295
// This is a helper utility to emulate pattern matching with std::visit.
296
// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
297
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
298
// explicit deduction guide (not needed as of C++20)
299
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
300

301
}
302

303
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc