/* * ValueTrigger.hh * * Created on: 22 апр. 2020 г. * Author: LeonidTitov */ #ifndef UMLIBRARY_SCHEMATIC_VALUETRIGGER_HH_ #define UMLIBRARY_SCHEMATIC_VALUETRIGGER_HH_ #include #include #include #include #include "../systemic/IValue.hpp" #include namespace schematic { class ValueTrigger : public systemic::IValue { public: typedef uint16_t Type; typedef uint16_t Id; template 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 threshold = std::make_pair( nullptr, 0 ) ); void reset( bool state ); operator bool() const; ValueTrigger( std::pmr::memory_resource * description ); void get_threshold( std::pair buff ) const; private: systemic::IValue * implement; bool state; struct TriggerInterface { virtual systemic::IValue * setup( Id id, Condition condition, Value value, std::pair threshold ) = 0; virtual void get_threshold( std::pair buff ) const = 0; virtual ~TriggerInterface() = default; }; TriggerInterface * trigger_interface; template struct TriggerProvider : public TriggerInterface { typedef typename ValueContainer::InterfaceType Interface; typedef typename ValueContainer::Type Type; systemic::IValue * setup( Id id, Condition condition, Value value, std::pair threshold ); void get_threshold( std::pair 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 { 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, std::pmr::polymorphic_allocator< std::pair< const Type, TriggerInterface * > > > TriggerProviders; TriggerProviders triggers; }; } template 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 > locator( triggers.get_allocator().resource() ); TriggerProvider * provider = locator.allocate(1); locator.construct( provider, container ); triggers.insert( iter, std::pair< const Type, TriggerInterface * >( type_code, provider ) ); } } template inline systemic::IValue * schematic::ValueTrigger::TriggerProvider< ValueContainer>::setup( Id id, Condition condition, Value value, std::pair binary_threshold ) { systemic::IValue * trigger = nullptr; Interface * interface = container.get( id ); bool self_check = dynamic_cast(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 inline schematic::ValueTrigger::TriggerProvider::TriggerProvider( ValueContainer & c ) : container(c) {} template inline schematic::ValueTrigger::TriggerProvider::TriggerImplementation::TriggerImplementation( Interface * value, Type threshold, Condition condition, bool update_threshold ) : value(value), threshold(threshold), condition(condition), update_threshold(update_threshold) {} template inline schematic::ValueTrigger::TriggerProvider::TriggerImplementation::TriggerImplementation( const TriggerImplementation & right ) : value(right.value), threshold(right.threshold), condition(right.condition), update_threshold(right.update_threshold) {} template inline typename schematic::ValueTrigger::TriggerProvider::TriggerImplementation & schematic::ValueTrigger::TriggerProvider::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_ */