blob: 5be8bf5110ca9010e7208c6c92ee5c6859f08574 [file] [log] [blame]
Brad Bishop65ffffa2016-11-29 12:31:31 -05001#pragma once
2
Brad Bishopd3d188d2018-12-11 16:49:29 -05003#include <cstring>
4#include <sdbusplus/message/types.hpp>
5#include <stdexcept>
6#include <string>
7#include <type_traits>
8#include <utility>
9
Brad Bishop65ffffa2016-11-29 12:31:31 -050010namespace phosphor
11{
12namespace inventory
13{
14namespace manager
15{
Brad Bishop9bbfcb12017-02-04 10:51:06 -050016/** @struct MakeVariantVisitor
17 * @brief Return a variant if the visited type is a possible variant type.
18 *
19 * @tparam V - The desired variant type.
20 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070021template <typename V>
22struct MakeVariantVisitor
Brad Bishop9bbfcb12017-02-04 10:51:06 -050023{
24 /** @struct Make
25 * @brief Return variant visitor.
26 *
27 * @tparam T - The variant type to return.
28 * @tparam Arg - The type being visited in the source variant.
29 * @tparam Enable - Overload resolution removal.
30 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070031 template <typename T, typename Arg, typename Enable = void>
32 struct Make
Brad Bishop9bbfcb12017-02-04 10:51:06 -050033 {
34 static auto make(Arg&& arg)
35 {
William A. Kennington III6e94b652018-11-06 17:11:28 -080036 throw std::runtime_error(
37 "Invalid conversion in MakeVariantVisitor");
Brad Bishop9bbfcb12017-02-04 10:51:06 -050038 return T();
39 }
40 };
Brad Bishop65ffffa2016-11-29 12:31:31 -050041
Brad Bishop9bbfcb12017-02-04 10:51:06 -050042 /** @struct Make
43 * @brief Return variant visitor.
44 *
45 * struct Make specialization if Arg is in T (int -> variant<int, char>).
46 */
47 template <typename T, typename Arg>
Brad Bishop615b2a82018-03-29 10:32:41 -040048 struct Make<
49 T, Arg,
50 typename std::enable_if<std::is_convertible<Arg, T>::value>::type>
Brad Bishop9bbfcb12017-02-04 10:51:06 -050051 {
52 static auto make(Arg&& arg)
53 {
54 return T(std::forward<Arg>(arg));
55 }
56 };
57
58 /** @brief Make variant visitor. */
Patrick Venturea680d1e2018-10-14 13:34:26 -070059 template <typename Arg>
60 auto operator()(Arg&& arg) const
Brad Bishop9bbfcb12017-02-04 10:51:06 -050061 {
62 return Make<V, Arg>::make(arg);
63 }
64};
65
66/** @brief Convert variants with different contained types.
67 *
68 * @tparam V - The desired variant type.
69 * @tparam Arg - The source variant type.
70 *
71 * @param[in] v - The source variant.
72 * @returns - The converted variant.
73 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070074template <typename V, typename Arg>
75auto convertVariant(Arg&& v)
Brad Bishop9bbfcb12017-02-04 10:51:06 -050076{
Patrick Williams26f86682020-05-13 11:36:19 -050077 return std::visit(MakeVariantVisitor<V>(), v);
Brad Bishop9bbfcb12017-02-04 10:51:06 -050078}
Brad Bishop86521582017-02-15 01:10:15 -050079
80/** @struct CompareFirst
81 * @brief std::pair binary comparison adapter.
82 *
83 * Adapt a binary comparison function to a comparison of
84 * the first pair element.
85 *
86 * @tparam Compare - The function object type being adapted.
87 */
Patrick Venturea680d1e2018-10-14 13:34:26 -070088template <typename Compare>
89struct CompareFirst
Brad Bishop86521582017-02-15 01:10:15 -050090{
91 /** @brief Construct a CompareFirst adapter.
92 *
93 * @param[in] c - The function object being adapted.
94 */
Brad Bishop615b2a82018-03-29 10:32:41 -040095 explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c))
96 {
97 }
Brad Bishop86521582017-02-15 01:10:15 -050098
99 /** @brief Compare two pairs adapter.
100 *
101 * @tparam L1 - First pair first_type.
102 * @tparam L2 - First pair second_type.
103 * @tparam R1 - Second pair first_type, convertible to L1.
104 * @tparam R2 - Second pair second_type.
105 *
106 * @param[in] l - The first pair.
107 * @param[in] r - The second pair.
108 *
109 * @returns - The result of the comparison.
110 */
111 template <typename L1, typename L2, typename R1, typename R2>
Brad Bishop615b2a82018-03-29 10:32:41 -0400112 bool operator()(const std::pair<L1, L2>& l,
113 const std::pair<R1, R2>& r) const
Brad Bishop86521582017-02-15 01:10:15 -0500114 {
115 return compare(l.first, r.first);
116 }
117
118 /** @brief Compare one pair adapter.
119 *
120 * @tparam L1 - Pair first_type.
121 * @tparam L2 - Pair second_type.
122 * @tparam R - Convertible to L1 for comparison.
123 *
124 * @param[in] l - The pair.
125 * @param[in] r - To be compared to l.first.
126 *
127 * @returns - The result of the comparison.
128 */
129 template <typename L1, typename L2, typename R>
130 bool operator()(const std::pair<L1, L2>& l, const R& r) const
131 {
132 return compare(l.first, r);
133 }
134
135 /** @brief Compare one pair adapter.
136 *
137 * @tparam L - Convertible to R1 for comparison.
138 * @tparam R1 - Pair first_type.
139 * @tparam R2 - Pair second_type.
140 *
141 * @param[in] l - To be compared to r.first.
142 * @param[in] r - The pair.
143 *
144 * @returns - The result of the comparison.
145 */
146 template <typename L, typename R1, typename R2>
147 bool operator()(const L& l, const std::pair<R1, R2>& r) const
148 {
149 return compare(l, r.first);
150 }
151
152 /* @brief The function being adapted. */
153 Compare compare;
154};
155
156/* @brief Implicit template instantation wrapper for CompareFirst. */
Patrick Venturea680d1e2018-10-14 13:34:26 -0700157template <typename Compare>
158CompareFirst<Compare> compareFirst(Compare&& c)
Brad Bishop86521582017-02-15 01:10:15 -0500159{
160 return CompareFirst<Compare>(std::forward<Compare>(c));
161}
162
163/** @struct RelPathCompare
164 * @brief Compare two strings after removing an optional prefix.
165 */
166struct RelPathCompare
167{
168 /** @brief Construct a RelPathCompare comparison functor.
169 *
170 * @param[in] p - The prefix to check for and remove.
171 */
Brad Bishop615b2a82018-03-29 10:32:41 -0400172 explicit RelPathCompare(const char* p) : prefix(p)
173 {
174 }
Brad Bishop86521582017-02-15 01:10:15 -0500175
176 /** @brief Check for the prefix and remove if found.
177 *
178 * @param[in] s - The string to check for and remove prefix from.
179 */
180 auto relPath(const std::string& s) const
181 {
182 if (s.find(prefix) == 0)
183 {
184 return s.substr(strlen(prefix));
185 }
186
187 return s;
188 }
189
190 /** @brief Comparison method.
191 *
192 * @param[in] l - The first string.
193 * @param[in] r - The second string.
194 *
195 * @returns - The result of the comparison.
196 */
197 bool operator()(const std::string& l, const std::string& r) const
198 {
199 return relPath(l) < relPath(r);
200 }
201
202 /* The path prefix to remove when comparing two paths. */
203 const char* prefix;
204};
Brad Bishop65ffffa2016-11-29 12:31:31 -0500205} // namespace manager
206} // namespace inventory
207} // namespace phosphor
208
209// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4