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