xref: /openbmc/phosphor-inventory-manager/utils.hpp (revision 51aff45e80ec084fb86c634ef84f6ce0a0bb5624)
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