Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:26:24

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/Primitives.h>
0016 #include <DD4hep/Exceptions.h>
0017 #include <DD4hep/Printout.h>
0018 
0019 // C/C++ include files
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 /// Local Utilities
0031 namespace {
0032 
0033 #if 0
0034 //-----------------------------------------------------------------------------
0035 // MurmurHash2, 64-bit versions, by Austin Appleby
0036 //
0037 // The same caveats as 32-bit MurmurHash2 apply here - beware of alignment 
0038 // and endian-ness issues if used across multiple platforms.
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   /// Original Pearson algorithm
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 /// Convert volumeID to string format (016X)
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 /// 64 bit hash function
0182 unsigned long long int dd4hep::detail::hash64(const char* key)   {
0183   return update_hash64(FNV1a_64::hashinit, key);
0184 }
0185 
0186 /// 64 bit hash function
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 /// 64 bit hash function
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 /// 64 bit hash update function
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 /// 64 bit hash update function
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 /// 64 bit hash update function
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 /// 16 bit hash function
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 /// 8 bit hash function
0224 unsigned char dd4hep::detail::hash8(const void* key, std::size_t len)   {
0225   return pearson_hash(key, len);
0226 }
0227 
0228 /// 8 bit hash function
0229 unsigned char dd4hep::detail::hash8(const char* key)   {
0230   return pearson_hash(key);
0231 }
0232 
0233 /// Replace all occurrencies of a string
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 /// Replace all occurrencies of a string
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 /// Replace all occurrencies of a string
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 /// C++ version to convert a string to lower case
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 /// C++ version to convert a string to upper case
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 /// Convert date into epoch time (seconds since 1970)
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     // The returned name is prefixed with "class "
0320     off = 6;
0321   }
0322   if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
0323     // The returned name is prefixed with "struct "
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   // Change any " *" to "*"
0342   while ( (off=result.find(" *")) != std::string::npos ) {
0343     result.replace(off, 2, "*");
0344   }
0345   // Change any " &" to "&"
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     // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf
0354     // for details
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 /// Throw exception when handles are check for validity
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     /// Generic function to convert to string
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     /// Convert string to string
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     /// Convert string to string
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     /// Convert string to string
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 /// Initializing Constructor
0524 dd4hep::Cast::Cast(const std::type_info& t, cast_t c) : type(t), cast(c)  {
0525 }
0526 #else
0527 /// Initializing Constructor
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 /// Defautl destructor
0537 dd4hep::Cast::~Cast() {
0538 }
0539 
0540 /// Apply cast using typeinfo instead of dynamic_cast
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   // First try down cast
0548   void *r = (*to.cast)(ptr);
0549   if (r)
0550     return r;
0551   // Now try the up-cast
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       // First try down cast
0567       void *r = cast_wrap(ptr, src_type, (const class_t*) abi_class, -1);
0568       if ( r ) return r;
0569       // Now try the up-cast
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 /// Apply cast using typeinfo instead of dynamic_cast
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 /// Apply cast using typeinfo instead of dynamic_cast
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     // Since we have to cast a 'to' pointer up to the real pointer
0602     // no virtual inheritance can be supported!
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 }