Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:29

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "COPYING".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #pragma once
0012 
0013 #include <Gaudi/PropertyFwd.h>
0014 #include <GaudiKernel/StatusCode.h>
0015 #include <GaudiKernel/System.h>
0016 #include <functional>
0017 #include <iostream>
0018 #include <set>
0019 #include <string>
0020 #include <string_view>
0021 #include <typeinfo>
0022 #include <utility>
0023 
0024 namespace Gaudi::Details {
0025   class WeakPropertyRef;
0026 
0027   // ============================================================================
0028   /** PropertyBase base class allowing PropertyBase* collections to be "homogeneous"
0029    *
0030    * \author Paul Maley
0031    * \author CTDay
0032    * \author Vanya BELYAEV ibelyaev@physics.syr.edu
0033    * \author Marco Clemencic
0034    */
0035   class GAUDI_API PropertyBase {
0036 
0037   public:
0038     /// property name
0039     const std::string name() const { return std::string{ m_name }; }
0040     /// property documentation
0041     std::string documentation() const { return std::string{ m_documentation }; }
0042     /// property semantics
0043     std::string semantics() const { return std::string{ m_semantics }; }
0044     /// property type-info
0045     const std::type_info* type_info() const { return m_typeinfo; }
0046     /// property type
0047     std::string type() const { return m_typeinfo->name(); }
0048     ///  export the property value to the destination
0049     virtual bool load( PropertyBase& dest ) const = 0;
0050     /// import the property value form the source
0051     virtual bool assign( const PropertyBase& source ) = 0;
0052 
0053   public:
0054     /// value  -> string
0055     virtual std::string toString() const = 0;
0056     /// value  -> stream
0057     virtual void toStream( std::ostream& out ) const = 0;
0058     /// string -> value
0059     virtual StatusCode fromString( const std::string& value ) = 0;
0060 
0061   public:
0062     /// set new callback for reading
0063     virtual PropertyBase& declareReadHandler( std::function<void( PropertyBase& )> fun ) = 0;
0064     /// set new callback for update
0065     virtual PropertyBase& declareUpdateHandler( std::function<void( PropertyBase& )> fun ) = 0;
0066 
0067     /// get a reference to the readCallBack
0068     virtual const std::function<void( PropertyBase& )> readCallBack() const = 0;
0069     /// get a reference to the updateCallBack
0070     virtual const std::function<void( PropertyBase& )> updateCallBack() const = 0;
0071 
0072     /// manual trigger for callback for update
0073     virtual bool useUpdateHandler() = 0;
0074 
0075     template <class HT>
0076     PropertyBase& declareReadHandler( void ( HT::*MF )( PropertyBase& ), HT* instance ) {
0077       return declareReadHandler( [=]( PropertyBase& p ) { ( instance->*MF )( p ); } );
0078     }
0079 
0080     template <class HT>
0081     PropertyBase& declareUpdateHandler( void ( HT::*MF )( PropertyBase& ), HT* instance ) {
0082       return declareUpdateHandler( [=]( PropertyBase& p ) { ( instance->*MF )( p ); } );
0083     }
0084 
0085   public:
0086     /// virtual destructor
0087     virtual inline ~PropertyBase();
0088     /// set the new value for the property name
0089     void setName( std::string value ) { m_name = to_view( std::move( value ) ); }
0090     /// set the documentation string
0091     void setDocumentation( std::string value ) { m_documentation = to_view( std::move( value ) ); }
0092     /// set the semantics string
0093     void setSemantics( std::string value ) { m_semantics = to_view( std::move( value ) ); }
0094     /// the printout of the property value
0095     virtual std::ostream& fillStream( std::ostream& ) const;
0096     /// clones the current property
0097     virtual PropertyBase* clone() const = 0;
0098 
0099     /// set the type of the owner class (used for documentation)
0100     void setOwnerType( const std::type_info& ownerType ) { m_ownerType = &ownerType; }
0101 
0102     /// set the type of the owner class (used for documentation)
0103     template <class OWNER>
0104     void setOwnerType() {
0105       setOwnerType( typeid( OWNER ) );
0106     }
0107 
0108     /// get the type of the owner class (used for documentation)
0109     const std::type_info* ownerType() const { return m_ownerType; }
0110 
0111     /// get the string for the type of the owner class (used for documentation)
0112     std::string ownerTypeName() const {
0113       return m_ownerType ? System::typeinfoName( *m_ownerType ) : std::string( "unknown owner type" );
0114     }
0115 
0116   protected:
0117     /// constructor from the property name and the type
0118     PropertyBase( const std::type_info& type, std::string name = "", std::string doc = "", std::string semantics = "" )
0119         : m_name( to_view( std::move( name ) ) )
0120         , m_documentation( to_view( std::move( doc ) ) )
0121         , m_semantics( to_view( std::move( semantics ) ) )
0122         , m_typeinfo( &type ) {}
0123     /// constructor from the property name and the type
0124     PropertyBase( std::string name, const std::type_info& type )
0125         : m_name( to_view( std::move( name ) ) ), m_documentation( m_name ), m_typeinfo( &type ) {}
0126     /// copy constructor
0127     PropertyBase( const PropertyBase& ) = default;
0128     /// assignment operator
0129     PropertyBase& operator=( const PropertyBase& ) = default;
0130 
0131   private:
0132     /// helper to map a string to a reliable std::string_view
0133     static std::string_view to_view( std::string str );
0134     /// property name
0135     std::string_view m_name;
0136     /// property doc string
0137     std::string_view m_documentation;
0138     /// property semantics
0139     std::string_view m_semantics;
0140     /// property type
0141     const std::type_info* m_typeinfo;
0142     /// type of owner of the property (if defined)
0143     const std::type_info* m_ownerType = nullptr;
0144 
0145     friend WeakPropertyRef;
0146     std::set<WeakPropertyRef*> m_weakReferences;
0147     void                       add( WeakPropertyRef* ref ) {
0148       if ( ref ) m_weakReferences.insert( ref );
0149     }
0150     void remove( WeakPropertyRef* ref ) { m_weakReferences.erase( ref ); }
0151   };
0152 
0153   /// Optional reference to a property that can be used to refer to a sting or
0154   /// to the string representation of a property instance value
0155   class GAUDI_API WeakPropertyRef {
0156     friend PropertyBase;
0157 
0158   public:
0159     WeakPropertyRef() = default;
0160     WeakPropertyRef( std::string value ) : m_value{ std::move( value ) }, m_unset{ false } {}
0161     WeakPropertyRef( PropertyBase& property ) : m_property{ &property } { property.add( this ); }
0162     WeakPropertyRef( const WeakPropertyRef& other ) = delete;
0163     WeakPropertyRef( WeakPropertyRef&& other )
0164         : m_property{ other.m_property }, m_value{ std::move( other.m_value ) }, m_unset{ other.m_unset } {
0165       if ( m_property ) {
0166         other.m_property = nullptr;
0167         m_property->remove( &other );
0168         m_property->add( this );
0169       }
0170     }
0171     ~WeakPropertyRef() {
0172       if ( m_property ) m_property->remove( this );
0173     }
0174     WeakPropertyRef& operator=( WeakPropertyRef&& other ) {
0175       if ( this != &other ) {
0176         if ( m_property ) m_property->remove( this );
0177         m_property       = other.m_property;
0178         other.m_property = nullptr;
0179         if ( m_property ) {
0180           m_property->remove( &other );
0181           m_property->add( this );
0182         }
0183         m_value = std::move( other.m_value );
0184         m_unset = other.m_unset;
0185       }
0186       return *this;
0187     }
0188     WeakPropertyRef& operator=( PropertyBase& value ) {
0189       if ( m_property != &value ) {
0190         if ( m_property ) {
0191           m_property->remove( this );
0192           if ( !m_unset ) m_value = m_property->toString();
0193         }
0194         if ( !m_unset ) value.fromString( m_value ).ignore();
0195         m_property = &value;
0196         value.add( this );
0197       }
0198       return *this;
0199     }
0200     WeakPropertyRef& operator=( const std::string& value ) {
0201       if ( m_property ) m_property->fromString( value ).ignore();
0202       m_value = value;
0203       m_unset = false;
0204       return *this;
0205     }
0206     operator std::string() const;
0207 
0208     inline bool isBound() const { return m_property; }
0209     inline bool isSet() const { return !m_unset; }
0210 
0211   private:
0212     PropertyBase* m_property = nullptr;
0213     std::string   m_value;
0214     bool          m_unset = true;
0215 
0216     void detach() { m_property = nullptr; }
0217   };
0218 
0219   inline PropertyBase::~PropertyBase() {
0220     for ( auto ref : m_weakReferences ) { ref->detach(); }
0221   }
0222 
0223   inline std::ostream& operator<<( std::ostream& stream, const PropertyBase& prop ) {
0224     return prop.fillStream( stream );
0225   }
0226 } // namespace Gaudi::Details