1 #pragma once 2 3 #include <utility> 4 #include <memory> 5 #include <sdbusplus/message.hpp> 6 #include "utils.hpp" 7 8 namespace phosphor 9 { 10 namespace inventory 11 { 12 namespace manager 13 { 14 15 class Manager; 16 namespace details 17 { 18 using FilterBase = holder::CallableBase< 19 bool, sdbusplus::message::message&, Manager&>; 20 using FilterBasePtr = std::shared_ptr<FilterBase>; 21 template <typename T> 22 using Filter = holder::CallableHolder< 23 T, bool, sdbusplus::message::message&, Manager&>; 24 25 /** @brief make_filter 26 * 27 * Adapt a filter function object. 28 * 29 * @param[in] filter - The filter being adapted. 30 * @returns - The adapted filter. 31 * 32 * @tparam T - The type of the filter being adapted. 33 */ 34 template <typename T> 35 auto make_filter(T&& filter) 36 { 37 return Filter<T>::template make_shared<Filter<T>>( 38 std::forward<T>(filter)); 39 } 40 } // namespace details 41 42 namespace filters 43 { 44 namespace details 45 { 46 namespace property_condition 47 { 48 49 /** @struct PropertyCondition 50 * @brief Match filter functor that tests a property value. 51 * 52 * @tparam T - The type of the property being tested. 53 * @tparam U - The type of the condition checking functor. 54 */ 55 template <typename T, typename U> 56 struct PropertyCondition 57 { 58 PropertyCondition() = delete; 59 ~PropertyCondition() = default; 60 PropertyCondition(const PropertyCondition&) = default; 61 PropertyCondition & operator=(const PropertyCondition&) = delete; 62 PropertyCondition(PropertyCondition&&) = default; 63 PropertyCondition& operator=(PropertyCondition&&) = default; 64 PropertyCondition(const char *iface, const char *property, U &&condition) : 65 _iface(iface), 66 _property(property), 67 _condition(std::forward<U>(condition)) { } 68 69 /** @brief Test a property value. 70 * 71 * Extract the property from the PropertiesChanged 72 * message and run the condition test. 73 */ 74 bool operator()(sdbusplus::message::message &msg, Manager &) const 75 { 76 std::map< 77 std::string, 78 sdbusplus::message::variant<T>> properties; 79 const char *iface = nullptr; 80 81 msg.read(iface); 82 if(strcmp(iface, _iface)) 83 return false; 84 85 msg.read(properties); 86 auto it = properties.find(_property); 87 if(it == properties.cend()) 88 return false; 89 90 return _condition(it->second); 91 } 92 93 private: 94 const char *_iface; 95 const char *_property; 96 U _condition; 97 }; 98 99 } // namespace property_condition 100 } // namespace details 101 102 /** @brief The default filter. */ 103 inline bool none(sdbusplus::message::message &, Manager &) noexcept 104 { 105 return true; 106 } 107 108 /** @brief Implicit type deduction for constructing PropertyCondition. */ 109 template <typename T> 110 auto propertyChangedTo( 111 const char *iface, 112 const char *property, 113 T val) 114 { 115 auto condition = [val = std::move(val)](auto arg){return arg == val;}; 116 using U = decltype(condition); 117 return details::property_condition::PropertyCondition<T, U>( 118 iface, property, std::move(condition)); 119 } 120 121 } // namespace filters 122 } // namespace manager 123 } // namespace inventory 124 } // namespace phosphor 125 126 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 127