Botan 3.11.0
Crypto and TLS for C&
stl_util.h
Go to the documentation of this file.
1/*
2* STL Utility Functions
3* (C) 1999-2007 Jack Lloyd
4* (C) 2015 Simon Warta (Kullo GmbH)
5* (C) 2023-2024 René Meusel - Rohde & Schwarz Cybersecurity
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#ifndef BOTAN_STL_UTIL_H_
11#define BOTAN_STL_UTIL_H_
12
13#include <botan/assert.h>
14#include <variant>
15#include <vector>
16
17namespace Botan {
18
19/**
20 * Reduce the values of @p keys into an accumulator initialized with @p acc using
21 * the reducer function @p reducer.
22 *
23 * The @p reducer is a function taking the accumulator and a single key to return the
24 * new accumulator. Keys are consecutively reduced into the accumulator.
25 *
26 * @return the accumulator containing the reduction of @p keys
27 */
28template <typename RetT, typename KeyT, typename ReducerT>
29RetT reduce(const std::vector<KeyT>& keys, RetT acc, ReducerT reducer)
30 requires std::invocable<ReducerT&, RetT, const KeyT&> &&
31 std::convertible_to<std::invoke_result_t<ReducerT&, RetT, const KeyT&>, RetT>
32{
33 for(const KeyT& key : keys) {
34 acc = reducer(std::move(acc), key);
35 }
36 return acc;
37}
38
39/**
40* Existence check for values
41*/
42template <typename T, typename V>
43bool value_exists(const std::vector<T>& vec, const V& val) {
44 for(const auto& elem : vec) {
45 if(elem == val) {
46 return true;
47 }
48 }
49 return false;
50}
51
52template <typename T, typename Pred>
53void map_remove_if(Pred pred, T& assoc) {
54 auto i = assoc.begin();
55 while(i != assoc.end()) {
56 if(pred(i->first)) {
57 assoc.erase(i++);
58 } else {
59 i++;
60 }
61 }
62}
63
64template <typename... Alts, typename... Ts>
65constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
66 return (std::holds_alternative<Alts>(v) || ...);
67}
68
69template <typename GeneralVariantT, typename SpecialT>
70constexpr bool is_generalizable_to(const SpecialT& /*unnamed*/) noexcept {
71 return std::is_constructible_v<GeneralVariantT, SpecialT>;
72}
73
74template <typename GeneralVariantT, typename... SpecialTs>
75constexpr bool is_generalizable_to(const std::variant<SpecialTs...>& /*unnamed*/) noexcept {
76 return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
77}
78
79/**
80 * @brief Converts a given variant into another variant-ish whose type states
81 * are a super set of the given variant.
82 *
83 * This is useful to convert restricted variant types into more general
84 * variants types.
85 */
86template <typename GeneralVariantT, typename SpecialT>
87constexpr GeneralVariantT generalize_to(SpecialT&& specific)
88 requires(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
89{
90 return std::forward<SpecialT>(specific);
91}
92
93/**
94 * @brief Converts a given variant into another variant-ish whose type states
95 * are a super set of the given variant.
96 *
97 * This is useful to convert restricted variant types into more general
98 * variants types.
99 */
100template <typename GeneralVariantT, typename... SpecialTs>
101constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) {
102 static_assert(
104 "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
105 return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
106}
107
108// This is a helper utility to emulate pattern matching with std::visit.
109// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
110template <class... Ts>
111struct overloaded : Ts... {
112 using Ts::operator()...;
113};
114// explicit deduction guide (not needed as of C++20)
115template <class... Ts>
116overloaded(Ts...) -> overloaded<Ts...>;
117
118// TODO: C++23: replace with std::to_underlying
119template <typename T>
120 requires std::is_enum_v<T>
121auto to_underlying(T e) noexcept {
122 return static_cast<std::underlying_type_t<T>>(e);
123}
124
125// TODO: C++23 - use std::out_ptr
126template <typename T>
127[[nodiscard]] constexpr auto out_ptr(T& outptr) noexcept {
128 class out_ptr_t {
129 public:
130 constexpr ~out_ptr_t() noexcept {
131 m_ptr.reset(m_rawptr);
132 m_rawptr = nullptr;
133 }
134
135 constexpr explicit out_ptr_t(T& outptr) noexcept : m_ptr(outptr), m_rawptr(nullptr) {}
136
137 out_ptr_t(const out_ptr_t&) = delete;
138 out_ptr_t(out_ptr_t&&) = delete;
139 out_ptr_t& operator=(const out_ptr_t&) = delete;
140 out_ptr_t& operator=(out_ptr_t&&) = delete;
141
142 // NOLINTNEXTLINE(*-explicit-conversions) - Implicit by design for C API interop
143 [[nodiscard]] constexpr operator typename T::element_type **() && noexcept { return &m_rawptr; }
144
145 private:
146 T& m_ptr;
147 typename T::element_type* m_rawptr;
148 };
149
150 return out_ptr_t{outptr};
151}
152
153} // namespace Botan
154
155#endif
void map_remove_if(Pred pred, T &assoc)
Definition stl_util.h:53
constexpr auto out_ptr(T &outptr) noexcept
Definition stl_util.h:127
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition stl_util.h:65
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:43
RetT reduce(const std::vector< KeyT > &keys, RetT acc, ReducerT reducer)
Definition stl_util.h:29
constexpr bool is_generalizable_to(const SpecialT &) noexcept
Definition stl_util.h:70
auto to_underlying(T e) noexcept
Definition stl_util.h:121
overloaded(Ts...) -> overloaded< Ts... >
constexpr GeneralVariantT generalize_to(SpecialT &&specific)
Converts a given variant into another variant-ish whose type states are a super set of the given vari...
Definition stl_util.h:87