// Copyright Sebastian Jeckel 2017. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef REACT_ALGORITHM_H_INCLUDED #define REACT_ALGORITHM_H_INCLUDED #pragma once #include "react/detail/defs.h" #include #include #include #include "react/api.h" #include "react/state.h" #include "react/event.h" #include "react/detail/algorithm_nodes.h" /*****************************************/ REACT_BEGIN /*****************************************/ /////////////////////////////////////////////////////////////////////////////////////////////////// /// Holds the most recent event in a state /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Hold(const Group& group, T&& initialValue, const Event& evnt) -> State { using REACT_IMPL::HoldNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; return CreateWrappedNode, HoldNode>( group, std::forward(initialValue), SameGroupOrLink(group, evnt)); } template auto Hold(T&& initialValue, const Event& evnt) -> State { return Hold(evnt.GetGroup(), std::forward(initialValue), evnt); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Emits value changes of target state. /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Monitor(const Group& group, const State& state) -> Event { using REACT_IMPL::MonitorNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; return CreateWrappedNode, MonitorNode>( group, SameGroupOrLink(group, state)); } template auto Monitor(const State& state) -> Event { return Monitor(state.GetGroup(), state); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Iteratively combines state value with values from event stream (aka Fold) /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Iterate(const Group& group, T&& initialValue, F&& func, const Event& evnt) -> State { using REACT_IMPL::IterateNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; using FuncType = typename std::decay::type; return CreateWrappedNode, IterateNode>( group, std::forward(initialValue), std::forward(func), SameGroupOrLink(group, evnt)); } template auto IterateByRef(const Group& group, T&& initialValue, F&& func, const Event& evnt) -> State { using REACT_IMPL::IterateByRefNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; using FuncType = typename std::decay::type; return CreateWrappedNode, IterateByRefNode>( group, std::forward(initialValue), std::forward(func), SameGroupOrLink(group, evnt)); } template auto Iterate(T&& initialValue, F&& func, const Event& evnt) -> State { return Iterate(evnt.GetGroup(), std::forward(initialValue), std::forward(func), evnt); } template auto IterateByRef(T&& initialValue, F&& func, const Event& evnt) -> State { return IterateByRef(evnt.GetGroup(), std::forward(initialValue), std::forward(func), evnt); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Iterate - Synced /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Iterate(const Group& group, T&& initialValue, F&& func, const Event& evnt, const State& ... states) -> State { using REACT_IMPL::SyncedIterateNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; using FuncType = typename std::decay::type; return CreateWrappedNode, SyncedIterateNode>( group, std::forward(initialValue), std::forward(func), SameGroupOrLink(group, evnt), SameGroupOrLink(group, states) ...); } template auto IterateByRef(const Group& group, T&& initialValue, F&& func, const Event& evnt, const State& ... states) -> State { using REACT_IMPL::SyncedIterateByRefNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; using FuncType = typename std::decay::type; return CreateWrappedNode, SyncedIterateByRefNode>( group, std::forward(initialValue), std::forward(func), SameGroupOrLink(group, evnt), SameGroupOrLink(group, states) ...); } template auto Iterate(T&& initialValue, F&& func, const Event& evnt, const State& ... states) -> State { return Iterate(evnt.GetGroup(), std::forward(initialValue), std::forward(func), evnt, states ...); } template auto IterateByRef(T&& initialValue, F&& func, const Event& evnt, const State& ... states) -> State { return IterateByRef(evnt.GetGroup(), std::forward(initialValue), std::forward(func), evnt, states ...); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Snapshot - Sets state value to value of other state when event is received /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Snapshot(const Group& group, const State& state, const Event& evnt) -> State { using REACT_IMPL::SnapshotNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; return CreateWrappedNode, SnapshotNode>( group, SameGroupOrLink(group, state), SameGroupOrLink(group, evnt)); } template auto Snapshot(const State& state, const Event& evnt) -> State { return Snapshot(state.GetGroup(), state, evnt); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Pulse - Emits value of target state when event is received /////////////////////////////////////////////////////////////////////////////////////////////////// template auto Pulse(const Group& group, const State& state, const Event& evnt) -> Event { using REACT_IMPL::PulseNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; return CreateWrappedNode, PulseNode>( group, SameGroupOrLink(group, state), SameGroupOrLink(group, evnt)); } template auto Pulse(const State& state, const Event& evnt) -> Event { return Pulse(state.GetGroup(), state, evnt); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Flatten /////////////////////////////////////////////////////////////////////////////////////////////////// template class TState, typename = std::enable_if_t, TState>>> auto Flatten(const Group& group, const State>& state) -> State { using REACT_IMPL::FlattenStateNode; using REACT_IMPL::SameGroupOrLink; using REACT_IMPL::CreateWrappedNode; return CreateWrappedNode, FlattenStateNode>(group, SameGroupOrLink(group, state)); } template class TState, typename = std::enable_if_t, TState>>> auto Flatten(const State>& state) -> State { return Flatten(state.GetGroup(), state); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// FlattenList /////////////////////////////////////////////////////////////////////////////////////////////////// template