| #pragma once |
| |
| #include <utility> |
| #include <memory> |
| #include <sdbusplus/message.hpp> |
| #include "utils.hpp" |
| |
| namespace phosphor |
| { |
| namespace inventory |
| { |
| namespace manager |
| { |
| |
| class Manager; |
| namespace details |
| { |
| using FilterBase = holder::CallableBase< |
| bool, sdbusplus::message::message&, Manager&>; |
| using FilterBasePtr = std::shared_ptr<FilterBase>; |
| template <typename T> |
| using Filter = holder::CallableHolder< |
| T, bool, sdbusplus::message::message&, Manager&>; |
| |
| /** @struct Event |
| * @brief Event object interface. |
| */ |
| struct Event |
| { |
| enum class Type |
| { |
| DBUS_SIGNAL, |
| }; |
| |
| virtual ~Event() = default; |
| Event(const Event&) = default; |
| Event& operator=(const Event&) = default; |
| Event(Event&&) = default; |
| Event& operator=(Event&&) = default; |
| explicit Event(Type t) : type(t) {} |
| |
| Type type; |
| }; |
| |
| using EventBasePtr = std::shared_ptr<Event>; |
| |
| /** @struct DbusSignal |
| * @brief DBus signal event. |
| * |
| * DBus signal events are an association of a match signature |
| * and filtering function object. |
| */ |
| struct DbusSignal final : |
| public Event, |
| public std::tuple<const char *, FilterBasePtr> |
| { |
| virtual ~DbusSignal() = default; |
| DbusSignal(const DbusSignal&) = default; |
| DbusSignal & operator=(const DbusSignal&) = delete; |
| DbusSignal(DbusSignal&&) = default; |
| DbusSignal& operator=(DbusSignal&&) = default; |
| |
| /** @brief Import from signature and filter constructor. |
| * |
| * @param[in] sig - The DBus match signature. |
| * @param[in] filter - A DBus signal match callback filtering function. |
| */ |
| DbusSignal(const char *sig, FilterBasePtr filter) : |
| Event(Type::DBUS_SIGNAL), |
| std::tuple<const char *, FilterBasePtr>( |
| sig, std::move(filter)) {} |
| }; |
| |
| /** @brief make_filter |
| * |
| * Adapt a filter function object. |
| * |
| * @param[in] filter - The filter being adapted. |
| * @returns - The adapted filter. |
| * |
| * @tparam T - The type of the filter being adapted. |
| */ |
| template <typename T> |
| auto make_filter(T&& filter) |
| { |
| return Filter<T>::template make_shared<Filter<T>>( |
| std::forward<T>(filter)); |
| } |
| } // namespace details |
| |
| namespace filters |
| { |
| namespace details |
| { |
| namespace property_condition |
| { |
| |
| /** @struct PropertyCondition |
| * @brief Match filter functor that tests a property value. |
| * |
| * @tparam T - The type of the property being tested. |
| * @tparam U - The type of the condition checking functor. |
| */ |
| template <typename T, typename U> |
| struct PropertyCondition |
| { |
| PropertyCondition() = delete; |
| ~PropertyCondition() = default; |
| PropertyCondition(const PropertyCondition&) = default; |
| PropertyCondition & operator=(const PropertyCondition&) = delete; |
| PropertyCondition(PropertyCondition&&) = default; |
| PropertyCondition& operator=(PropertyCondition&&) = default; |
| PropertyCondition(const char *iface, const char *property, U &&condition) : |
| _iface(iface), |
| _property(property), |
| _condition(std::forward<U>(condition)) { } |
| |
| /** @brief Test a property value. |
| * |
| * Extract the property from the PropertiesChanged |
| * message and run the condition test. |
| */ |
| bool operator()(sdbusplus::message::message &msg, Manager &) const |
| { |
| std::map< |
| std::string, |
| sdbusplus::message::variant<T>> properties; |
| const char *iface = nullptr; |
| |
| msg.read(iface); |
| if(strcmp(iface, _iface)) |
| return false; |
| |
| msg.read(properties); |
| auto it = properties.find(_property); |
| if(it == properties.cend()) |
| return false; |
| |
| return _condition(it->second.template get<T>()); |
| } |
| |
| private: |
| const char *_iface; |
| const char *_property; |
| U _condition; |
| }; |
| |
| } // namespace property_condition |
| } // namespace details |
| |
| /** @brief The default filter. */ |
| inline bool none(sdbusplus::message::message &, Manager &) noexcept |
| { |
| return true; |
| } |
| |
| /** @brief Implicit type deduction for constructing PropertyCondition. */ |
| template <typename T> |
| auto propertyChangedTo( |
| const char *iface, |
| const char *property, |
| T val) |
| { |
| auto condition = [val = std::move(val)](const std::string &arg) |
| { |
| return arg == val; |
| }; |
| using U = decltype(condition); |
| return details::property_condition::PropertyCondition<T, U>( |
| iface, property, std::move(condition)); |
| } |
| |
| } // namespace filters |
| } // namespace manager |
| } // namespace inventory |
| } // namespace phosphor |
| |
| // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |