165ffffa9SBrad Bishop #pragma once
265ffffa9SBrad Bishop
3706a9fccSPatrick Williams #include <sdbusplus/message/native_types.hpp>
4a83db30eSBrad Bishop
5a83db30eSBrad Bishop #include <cstring>
6d3d188d5SBrad Bishop #include <stdexcept>
7d3d188d5SBrad Bishop #include <string>
8d3d188d5SBrad Bishop #include <type_traits>
9d3d188d5SBrad Bishop #include <utility>
10d3d188d5SBrad Bishop
1165ffffa9SBrad Bishop namespace phosphor
1265ffffa9SBrad Bishop {
1365ffffa9SBrad Bishop namespace inventory
1465ffffa9SBrad Bishop {
1565ffffa9SBrad Bishop namespace manager
1665ffffa9SBrad Bishop {
179bbfcb18SBrad Bishop /** @struct MakeVariantVisitor
189bbfcb18SBrad Bishop * @brief Return a variant if the visited type is a possible variant type.
199bbfcb18SBrad Bishop *
209bbfcb18SBrad Bishop * @tparam V - The desired variant type.
219bbfcb18SBrad Bishop */
22a680d1efSPatrick Venture template <typename V>
23a680d1efSPatrick Venture struct MakeVariantVisitor
249bbfcb18SBrad Bishop {
259bbfcb18SBrad Bishop /** @struct Make
269bbfcb18SBrad Bishop * @brief Return variant visitor.
279bbfcb18SBrad Bishop *
289bbfcb18SBrad Bishop * @tparam T - The variant type to return.
299bbfcb18SBrad Bishop * @tparam Arg - The type being visited in the source variant.
309bbfcb18SBrad Bishop * @tparam Enable - Overload resolution removal.
319bbfcb18SBrad Bishop */
32a680d1efSPatrick Venture template <typename T, typename Arg, typename Enable = void>
33a680d1efSPatrick Venture struct Make
349bbfcb18SBrad Bishop {
makephosphor::inventory::manager::MakeVariantVisitor::Make3523314a5cSGeorge Liu static auto make(Arg&& /* arg */)
369bbfcb18SBrad Bishop {
376e94b652SWilliam A. Kennington III throw std::runtime_error(
384ccd3960SPatrick Williams std::string("Invalid conversion in MakeVariantVisitor::") +
394ccd3960SPatrick Williams __PRETTY_FUNCTION__);
409bbfcb18SBrad Bishop return T();
419bbfcb18SBrad Bishop }
429bbfcb18SBrad Bishop };
4365ffffa9SBrad Bishop
449bbfcb18SBrad Bishop /** @struct Make
459bbfcb18SBrad Bishop * @brief Return variant visitor.
469bbfcb18SBrad Bishop *
47a18caeaaSSantosh Puranik * struct Make specialization if Arg is in T (int -> variant<int, char>),
48a18caeaaSSantosh Puranik * but not a string. Strings are used to represent enumerations by
49a18caeaaSSantosh Puranik * sdbusplus, so they are attempted in the following specialization.
509bbfcb18SBrad Bishop */
519bbfcb18SBrad Bishop template <typename T, typename Arg>
52a18caeaaSSantosh Puranik struct Make<
53a18caeaaSSantosh Puranik T, Arg,
54a18caeaaSSantosh Puranik typename std::enable_if_t<
55a18caeaaSSantosh Puranik !std::is_same_v<std::string,
56a18caeaaSSantosh Puranik std::remove_cv_t<std::remove_reference_t<Arg>>> &&
57a18caeaaSSantosh Puranik std::is_convertible_v<Arg, T>>>
589bbfcb18SBrad Bishop {
makephosphor::inventory::manager::MakeVariantVisitor::Make599bbfcb18SBrad Bishop static auto make(Arg&& arg)
609bbfcb18SBrad Bishop {
619bbfcb18SBrad Bishop return T(std::forward<Arg>(arg));
629bbfcb18SBrad Bishop }
639bbfcb18SBrad Bishop };
649bbfcb18SBrad Bishop
65706a9fccSPatrick Williams /** @struct Make
66706a9fccSPatrick Williams * @brief Return variant visitor.
67706a9fccSPatrick Williams *
68a18caeaaSSantosh Puranik * struct Make specialization if Arg is a string.Strings might
69a18caeaaSSantosh Puranik * be convertable (for ex. to enumerations) using underlying sdbusplus
70a18caeaaSSantosh Puranik * routines, so give them an attempt. In case the string is not convertible
71a18caeaaSSantosh Puranik * to an enumeration, sdbusplus::message::convert_from_string will return a
72a18caeaaSSantosh Puranik * string back anyway.
73706a9fccSPatrick Williams */
74706a9fccSPatrick Williams template <typename T, typename Arg>
75706a9fccSPatrick Williams struct Make<
76706a9fccSPatrick Williams T, Arg,
77706a9fccSPatrick Williams typename std::enable_if_t<
78706a9fccSPatrick Williams std::is_same_v<std::string,
79706a9fccSPatrick Williams std::remove_cv_t<std::remove_reference_t<Arg>>> &&
80706a9fccSPatrick Williams sdbusplus::message::has_convert_from_string_v<T>>>
81706a9fccSPatrick Williams {
makephosphor::inventory::manager::MakeVariantVisitor::Make82706a9fccSPatrick Williams static auto make(Arg&& arg) -> T
83706a9fccSPatrick Williams {
84706a9fccSPatrick Williams auto r = sdbusplus::message::convert_from_string<T>(
85706a9fccSPatrick Williams std::forward<Arg>(arg));
86706a9fccSPatrick Williams if (r)
87706a9fccSPatrick Williams {
88706a9fccSPatrick Williams return *r;
89706a9fccSPatrick Williams }
90706a9fccSPatrick Williams
91706a9fccSPatrick Williams throw std::runtime_error(
92706a9fccSPatrick Williams std::string("Invalid conversion in MakeVariantVisitor::") +
93706a9fccSPatrick Williams __PRETTY_FUNCTION__);
94706a9fccSPatrick Williams
95706a9fccSPatrick Williams return {};
96706a9fccSPatrick Williams }
97706a9fccSPatrick Williams };
98706a9fccSPatrick Williams
999bbfcb18SBrad Bishop /** @brief Make variant visitor. */
100a680d1efSPatrick Venture template <typename Arg>
operator ()phosphor::inventory::manager::MakeVariantVisitor101a680d1efSPatrick Venture auto operator()(Arg&& arg) const
1029bbfcb18SBrad Bishop {
1039bbfcb18SBrad Bishop return Make<V, Arg>::make(arg);
1049bbfcb18SBrad Bishop }
1059bbfcb18SBrad Bishop };
1069bbfcb18SBrad Bishop
1079bbfcb18SBrad Bishop /** @brief Convert variants with different contained types.
1089bbfcb18SBrad Bishop *
1099bbfcb18SBrad Bishop * @tparam V - The desired variant type.
1109bbfcb18SBrad Bishop * @tparam Arg - The source variant type.
1119bbfcb18SBrad Bishop *
1129bbfcb18SBrad Bishop * @param[in] v - The source variant.
1139bbfcb18SBrad Bishop * @returns - The converted variant.
1149bbfcb18SBrad Bishop */
115a680d1efSPatrick Venture template <typename V, typename Arg>
convertVariant(Arg && v)116a680d1efSPatrick Venture auto convertVariant(Arg&& v)
1179bbfcb18SBrad Bishop {
11826f8668dSPatrick Williams return std::visit(MakeVariantVisitor<V>(), v);
1199bbfcb18SBrad Bishop }
12086521587SBrad Bishop
12186521587SBrad Bishop /** @struct CompareFirst
12286521587SBrad Bishop * @brief std::pair binary comparison adapter.
12386521587SBrad Bishop *
12486521587SBrad Bishop * Adapt a binary comparison function to a comparison of
12586521587SBrad Bishop * the first pair element.
12686521587SBrad Bishop *
12786521587SBrad Bishop * @tparam Compare - The function object type being adapted.
12886521587SBrad Bishop */
129a680d1efSPatrick Venture template <typename Compare>
130a680d1efSPatrick Venture struct CompareFirst
13186521587SBrad Bishop {
13286521587SBrad Bishop /** @brief Construct a CompareFirst adapter.
13386521587SBrad Bishop *
13486521587SBrad Bishop * @param[in] c - The function object being adapted.
13586521587SBrad Bishop */
CompareFirstphosphor::inventory::manager::CompareFirst136*7edafe06SPatrick Williams explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c)) {}
13786521587SBrad Bishop
13886521587SBrad Bishop /** @brief Compare two pairs adapter.
13986521587SBrad Bishop *
14086521587SBrad Bishop * @tparam L1 - First pair first_type.
14186521587SBrad Bishop * @tparam L2 - First pair second_type.
14286521587SBrad Bishop * @tparam R1 - Second pair first_type, convertible to L1.
14386521587SBrad Bishop * @tparam R2 - Second pair second_type.
14486521587SBrad Bishop *
14586521587SBrad Bishop * @param[in] l - The first pair.
14686521587SBrad Bishop * @param[in] r - The second pair.
14786521587SBrad Bishop *
14886521587SBrad Bishop * @returns - The result of the comparison.
14986521587SBrad Bishop */
15086521587SBrad Bishop template <typename L1, typename L2, typename R1, typename R2>
operator ()phosphor::inventory::manager::CompareFirst151615b2a8fSBrad Bishop bool operator()(const std::pair<L1, L2>& l,
152615b2a8fSBrad Bishop const std::pair<R1, R2>& r) const
15386521587SBrad Bishop {
15486521587SBrad Bishop return compare(l.first, r.first);
15586521587SBrad Bishop }
15686521587SBrad Bishop
15786521587SBrad Bishop /** @brief Compare one pair adapter.
15886521587SBrad Bishop *
15986521587SBrad Bishop * @tparam L1 - Pair first_type.
16086521587SBrad Bishop * @tparam L2 - Pair second_type.
16186521587SBrad Bishop * @tparam R - Convertible to L1 for comparison.
16286521587SBrad Bishop *
16386521587SBrad Bishop * @param[in] l - The pair.
16486521587SBrad Bishop * @param[in] r - To be compared to l.first.
16586521587SBrad Bishop *
16686521587SBrad Bishop * @returns - The result of the comparison.
16786521587SBrad Bishop */
16886521587SBrad Bishop template <typename L1, typename L2, typename R>
operator ()phosphor::inventory::manager::CompareFirst16986521587SBrad Bishop bool operator()(const std::pair<L1, L2>& l, const R& r) const
17086521587SBrad Bishop {
17186521587SBrad Bishop return compare(l.first, r);
17286521587SBrad Bishop }
17386521587SBrad Bishop
17486521587SBrad Bishop /** @brief Compare one pair adapter.
17586521587SBrad Bishop *
17686521587SBrad Bishop * @tparam L - Convertible to R1 for comparison.
17786521587SBrad Bishop * @tparam R1 - Pair first_type.
17886521587SBrad Bishop * @tparam R2 - Pair second_type.
17986521587SBrad Bishop *
18086521587SBrad Bishop * @param[in] l - To be compared to r.first.
18186521587SBrad Bishop * @param[in] r - The pair.
18286521587SBrad Bishop *
18386521587SBrad Bishop * @returns - The result of the comparison.
18486521587SBrad Bishop */
18586521587SBrad Bishop template <typename L, typename R1, typename R2>
operator ()phosphor::inventory::manager::CompareFirst18686521587SBrad Bishop bool operator()(const L& l, const std::pair<R1, R2>& r) const
18786521587SBrad Bishop {
18886521587SBrad Bishop return compare(l, r.first);
18986521587SBrad Bishop }
19086521587SBrad Bishop
19186521587SBrad Bishop /* @brief The function being adapted. */
19286521587SBrad Bishop Compare compare;
19386521587SBrad Bishop };
19486521587SBrad Bishop
19586521587SBrad Bishop /* @brief Implicit template instantation wrapper for CompareFirst. */
196a680d1efSPatrick Venture template <typename Compare>
compareFirst(Compare && c)197a680d1efSPatrick Venture CompareFirst<Compare> compareFirst(Compare&& c)
19886521587SBrad Bishop {
19986521587SBrad Bishop return CompareFirst<Compare>(std::forward<Compare>(c));
20086521587SBrad Bishop }
20186521587SBrad Bishop
20286521587SBrad Bishop /** @struct RelPathCompare
20386521587SBrad Bishop * @brief Compare two strings after removing an optional prefix.
20486521587SBrad Bishop */
20586521587SBrad Bishop struct RelPathCompare
20686521587SBrad Bishop {
20786521587SBrad Bishop /** @brief Construct a RelPathCompare comparison functor.
20886521587SBrad Bishop *
20986521587SBrad Bishop * @param[in] p - The prefix to check for and remove.
21086521587SBrad Bishop */
RelPathComparephosphor::inventory::manager::RelPathCompare211*7edafe06SPatrick Williams explicit RelPathCompare(const char* p) : prefix(p) {}
21286521587SBrad Bishop
21386521587SBrad Bishop /** @brief Check for the prefix and remove if found.
21486521587SBrad Bishop *
21586521587SBrad Bishop * @param[in] s - The string to check for and remove prefix from.
21686521587SBrad Bishop */
relPathphosphor::inventory::manager::RelPathCompare21786521587SBrad Bishop auto relPath(const std::string& s) const
21886521587SBrad Bishop {
21986521587SBrad Bishop if (s.find(prefix) == 0)
22086521587SBrad Bishop {
22186521587SBrad Bishop return s.substr(strlen(prefix));
22286521587SBrad Bishop }
22386521587SBrad Bishop
22486521587SBrad Bishop return s;
22586521587SBrad Bishop }
22686521587SBrad Bishop
22786521587SBrad Bishop /** @brief Comparison method.
22886521587SBrad Bishop *
22986521587SBrad Bishop * @param[in] l - The first string.
23086521587SBrad Bishop * @param[in] r - The second string.
23186521587SBrad Bishop *
23286521587SBrad Bishop * @returns - The result of the comparison.
23386521587SBrad Bishop */
operator ()phosphor::inventory::manager::RelPathCompare23486521587SBrad Bishop bool operator()(const std::string& l, const std::string& r) const
23586521587SBrad Bishop {
23686521587SBrad Bishop return relPath(l) < relPath(r);
23786521587SBrad Bishop }
23886521587SBrad Bishop
23986521587SBrad Bishop /* The path prefix to remove when comparing two paths. */
24086521587SBrad Bishop const char* prefix;
24186521587SBrad Bishop };
24265ffffa9SBrad Bishop } // namespace manager
24365ffffa9SBrad Bishop } // namespace inventory
24465ffffa9SBrad Bishop } // namespace phosphor
245