MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/schematic/ValueTrigger.hh

225 lines
6.6 KiB
C++
Raw Normal View History

/*
* 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_ */