File indexing completed on 2025-03-13 08:19:39
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 <algorithm>
0027 #include <stdexcept>
0028 #include <mutex>
0029 #include <map>
0030
0031 #if defined(DD4HEP_PARSER_HEADER)
0032
0033 #define DD4HEP_NEED_EVALUATOR
0034
0035
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
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
0067 namespace dd4hep {
0068
0069
0070 namespace detail {
0071
0072 std::string grammar_pre_parse_map(const std::string& in);
0073
0074 std::string grammar_pre_parse_obj(const std::string& in);
0075
0076 std::string grammar_pre_parse_cont(const std::string& in);
0077
0078 std::pair<int,double> grammar_evaluate_item(std::string val);
0079 }
0080
0081
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
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
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
0115 dd4hep::BasicGrammar::~BasicGrammar() {
0116 }
0117 #include <iostream>
0118
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
0141 dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]",
0142 typeName(info).c_str(), hash);
0143 }
0144 }
0145
0146 auto i = active_registry().find(hash);
0147 if ( i != active_registry().end() ) {
0148 i->second->specialization = specs;
0149 }
0150 }
0151
0152
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";
0181 }
0182
0183
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";
0195 }
0196
0197
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
0218 int dd4hep::BasicGrammar::initialized_data_type() const {
0219 this->initialize();
0220 return root_data_type;
0221 }
0222
0223
0224 TClass* dd4hep::BasicGrammar::initialized_clazz() const {
0225 this->initialize();
0226 return root_class;
0227 }
0228
0229
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
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
0247 void dd4hep::BasicGrammar::setCast(const Cast* cast) const {
0248 BasicGrammar* g = const_cast<BasicGrammar*>(this);
0249 g->specialization.cast = cast;
0250 }
0251
0252
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
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
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
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
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
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
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
0363 return res;
0364 }
0365
0366
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
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
0423 return res;
0424 }
0425
0426
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
0451 return res;
0452 }
0453
0454
0455 const dd4hep::GrammarRegistry& dd4hep::GrammarRegistry::instance() {
0456 static GrammarRegistry s_reg;
0457 return s_reg;
0458 }
0459