MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/schematic/ValueTrigger.hh
2024-06-07 11:12:56 +03:00

236 lines
7.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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