225 lines
6.6 KiB
C++
225 lines
6.6 KiB
C++
|
|
/*
|
|||
|
|
* ValueTrigger.hh
|
|||
|
|
*
|
|||
|
|
* Created on: 22 <EFBFBD><EFBFBD><EFBFBD>. 2020 <EFBFBD>.
|
|||
|
|
* 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 ~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) );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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, bool update_threshold );
|
|||
|
|
TriggerImplementation( const TriggerImplementation & right );
|
|||
|
|
TriggerImplementation & operator=( const TriggerImplementation & right );
|
|||
|
|
|
|||
|
|
Interface * value;
|
|||
|
|
mutable Type threshold;
|
|||
|
|
Condition condition;
|
|||
|
|
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 == 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,
|
|||
|
|
bool update_threshold ) : value(value), threshold(threshold), condition(condition), 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_ */
|