File indexing completed on 2025-01-18 09:57:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #pragma once
0012
0013 #include <Gaudi/Details/PropertyBase.h>
0014 #include <Gaudi/Parsers/CommonParsers.h>
0015 #include <Gaudi/Parsers/InputData.h>
0016 #include <Gaudi/PropertyFwd.h>
0017 #include <GaudiKernel/TaggedBool.h>
0018 #include <GaudiKernel/ToStream.h>
0019 #include <string>
0020 #include <utility>
0021
0022 namespace Gaudi::Details::Property {
0023 using ImmediatelyInvokeHandler = Gaudi::tagged_bool<class ImmediatelyInvokeHandler_tag>;
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 template <class TYPE>
0048 struct DefaultStringConverterImpl {
0049 public:
0050 virtual ~DefaultStringConverterImpl() = default;
0051 std::string toString( const TYPE& v ) {
0052 using Gaudi::Utils::toString;
0053 return toString( v );
0054 }
0055
0056
0057
0058
0059 virtual TYPE fromString( const TYPE& ref_value, const std::string& s ) = 0;
0060
0061 protected:
0062 void fromStringImpl( TYPE& buffer, const std::string& s ) {
0063 using Gaudi::Parsers::InputData;
0064 if ( !parse( buffer, InputData{ s } ).isSuccess() ) {
0065 throw std::invalid_argument( "cannot parse '" + s + "' to " + System::typeinfoName( typeid( TYPE ) ) );
0066 }
0067 }
0068 };
0069
0070
0071 template <>
0072 inline std::string DefaultStringConverterImpl<std::string>::toString( const std::string& v ) {
0073 return v;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083 template <typename TYPE, typename Enable = void>
0084 struct DefaultStringConverter : DefaultStringConverterImpl<TYPE> {
0085 TYPE fromString( const TYPE& ref_value, const std::string& s ) final override {
0086 TYPE buffer = ref_value;
0087 this->fromStringImpl( buffer, s );
0088 return buffer;
0089 }
0090 };
0091
0092 template <class TYPE>
0093 struct DefaultStringConverter<TYPE, std::enable_if_t<std::is_default_constructible_v<TYPE>>>
0094 : DefaultStringConverterImpl<TYPE> {
0095 TYPE fromString( const TYPE& , const std::string& s ) final override {
0096 TYPE buffer{};
0097 this->fromStringImpl( buffer, s );
0098 return buffer;
0099 }
0100 };
0101
0102
0103 template <typename TYPE>
0104 struct StringConverter : DefaultStringConverter<TYPE> {};
0105
0106 struct NullVerifier {
0107 template <class TYPE>
0108 void operator()( const TYPE& ) const {}
0109 };
0110 template <class TYPE>
0111 struct BoundedVerifier {
0112 void operator()( const TYPE& value ) const {
0113 using Gaudi::Utils::toString;
0114
0115 if ( ( m_hasLowerBound && ( value < m_lowerBound ) ) || ( m_hasUpperBound && ( m_upperBound < value ) ) )
0116 throw std::out_of_range( "value " + toString( value ) + " outside range" );
0117 }
0118
0119
0120 bool hasLower() const { return m_hasLowerBound; }
0121
0122 bool hasUpper() const { return m_hasUpperBound; }
0123
0124 const TYPE& lower() const { return m_lowerBound; }
0125
0126 const TYPE& upper() const { return m_upperBound; }
0127
0128
0129 void setLower( const TYPE& value ) {
0130 m_hasLowerBound = true;
0131 m_lowerBound = value;
0132 }
0133
0134 void setUpper( const TYPE& value ) {
0135 m_hasUpperBound = true;
0136 m_upperBound = value;
0137 }
0138
0139 void clearLower() {
0140 m_hasLowerBound = false;
0141 m_lowerBound = TYPE();
0142 }
0143
0144 void clearUpper() {
0145 m_hasUpperBound = false;
0146 m_upperBound = TYPE();
0147 }
0148
0149
0150 void setBounds( const TYPE& lower, const TYPE& upper ) {
0151 setLower( lower );
0152 setUpper( upper );
0153 }
0154
0155
0156 void clearBounds() {
0157 clearLower();
0158 clearUpper();
0159 }
0160
0161 private:
0162
0163 bool m_hasLowerBound{ false };
0164 bool m_hasUpperBound{ false };
0165 TYPE m_lowerBound{};
0166 TYPE m_upperBound{};
0167 };
0168
0169
0170 struct SwapCall {
0171 using callback_t = std::function<void( PropertyBase& )>;
0172 callback_t tmp, &orig;
0173 SwapCall( callback_t& input ) : orig( input ) { tmp.swap( orig ); }
0174 ~SwapCall() { orig.swap( tmp ); }
0175 void operator()( PropertyBase& p ) const { tmp( p ); }
0176 };
0177
0178 struct NoHandler {
0179 void useReadHandler( const PropertyBase& ) const {}
0180 void setReadHandler( std::function<void( PropertyBase& )> ) {
0181 throw std::logic_error( "setReadHandler not implemented for this class" );
0182 }
0183 std::function<void( PropertyBase& )> getReadHandler() const { return nullptr; }
0184 void useUpdateHandler( const PropertyBase& ) const {}
0185 void setUpdateHandler( std::function<void( PropertyBase& )> ) {
0186 throw std::logic_error( "setUpdateHandler not implemented for this class" );
0187 }
0188 std::function<void( PropertyBase& )> getUpdateHandler() const { return nullptr; }
0189 };
0190 struct ReadHandler : NoHandler {
0191 mutable std::function<void( PropertyBase& )> m_readCallBack;
0192 void useReadHandler( const PropertyBase& p ) const {
0193 if ( m_readCallBack ) { SwapCall{ m_readCallBack }( const_cast<PropertyBase&>( p ) ); }
0194 }
0195 void setReadHandler( std::function<void( PropertyBase& )> fun ) { m_readCallBack = std::move( fun ); }
0196 std::function<void( PropertyBase& )> getReadHandler() const { return m_readCallBack; }
0197 };
0198 struct UpdateHandler : NoHandler {
0199 std::function<void( PropertyBase& )> m_updateCallBack;
0200 void useUpdateHandler( PropertyBase& p ) {
0201 if ( m_updateCallBack ) {
0202 try {
0203 SwapCall{ m_updateCallBack }( p );
0204 } catch ( const std::exception& x ) {
0205 throw std::invalid_argument( "failure in update handler of '" + p.name() + "': " + x.what() );
0206 }
0207 }
0208 }
0209 void setUpdateHandler( std::function<void( PropertyBase& )> fun ) { m_updateCallBack = std::move( fun ); }
0210 std::function<void( PropertyBase& )> getUpdateHandler() const { return m_updateCallBack; }
0211 };
0212 struct ReadUpdateHandler : ReadHandler, UpdateHandler {
0213 using ReadHandler::getReadHandler;
0214 using ReadHandler::setReadHandler;
0215 using ReadHandler::useReadHandler;
0216 using UpdateHandler::getUpdateHandler;
0217 using UpdateHandler::setUpdateHandler;
0218 using UpdateHandler::useUpdateHandler;
0219 };
0220
0221 enum class ParsingErrorPolicy { Ignore, Warning, Exception, Abort };
0222 ParsingErrorPolicy parsingErrorPolicy();
0223 ParsingErrorPolicy setParsingErrorPolicy( ParsingErrorPolicy p );
0224 }