File indexing completed on 2025-07-05 08:13:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0022 #include <TDataType.h>
0023 #include <TROOT.h>
0024
0025
0026 #include <mutex>
0027 #include <map>
0028 #include <string>
0029
0030 #if defined(DD4HEP_PARSER_HEADER)
0031
0032 #define DD4HEP_NEED_EVALUATOR
0033
0034
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
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
0066 namespace dd4hep {
0067
0068
0069 namespace detail {
0070
0071 std::string grammar_pre_parse_map(const std::string& in);
0072
0073 std::string grammar_pre_parse_obj(const std::string& in);
0074
0075 std::string grammar_pre_parse_cont(const std::string& in);
0076
0077 std::pair<int,double> grammar_evaluate_item(std::string val);
0078 }
0079
0080
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
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
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
0114 dd4hep::BasicGrammar::~BasicGrammar() {
0115 }
0116 #include <iostream>
0117
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
0140 dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]",
0141 typeName(info).c_str(), hash);
0142 }
0143 }
0144
0145 auto i = active_registry().find(hash);
0146 if ( i != active_registry().end() ) {
0147 i->second->specialization = specs;
0148 }
0149 }
0150
0151
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";
0180 }
0181
0182
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";
0194 }
0195
0196
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
0217 int dd4hep::BasicGrammar::initialized_data_type() const {
0218 this->initialize();
0219 return root_data_type;
0220 }
0221
0222
0223 TClass* dd4hep::BasicGrammar::initialized_clazz() const {
0224 this->initialize();
0225 return root_class;
0226 }
0227
0228
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
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
0246 void dd4hep::BasicGrammar::setCast(const Cast* cast) const {
0247 BasicGrammar* g = const_cast<BasicGrammar*>(this);
0248 g->specialization.cast = cast;
0249 }
0250
0251
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
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
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
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
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
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
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
0362 return res;
0363 }
0364
0365
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
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
0422 return res;
0423 }
0424
0425
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
0450 return res;
0451 }
0452
0453
0454 const dd4hep::GrammarRegistry& dd4hep::GrammarRegistry::instance() {
0455 static GrammarRegistry s_reg;
0456 return s_reg;
0457 }
0458