File indexing completed on 2025-12-16 09:26:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Primitives.h>
0016 #include <DD4hep/Exceptions.h>
0017 #include <DD4hep/Printout.h>
0018
0019
0020 #include <cstring>
0021
0022 #if defined(__linux) || defined(__APPLE__) || defined(__powerpc64__)
0023 #include <cxxabi.h>
0024 #ifndef __APPLE__
0025 typedef abi::__class_type_info class_t;
0026 using abi::__dynamic_cast;
0027 #endif
0028 #endif
0029
0030
0031 namespace {
0032
0033 #if 0
0034
0035
0036
0037
0038
0039 inline uint64_t murmur_hash_64 ( const void * key, int len) {
0040 #define seed 0xFEEDBABE
0041 typedef unsigned long long int uint64;
0042
0043 #if INTPTR_MAX == INT32_MAX
0044 const unsigned int * data = (const unsigned int *)key;
0045 const unsigned int m = 0x5bd1e995;
0046 const int r = 24;
0047
0048 unsigned int h1 = seed ^ len;
0049 unsigned int h2 = 0;
0050
0051 while(len >= 8)
0052 {
0053 unsigned int k1 = *data++;
0054 k1 *= m; k1 ^= k1 >> r; k1 *= m;
0055 h1 *= m; h1 ^= k1;
0056 len -= 4;
0057
0058 unsigned int k2 = *data++;
0059 k2 *= m; k2 ^= k2 >> r; k2 *= m;
0060 h2 *= m; h2 ^= k2;
0061 len -= 4;
0062 }
0063
0064 if(len >= 4)
0065 {
0066 unsigned int k1 = *data++;
0067 k1 *= m; k1 ^= k1 >> r; k1 *= m;
0068 h1 *= m; h1 ^= k1;
0069 len -= 4;
0070 }
0071
0072 switch(len)
0073 {
0074 case 3: h2 ^= ((unsigned char*)data)[2] << 16;
0075 case 2: h2 ^= ((unsigned char*)data)[1] << 8;
0076 case 1: h2 ^= ((unsigned char*)data)[0];
0077 h2 *= m;
0078 };
0079
0080 h1 ^= h2 >> 18; h1 *= m;
0081 h2 ^= h1 >> 22; h2 *= m;
0082 h1 ^= h2 >> 17; h1 *= m;
0083 h2 ^= h1 >> 19; h2 *= m;
0084
0085 uint64 h = h1;
0086
0087 h = (h << 32) | h2;
0088 #elif INTPTR_MAX == INT64_MAX
0089 const uint64* data = (const uint64*)key;
0090 const uint64 m = 0xc6a4a7935bd1e995;
0091 const int r = 47;
0092
0093 uint64 h = seed ^ (len * m);
0094
0095 const uint64 * end = data + (len/8);
0096
0097 while(data != end)
0098 {
0099 uint64 k = *data++;
0100
0101 k *= m;
0102 k ^= k >> r;
0103 k *= m;
0104
0105 h ^= k;
0106 h *= m;
0107 }
0108
0109 const unsigned char * data2 = (const unsigned char*)data;
0110
0111 switch(len & 7)
0112 {
0113 case 7: h ^= uint64(data2[6]) << 48;
0114 case 6: h ^= uint64(data2[5]) << 40;
0115 case 5: h ^= uint64(data2[4]) << 32;
0116 case 4: h ^= uint64(data2[3]) << 24;
0117 case 3: h ^= uint64(data2[2]) << 16;
0118 case 2: h ^= uint64(data2[1]) << 8;
0119 case 1: h ^= uint64(data2[0]);
0120 h *= m;
0121 };
0122
0123 h ^= h >> r;
0124 h *= m;
0125 h ^= h >> r;
0126
0127 #else
0128 #error "Environment not 32 or 64-bit."
0129 #endif
0130 return h;
0131 }
0132 #endif
0133
0134 struct FNV1a_64 {
0135 static const unsigned long long int hashinit = 14695981039346656037ull;
0136 static constexpr unsigned long long int doByte(unsigned long long int hash,unsigned char val)
0137 { return (hash ^ val) * 1099511628211ull; }
0138 };
0139
0140 static unsigned char crc8_table[] =
0141 { 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
0142 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
0143 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
0144 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
0145 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
0146 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
0147 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
0148 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
0149 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
0150 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
0151 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
0152 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
0153 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
0154 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
0155 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
0156 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
0157 };
0158
0159 static unsigned char pearson_hash(const void *data, size_t len) {
0160 const char *s = (const char*)data;
0161 unsigned char c = 0;
0162 while (--len) c = crc8_table[c ^ *s++];
0163 return c;
0164 }
0165 static unsigned char pearson_hash(const char *data) {
0166 const char *s = data;
0167 unsigned char c = 0;
0168 while (*s) c = crc8_table[c ^ *s++];
0169 return c;
0170 }
0171 }
0172
0173
0174 std::string dd4hep::volumeID(VolumeID vid) {
0175 char text[32];
0176 unsigned long long id = (unsigned long long)vid;
0177 ::snprintf(text,sizeof(text), "%016llx", id);
0178 return text;
0179 }
0180
0181
0182 unsigned long long int dd4hep::detail::hash64(const char* key) {
0183 return update_hash64(FNV1a_64::hashinit, key);
0184 }
0185
0186
0187 unsigned long long int dd4hep::detail::hash64(const std::string& key) {
0188 return update_hash64(FNV1a_64::hashinit, key.c_str(), key.length());
0189 }
0190
0191
0192 unsigned long long int dd4hep::detail::hash64(const void* key, std::size_t len) {
0193 return update_hash64(FNV1a_64::hashinit, key, len);
0194 }
0195
0196
0197 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const std::string& key) {
0198 return update_hash64(hash, key.c_str(), key.length());
0199 }
0200
0201
0202 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const char* key) {
0203 const unsigned char* str = (const unsigned char*)key;
0204 for ( ; *str; ++str) hash = FNV1a_64::doByte(hash, *str);
0205 return hash;
0206 }
0207
0208
0209 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const void* key, std::size_t len) {
0210 const unsigned char* str = (const unsigned char*)key;
0211 if ( len > 0 ) {
0212 for ( ; --len; ++str) hash = FNV1a_64::doByte(hash, *str);
0213 }
0214 return hash;
0215 }
0216
0217
0218 unsigned short dd4hep::detail::hash16(const void* key, std::size_t len) {
0219 unsigned short value = (unsigned short)hash32(key, len);
0220 return value;
0221 }
0222
0223
0224 unsigned char dd4hep::detail::hash8(const void* key, std::size_t len) {
0225 return pearson_hash(key, len);
0226 }
0227
0228
0229 unsigned char dd4hep::detail::hash8(const char* key) {
0230 return pearson_hash(key);
0231 }
0232
0233
0234 std::string dd4hep::detail::str_replace(const std::string& str,
0235 const std::string& pattern,
0236 const std::string& replacement) {
0237 std::string res = str;
0238 for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
0239 res.replace(id, pattern.length(), replacement);
0240 return res;
0241 }
0242
0243
0244 std::string dd4hep::detail::str_replace(const std::string& str,
0245 char pattern,
0246 const std::string& replacement) {
0247 std::string res = str;
0248 for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
0249 res.replace(id, 1, replacement);
0250 return res;
0251 }
0252
0253
0254 std::string dd4hep::detail::str_replace(const std::string& str,
0255 char pattern,
0256 char replacement) {
0257 std::string res = str;
0258 for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
0259 res.replace(id, 1, 1, replacement);
0260 return res;
0261 }
0262
0263
0264 std::string dd4hep::detail::str_lower(const std::string& str) {
0265 std::string res = str.c_str();
0266 std::transform(res.begin(), res.end(), res.begin(), ::tolower);
0267 return res;
0268 }
0269
0270
0271 std::string dd4hep::detail::str_upper(const std::string& str) {
0272 std::string res = str.c_str();
0273 std::transform(res.begin(), res.end(), res.begin(), ::toupper);
0274 return res;
0275 }
0276
0277 long int dd4hep::detail::makeTime(int year, int month, int day,
0278 int hour, int minutes, int seconds)
0279 {
0280 struct tm tm_init;
0281 ::memset(&tm_init,0,sizeof(tm_init));
0282 tm_init.tm_year = year > 1900 ? year-1900 : year;
0283 tm_init.tm_mon = month;
0284 tm_init.tm_mday = day;
0285 tm_init.tm_hour = hour;
0286 tm_init.tm_min = minutes;
0287 tm_init.tm_sec = seconds;
0288 tm_init.tm_isdst = -1;
0289 long int ti = ::mktime(&tm_init);
0290 if ( ti >= 0 ) return ti;
0291 except("dd4hep","Invalid time data given for conversion to epoch: %d-%d-%d %02d:%02d:%02d",
0292 year, month, day, hour, minutes, seconds);
0293 return ti;
0294 }
0295
0296
0297 long int dd4hep::detail::makeTime(const std::string& date, const char* fmt) {
0298 struct tm tm;
0299 char* c = ::strptime(date.c_str(),fmt,&tm);
0300 if ( 0 == c ) {
0301 except("dd4hep",
0302 "Invalid time format given for update:%s should be: %s",
0303 date.c_str(), fmt);
0304 }
0305 long ti = ::mktime(&tm);
0306 if ( ti >= 0 ) return ti;
0307 except("dd4hep",
0308 "Invalid time string given for conversion to epoch: %s (fmt='%s')",
0309 date.c_str(), fmt);
0310 return ti;
0311 }
0312
0313 static const std::string __typeinfoName(const std::type_info& tinfo) {
0314 const char* class_name = tinfo.name();
0315 std::string result;
0316 #ifdef WIN32
0317 std::size_t off = 0;
0318 if ( ::strncmp(class_name, "class ", 6) == 0 ) {
0319
0320 off = 6;
0321 }
0322 if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
0323
0324 off = 7;
0325 }
0326 if ( off != std::string::npos ) {
0327 std::string tmp = class_name + off;
0328 size_t loc = 0;
0329 while( (loc = tmp.find("class ")) != std::string::npos ) {
0330 tmp.erase(loc, 6);
0331 }
0332 loc = 0;
0333 while( (loc = tmp.find("struct ")) != std::string::npos ) {
0334 tmp.erase(loc, 7);
0335 }
0336 result = tmp;
0337 }
0338 else {
0339 result = class_name;
0340 }
0341
0342 while ( (off=result.find(" *")) != std::string::npos ) {
0343 result.replace(off, 2, "*");
0344 }
0345
0346 while ( (off=result.find(" &")) != std::string::npos ) {
0347 result.replace(off, 2, "&");
0348 }
0349 #elif defined(sun)
0350 result = class_name;
0351 #elif !defined(__ICC)
0352 if (::strlen(class_name) == 1) {
0353
0354
0355 switch (class_name[0]) {
0356 case 'v':
0357 result = "void";
0358 break;
0359 case 'w':
0360 result = "wchar_t";
0361 break;
0362 case 'b':
0363 result = "bool";
0364 break;
0365 case 'c':
0366 result = "char";
0367 break;
0368 case 'h':
0369 result = "unsigned char";
0370 break;
0371 case 's':
0372 result = "short";
0373 break;
0374 case 't':
0375 result = "unsigned short";
0376 break;
0377 case 'i':
0378 result = "int";
0379 break;
0380 case 'j':
0381 result = "unsigned int";
0382 break;
0383 case 'l':
0384 result = "long";
0385 break;
0386 case 'm':
0387 result = "unsigned long";
0388 break;
0389 case 'x':
0390 result = "long long";
0391 break;
0392 case 'y':
0393 result = "unsigned long long";
0394 break;
0395 case 'n':
0396 result = "__int128";
0397 break;
0398 case 'o':
0399 result = "unsigned __int128";
0400 break;
0401 case 'f':
0402 result = "float";
0403 break;
0404 case 'd':
0405 result = "double";
0406 break;
0407 case 'e':
0408 result = "long double";
0409 break;
0410 case 'g':
0411 result = "__float128";
0412 break;
0413 case 'z':
0414 result = "ellipsis";
0415 break;
0416 }
0417 }
0418 else {
0419 char buff[16 * 1024];
0420 std::size_t len = sizeof(buff);
0421 int status = 0;
0422 result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status);
0423 }
0424 #else
0425 result = class_name;
0426 throw std::runtime_error("CXXABI is missing for ICC!");
0427 #endif
0428 return result;
0429 }
0430
0431 std::string dd4hep::typeName(const std::type_info& typ) {
0432 return __typeinfoName(typ);
0433 }
0434
0435 void dd4hep::invalidHandleError(const std::type_info& type)
0436 {
0437 throw invalid_handle_exception("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]");
0438 }
0439
0440 void dd4hep::invalidHandleAssignmentError(const std::type_info& from,
0441 const std::type_info& to)
0442 {
0443 std::string msg = "Wrong assingment from ";
0444 msg += typeName(from);
0445 msg += " to ";
0446 msg += typeName(to);
0447 msg += " not possible!!";
0448 throw invalid_handle_exception(msg);
0449 }
0450
0451
0452 void dd4hep::notImplemented(const std::string& msg)
0453 {
0454 std::string m = "The requested feature " + msg + " is not implemented!";
0455 throw std::runtime_error(m);
0456 }
0457
0458 void dd4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text)
0459 {
0460 if (typ1 != typ2) {
0461 throw unrelated_type_error(typ1, typ2, text);
0462 }
0463 }
0464
0465 namespace dd4hep {
0466 namespace detail {
0467 template<> const char* Primitive<bool>::default_format() { return "%d"; }
0468 template<> const char* Primitive<char>::default_format() { return "%c"; }
0469 template<> const char* Primitive<unsigned char>::default_format() { return "%02X"; }
0470 template<> const char* Primitive<short>::default_format() { return "%d"; }
0471 template<> const char* Primitive<unsigned short>::default_format() { return "%04X"; }
0472 template<> const char* Primitive<int>::default_format() { return "%d"; }
0473 template<> const char* Primitive<unsigned int>::default_format() { return "%08X"; }
0474 template<> const char* Primitive<long>::default_format() { return "%ld"; }
0475 template<> const char* Primitive<unsigned long>::default_format() { return "%016X"; }
0476 template<> const char* Primitive<float>::default_format() { return "%f"; }
0477 template<> const char* Primitive<double>::default_format() { return "%g"; }
0478 template<> const char* Primitive<char*>::default_format() { return "%s"; }
0479 template<> const char* Primitive<const char*>::default_format() { return "%s"; }
0480 template<> const char* Primitive<std::string>::default_format() { return "%s"; }
0481
0482
0483 template <typename T> std::string Primitive<T>::toString(T value) {
0484 char text[1024];
0485 ::snprintf(text,sizeof(text),default_format(),value);
0486 return text;
0487 }
0488
0489
0490 template <> std::string Primitive<const char*>::toString(const char* value) {
0491 if ( value ) {
0492 return value;
0493 }
0494 throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
0495 }
0496
0497 template <> std::string Primitive<char*>::toString(char* value) {
0498 if ( value ) {
0499 return value;
0500 }
0501 throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
0502 }
0503
0504 template <> std::string Primitive<std::string>::toString(std::string value) {
0505 return value;
0506 }
0507
0508 template std::string Primitive<bool>::toString(bool value);
0509 template std::string Primitive<char>::toString(char value);
0510 template std::string Primitive<unsigned char>::toString(unsigned char value);
0511 template std::string Primitive<short>::toString(short value);
0512 template std::string Primitive<unsigned short>::toString(unsigned short value);
0513 template std::string Primitive<int>::toString(int value);
0514 template std::string Primitive<unsigned int>::toString(unsigned int value);
0515 template std::string Primitive<long>::toString(long value);
0516 template std::string Primitive<unsigned long>::toString(unsigned long value);
0517 template std::string Primitive<float>::toString(float value);
0518 template std::string Primitive<double>::toString(double value);
0519 }
0520 }
0521
0522 #ifdef __APPLE__
0523
0524 dd4hep::Cast::Cast(const std::type_info& t, cast_t c) : type(t), cast(c) {
0525 }
0526 #else
0527
0528 dd4hep::Cast::Cast(const std::type_info& t) : type(t) {
0529 abi_class = dynamic_cast<const class_t*>(&type);
0530 if (!abi_class) {
0531 throw std::runtime_error("Class type " + typeName(type) + " is not an abi object type!");
0532 }
0533 }
0534 #endif
0535
0536
0537 dd4hep::Cast::~Cast() {
0538 }
0539
0540
0541 void* dd4hep::Cast::apply_dynCast(const Cast& to, const void* ptr) const
0542 {
0543 if (&to == this) {
0544 return (void*) ptr;
0545 }
0546 #ifdef __APPLE__
0547
0548 void *r = (*to.cast)(ptr);
0549 if (r)
0550 return r;
0551
0552 r = (*cast)(ptr);
0553 if (r) return r;
0554 throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
0555 #else
0556 void* r = (void*)ptr;
0557 if ( to.abi_class ) {
0558 bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
0559 if ( cast_worked ) return r;
0560 r = (void*)ptr;
0561 cast_worked = to.type.__do_upcast((const class_t*)abi_class,&r);
0562 if ( cast_worked ) return r;
0563 #if 0
0564 const class_t* src_type = (const class_t*)to.abi_class;
0565 if (src_type) {
0566
0567 void *r = cast_wrap(ptr, src_type, (const class_t*) abi_class, -1);
0568 if ( r ) return r;
0569
0570 r = cast_wrap(ptr, (const class_t*) abi_class, src_type, -1);
0571 if (r) return r;
0572 }
0573 #endif
0574 throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
0575 }
0576 #endif
0577 throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
0578 }
0579
0580
0581 void* dd4hep::Cast::apply_upCast(const Cast& to, const void* ptr) const
0582 {
0583 if (&to == this) {
0584 return (void*) ptr;
0585 }
0586 return apply_dynCast(to, ptr);
0587 }
0588
0589
0590 void* dd4hep::Cast::apply_downCast(const Cast& to, const void* ptr) const
0591 {
0592 if (&to == this) {
0593 return (void*) ptr;
0594 }
0595 #ifdef __APPLE__
0596 void *r = (*to.cast)(ptr);
0597 if (r) return r;
0598 throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
0599 #else
0600 if ( to.abi_class ) {
0601
0602
0603 void* r = (void*)ptr;
0604 bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
0605 if ( cast_worked ) return r;
0606 #if 0
0607 void *r = cast_wrap(ptr, src_type, (const class_t*)abi_class, -1);
0608 if (r) return r;
0609 #endif
0610 throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
0611 }
0612 throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
0613 #endif
0614 }