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

randombit / botan / 5122901828

30 May 2023 02:42PM UTC coverage: 92.22% (+0.01%) from 92.209%
5122901828

Pull #3549

github

web-flow
Merge 26dd3cf4b into 057bcbc35
Pull Request #3549: SPHINCS+

76784 of 83262 relevant lines covered (92.22%)

12270748.88 hits per line

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

83.75
/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 <map>
13
#include <set>
14
#include <span>
15
#include <string>
16
#include <tuple>
17
#include <variant>
18
#include <vector>
19

20
#include <botan/concepts.h>
21
#include <botan/secmem.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) { return std::vector<uint8_t>(s.cbegin(), s.cend()); }
631✔
27

28
inline std::string to_string(const secure_vector<uint8_t>& bytes) { return std::string(bytes.cbegin(), bytes.cend()); }
29

30
/**
31
* Return the keys of a map as a std::set
32
*/
33
template <typename K, typename V>
34
std::set<K> map_keys_as_set(const std::map<K, V>& kv) {
×
35
   std::set<K> s;
×
36
   for(auto&& i : kv) {
×
37
      s.insert(i.first);
×
38
   }
39
   return s;
×
40
}
×
41

42
/**
43
* Return the keys of a multimap as a std::set
44
*/
45
template <typename K, typename V>
46
std::set<K> map_keys_as_set(const std::multimap<K, V>& kv) {
×
47
   std::set<K> s;
×
48
   for(auto&& i : kv) {
×
49
      s.insert(i.first);
×
50
   }
51
   return s;
×
52
}
×
53

54
/*
55
* Searching through a std::map
56
* @param mapping the map to search
57
* @param key is what to look for
58
* @param null_result is the value to return if key is not in mapping
59
* @return mapping[key] or null_result
60
*/
61
template <typename K, typename V>
62
inline V search_map(const std::map<K, V>& mapping, const K& key, const V& null_result = V()) {
17✔
63
   auto i = mapping.find(key);
17✔
64
   if(i == mapping.end())
17✔
65
      return null_result;
17✔
66
   return i->second;
16✔
67
}
68

69
template <typename K, typename V, typename R>
70
inline R search_map(const std::map<K, V>& mapping, const K& key, const R& null_result, const R& found_result) {
71
   auto i = mapping.find(key);
72
   if(i == mapping.end())
73
      return null_result;
74
   return found_result;
75
}
76

77
/*
78
* Insert a key/value pair into a multimap
79
*/
80
template <typename K, typename V>
81
void multimap_insert(std::multimap<K, V>& multimap, const K& key, const V& value) {
591,688✔
82
   multimap.insert(std::make_pair(key, value));
591,688✔
83
}
591,688✔
84

85
/**
86
* Existence check for values
87
*/
88
template <typename T, typename OT>
89
bool value_exists(const std::vector<T>& vec, const OT& val) {
189,622✔
90
   for(size_t i = 0; i != vec.size(); ++i)
675,233✔
91
      if(vec[i] == val)
724,309✔
92
         return true;
97,385✔
93
   return false;
94
}
95

96
template <typename T, typename Pred>
97
void map_remove_if(Pred pred, T& assoc) {
2,048✔
98
   auto i = assoc.begin();
2,048✔
99
   while(i != assoc.end()) {
2,048✔
100
      if(pred(i->first))
4,096✔
101
         assoc.erase(i++);
2,048✔
102
      else
103
         i++;
6,144✔
104
   }
105
}
2,048✔
106

107
/**
108
 * Helper class to ease unmarshalling of concatenated fixed-length values
109
 */
110
class BufferSlicer final {
111
   public:
112
      BufferSlicer(std::span<const uint8_t> buffer) : m_remaining(buffer) {}
3,561✔
113

114
      template <concepts::contiguous_container ContainerT>
115
      auto copy(const size_t count) {
3,319✔
116
         const auto result = take(count);
3,319✔
117
         return ContainerT(result.begin(), result.end());
3,317✔
118
      }
119

120
      auto copy_as_vector(const size_t count) { return copy<std::vector<uint8_t>>(count); }
2,056✔
121

122
      auto copy_as_secure_vector(const size_t count) { return copy<secure_vector<uint8_t>>(count); }
1,238✔
123

124
      std::span<const uint8_t> take(const size_t count) {
22,013✔
125
         BOTAN_STATE_CHECK(remaining() >= count);
6✔
126
         auto result = m_remaining.first(count);
22,007✔
127
         m_remaining = m_remaining.subspan(count);
22,007✔
128
         return result;
22,007✔
129
      }
130

131
      template <concepts::contiguous_strong_type T>
132
      StrongSpan<const T> take(const size_t count) {
15,353✔
133
         return StrongSpan<const T>(take(count));
15,143✔
134
      }
135

136
      void copy_into(std::span<uint8_t> sink) {
2✔
137
         const auto data = take(sink.size());
2✔
138
         std::copy(data.begin(), data.end(), sink.begin());
2✔
139
      }
2✔
140

141
      void skip(const size_t count) { take(count); }
578✔
142

143
      size_t remaining() const { return m_remaining.size(); }
23,315✔
144

145
      bool empty() const { return m_remaining.empty(); }
1,568✔
146

147
   private:
148
      std::span<const uint8_t> m_remaining;
149
};
150

151
/**
152
 * @brief Helper class to ease in-place marshalling of concatenated fixed-length
153
 *        values.
154
 *
155
 * The size of the final buffer must be known from the start, reallocations are
156
 * not performed.
157
 */
158
class BufferStuffer {
159
   public:
160
      BufferStuffer(std::span<uint8_t> buffer) : m_buffer(buffer) {}
22,705✔
161

162
      /**
163
       * @returns a span for the next @p bytes bytes in the concatenated buffer.
164
       *          Checks that the buffer is not exceded.
165
       */
166
      std::span<uint8_t> next(size_t bytes) {
1,102,991✔
167
         BOTAN_STATE_CHECK(m_buffer.size() >= bytes);
1,102,991✔
168

169
         auto result = m_buffer.first(bytes);
1,102,987✔
170
         m_buffer = m_buffer.subspan(bytes);
1,102,987✔
171
         return result;
1,102,987✔
172
      }
173

174
      template <concepts::contiguous_strong_type StrongT>
175
      StrongSpan<StrongT> next(size_t bytes) {
1,101,180✔
176
         return StrongSpan<StrongT>(next(bytes));
1,102,264✔
177
      }
178

179
      void append(std::span<const uint8_t> buffer) {
3✔
180
         auto sink = next(buffer.size());
3✔
181
         std::copy(buffer.begin(), buffer.end(), sink.begin());
1✔
182
      }
1✔
183

184
      bool full() const { return m_buffer.empty(); }
57✔
185

186
      size_t remaining_capacity() const { return m_buffer.size(); }
182✔
187

188
   private:
189
      std::span<uint8_t> m_buffer;
190
};
191

192
/**
193
 * Concatenate an arbitrary number of buffers.
194
 * @return the concatenation of \p buffers as the container type of the first buffer
195
 */
196
template <typename... Ts>
197
decltype(auto) concat(Ts&&... buffers) {
3,122,929✔
198
   static_assert(sizeof...(buffers) > 0, "concat requires at least one buffer");
199

200
   using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>;
201
   result_t result;
3,122,929✔
202
   result.reserve((buffers.size() + ...));
3,122,929✔
203
   (result.insert(result.end(), buffers.begin(), buffers.end()), ...);
3,122,929✔
204
   return result;
3,122,929✔
205
}
×
206

207
/**
208
 * Concatenate an arbitrary number of buffers and define the output buffer
209
 * type as a mandatory template parameter.
210
 * @return the concatenation of \p buffers as the user-defined container type
211
 */
212
template <typename ResultT, typename... Ts>
213
ResultT concat_as(Ts&&... buffers) {
3,117,024✔
214
   return concat(ResultT(), std::forward<Ts>(buffers)...);
6,234,048✔
215
}
216

217
template <typename... Alts, typename... Ts>
218
constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
3,624✔
219
   return (std::holds_alternative<Alts>(v) || ...);
3,624✔
220
}
221

222
template <typename GeneralVariantT, typename SpecialT>
223
constexpr bool is_generalizable_to(const SpecialT&) noexcept {
224
   return std::is_constructible_v<GeneralVariantT, SpecialT>;
225
}
226

227
template <typename GeneralVariantT, typename... SpecialTs>
228
constexpr bool is_generalizable_to(const std::variant<SpecialTs...>&) noexcept {
229
   return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
230
}
231

232
/**
233
 * @brief Converts a given variant into another variant-ish whose type states
234
 *        are a super set of the given variant.
235
 *
236
 * This is useful to convert restricted variant types into more general
237
 * variants types.
238
 */
239
template <typename GeneralVariantT, typename SpecialT>
240
constexpr GeneralVariantT generalize_to(SpecialT&& specific) noexcept
1,369✔
241
   requires(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
242
{
243
   return std::forward<SpecialT>(specific);
1,369✔
244
}
245

246
/**
247
 * @brief Converts a given variant into another variant-ish whose type states
248
 *        are a super set of the given variant.
249
 *
250
 * This is useful to convert restricted variant types into more general
251
 * variants types.
252
 */
253
template <typename GeneralVariantT, typename... SpecialTs>
254
constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) noexcept {
3,226✔
255
   static_assert(
256
      is_generalizable_to<GeneralVariantT>(specific),
257
      "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
258
   return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
5,083✔
259
}
260

261
// This is a helper utility to emulate pattern matching with std::visit.
262
// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
263
template <class... Ts>
264
struct overloaded : Ts... {
265
      using Ts::operator()...;
266
};
267
// explicit deduction guide (not needed as of C++20)
268
template <class... Ts>
269
overloaded(Ts...) -> overloaded<Ts...>;
270

271
}  // namespace Botan
272

273
#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