// 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(
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(
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(
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(
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(
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(
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(
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(
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
auto Flatten(const Group& group, const State& state) -> State
{
using REACT_IMPL::FlattenStateNode;
using REACT_IMPL::SameGroupOrLink;
using REACT_IMPL::CreateWrappedNode;
return CreateWrappedNode(group, SameGroupOrLink(group, state));
}
template
auto Flatten(const State& state) -> State
{ return Flatten(state.GetGroup(), state); }
///////////////////////////////////////////////////////////////////////////////////////////////////
/// FlattenList
///////////////////////////////////////////////////////////////////////////////////////////////////
template
auto FlattenList(const Group& group, const State& list) -> State
{
using REACT_IMPL::FlattenStateListNode;
using REACT_IMPL::SameGroupOrLink;
using REACT_IMPL::CreateWrappedNode;
return CreateWrappedNode(
group, SameGroupOrLink(group, list));
}
template
auto FlattenList(const State& list) -> State
{ return FlattenList(list.GetGroup(), list); }
///////////////////////////////////////////////////////////////////////////////////////////////////
/// FlattenMap
///////////////////////////////////////////////////////////////////////////////////////////////////
template
auto FlattenMap(const Group& group, const State& map) -> State
{
using REACT_IMPL::FlattenStateMapNode;
using REACT_IMPL::SameGroupOrLink;
using REACT_IMPL::CreateWrappedNode;
return CreateWrappedNode(
group, SameGroupOrLink(group, map));
}
template
auto FlattenMap(const State& map) -> State
{ return FlattenMap(map.GetGroup(), map); }
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Flattened
///////////////////////////////////////////////////////////////////////////////////////////////////
template
class Flattened : public C
{
public:
using C::C;
Flattened(const C& base) :
C( base )
{ }
Flattened(const C& base, REACT_IMPL::FlattenedInitTag) :
C( base ),
initMode_( true )
{ }
Flattened(const C& base, REACT_IMPL::FlattenedInitTag, std::vector&& emptyMemberIds) :
C( base ),
initMode_( true ),
memberIds_( std::move(emptyMemberIds) ) // This will be empty, but has pre-allocated storage. It's a tweak.
{ }
template
Ref Flatten(State& signal)
{
if (initMode_)
memberIds_.push_back(GetInternals(signal).GetNodeId());
return GetInternals(signal).Value();
}
private:
bool initMode_ = false;
std::vector memberIds_;
template
friend class impl::FlattenObjectNode;
};
///////////////////////////////////////////////////////////////////////////////////////////////////
/// FlattenObject
///////////////////////////////////////////////////////////////////////////////////////////////////
template
auto FlattenObject(const Group& group, const State& obj) -> State
{
using REACT_IMPL::FlattenObjectNode;
using REACT_IMPL::SameGroupOrLink;
using REACT_IMPL::CreateWrappedNode;
return CreateWrappedNode(group, obj);
}
template
auto FlattenObject(const State& obj) -> State
{ return FlattenObject(obj.GetGroup(), obj); }
template
auto FlattenObject(const Group& group, const State& obj) -> State
{
using REACT_IMPL::FlattenObjectNode;
using REACT_IMPL::SameGroupOrLink;
using REACT_IMPL::CreateWrappedNode;
return CreateWrappedNode(group, obj);
}
template
auto FlattenObject(const State& obj) -> State
{ return FlattenObject(obj.GetGroup(), obj); }
/******************************************/ REACT_END /******************************************/
#endif // REACT_ALGORITHM_H_INCLUDED