1 #pragma once 2 3 #include <sdbusplus/message/native_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<T, Arg, 51 typename std::enable_if_t<std::is_convertible_v<Arg, T>>> 52 { 53 static auto make(Arg&& arg) 54 { 55 return T(std::forward<Arg>(arg)); 56 } 57 }; 58 59 /** @struct Make 60 * @brief Return variant visitor. 61 * 62 * struct Make specialization if Arg is a string, but not otherwise 63 * directly convertable by C++ conversion constructors. Strings might 64 * be convertable using underlying sdbusplus routines, so give them an 65 * attempt. 66 */ 67 template <typename T, typename Arg> 68 struct Make< 69 T, Arg, 70 typename std::enable_if_t< 71 !std::is_convertible_v<Arg, T> && 72 std::is_same_v<std::string, 73 std::remove_cv_t<std::remove_reference_t<Arg>>> && 74 sdbusplus::message::has_convert_from_string_v<T>>> 75 { 76 static auto make(Arg&& arg) -> T 77 { 78 auto r = sdbusplus::message::convert_from_string<T>( 79 std::forward<Arg>(arg)); 80 if (r) 81 { 82 return *r; 83 } 84 85 throw std::runtime_error( 86 std::string("Invalid conversion in MakeVariantVisitor::") + 87 __PRETTY_FUNCTION__); 88 89 return {}; 90 } 91 }; 92 93 /** @brief Make variant visitor. */ 94 template <typename Arg> 95 auto operator()(Arg&& arg) const 96 { 97 return Make<V, Arg>::make(arg); 98 } 99 }; 100 101 /** @brief Convert variants with different contained types. 102 * 103 * @tparam V - The desired variant type. 104 * @tparam Arg - The source variant type. 105 * 106 * @param[in] v - The source variant. 107 * @returns - The converted variant. 108 */ 109 template <typename V, typename Arg> 110 auto convertVariant(Arg&& v) 111 { 112 return std::visit(MakeVariantVisitor<V>(), v); 113 } 114 115 /** @struct CompareFirst 116 * @brief std::pair binary comparison adapter. 117 * 118 * Adapt a binary comparison function to a comparison of 119 * the first pair element. 120 * 121 * @tparam Compare - The function object type being adapted. 122 */ 123 template <typename Compare> 124 struct CompareFirst 125 { 126 /** @brief Construct a CompareFirst adapter. 127 * 128 * @param[in] c - The function object being adapted. 129 */ 130 explicit CompareFirst(Compare&& c) : compare(std::forward<Compare>(c)) 131 {} 132 133 /** @brief Compare two pairs adapter. 134 * 135 * @tparam L1 - First pair first_type. 136 * @tparam L2 - First pair second_type. 137 * @tparam R1 - Second pair first_type, convertible to L1. 138 * @tparam R2 - Second pair second_type. 139 * 140 * @param[in] l - The first pair. 141 * @param[in] r - The second pair. 142 * 143 * @returns - The result of the comparison. 144 */ 145 template <typename L1, typename L2, typename R1, typename R2> 146 bool operator()(const std::pair<L1, L2>& l, 147 const std::pair<R1, R2>& r) const 148 { 149 return compare(l.first, r.first); 150 } 151 152 /** @brief Compare one pair adapter. 153 * 154 * @tparam L1 - Pair first_type. 155 * @tparam L2 - Pair second_type. 156 * @tparam R - Convertible to L1 for comparison. 157 * 158 * @param[in] l - The pair. 159 * @param[in] r - To be compared to l.first. 160 * 161 * @returns - The result of the comparison. 162 */ 163 template <typename L1, typename L2, typename R> 164 bool operator()(const std::pair<L1, L2>& l, const R& r) const 165 { 166 return compare(l.first, r); 167 } 168 169 /** @brief Compare one pair adapter. 170 * 171 * @tparam L - Convertible to R1 for comparison. 172 * @tparam R1 - Pair first_type. 173 * @tparam R2 - Pair second_type. 174 * 175 * @param[in] l - To be compared to r.first. 176 * @param[in] r - The pair. 177 * 178 * @returns - The result of the comparison. 179 */ 180 template <typename L, typename R1, typename R2> 181 bool operator()(const L& l, const std::pair<R1, R2>& r) const 182 { 183 return compare(l, r.first); 184 } 185 186 /* @brief The function being adapted. */ 187 Compare compare; 188 }; 189 190 /* @brief Implicit template instantation wrapper for CompareFirst. */ 191 template <typename Compare> 192 CompareFirst<Compare> compareFirst(Compare&& c) 193 { 194 return CompareFirst<Compare>(std::forward<Compare>(c)); 195 } 196 197 /** @struct RelPathCompare 198 * @brief Compare two strings after removing an optional prefix. 199 */ 200 struct RelPathCompare 201 { 202 /** @brief Construct a RelPathCompare comparison functor. 203 * 204 * @param[in] p - The prefix to check for and remove. 205 */ 206 explicit RelPathCompare(const char* p) : prefix(p) 207 {} 208 209 /** @brief Check for the prefix and remove if found. 210 * 211 * @param[in] s - The string to check for and remove prefix from. 212 */ 213 auto relPath(const std::string& s) const 214 { 215 if (s.find(prefix) == 0) 216 { 217 return s.substr(strlen(prefix)); 218 } 219 220 return s; 221 } 222 223 /** @brief Comparison method. 224 * 225 * @param[in] l - The first string. 226 * @param[in] r - The second string. 227 * 228 * @returns - The result of the comparison. 229 */ 230 bool operator()(const std::string& l, const std::string& r) const 231 { 232 return relPath(l) < relPath(r); 233 } 234 235 /* The path prefix to remove when comparing two paths. */ 236 const char* prefix; 237 }; 238 } // namespace manager 239 } // namespace inventory 240 } // namespace phosphor 241 242 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 243