Skip to content

Commit

Permalink
Simplify and fix late grammars in component properties
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkusFrankATcernch committed Nov 21, 2022
1 parent fa31a09 commit 4fd3018
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 143 deletions.
75 changes: 14 additions & 61 deletions DDCore/include/DD4hep/ComponentProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <algorithm>
#include <stdexcept>
#include <typeinfo>
#include <iostream>
#include <sstream>
#include <string>
#include <map>
Expand All @@ -29,53 +30,6 @@ namespace dd4hep {

class Property;
class BasicGrammar;
class PropertyGrammar;

/// Interface class to configure properties in components
/**
* Placeholder interface.
*
* \author M.Frank
* \version 1.0
* \ingroup DD4HEP_CORE
*/
class PropertyConfigurator {
protected:
/// Default destructor
virtual ~PropertyConfigurator();
public:
virtual void set(const PropertyGrammar& setter, const std::string&, const std::string&, void* ptr) const = 0;
};


/// Class describing the grammar representation of a given data type
/**
* Note: This class cannot be saved to a ROOT file!
*
* \author M.Frank
* \version 1.0
* \ingroup DD4HEP_CORE
*/
class PropertyGrammar {
protected:
friend class Property;
const BasicGrammar& m_grammar; //! This member is not ROOT persistent as the entire class is not.
public:
/// Default constructor
PropertyGrammar(const BasicGrammar& g);
/// Default destructor
virtual ~PropertyGrammar();
/// Error callback on invalid conversion
static void invalidConversion(const std::type_info& from, const std::type_info& to);
/// Error callback on invalid conversion
static void invalidConversion(const std::string& value, const std::type_info& to);
/// Access to the type information
virtual const std::type_info& type() const;
/// Serialize an opaque value to a string
virtual std::string str(const void* ptr) const;
/// Set value from serialized string. On successful data conversion TRUE is returned.
virtual bool fromString(void* ptr, const std::string& value) const;
};

/// The property class to assign options to actions.
/**
Expand All @@ -94,9 +48,9 @@ namespace dd4hep {
class Property {
protected:
/// Pointer to the data location
void* m_par = 0;
void* m_par { nullptr };
/// Reference to the grammar of this property (extended type description)
const PropertyGrammar* m_hdl = 0;
const BasicGrammar* m_hdl { nullptr };

public:
/// Default constructor
Expand All @@ -114,7 +68,7 @@ namespace dd4hep {
/// Property type name
std::string type() const;
/// Access grammar object
const PropertyGrammar& grammar() const;
const BasicGrammar& grammar() const;
/// Conversion to string value
std::string str() const;
/// Conversion from string value
Expand All @@ -138,18 +92,19 @@ namespace dd4hep {
};

/// User constructor
template <typename TYPE> Property::Property(TYPE& val) : m_par(&val), m_hdl(0) {
static PropertyGrammar grammar(BasicGrammar::instance<TYPE>());
m_hdl = &grammar;
}
template <typename TYPE> Property::Property(TYPE& val)
: m_par(&val), m_hdl(0)
{
m_hdl = &BasicGrammar::get(typeid(TYPE));
}

/// Set value of this property
template <typename TYPE> void Property::set(const TYPE& val) {
const PropertyGrammar& grm = grammar();
const auto& grm = grammar();
if (grm.type() == typeid(TYPE))
*(TYPE*) m_par = val;
else if (!grm.fromString(m_par, BasicGrammar::instance< TYPE >().str(&val)))
PropertyGrammar::invalidConversion(typeid(TYPE), grm.type());
BasicGrammar::invalidConversion(typeid(TYPE), grm.type());
}

/// Assignment operator / set new balue
Expand All @@ -160,11 +115,11 @@ namespace dd4hep {

/// Retrieve value from stack (large values e.g. vectors etc.)
template <typename TYPE> void Property::value(TYPE& val) const {
const PropertyGrammar& grm = grammar();
const auto& grm = grammar();
if (grm.type() == typeid(TYPE))
val = *(TYPE*) m_par;
else if (!BasicGrammar::instance< TYPE >().fromString(&val, this->str()))
PropertyGrammar::invalidConversion(grm.type(), typeid(TYPE));
BasicGrammar::invalidConversion(grm.type(), typeid(TYPE));
}

/// Retrieve value
Expand Down Expand Up @@ -196,7 +151,7 @@ namespace dd4hep {
/// Equality operator
bool operator==(const TYPE& val) const { return val == data; }
/// Access grammar object
const PropertyGrammar& grammar() const { return this->Property::grammar(); }
const BasicGrammar& grammar() const { return this->Property::grammar(); }
/// Conversion to string value
std::string str() const { return this->Property::str(); }
/// Retrieve value with data conversion
Expand Down Expand Up @@ -258,8 +213,6 @@ namespace dd4hep {
template <typename T> void add(const std::string& name, T& value) {
add(name, Property(value));
}
/// Bulk set of all properties
void set(const std::string& component_name, PropertyConfigurator& setup);
/// Apply functor on properties
template <typename FUNCTOR> void for_each(FUNCTOR& func) {
std::for_each(m_properties.begin(), m_properties.end(), func);
Expand Down
1 change: 1 addition & 0 deletions DDCore/include/DD4hep/Grammar.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

// C/C++ include files
#include <string>
#include <iostream>
#include <typeinfo>

// Forward declarations
Expand Down
22 changes: 16 additions & 6 deletions DDCore/include/DD4hep/GrammarParsed.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,35 @@ namespace dd4hep {
std::pair<int,double> grammar_evaluate_item(std::string val);

/// PropertyGrammar overload: Retrieve value from string
template <typename TYPE> bool grammar_fromString(const BasicGrammar& gr, void* ptr, const std::string& string_val) {
template <typename TYPE> bool grammar_fromString(const BasicGrammar& gr, void* ptr, const std::string& val) {
int sc = 0;
TYPE temp;
try {
sc = ::dd4hep::Parsers::parse(temp,string_val);
#ifdef DD4HEP_DEBUG_PROPERTIES
std::cout << "Parsing " << val << std::endl;
#endif
sc = ::dd4hep::Parsers::parse(temp, val);
if ( sc ) {
*(TYPE*)ptr = temp;
return true;
}
}
catch (...) {
}
if ( !sc ) sc = gr.evaluate(&temp,string_val);
#if 0
std::cout << "Sc=" << sc << " Converting value: " << string_val
#ifdef DD4HEP_DEBUG_PROPERTIES
std::cout << "Parsing " << val << "FAILED" << std::endl;
#endif
if ( !sc ) sc = gr.evaluate(&temp,val);
#ifdef DD4HEP_DEBUG_PROPERTIES
std::cout << "Sc=" << sc << " Converting value: " << val
<< " to type " << typeid(TYPE).name()
<< std::endl;
#endif
if ( sc ) {
*(TYPE*)ptr = temp;
return true;
}
BasicGrammar::invalidConversion(string_val, typeid(TYPE));
BasicGrammar::invalidConversion(val, typeid(TYPE));
return false;
}

Expand Down
49 changes: 1 addition & 48 deletions DDCore/src/ComponentProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,6 @@
using namespace std;
using namespace dd4hep;

/// Default destructor
PropertyConfigurator::~PropertyConfigurator() {
}

/// Default constructor
PropertyGrammar::PropertyGrammar(const BasicGrammar& g) : m_grammar(g) {
}

/// Default destructor
PropertyGrammar::~PropertyGrammar() {
}

/// Error callback on invalid conversion
void PropertyGrammar::invalidConversion(const std::type_info& from,
const std::type_info& to)
{
BasicGrammar::invalidConversion(from,to);
}

/// Error callback on invalid conversion
void PropertyGrammar::invalidConversion(const std::string& value,
const std::type_info& to)
{
BasicGrammar::invalidConversion(value,to);
}

/// Access to the type information
const std::type_info& PropertyGrammar::type() const {
return m_grammar.type();
}

/// Serialize an opaque value to a string
std::string PropertyGrammar::str(const void* ptr) const {
return m_grammar.str(ptr);
}

/// Set value from serialized string. On successful data conversion TRUE is returned.
bool PropertyGrammar::fromString(void* ptr, const std::string& value) const {
return m_grammar.fromString(ptr,value);
}

/// Property type name
string Property::type(const Property& property) {
return type(property.grammar().type());
Expand All @@ -80,7 +39,7 @@ string Property::type() const {
return Property::type(grammar().type());
}

const PropertyGrammar& Property::grammar() const {
const BasicGrammar& Property::grammar() const {
if ( m_hdl )
return *m_hdl;
throw runtime_error("Attempt to access property grammar from invalid object.");
Expand Down Expand Up @@ -198,12 +157,6 @@ void PropertyManager::add(const string& name, const Property& prop) {
m_properties.emplace(name, prop);
}

/// Bulk set of all properties
void PropertyManager::set(const string& component_name, PropertyConfigurator& cfg) {
for (auto& i : m_properties )
cfg.set(i.second.grammar(), component_name, i.first, i.second.ptr());
}

/// Dump string values
void PropertyManager::dump() const {
for (const auto& i : m_properties )
Expand Down
49 changes: 43 additions & 6 deletions DDCore/src/Grammar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ namespace dd4hep {
}
}


/// Equality operator
bool dd4hep::BasicGrammar::specialization_t::operator==(const specialization_t& cp) const {
return this->bind == cp.bind &&
Expand All @@ -115,31 +114,68 @@ dd4hep::BasicGrammar::BasicGrammar(const std::string& typ)
/// Default destructor
dd4hep::BasicGrammar::~BasicGrammar() {
}

#include <iostream>
/// Prenote loadable grammar
void dd4hep::BasicGrammar::pre_note(const std::type_info& info,
const BasicGrammar& (*fcn)(),
specialization_t specs) {
key_type hash = dd4hep::detail::hash64(typeName(info));
#ifdef DD4HEP_DEBUG_PROPERTIES
std::cout << "pre_note(1) " << typeName(info)
<< " " << (void*)specs.str
<< " " << (void*)specs.fromString
<< std::endl;
#endif
if ( !prenote_registry().emplace(hash, std::make_pair(fcn,specs)).second ) {
auto j = prenote_registry().find(hash);
const auto& entry = (*j).second;
#ifdef DD4HEP_DEBUG_PROPERTIES
const auto& gramm = entry.first();
std::cout << "pre_note(2) " << typeName(info)
<< " " << (void*)gramm.specialization.fromString
<< " " << (void*)entry.second.fromString
<< std::endl;
#endif
if ( !(entry.first == fcn && entry.second == specs) ) {
// Error: Already existing grammar.
dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]",
typeName(info).c_str(), hash);
}
}
/// If the grammer was instantiated before the pre-note: update the grammar...
auto i = active_registry().find(hash);
if ( i != active_registry().end() ) {
i->second->specialization = specs;
}
}

/// Lookup existing grammar using hash code (reading objects)
const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(key_type hash) {
auto i = active_registry().find(hash);
if ( i != active_registry().end() )
if ( i != active_registry().end() ) {
#ifdef DD4HEP_DEBUG_PROPERTIES
const auto& entry = (*i).second;
const auto& gramm = *entry;
std::cout << "get(1) " << hash
<< " grammar: " << (void*)&gramm
<< " " << (void*)gramm.specialization.fromString
<< " " << (void*)entry->specialization.fromString
<< std::endl;
#endif
return *(i->second);
}
auto j = prenote_registry().find(hash);
if ( j != prenote_registry().end() )
if ( j != prenote_registry().end() ) {
#ifdef DD4HEP_DEBUG_PROPERTIES
const auto& entry = (*j).second;
const auto& gramm = entry.first();
std::cout << "get(2) " << hash
<< " " << (void*)gramm.specialization.fromString
<< " " << (void*)entry.second.fromString
<< std::endl;
#endif
return (j->second.first)();
}
dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX",hash);
throw "Error"; // Not reachable anyhow. Simply to please the compiler!
}
Expand Down Expand Up @@ -232,8 +268,9 @@ std::string dd4hep::BasicGrammar::str(const void* ptr) const {
/// Set value from serialized string. On successful data conversion TRUE is returned.
bool dd4hep::BasicGrammar::fromString(void* ptr, const std::string& value) const {
if ( specialization.fromString )
return specialization.fromString(*this,ptr, value);
except("Grammar", "Cannot deserialize object with incomplete grammar: %s", type_name().c_str());
return specialization.fromString(*this, ptr, value);
except("Grammar", "Cannot deserialize object with incomplete grammar: %s [%s] %p fromString: %s",
type_name().c_str(), this->name.c_str(), (void*)this, (void*)specialization.fromString);
return false;
}

Expand Down
2 changes: 0 additions & 2 deletions DDCore/src/PropertyDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ template class std::map<std::string, dd4hep::Property>;
#pragma link C++ class std::map<std::string, dd4hep::Property>-;
#pragma link C++ class dd4hep::PropertyManager-;
#pragma link C++ class dd4hep::PropertyConfigurable-;
#pragma link C++ class dd4hep::PropertyConfigurator-;
#pragma link C++ class dd4hep::PropertyGrammar-;

#endif // __CINT__
#endif // DDCORE_SRC_PROPERTYDICTIONARY_H
3 changes: 0 additions & 3 deletions DDG4/include/DDG4/Geant4Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,6 @@ namespace dd4hep {
bool hasProperty(const std::string& name) const;
/// Access single property
Property& property(const std::string& name);
/// Set object properties
Geant4Action& setProperties(PropertyConfigurator& setup);

/// Install property control messenger if wanted
virtual void installMessengers();
/// Install command control messenger if wanted
Expand Down
6 changes: 0 additions & 6 deletions DDG4/src/Geant4Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,6 @@ PrintLevel Geant4Action::setOutputLevel(PrintLevel new_level) {
return (PrintLevel)old;
}

/// Set object properties
Geant4Action& Geant4Action::setProperties(PropertyConfigurator& setup) {
m_properties.set(m_name, setup);
return *this;
}

/// Check property for existence
bool Geant4Action::hasProperty(const string& nam) const {
return m_properties.exists(nam);
Expand Down
Loading

0 comments on commit 4fd3018

Please sign in to comment.