summaryrefslogtreecommitdiffstats
path: root/filters.hpp
blob: e2a87e372195399687d741d2129cdeb53cb4890c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#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&>;

/** @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);
    }

    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)](auto 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
OpenPOWER on IntegriCloud