blob: 9f82b4784f7ecc32f00814843b6a4e7ffe4710df [file] [log] [blame]
Brad Bishop65ffffa2016-11-29 12:31:31 -05001#pragma once
2
Patrick Williams706a9fc2021-07-16 12:38:19 -05003#include <sdbusplus/message/native_types.hpp>
Brad Bishopa83db302020-12-06 14:51:23 -05004
5#include <cstring>
Brad Bishopd3d188d2018-12-11 16:49:29 -05006#include <stdexcept>
7#include <string>
8#include <type_traits>
9#include <utility>
10
Brad Bishop65ffffa2016-11-29 12:31:31 -050011namespace phosphor
12{
13namespace inventory
14{
15namespace manager
16{
Brad Bishop9bbfcb12017-02-04 10:51:06 -050017/** @struct MakeVariantVisitor
18 * @brief Return a variant if the visited type is a possible variant type.
19 *
20 * @tparam V - The desired variant type.
21 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070022template <typename V>
23struct MakeVariantVisitor
Brad Bishop9bbfcb12017-02-04 10:51:06 -050024{
25 /** @struct Make
26 * @brief Return variant visitor.
27 *
28 * @tparam T - The variant type to return.
29 * @tparam Arg - The type being visited in the source variant.
30 * @tparam Enable - Overload resolution removal.
31 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070032 template <typename T, typename Arg, typename Enable = void>
33 struct Make
Brad Bishop9bbfcb12017-02-04 10:51:06 -050034 {
George Liu23314a52022-04-13 18:26:03 +080035 static auto make(Arg&& /* arg */)
Brad Bishop9bbfcb12017-02-04 10:51:06 -050036 {
William A. Kennington III6e94b652018-11-06 17:11:28 -080037 throw std::runtime_error(
Patrick Williams4ccd3962021-07-13 11:12:19 -050038 std::string("Invalid conversion in MakeVariantVisitor::") +
39 __PRETTY_FUNCTION__);
Brad Bishop9bbfcb12017-02-04 10:51:06 -050040 return T();
41 }
42 };
Brad Bishop65ffffa2016-11-29 12:31:31 -050043
Brad Bishop9bbfcb12017-02-04 10:51:06 -050044 /** @struct Make
45 * @brief Return variant visitor.
46 *
47 * struct Make specialization if Arg is in T (int -> variant<int, char>).
48 */
49 template <typename T, typename Arg>
Patrick Williams706a9fc2021-07-16 12:38:19 -050050 struct Make<T, Arg,
51 typename std::enable_if_t<std::is_convertible_v<Arg, T>>>
Brad Bishop9bbfcb12017-02-04 10:51:06 -050052 {
53 static auto make(Arg&& arg)
54 {
55 return T(std::forward<Arg>(arg));
56 }
57 };
58
Patrick Williams706a9fc2021-07-16 12:38:19 -050059 /** @struct Make
60 * @brief Return variant visitor.
61 *
62 * struct Make specialization if Arg is a string, but not otherwise
63 * directly convertable by C++ conversion constructors. Strings might
64 * be convertable using underlying sdbusplus routines, so give them an
65 * attempt.
66 */
67 template <typename T, typename Arg>
68 struct Make<
69 T, Arg,
70 typename std::enable_if_t<
71 !std::is_convertible_v<Arg, T> &&
72 std::is_same_v<std::string,
73 std::remove_cv_t<std::remove_reference_t<Arg>>> &&
74 sdbusplus::message::has_convert_from_string_v<T>>>
75 {
76 static auto make(Arg&& arg) -> T
77 {
78 auto r = sdbusplus::message::convert_from_string<T>(
79 std::forward<Arg>(arg));
80 if (r)
81 {
82 return *r;
83 }
84
85 throw std::runtime_error(
86 std::string("Invalid conversion in MakeVariantVisitor::") +
87 __PRETTY_FUNCTION__);
88
89 return {};
90 }
91 };
92
Brad Bishop9bbfcb12017-02-04 10:51:06 -050093 /** @brief Make variant visitor. */
Patrick Venturea680d1e2018-10-14 13:34:26 -070094 template <typename Arg>
95 auto operator()(Arg&& arg) const
Brad Bishop9bbfcb12017-02-04 10:51:06 -050096 {
97 return Make<V, Arg>::make(arg);
98 }
99};
100
101/** @brief Convert variants with different contained types.
102 *
103 * @tparam V - The desired variant type.
104 * @tparam Arg - The source variant type.
105 *
106 * @param[in] v - The source variant.
107 * @returns - The converted variant.
108 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700109template <typename V, typename Arg>
110auto convertVariant(Arg&& v)
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500111{
Patrick Williams26f86682020-05-13 11:36:19 -0500112 return std::visit(MakeVariantVisitor<V>(), v);
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500113}
Brad Bishop86521582017-02-15 01:10:15 -0500114
115/** @struct CompareFirst
116 * @brief std::pair binary comparison adapter.
117 *
118 * Adapt a binary comparison function to a comparison of
119 * the first pair element.
120 *
121 * @tparam Compare - The function object type being adapted.
122 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700123template <typename Compare>
124struct CompareFirst
Brad Bishop86521582017-02-15 01:10:15 -0500125{
126 /** @brief Construct a CompareFirst adapter.
127 *
128 * @param[in] c - The function object being adapted.
129 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400130 explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c))
Brad Bishopa83db302020-12-06 14:51:23 -0500131 {}
Brad Bishop86521582017-02-15 01:10:15 -0500132
133 /** @brief Compare two pairs adapter.
134 *
135 * @tparam L1 - First pair first_type.
136 * @tparam L2 - First pair second_type.
137 * @tparam R1 - Second pair first_type, convertible to L1.
138 * @tparam R2 - Second pair second_type.
139 *
140 * @param[in] l - The first pair.
141 * @param[in] r - The second pair.
142 *
143 * @returns - The result of the comparison.
144 */
145 template <typename L1, typename L2, typename R1, typename R2>
Brad Bishop615b2a82018-03-29 10:32:41 -0400146 bool operator()(const std::pair<L1, L2>& l,
147 const std::pair<R1, R2>& r) const
Brad Bishop86521582017-02-15 01:10:15 -0500148 {
149 return compare(l.first, r.first);
150 }
151
152 /** @brief Compare one pair adapter.
153 *
154 * @tparam L1 - Pair first_type.
155 * @tparam L2 - Pair second_type.
156 * @tparam R - Convertible to L1 for comparison.
157 *
158 * @param[in] l - The pair.
159 * @param[in] r - To be compared to l.first.
160 *
161 * @returns - The result of the comparison.
162 */
163 template <typename L1, typename L2, typename R>
164 bool operator()(const std::pair<L1, L2>& l, const R& r) const
165 {
166 return compare(l.first, r);
167 }
168
169 /** @brief Compare one pair adapter.
170 *
171 * @tparam L - Convertible to R1 for comparison.
172 * @tparam R1 - Pair first_type.
173 * @tparam R2 - Pair second_type.
174 *
175 * @param[in] l - To be compared to r.first.
176 * @param[in] r - The pair.
177 *
178 * @returns - The result of the comparison.
179 */
180 template <typename L, typename R1, typename R2>
181 bool operator()(const L& l, const std::pair<R1, R2>& r) const
182 {
183 return compare(l, r.first);
184 }
185
186 /* @brief The function being adapted. */
187 Compare compare;
188};
189
190/* @brief Implicit template instantation wrapper for CompareFirst. */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700191template <typename Compare>
192CompareFirst<Compare> compareFirst(Compare&& c)
Brad Bishop86521582017-02-15 01:10:15 -0500193{
194 return CompareFirst<Compare>(std::forward<Compare>(c));
195}
196
197/** @struct RelPathCompare
198 * @brief Compare two strings after removing an optional prefix.
199 */
200struct RelPathCompare
201{
202 /** @brief Construct a RelPathCompare comparison functor.
203 *
204 * @param[in] p - The prefix to check for and remove.
205 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400206 explicit RelPathCompare(const char* p) : prefix(p)
Brad Bishopa83db302020-12-06 14:51:23 -0500207 {}
Brad Bishop86521582017-02-15 01:10:15 -0500208
209 /** @brief Check for the prefix and remove if found.
210 *
211 * @param[in] s - The string to check for and remove prefix from.
212 */
213 auto relPath(const std::string& s) const
214 {
215 if (s.find(prefix) == 0)
216 {
217 return s.substr(strlen(prefix));
218 }
219
220 return s;
221 }
222
223 /** @brief Comparison method.
224 *
225 * @param[in] l - The first string.
226 * @param[in] r - The second string.
227 *
228 * @returns - The result of the comparison.
229 */
230 bool operator()(const std::string& l, const std::string& r) const
231 {
232 return relPath(l) < relPath(r);
233 }
234
235 /* The path prefix to remove when comparing two paths. */
236 const char* prefix;
237};
Brad Bishop65ffffa2016-11-29 12:31:31 -0500238} // namespace manager
239} // namespace inventory
240} // namespace phosphor
241
242// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4