Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:13:48

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Primitives.h>
0017 #include <DD4hep/Exceptions.h>
0018 #include <DD4hep/Grammar.h>
0019 #include <Evaluator/Evaluator.h>
0020 
0021 // ROOT include files
0022 #include <TDataType.h>
0023 #include <TROOT.h>
0024 
0025 // C/C++ include files
0026 #include <mutex>
0027 #include <map>
0028 #include <string>
0029 
0030 #if defined(DD4HEP_PARSER_HEADER)
0031 
0032 #define DD4HEP_NEED_EVALUATOR
0033 // This is the case, if the parsers are externalized
0034 // and the dd4hep namespace is renamed!
0035 #include DD4HEP_PARSER_HEADER
0036 
0037 #endif
0038 
0039 namespace dd4hep {
0040   const dd4hep::tools::Evaluator& evaluator();
0041   const dd4hep::tools::Evaluator& g4Evaluator();
0042 }
0043 namespace {
0044   static const dd4hep::tools::Evaluator* s__eval(&dd4hep::g4Evaluator());
0045 }
0046 
0047 
0048 namespace {
0049   std::mutex s_mutex;
0050 
0051   typedef const dd4hep::BasicGrammar& (*grammar_create_t)();
0052   typedef std::pair<grammar_create_t, dd4hep::BasicGrammar::specialization_t> grammar_args_t;
0053 
0054   // This static object needs to be in function to trick out static constructors populating this registry....
0055   static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*>& active_registry()  {
0056     static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*> s_registry;
0057     return s_registry;
0058   }
0059   static std::map<dd4hep::BasicGrammar::key_type, grammar_args_t>& prenote_registry()  {
0060     static std::map<dd4hep::BasicGrammar::key_type, grammar_args_t> s_registry;
0061     return s_registry;
0062   }
0063 }
0064 
0065 /// Namespace for the AIDA detector description toolkit
0066 namespace dd4hep {
0067 
0068   /// Alignments internal namespace declaration
0069   namespace detail  {
0070     /// Helper function to parse data type
0071     std::string grammar_pre_parse_map(const std::string& in);
0072     /// Helper function to parse data type
0073     std::string grammar_pre_parse_obj(const std::string& in);
0074     /// Helper function to parse data type
0075     std::string grammar_pre_parse_cont(const std::string& in);
0076     /// Helper to parse single item
0077     std::pair<int,double> grammar_evaluate_item(std::string val);
0078   }
0079 
0080   /// Set grammar evaluator
0081   void setGrammarEvaluator(const std::string& type)    {
0082     if ( type == "TGeo" )
0083       s__eval = &evaluator();
0084     else if ( type == "Geant4" || type == "G4" )
0085       s__eval = &g4Evaluator();
0086     else if ( type == "CGS" )
0087       s__eval = &g4Evaluator();
0088     else
0089       except("Grammar","++ Undefined evaluator type: "+type);
0090   }
0091 }
0092 
0093 /// Equality operator
0094 bool dd4hep::BasicGrammar::specialization_t::operator==(const specialization_t& cp)  const  {
0095   return this->bind  == cp.bind &&
0096     this->copy       == cp.copy && this->str == cp.str &&
0097     this->fromString == cp.fromString && this->eval == cp.eval;
0098 }
0099 
0100 /// Default constructor
0101 dd4hep::BasicGrammar::BasicGrammar(const std::string& typ)
0102   : name(typ), hash_value(dd4hep::detail::hash64(typ))
0103 {
0104   auto j = prenote_registry().find(hash_value);
0105   if ( j != prenote_registry().end() )   {
0106     specialization = j->second.second;
0107   }
0108   if ( !active_registry().emplace(hash_value,this).second )   {
0109   }
0110 }
0111 
0112 
0113 /// Default destructor
0114 dd4hep::BasicGrammar::~BasicGrammar()   {
0115 }
0116 #include <iostream>
0117 /// Prenote loadable grammar
0118 void dd4hep::BasicGrammar::pre_note(const std::type_info& info,
0119                                     const BasicGrammar& (*fcn)(),
0120                                     specialization_t specs)   {
0121   key_type hash = dd4hep::detail::hash64(typeName(info));
0122 #ifdef DD4HEP_DEBUG_PROPERTIES
0123   std::cout << "pre_note(1) " << typeName(info) 
0124             << " " << (void*)specs.str
0125             << " " << (void*)specs.fromString
0126             << std::endl;
0127 #endif
0128   if ( !prenote_registry().emplace(hash, std::make_pair(fcn,specs)).second )  {
0129     auto j = prenote_registry().find(hash);
0130     const auto& entry = (*j).second;
0131 #ifdef DD4HEP_DEBUG_PROPERTIES
0132     const auto& gramm = entry.first();
0133     std::cout << "pre_note(2) " << typeName(info) 
0134               << " " << (void*)gramm.specialization.fromString
0135               << " " << (void*)entry.second.fromString
0136               << std::endl;
0137 #endif
0138     if ( !(entry.first == fcn && entry.second == specs) )   {
0139       // Error: Already existing grammar.
0140       dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]",
0141                      typeName(info).c_str(), hash);
0142     }
0143   }
0144   /// If the grammer was instantiated before the pre-note: update the grammar...
0145   auto i = active_registry().find(hash);
0146   if ( i != active_registry().end() )   {
0147     i->second->specialization = specs;
0148   }
0149 }
0150 
0151 /// Lookup existing grammar using hash code (reading objects)
0152 const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(key_type hash)   {
0153   auto i = active_registry().find(hash);
0154   if ( i != active_registry().end() )   {
0155 #ifdef DD4HEP_DEBUG_PROPERTIES
0156     const auto& entry = (*i).second;
0157     const auto& gramm = *entry;
0158     std::cout << "get(1) " << hash
0159               << " grammar: " << (void*)&gramm
0160               << " " << (void*)gramm.specialization.fromString
0161               << " " << (void*)entry->specialization.fromString
0162               << std::endl;
0163 #endif
0164     return *(i->second);
0165   }
0166   auto j = prenote_registry().find(hash);
0167   if ( j != prenote_registry().end() )  {
0168 #ifdef DD4HEP_DEBUG_PROPERTIES
0169     const auto& entry = (*j).second;
0170     const auto& gramm = entry.first();
0171     std::cout << "get(2) " << hash
0172               << " " << (void*)gramm.specialization.fromString
0173               << " " << (void*)entry.second.fromString
0174               << std::endl;
0175 #endif
0176     return (j->second.first)();
0177   }
0178   dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX",hash);
0179   throw "Error";  // Not reachable anyhow. Simply to please the compiler!
0180 }
0181 
0182 /// Lookup existing grammar using hash code (reading objects)
0183 const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(const std::type_info& info)    {
0184   key_type hash = dd4hep::detail::hash64(typeName(info));
0185   auto i = active_registry().find(hash);
0186   if ( i != active_registry().end() )
0187     return *(i->second);
0188   auto j = prenote_registry().find(hash);
0189   if ( j != prenote_registry().end() )
0190     return (j->second.first)();
0191   dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX [%s]",
0192                  hash, typeName(info).c_str());
0193   throw "Error";  // Not reachable anyhow. Simply to please the compiler!  
0194 }
0195 
0196 /// Second step initialization after the virtual table is fixed
0197 void dd4hep::BasicGrammar::initialize()  const  {
0198   std::lock_guard<std::mutex> lock(s_mutex);
0199   if ( !inited )   {
0200     TClass* cl = gROOT->GetClass(type());
0201     if ( cl )  {
0202       root_class = cl;
0203       inited = true;
0204       return;
0205     }
0206     root_data_type = TDataType::GetType(type());
0207     if ( root_data_type == kOther_t )  {
0208       except("BasicGrammar",
0209              "+++ ERROR +++ Cannot initialize gammar object: %s. "
0210              "No TClass and no data type information present!",name.c_str());
0211     }
0212     inited = true;
0213   }
0214 }
0215 
0216 /// Access ROOT data type for fundamentals
0217 int dd4hep::BasicGrammar::initialized_data_type()  const   {
0218   this->initialize();
0219   return root_data_type;
0220 }
0221 
0222 /// Access the ROOT class for complex objects
0223 TClass* dd4hep::BasicGrammar::initialized_clazz()  const   {
0224   this->initialize();
0225   return root_class;
0226 }
0227 
0228 /// Error callback on invalid conversion
0229 void dd4hep::BasicGrammar::invalidConversion(const std::string& value, const std::type_info& to) {
0230   std::string to_name = typeName(to);
0231   throw unrelated_value_error(to,
0232                               "Data conversion of " + value + " to type '" + 
0233                               to_name + "' is not defined.");
0234 }
0235 
0236 /// Error callback on invalid conversion
0237 void dd4hep::BasicGrammar::invalidConversion(const std::type_info& from, const std::type_info& to) {
0238   std::string to_name   = typeName(to);
0239   std::string from_name = typeName(from);
0240   throw unrelated_type_error(from, to,
0241                              "Data conversion from '" + from_name + 
0242                              "' to '" + to_name + "' is not implemented.");
0243 }
0244 
0245 /// Set cast structure
0246 void dd4hep::BasicGrammar::setCast(const Cast* cast)  const   {
0247   BasicGrammar* g = const_cast<BasicGrammar*>(this);
0248   g->specialization.cast = cast;
0249 }
0250 
0251 /// Access ABI object cast
0252 const dd4hep::Cast& dd4hep::BasicGrammar::cast() const   {
0253   if ( specialization.cast )
0254     return *specialization.cast;
0255   except("Grammar","Cannot serialize object with incomplete grammar: %s",type_name().c_str());
0256   return *specialization.cast;
0257 }
0258 
0259 /// Serialize an opaque value to a string
0260 std::string dd4hep::BasicGrammar::str(const void* ptr) const    {
0261   if ( specialization.str )
0262     return specialization.str(*this, ptr);
0263   except("Grammar", "Cannot serialize object with incomplete grammar: %s", type_name().c_str());
0264   return "";
0265 }
0266 
0267 /// Set value from serialized string. On successful data conversion TRUE is returned.
0268 bool dd4hep::BasicGrammar::fromString(void* ptr, const std::string& value) const    {
0269   if ( specialization.fromString )
0270     return specialization.fromString(*this, ptr, value);
0271   except("Grammar", "Cannot deserialize object with incomplete grammar: %s [%s]  %p fromString: %s",
0272          type_name().c_str(), this->name.c_str(), (void*)this, (void*)specialization.fromString);
0273   return false;
0274 }
0275 
0276 /// Evaluate string value if possible before calling boost::spirit
0277 int dd4hep::BasicGrammar::evaluate(void* ptr, const std::string& value) const    {
0278   if ( specialization.eval )
0279     return specialization.eval(*this, ptr, value);
0280   except("Grammar", "Cannot evaluate object with incomplete grammar: %s", type_name().c_str());
0281   return 0;
0282 }
0283 
0284 /// Helper to parse single item
0285 std::pair<int,double> dd4hep::detail::grammar_evaluate_item(std::string val)   {
0286   size_t idx = val.find("(int)");
0287   if (idx != std::string::npos)
0288     val.erase(idx, 5);
0289   while (val[0] == ' ')
0290     val.erase(0, 1);
0291   auto result = s__eval->evaluate(val.c_str());
0292   return result;
0293 }
0294 
0295 /// Helper function to parse data type
0296 std::string dd4hep::detail::grammar_pre_parse_map(const std::string& in)   {
0297   bool ignore_blanks = true;
0298   bool str_open = false;
0299   bool obj_open = false;
0300   bool start = false;
0301   std::string res = "";
0302   res.reserve(1024);
0303   // std::cout << "Pre-parsed   (in):" << in << std::endl;
0304   for(const char* c = in.c_str(); *c; ++c)   {
0305     switch(*c)  {
0306     case '\'':
0307       res += *c;
0308       if ( start ) { start = false; }
0309       if ( str_open ) { str_open = false; }
0310       break;
0311     case ':':
0312       if ( str_open ) { res += '\''; }
0313       res += *c;
0314       res += ' ';
0315       res += '\'';
0316       str_open = true;
0317       ignore_blanks = true;
0318       break;
0319     case ',':
0320       if ( !obj_open && str_open ) { res += '\''; str_open = false; }
0321       res += ",";
0322       start = true;
0323       ignore_blanks = true;
0324       break;
0325     case '(':
0326       res += *c ;
0327       obj_open = true;
0328       break;
0329     case ')':
0330       res += *c ;
0331       obj_open = false;
0332       break;
0333     case '[':
0334     case '{':
0335       res += *c ;
0336       start = true;
0337       ignore_blanks = true;
0338       break;
0339     case ']':
0340     case '}':
0341       if ( str_open ) {
0342         res += '\'';
0343         str_open = false;
0344       }
0345       res += *c ;
0346       break;
0347     case ' ':
0348       if ( !ignore_blanks ) res += *c;
0349       break;
0350     default:
0351       if ( start ) {
0352         if ( !obj_open ) res += '\'';
0353         start = false;
0354         str_open = true;
0355       }
0356       ignore_blanks = false;
0357       res += *c;
0358       break;
0359     }
0360   }
0361   // std::cout << "Pre-parsed  (out):" << res << std::endl;
0362   return res;
0363 }
0364 
0365 /// Helper function to parse data type
0366 std::string dd4hep::detail::grammar_pre_parse_cont(const std::string& in)   {
0367   bool ignore_blanks = true;
0368   bool str_open = false;
0369   bool start = false;
0370   std::string res = "";
0371   res.reserve(1024);
0372   // std::cout << "Pre-parsed   (in):" << in << std::endl;
0373   for(const char* c = in.c_str(); *c; ++c)   {
0374     switch(*c)  {
0375     case '\'':
0376       res += *c;
0377       if ( start ) { start = false; }
0378       if ( str_open ) { str_open = false; }
0379       break;
0380     case ':':
0381       if ( str_open ) { res += '\''; }
0382       res += *c;
0383       res += ' ';
0384       res += '\'';
0385       str_open = true;
0386       ignore_blanks = true;
0387       break;
0388     case ',':
0389       if ( str_open ) { res += '\''; str_open = false; }
0390       res += ",";
0391       start = true;
0392       ignore_blanks = true;
0393       break;
0394     case '(':
0395     case '[':
0396     case '{':
0397       res += *c ;
0398       start = true;
0399       ignore_blanks = true;
0400       break;
0401     case ')':
0402     case ']':
0403     case '}':
0404       if ( str_open ) { res += '\''; str_open = false; }
0405       res += *c ;
0406       break;
0407     case ' ':
0408       if ( !ignore_blanks ) res += *c;
0409       break;
0410     default:
0411       if ( start ) {
0412         res += '\'';
0413         start = false;
0414         str_open = true;
0415       }
0416       ignore_blanks = false;
0417       res += *c;
0418       break;
0419     }
0420   }
0421   // std::cout << "Pre-parsed  (out):" << res << std::endl;
0422   return res;
0423 }
0424 
0425 /// Helper function to parse data type
0426 std::string dd4hep::detail::grammar_pre_parse_obj(const std::string& in)   {
0427   std::string res = "";
0428   res.reserve(1024);
0429   for(const char* c = in.c_str(); *c; ++c)   {
0430     switch(*c)  {
0431     case '\'':
0432       return "Bad object representation";
0433     case ',':
0434       res += "','";
0435       break;
0436     case '(':
0437     case '[':
0438       res += "['";
0439       break;
0440     case ')':
0441     case ']':
0442       res += "']";
0443       break;
0444     default:
0445       res += *c;
0446       break;
0447     }
0448   }
0449   //cout << "Pre-parsed:" << res << endl;
0450   return res;
0451 }
0452 
0453 /// Registry instance singleton
0454 const dd4hep::GrammarRegistry& dd4hep::GrammarRegistry::instance()   {
0455   static GrammarRegistry s_reg;
0456   return s_reg;
0457 }
0458