1 #pragma once
2 
3 #include <sdbusplus/message/types.hpp>
4 
5 #include <cstring>
6 #include <stdexcept>
7 #include <string>
8 #include <type_traits>
9 #include <utility>
10 
11 namespace phosphor
12 {
13 namespace inventory
14 {
15 namespace manager
16 {
17 /** @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  */
22 template <typename V>
23 struct MakeVariantVisitor
24 {
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      */
32     template <typename T, typename Arg, typename Enable = void>
33     struct Make
34     {
35         static auto make(Arg&& arg)
36         {
37             throw std::runtime_error(
38                 std::string("Invalid conversion in MakeVariantVisitor::") +
39                 __PRETTY_FUNCTION__);
40             return T();
41         }
42     };
43 
44     /** @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>
50     struct Make<
51         T, Arg,
52         typename std::enable_if<std::is_convertible<Arg, T>::value>::type>
53     {
54         static auto make(Arg&& arg)
55         {
56             return T(std::forward<Arg>(arg));
57         }
58     };
59 
60     /** @brief Make variant visitor.  */
61     template <typename Arg>
62     auto operator()(Arg&& arg) const
63     {
64         return Make<V, Arg>::make(arg);
65     }
66 };
67 
68 /** @brief Convert variants with different contained types.
69  *
70  *  @tparam V - The desired variant type.
71  *  @tparam Arg - The source variant type.
72  *
73  *  @param[in] v - The source variant.
74  *  @returns - The converted variant.
75  */
76 template <typename V, typename Arg>
77 auto convertVariant(Arg&& v)
78 {
79     return std::visit(MakeVariantVisitor<V>(), v);
80 }
81 
82 /** @struct CompareFirst
83  *  @brief std::pair binary comparison adapter.
84  *
85  *  Adapt a binary comparison function to a comparison of
86  *  the first pair element.
87  *
88  *  @tparam Compare - The function object type being adapted.
89  */
90 template <typename Compare>
91 struct CompareFirst
92 {
93     /** @brief Construct a CompareFirst adapter.
94      *
95      *  @param[in] c - The function object being adapted.
96      */
97     explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c))
98     {}
99 
100     /** @brief Compare two pairs adapter.
101      *
102      *  @tparam L1 - First pair first_type.
103      *  @tparam L2 - First pair second_type.
104      *  @tparam R1 - Second pair first_type, convertible to L1.
105      *  @tparam R2 - Second pair second_type.
106      *
107      *  @param[in] l - The first pair.
108      *  @param[in] r - The second pair.
109      *
110      *  @returns - The result of the comparison.
111      */
112     template <typename L1, typename L2, typename R1, typename R2>
113     bool operator()(const std::pair<L1, L2>& l,
114                     const std::pair<R1, R2>& r) const
115     {
116         return compare(l.first, r.first);
117     }
118 
119     /** @brief Compare one pair adapter.
120      *
121      *  @tparam L1 - Pair first_type.
122      *  @tparam L2 - Pair second_type.
123      *  @tparam R - Convertible to L1 for comparison.
124      *
125      *  @param[in] l - The pair.
126      *  @param[in] r - To be compared to l.first.
127      *
128      *  @returns - The result of the comparison.
129      */
130     template <typename L1, typename L2, typename R>
131     bool operator()(const std::pair<L1, L2>& l, const R& r) const
132     {
133         return compare(l.first, r);
134     }
135 
136     /** @brief Compare one pair adapter.
137      *
138      *  @tparam L - Convertible to R1 for comparison.
139      *  @tparam R1 - Pair first_type.
140      *  @tparam R2 - Pair second_type.
141      *
142      *  @param[in] l - To be compared to r.first.
143      *  @param[in] r - The pair.
144      *
145      *  @returns - The result of the comparison.
146      */
147     template <typename L, typename R1, typename R2>
148     bool operator()(const L& l, const std::pair<R1, R2>& r) const
149     {
150         return compare(l, r.first);
151     }
152 
153     /* @brief The function being adapted. */
154     Compare compare;
155 };
156 
157 /* @brief Implicit template instantation wrapper for CompareFirst. */
158 template <typename Compare>
159 CompareFirst<Compare> compareFirst(Compare&& c)
160 {
161     return CompareFirst<Compare>(std::forward<Compare>(c));
162 }
163 
164 /** @struct RelPathCompare
165  *  @brief Compare two strings after removing an optional prefix.
166  */
167 struct RelPathCompare
168 {
169     /** @brief Construct a RelPathCompare comparison functor.
170      *
171      *  @param[in] p - The prefix to check for and remove.
172      */
173     explicit RelPathCompare(const char* p) : prefix(p)
174     {}
175 
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 };
205 } // namespace manager
206 } // namespace inventory
207 } // namespace phosphor
208 
209 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
210