blob: fbe1d6a2fd423aadbda4368396f510f9b3bd687e [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 *
Santosh Puranika18caea2022-06-09 23:45:56 +053047 * struct Make specialization if Arg is in T (int -> variant<int, char>),
48 * but not a string. Strings are used to represent enumerations by
49 * sdbusplus, so they are attempted in the following specialization.
Brad Bishop9bbfcb12017-02-04 10:51:06 -050050 */
51 template <typename T, typename Arg>
Santosh Puranika18caea2022-06-09 23:45:56 +053052 struct Make<
53 T, Arg,
54 typename std::enable_if_t<
55 !std::is_same_v<std::string,
56 std::remove_cv_t<std::remove_reference_t<Arg>>> &&
57 std::is_convertible_v<Arg, T>>>
Brad Bishop9bbfcb12017-02-04 10:51:06 -050058 {
59 static auto make(Arg&& arg)
60 {
61 return T(std::forward<Arg>(arg));
62 }
63 };
64
Patrick Williams706a9fc2021-07-16 12:38:19 -050065 /** @struct Make
66 * @brief Return variant visitor.
67 *
Santosh Puranika18caea2022-06-09 23:45:56 +053068 * struct Make specialization if Arg is a string.Strings might
69 * be convertable (for ex. to enumerations) using underlying sdbusplus
70 * routines, so give them an attempt. In case the string is not convertible
71 * to an enumeration, sdbusplus::message::convert_from_string will return a
72 * string back anyway.
Patrick Williams706a9fc2021-07-16 12:38:19 -050073 */
74 template <typename T, typename Arg>
75 struct Make<
76 T, Arg,
77 typename std::enable_if_t<
Patrick Williams706a9fc2021-07-16 12:38:19 -050078 std::is_same_v<std::string,
79 std::remove_cv_t<std::remove_reference_t<Arg>>> &&
80 sdbusplus::message::has_convert_from_string_v<T>>>
81 {
82 static auto make(Arg&& arg) -> T
83 {
84 auto r = sdbusplus::message::convert_from_string<T>(
85 std::forward<Arg>(arg));
86 if (r)
87 {
88 return *r;
89 }
90
91 throw std::runtime_error(
92 std::string("Invalid conversion in MakeVariantVisitor::") +
93 __PRETTY_FUNCTION__);
94
95 return {};
96 }
97 };
98
Brad Bishop9bbfcb12017-02-04 10:51:06 -050099 /** @brief Make variant visitor. */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700100 template <typename Arg>
101 auto operator()(Arg&& arg) const
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500102 {
103 return Make<V, Arg>::make(arg);
104 }
105};
106
107/** @brief Convert variants with different contained types.
108 *
109 * @tparam V - The desired variant type.
110 * @tparam Arg - The source variant type.
111 *
112 * @param[in] v - The source variant.
113 * @returns - The converted variant.
114 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700115template <typename V, typename Arg>
116auto convertVariant(Arg&& v)
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500117{
Patrick Williams26f86682020-05-13 11:36:19 -0500118 return std::visit(MakeVariantVisitor<V>(), v);
Brad Bishop9bbfcb12017-02-04 10:51:06 -0500119}
Brad Bishop86521582017-02-15 01:10:15 -0500120
121/** @struct CompareFirst
122 * @brief std::pair binary comparison adapter.
123 *
124 * Adapt a binary comparison function to a comparison of
125 * the first pair element.
126 *
127 * @tparam Compare - The function object type being adapted.
128 */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700129template <typename Compare>
130struct CompareFirst
Brad Bishop86521582017-02-15 01:10:15 -0500131{
132 /** @brief Construct a CompareFirst adapter.
133 *
134 * @param[in] c - The function object being adapted.
135 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400136 explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c))
Brad Bishopa83db302020-12-06 14:51:23 -0500137 {}
Brad Bishop86521582017-02-15 01:10:15 -0500138
139 /** @brief Compare two pairs adapter.
140 *
141 * @tparam L1 - First pair first_type.
142 * @tparam L2 - First pair second_type.
143 * @tparam R1 - Second pair first_type, convertible to L1.
144 * @tparam R2 - Second pair second_type.
145 *
146 * @param[in] l - The first pair.
147 * @param[in] r - The second pair.
148 *
149 * @returns - The result of the comparison.
150 */
151 template <typename L1, typename L2, typename R1, typename R2>
Brad Bishop615b2a82018-03-29 10:32:41 -0400152 bool operator()(const std::pair<L1, L2>& l,
153 const std::pair<R1, R2>& r) const
Brad Bishop86521582017-02-15 01:10:15 -0500154 {
155 return compare(l.first, r.first);
156 }
157
158 /** @brief Compare one pair adapter.
159 *
160 * @tparam L1 - Pair first_type.
161 * @tparam L2 - Pair second_type.
162 * @tparam R - Convertible to L1 for comparison.
163 *
164 * @param[in] l - The pair.
165 * @param[in] r - To be compared to l.first.
166 *
167 * @returns - The result of the comparison.
168 */
169 template <typename L1, typename L2, typename R>
170 bool operator()(const std::pair<L1, L2>& l, const R& r) const
171 {
172 return compare(l.first, r);
173 }
174
175 /** @brief Compare one pair adapter.
176 *
177 * @tparam L - Convertible to R1 for comparison.
178 * @tparam R1 - Pair first_type.
179 * @tparam R2 - Pair second_type.
180 *
181 * @param[in] l - To be compared to r.first.
182 * @param[in] r - The pair.
183 *
184 * @returns - The result of the comparison.
185 */
186 template <typename L, typename R1, typename R2>
187 bool operator()(const L& l, const std::pair<R1, R2>& r) const
188 {
189 return compare(l, r.first);
190 }
191
192 /* @brief The function being adapted. */
193 Compare compare;
194};
195
196/* @brief Implicit template instantation wrapper for CompareFirst. */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700197template <typename Compare>
198CompareFirst<Compare> compareFirst(Compare&& c)
Brad Bishop86521582017-02-15 01:10:15 -0500199{
200 return CompareFirst<Compare>(std::forward<Compare>(c));
201}
202
203/** @struct RelPathCompare
204 * @brief Compare two strings after removing an optional prefix.
205 */
206struct RelPathCompare
207{
208 /** @brief Construct a RelPathCompare comparison functor.
209 *
210 * @param[in] p - The prefix to check for and remove.
211 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400212 explicit RelPathCompare(const char* p) : prefix(p)
Brad Bishopa83db302020-12-06 14:51:23 -0500213 {}
Brad Bishop86521582017-02-15 01:10:15 -0500214
215 /** @brief Check for the prefix and remove if found.
216 *
217 * @param[in] s - The string to check for and remove prefix from.
218 */
219 auto relPath(const std::string& s) const
220 {
221 if (s.find(prefix) == 0)
222 {
223 return s.substr(strlen(prefix));
224 }
225
226 return s;
227 }
228
229 /** @brief Comparison method.
230 *
231 * @param[in] l - The first string.
232 * @param[in] r - The second string.
233 *
234 * @returns - The result of the comparison.
235 */
236 bool operator()(const std::string& l, const std::string& r) const
237 {
238 return relPath(l) < relPath(r);
239 }
240
241 /* The path prefix to remove when comparing two paths. */
242 const char* prefix;
243};
Brad Bishop65ffffa2016-11-29 12:31:31 -0500244} // namespace manager
245} // namespace inventory
246} // namespace phosphor
247
248// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4