Botan 3.12.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 <optional>
15#include <variant>
16#include <vector>
17
18namespace Botan {
19
20/**
21 * Reduce the values of @p keys into an accumulator initialized with @p acc using
22 * the reducer function @p reducer.
23 *
24 * The @p reducer is a function taking the accumulator and a single key to return the
25 * new accumulator. Keys are consecutively reduced into the accumulator.
26 *
27 * @return the accumulator containing the reduction of @p keys
28 */
29template <typename RetT, typename KeyT, typename ReducerT>
30RetT reduce(const std::vector<KeyT>& keys, RetT acc, ReducerT reducer)
31 requires std::invocable<ReducerT&, RetT, const KeyT&> &&
32 std::convertible_to<std::invoke_result_t<ReducerT&, RetT, const KeyT&>, RetT>
33{
34 for(const KeyT& key : keys) {
35 acc = reducer(std::move(acc), key);
36 }
37 return acc;
38}
39
40/**
41* Existence check for values
42*/
43template <typename T, typename V>
44bool value_exists(const std::vector<T>& vec, const V& val) {
45 for(const auto& elem : vec) {
46 if(elem == val) {
47 return true;
48 }
49 }
50 return false;
51}
52
53template <typename T, typename Pred>
54void map_remove_if(Pred pred, T& assoc) {
55 auto i = assoc.begin();
56 while(i != assoc.end()) {
57 if(pred(i->first)) {
58 assoc.erase(i++);
59 } else {
60 i++;
61 }
62 }
63}
64
65template <typename... Alts, typename... Ts>
66constexpr bool holds_any_of(const std::variant<Ts...>& v) noexcept {
67 return (std::holds_alternative<Alts>(v) || ...);
68}
69
70template <typename GeneralVariantT, typename SpecialT>
71constexpr bool is_generalizable_to(const SpecialT& /*unnamed*/) noexcept {
72 return std::is_constructible_v<GeneralVariantT, SpecialT>;
73}
74
75template <typename GeneralVariantT, typename... SpecialTs>
76constexpr bool is_generalizable_to(const std::variant<SpecialTs...>& /*unnamed*/) noexcept {
77 return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
78}
79
80/**
81 * @brief Converts a given variant into another variant-ish whose type states
82 * are a super set of the given variant.
83 *
84 * This is useful to convert restricted variant types into more general
85 * variants types.
86 */
87template <typename GeneralVariantT, typename SpecialT>
88constexpr GeneralVariantT generalize_to(SpecialT&& specific)
89 requires(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
90{
91 return std::forward<SpecialT>(specific);
92}
93
94/**
95 * @brief Converts a given variant into another variant-ish whose type states
96 * are a super set of the given variant.
97 *
98 * This is useful to convert restricted variant types into more general
99 * variants types.
100 */
101template <typename GeneralVariantT, typename... SpecialTs>
102constexpr GeneralVariantT generalize_to(std::variant<SpecialTs...> specific) {
103 static_assert(
105 "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
106 return std::visit([](auto s) -> GeneralVariantT { return s; }, std::move(specific));
107}
108
109/**
110 * @brief Converts a given variant into another variant whose type states
111 * are a subset of the given variant.
112 *
113 * @returns a variant of type SpecificVariantT if the given variant holds a
114 * type in SpecificVariantT, std::nullopt otherwise.
115 */
116template <typename SpecificVariantT, typename GeneralVariantT>
117constexpr std::optional<SpecificVariantT> specialize_to(GeneralVariantT&& v) {
118 return std::visit(
119 []<typename AlternativeT>(AlternativeT&& obj) -> std::optional<SpecificVariantT> {
120 if constexpr(std::is_constructible_v<SpecificVariantT, AlternativeT>) {
121 return std::forward<AlternativeT>(obj);
122 } else {
123 return std::nullopt;
124 }
125 },
126 std::forward<GeneralVariantT>(v));
127}
128
129// This is a helper utility to emulate pattern matching with std::visit.
130// See https://en.cppreference.com/w/cpp/utility/variant/visit for more info.
131template <class... Ts>
132struct overloaded : Ts... {
133 using Ts::operator()...;
134};
135// explicit deduction guide (not needed as of C++20)
136template <class... Ts>
137overloaded(Ts...) -> overloaded<Ts...>;
138
139// TODO: C++23: replace with std::to_underlying
140template <typename T>
141 requires std::is_enum_v<T>
142auto to_underlying(T e) noexcept {
143 return static_cast<std::underlying_type_t<T>>(e);
144}
145
146// TODO: C++23 - use std::out_ptr
147template <typename T>
148[[nodiscard]] constexpr auto out_ptr(T& outptr) noexcept {
149 class out_ptr_t {
150 public:
151 constexpr ~out_ptr_t() noexcept {
152 m_ptr.reset(m_rawptr);
153 m_rawptr = nullptr;
154 }
155
156 constexpr explicit out_ptr_t(T& outptr) noexcept : m_ptr(outptr), m_rawptr(nullptr) {}
157
158 out_ptr_t(const out_ptr_t&) = delete;
159 out_ptr_t(out_ptr_t&&) = delete;
160 out_ptr_t& operator=(const out_ptr_t&) = delete;
161 out_ptr_t& operator=(out_ptr_t&&) = delete;
162
163 // NOLINTNEXTLINE(*-explicit-conversions) - Implicit by design for C API interop
164 [[nodiscard]] constexpr operator typename T::element_type **() && noexcept { return &m_rawptr; }
165
166 private:
167 T& m_ptr;
168 typename T::element_type* m_rawptr;
169 };
170
171 return out_ptr_t{outptr};
172}
173
174} // namespace Botan
175
176#endif
void map_remove_if(Pred pred, T &assoc)
Definition stl_util.h:54
constexpr auto out_ptr(T &outptr) noexcept
Definition stl_util.h:148
auto to_underlying(T e) noexcept
Definition stl_util.h:142
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition stl_util.h:66
constexpr std::optional< SpecificVariantT > specialize_to(GeneralVariantT &&v)
Converts a given variant into another variant whose type states are a subset of the given variant.
Definition stl_util.h:117
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:44
RetT reduce(const std::vector< KeyT > &keys, RetT acc, ReducerT reducer)
Definition stl_util.h:30
constexpr bool is_generalizable_to(const SpecialT &) noexcept
Definition stl_util.h:71
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:88