Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-13 08:19:39

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