236 lines
7.0 KiB
C++
236 lines
7.0 KiB
C++
/*
|
||
* ValueTrigger.hh
|
||
*
|
||
* Created on: 22 апр. 2020 г.
|
||
* Author: LeonidTitov
|
||
*/
|
||
|
||
#ifndef UMLIBRARY_SCHEMATIC_VALUETRIGGER_HH_
|
||
#define UMLIBRARY_SCHEMATIC_VALUETRIGGER_HH_
|
||
|
||
#include <cstddef>
|
||
#include <stdint.h>
|
||
#include <memory_resource>
|
||
#include <cstring>
|
||
|
||
#include "../systemic/IValue.hpp"
|
||
|
||
#include <map>
|
||
|
||
namespace schematic {
|
||
|
||
class ValueTrigger : public systemic::IValue<bool> {
|
||
public:
|
||
typedef uint16_t Type;
|
||
typedef uint16_t Id;
|
||
|
||
template<class ValueContainer>
|
||
void setValueContainer( ValueContainer & container, Type type_code );
|
||
|
||
enum Condition {
|
||
Less,
|
||
Great,
|
||
Equal,
|
||
NotEqual
|
||
};
|
||
|
||
enum Value {
|
||
Threshold,
|
||
Activated,
|
||
Previous
|
||
};
|
||
|
||
bool setup( Type type, Id id,
|
||
Condition condition, Value value,
|
||
std::pair<const char *, std::size_t> threshold =
|
||
std::make_pair<const char *, std::size_t>( nullptr, 0 ) );
|
||
void reset( bool state );
|
||
|
||
operator bool() const;
|
||
|
||
ValueTrigger( std::pmr::memory_resource * description );
|
||
|
||
void get_threshold( std::pair<char *, std::size_t> buff ) const;
|
||
|
||
private:
|
||
|
||
systemic::IValue<bool> * implement;
|
||
|
||
|
||
|
||
bool state;
|
||
|
||
struct TriggerInterface {
|
||
|
||
virtual systemic::IValue<bool> * setup( Id id, Condition condition, Value value,
|
||
std::pair<const char *, std::size_t> threshold ) = 0;
|
||
|
||
virtual void get_threshold( std::pair<char *, std::size_t> buff ) const = 0;
|
||
virtual Value get_value() const = 0;
|
||
virtual Condition get_condition() const = 0;
|
||
|
||
virtual ~TriggerInterface() = default;
|
||
};
|
||
|
||
TriggerInterface * trigger_interface;
|
||
|
||
template<class ValueContainer>
|
||
struct TriggerProvider : public TriggerInterface {
|
||
typedef typename ValueContainer::InterfaceType Interface;
|
||
typedef typename ValueContainer::Type Type;
|
||
|
||
systemic::IValue<bool> * setup( Id id, Condition condition, Value value,
|
||
std::pair<const char *, std::size_t> threshold );
|
||
|
||
void get_threshold( std::pair<char *, std::size_t> buff ) const {
|
||
|
||
Type threshold_value;
|
||
|
||
do {
|
||
|
||
threshold_value = trigger_implementation.threshold;
|
||
|
||
} while( threshold_value != trigger_implementation.threshold );
|
||
|
||
std::memcpy( buff.first, &threshold_value, sizeof(threshold_value) );
|
||
|
||
}
|
||
|
||
Value get_value() const {
|
||
return trigger_implementation.mode;
|
||
}
|
||
|
||
Condition get_condition() const {
|
||
return trigger_implementation.condition;
|
||
}
|
||
|
||
TriggerProvider( ValueContainer & c );
|
||
|
||
private:
|
||
ValueContainer & container;
|
||
|
||
struct TriggerImplementation : public systemic::IValue<bool> {
|
||
|
||
operator bool() const {
|
||
|
||
bool result;
|
||
|
||
Type val = *value;
|
||
|
||
switch( condition ) {
|
||
case Less: { result = val < threshold; } break;
|
||
case Great: { result = val > threshold; } break;
|
||
case Equal: { result = val == threshold; } break;
|
||
case NotEqual: { result = val != threshold; } break;
|
||
|
||
default: { result = true; } break;
|
||
}
|
||
|
||
if( update_threshold )
|
||
threshold = val;
|
||
|
||
return result;
|
||
}
|
||
|
||
TriggerImplementation() : value(nullptr), threshold(), condition(NotEqual), update_threshold(false) {}
|
||
TriggerImplementation( Interface * value, Type treshold, Condition condition, Value mode, bool update_threshold );
|
||
TriggerImplementation( const TriggerImplementation & right );
|
||
TriggerImplementation & operator=( const TriggerImplementation & right );
|
||
|
||
Interface * value;
|
||
mutable Type threshold;
|
||
Condition condition;
|
||
Value mode;
|
||
bool update_threshold;
|
||
};
|
||
|
||
TriggerImplementation trigger_implementation;
|
||
};
|
||
|
||
|
||
typedef std::map< Type, TriggerInterface *, std::less<Type>, std::pmr::polymorphic_allocator< std::pair< const Type, TriggerInterface * > > > TriggerProviders;
|
||
|
||
TriggerProviders triggers;
|
||
};
|
||
|
||
|
||
}
|
||
|
||
template<class ValueContainer>
|
||
inline void schematic::ValueTrigger::setValueContainer(
|
||
ValueContainer & container, Type type_code ) {
|
||
|
||
TriggerProviders::iterator iter = triggers.find(type_code);
|
||
|
||
if( iter == triggers.end() ) {
|
||
|
||
std::pmr::polymorphic_allocator< TriggerProvider<ValueContainer> > locator( triggers.get_allocator().resource() );
|
||
|
||
TriggerProvider<ValueContainer> * provider = locator.allocate(1);
|
||
locator.construct( provider, container );
|
||
|
||
triggers.insert( iter, std::pair< const Type, TriggerInterface * >( type_code, provider ) );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<class ValueContainer>
|
||
inline systemic::IValue<bool> * schematic::ValueTrigger::TriggerProvider<
|
||
ValueContainer>::setup( Id id, Condition condition, Value value,
|
||
std::pair<const char*, std::size_t> binary_threshold ) {
|
||
|
||
systemic::IValue<bool> * trigger = nullptr;
|
||
Interface * interface = container.get( id );
|
||
|
||
bool self_check = dynamic_cast<Interface *>(this) != interface;
|
||
|
||
if( interface and self_check ) {
|
||
|
||
Type threshold = *interface;
|
||
|
||
if( value == Threshold ) {
|
||
|
||
if( binary_threshold.second < sizeof(Type) )
|
||
return nullptr;
|
||
|
||
std::memcpy( &threshold, binary_threshold.first, sizeof(Type) );
|
||
}
|
||
|
||
trigger_implementation = TriggerImplementation( interface, threshold, condition, value, value == Previous );
|
||
|
||
trigger = &trigger_implementation;
|
||
|
||
}
|
||
|
||
return trigger;
|
||
}
|
||
|
||
template<class ValueContainer>
|
||
inline schematic::ValueTrigger::TriggerProvider<ValueContainer>::TriggerProvider(
|
||
ValueContainer & c ) : container(c) {}
|
||
|
||
template<class ValueContainer>
|
||
inline schematic::ValueTrigger::TriggerProvider<ValueContainer>::TriggerImplementation::TriggerImplementation(
|
||
Interface * value, Type threshold, Condition condition,
|
||
Value mode, bool update_threshold ) : value(value), threshold(threshold), condition(condition), mode(mode), update_threshold(update_threshold) {}
|
||
|
||
template<class ValueContainer>
|
||
inline schematic::ValueTrigger::TriggerProvider<ValueContainer>::TriggerImplementation::TriggerImplementation(
|
||
const TriggerImplementation & right ) : value(right.value), threshold(right.threshold), condition(right.condition), update_threshold(right.update_threshold) {}
|
||
|
||
template<class ValueContainer>
|
||
inline typename schematic::ValueTrigger::TriggerProvider<ValueContainer>::TriggerImplementation & schematic::ValueTrigger::TriggerProvider<ValueContainer>::TriggerImplementation::operator=(
|
||
const TriggerImplementation & right ) {
|
||
|
||
value = right.value;
|
||
threshold = right.threshold;
|
||
condition = right.condition;
|
||
update_threshold = right.update_threshold;
|
||
|
||
return *this;
|
||
|
||
}
|
||
|
||
#endif /* UMLIBRARY_SCHEMATIC_VALUETRIGGER_HH_ */
|