Add support for processing signal event triggers

Process signal event triggers' list of conditions on a group and perform
the defined actions.

This re-uses the following struct directly from
phosphor-inventory-manager:
--struct PropertyChangedCondition

Change-Id: I98552f3d168cfcd9f0c1c357289b7000374ae60e
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/src/functor.hpp b/src/functor.hpp
index c2c586e..b3ad9a0 100644
--- a/src/functor.hpp
+++ b/src/functor.hpp
@@ -23,6 +23,59 @@
     return Action(std::forward<T>(action));
 }
 
+template <typename T, typename U>
+struct PropertyChangedCondition
+{
+    PropertyChangedCondition() = delete;
+    ~PropertyChangedCondition() = default;
+    PropertyChangedCondition(const PropertyChangedCondition&) = default;
+    PropertyChangedCondition& operator=(const PropertyChangedCondition&) =
+        default;
+    PropertyChangedCondition(PropertyChangedCondition&&) = default;
+    PropertyChangedCondition& operator=(PropertyChangedCondition&&) =
+        default;
+    PropertyChangedCondition(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::bus::bus&,
+        sdbusplus::message::message& msg,
+        Monitor&) const
+    {
+        std::map<std::string, sdbusplus::message::variant<T>> properties;
+        const char* iface = nullptr;
+
+        msg.read(iface);
+        if (!iface || strcmp(iface, _iface))
+        {
+            return false;
+        }
+
+        msg.read(properties);
+        auto it = properties.find(_property);
+        if (it == properties.cend())
+        {
+            return false;
+        }
+
+        return _condition(
+                   std::forward<T>(it->second.template get<T>()));
+    }
+
+private:
+    const char* _iface;
+    const char* _property;
+    U _condition;
+};
+
 struct PropertyConditionBase
 {
     PropertyConditionBase() = delete;
@@ -125,6 +178,16 @@
 };
 
 template <typename T, typename U>
+auto propertySignal(const char* iface,
+                    const char* property,
+                    U&& condition)
+{
+    return PropertyChangedCondition<T, U>(iface,
+                                          property,
+                                          std::move(condition));
+}
+
+template <typename T, typename U>
 auto propertyStart(const char* path,
                    const char* iface,
                    const char* property,