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

randombit / botan / 5910687851

19 Aug 2023 09:36AM UTC coverage: 91.711% (-0.001%) from 91.712%
5910687851

Pull #3675

github

web-flow
Merge 88c4a1ce7 into dfe17143e
Pull Request #3675: Refactor: Keccak Permutation

78576 of 85678 relevant lines covered (91.71%)

8450547.28 hits per line

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

84.71
/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
template <concepts::contiguous_container T = std::vector<uint8_t>>
27
inline T to_byte_vector(std::string_view s) {
739✔
28
   return T(s.cbegin(), s.cend());
739✔
29
}
30

31
inline std::string to_string(std::span<const uint8_t> bytes) {
8✔
32
   return std::string(bytes.begin(), bytes.end());
8✔
33
}
34

35
/**
36
* Return the keys of a map as a std::set
37
*/
38
template <typename K, typename V>
39
std::set<K> map_keys_as_set(const std::map<K, V>& kv) {
×
40
   std::set<K> s;
×
41
   for(auto&& i : kv) {
×
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
   std::set<K> s;
×
53
   for(auto&& i : kv) {
×
54
      s.insert(i.first);
×
55
   }
56
   return s;
×
57
}
×
58

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

75
template <typename K, typename V, typename R>
76
inline R search_map(const std::map<K, V>& mapping, const K& key, const R& null_result, const R& found_result) {
77
   auto i = mapping.find(key);
78
   if(i == mapping.end()) {
79
      return null_result;
80
   }
81
   return found_result;
82
}
83

84
/*
85
* Insert a key/value pair into a multimap
86
*/
87
template <typename K, typename V>
88
void multimap_insert(std::multimap<K, V>& multimap, const K& key, const V& value) {
646,317✔
89
   multimap.insert(std::make_pair(key, value));
646,317✔
90
}
646,317✔
91

92
/**
93
* Existence check for values
94
*/
95
template <typename T, typename OT>
96
bool value_exists(const std::vector<T>& vec, const OT& val) {
193,206✔
97
   for(size_t i = 0; i != vec.size(); ++i) {
2,826,274✔
98
      if(vec[i] == val) {
2,799,396✔
99
         return true;
98,922✔
100
      }
101
   }
102
   return false;
103
}
104

105
template <typename T, typename Pred>
106
void map_remove_if(Pred pred, T& assoc) {
2,060✔
107
   auto i = assoc.begin();
2,060✔
108
   while(i != assoc.end()) {
2,060✔
109
      if(pred(i->first)) {
4,120✔
110
         assoc.erase(i++);
2,060✔
111
      } else {
112
         i++;
6,180✔
113
      }
114
   }
115
}
2,060✔
116

117
/**
118
 * Helper class to ease unmarshalling of concatenated fixed-length values
119
 */
120
class BufferSlicer final {
121
   public:
122
      BufferSlicer(std::span<const uint8_t> buffer) : m_remaining(buffer) {}
727,504,525✔
123

124
      template <concepts::contiguous_container ContainerT>
125
      auto copy(const size_t count) {
3,712✔
126
         const auto result = take(count);
3,712✔
127
         return ContainerT(result.begin(), result.end());
3,710✔
128
      }
129

130
      auto copy_as_vector(const size_t count) { return copy<std::vector<uint8_t>>(count); }
2,064✔
131

132
      auto copy_as_secure_vector(const size_t count) { return copy<secure_vector<uint8_t>>(count); }
1,264✔
133

134
      std::span<const uint8_t> take(const size_t count) {
2,147,483,647✔
135
         BOTAN_STATE_CHECK(remaining() >= count);
6✔
136
         auto result = m_remaining.first(count);
2,147,483,647✔
137
         m_remaining = m_remaining.subspan(count);
2,147,483,647✔
138
         return result;
2,147,483,647✔
139
      }
140

141
      template <concepts::contiguous_strong_type T>
142
      StrongSpan<const T> take(const size_t count) {
25,219✔
143
         return StrongSpan<const T>(take(count));
24,357✔
144
      }
145

146
      uint8_t take_byte() { return take(1)[0]; }
668,015,344✔
147

148
      void copy_into(std::span<uint8_t> sink) {
2✔
149
         const auto data = take(sink.size());
2✔
150
         std::copy(data.begin(), data.end(), sink.begin());
2✔
151
      }
2✔
152

153
      void skip(const size_t count) { take(count); }
593✔
154

155
      size_t remaining() const { return m_remaining.size(); }
2,147,483,647✔
156

157
      bool empty() const { return m_remaining.empty(); }
2,147,483,647✔
158

159
   private:
160
      std::span<const uint8_t> m_remaining;
161
};
162

163
/**
164
 * @brief Helper class to ease in-place marshalling of concatenated fixed-length
165
 *        values.
166
 *
167
 * The size of the final buffer must be known from the start, reallocations are
168
 * not performed.
169
 */
170
class BufferStuffer {
171
   public:
172
      BufferStuffer(std::span<uint8_t> buffer) : m_buffer(buffer) {}
163,665,977✔
173

174
      /**
175
       * @returns a span for the next @p bytes bytes in the concatenated buffer.
176
       *          Checks that the buffer is not exceded.
177
       */
178
      std::span<uint8_t> next(size_t bytes) {
507,986,976✔
179
         BOTAN_STATE_CHECK(m_buffer.size() >= bytes);
507,986,976✔
180

181
         auto result = m_buffer.first(bytes);
507,986,972✔
182
         m_buffer = m_buffer.subspan(bytes);
507,986,972✔
183
         return result;
507,986,972✔
184
      }
185

186
      template <concepts::contiguous_strong_type StrongT>
187
      StrongSpan<StrongT> next(size_t bytes) {
1,391,906✔
188
         return StrongSpan<StrongT>(next(bytes));
1,393,187✔
189
      }
190

191
      /**
192
       * @returns a reference to the next single byte in the buffer
193
       */
194
      uint8_t& next_byte() { return next(1)[0]; }
44,002✔
195

196
      void append(std::span<const uint8_t> buffer) {
10,247✔
197
         auto sink = next(buffer.size());
10,247✔
198
         std::copy(buffer.begin(), buffer.end(), sink.begin());
10,245✔
199
      }
10,245✔
200

201
      bool full() const { return m_buffer.empty(); }
327,673,289✔
202

203
      size_t remaining_capacity() const { return m_buffer.size(); }
588,538,021✔
204

205
   private:
206
      std::span<uint8_t> m_buffer;
207
};
208

209
/**
210
 * Concatenate an arbitrary number of buffers.
211
 * @return the concatenation of \p buffers as the container type of the first buffer
212
 */
213
template <typename... Ts>
214
decltype(auto) concat(Ts&&... buffers) {
3,708,762✔
215
   static_assert(sizeof...(buffers) > 0, "concat requires at least one buffer");
216

217
   using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>;
218
   result_t result;
3,708,762✔
219
   result.reserve((buffers.size() + ...));
3,708,762✔
220
   (result.insert(result.end(), buffers.begin(), buffers.end()), ...);
3,708,762✔
221
   return result;
3,708,762✔
222
}
×
223

224
/**
225
 * Concatenate an arbitrary number of buffers and define the output buffer
226
 * type as a mandatory template parameter.
227
 * @return the concatenation of \p buffers as the user-defined container type
228
 */
229
template <typename ResultT, typename... Ts>
230
ResultT concat_as(Ts&&... buffers) {
3,519,838✔
231
   return concat(ResultT(), std::forward<Ts>(buffers)...);
7,039,676✔
232
}
233

234
template <typename... Alts, typename... Ts>
235
constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
3,638✔
236
   return (std::holds_alternative<Alts>(v) || ...);
3,638✔
237
}
238

239
template <typename GeneralVariantT, typename SpecialT>
240
constexpr bool is_generalizable_to(const SpecialT&) noexcept {
241
   return std::is_constructible_v<GeneralVariantT, SpecialT>;
242
}
243

244
template <typename GeneralVariantT, typename... SpecialTs>
245
constexpr bool is_generalizable_to(const std::variant<SpecialTs...>&) noexcept {
246
   return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
247
}
248

249
/**
250
 * @brief Converts a given variant into another variant-ish whose type states
251
 *        are a super set of the given variant.
252
 *
253
 * This is useful to convert restricted variant types into more general
254
 * variants types.
255
 */
256
template <typename GeneralVariantT, typename SpecialT>
257
constexpr GeneralVariantT generalize_to(SpecialT&& specific) noexcept
1,375✔
258
   requires(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
259
{
260
   return std::forward<SpecialT>(specific);
1,375✔
261
}
262

263
/**
264
 * @brief Converts a given variant into another variant-ish whose type states
265
 *        are a super set of the given variant.
266
 *
267
 * This is useful to convert restricted variant types into more general
268
 * variants types.
269
 */
270
template <typename GeneralVariantT, typename... SpecialTs>
271
constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) noexcept {
3,242✔
272
   static_assert(
273
      is_generalizable_to<GeneralVariantT>(specific),
274
      "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
275
   return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
5,109✔
276
}
277

278
// This is a helper utility to emulate pattern matching with std::visit.
279
// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
280
template <class... Ts>
281
struct overloaded : Ts... {
282
      using Ts::operator()...;
283
};
284
// explicit deduction guide (not needed as of C++20)
285
template <class... Ts>
286
overloaded(Ts...) -> overloaded<Ts...>;
287

288
}  // namespace Botan
289

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