DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Primitives.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Primitives.h>
16 #include <DD4hep/Exceptions.h>
17 #include <DD4hep/Printout.h>
18 
19 // C/C++ include files
20 #include <cstring>
21 
22 #if defined(__linux) || defined(__APPLE__) || defined(__powerpc64__)
23 #include <cxxabi.h>
24 #ifndef __APPLE__
25 typedef abi::__class_type_info class_t;
26 using abi::__dynamic_cast;
27 #endif
28 #endif
29 
31 namespace {
32 
33 #if 0
34 //-----------------------------------------------------------------------------
35 // MurmurHash2, 64-bit versions, by Austin Appleby
36 //
37 // The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
38 // and endian-ness issues if used across multiple platforms.
39  inline uint64_t murmur_hash_64 ( const void * key, int len) {
40 #define seed 0xFEEDBABE
41  typedef unsigned long long int uint64;
42 
43 #if INTPTR_MAX == INT32_MAX
44  const unsigned int * data = (const unsigned int *)key;
45  const unsigned int m = 0x5bd1e995;
46  const int r = 24;
47 
48  unsigned int h1 = seed ^ len;
49  unsigned int h2 = 0;
50 
51  while(len >= 8)
52  {
53  unsigned int k1 = *data++;
54  k1 *= m; k1 ^= k1 >> r; k1 *= m;
55  h1 *= m; h1 ^= k1;
56  len -= 4;
57 
58  unsigned int k2 = *data++;
59  k2 *= m; k2 ^= k2 >> r; k2 *= m;
60  h2 *= m; h2 ^= k2;
61  len -= 4;
62  }
63 
64  if(len >= 4)
65  {
66  unsigned int k1 = *data++;
67  k1 *= m; k1 ^= k1 >> r; k1 *= m;
68  h1 *= m; h1 ^= k1;
69  len -= 4;
70  }
71 
72  switch(len)
73  {
74  case 3: h2 ^= ((unsigned char*)data)[2] << 16;
75  case 2: h2 ^= ((unsigned char*)data)[1] << 8;
76  case 1: h2 ^= ((unsigned char*)data)[0];
77  h2 *= m;
78  };
79 
80  h1 ^= h2 >> 18; h1 *= m;
81  h2 ^= h1 >> 22; h2 *= m;
82  h1 ^= h2 >> 17; h1 *= m;
83  h2 ^= h1 >> 19; h2 *= m;
84 
85  uint64 h = h1;
86 
87  h = (h << 32) | h2;
88 #elif INTPTR_MAX == INT64_MAX
89  const uint64* data = (const uint64*)key;
90  const uint64 m = 0xc6a4a7935bd1e995;
91  const int r = 47;
92 
93  uint64 h = seed ^ (len * m);
94 
95  const uint64 * end = data + (len/8);
96 
97  while(data != end)
98  {
99  uint64 k = *data++;
100 
101  k *= m;
102  k ^= k >> r;
103  k *= m;
104 
105  h ^= k;
106  h *= m;
107  }
108 
109  const unsigned char * data2 = (const unsigned char*)data;
110 
111  switch(len & 7)
112  {
113  case 7: h ^= uint64(data2[6]) << 48;
114  case 6: h ^= uint64(data2[5]) << 40;
115  case 5: h ^= uint64(data2[4]) << 32;
116  case 4: h ^= uint64(data2[3]) << 24;
117  case 3: h ^= uint64(data2[2]) << 16;
118  case 2: h ^= uint64(data2[1]) << 8;
119  case 1: h ^= uint64(data2[0]);
120  h *= m;
121  };
122 
123  h ^= h >> r;
124  h *= m;
125  h ^= h >> r;
126 
127 #else
128 #error "Environment not 32 or 64-bit."
129 #endif
130  return h;
131  }
132 #endif
133 
134  struct FNV1a_64 {
135  static const unsigned long long int hashinit = 14695981039346656037ull;
136  static constexpr unsigned long long int doByte(unsigned long long int hash,unsigned char val)
137  { return (hash ^ val) * 1099511628211ull; }
138  };
139 
140  static unsigned char crc8_table[] =
141  { 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
142  157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
143  35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
144  190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
145  70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
146  219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
147  101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
148  248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
149  140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
150  17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
151  175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
152  50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
153  202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
154  87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
155  233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
156  116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
157  };
159  static unsigned char pearson_hash(const void *data, size_t len) {
160  const char *s = (const char*)data;
161  unsigned char c = 0;
162  while (--len) c = crc8_table[c ^ *s++];
163  return c;
164  }
165  static unsigned char pearson_hash(const char *data) {
166  const char *s = data;
167  unsigned char c = 0;
168  while (*s) c = crc8_table[c ^ *s++];
169  return c;
170  }
171 }
172 
174 std::string dd4hep::volumeID(VolumeID vid) {
175  char text[32];
176  unsigned long long id = (unsigned long long)vid;
177  ::snprintf(text,sizeof(text), "%016llx", id);
178  return text;
179 }
180 
182 unsigned long long int dd4hep::detail::hash64(const char* key) {
183  return update_hash64(FNV1a_64::hashinit, key);
184 }
185 
187 unsigned long long int dd4hep::detail::hash64(const std::string& key) {
188  return update_hash64(FNV1a_64::hashinit, key.c_str(), key.length());
189 }
190 
192 unsigned long long int dd4hep::detail::hash64(const void* key, std::size_t len) {
193  return update_hash64(FNV1a_64::hashinit, key, len);
194 }
195 
197 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const std::string& key) {
198  return update_hash64(hash, key.c_str(), key.length());
199 }
200 
202 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const char* key) {
203  const unsigned char* str = (const unsigned char*)key;
204  for ( ; *str; ++str) hash = FNV1a_64::doByte(hash, *str);
205  return hash;
206 }
207 
209 unsigned long long int dd4hep::detail::update_hash64(unsigned long long int hash, const void* key, std::size_t len) {
210  const unsigned char* str = (const unsigned char*)key;
211  if ( len > 0 ) {
212  for ( ; --len; ++str) hash = FNV1a_64::doByte(hash, *str);
213  }
214  return hash;
215 }
216 
218 unsigned short dd4hep::detail::hash16(const void* key, std::size_t len) {
219  unsigned short value = (unsigned short)hash32(key, len);
220  return value;
221 }
222 
224 unsigned char dd4hep::detail::hash8(const void* key, std::size_t len) {
225  return pearson_hash(key, len);
226 }
227 
229 unsigned char dd4hep::detail::hash8(const char* key) {
230  return pearson_hash(key);
231 }
232 
234 std::string dd4hep::detail::str_replace(const std::string& str,
235  const std::string& pattern,
236  const std::string& replacement) {
237  std::string res = str;
238  for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
239  res.replace(id, pattern.length(), replacement);
240  return res;
241 }
242 
244 std::string dd4hep::detail::str_replace(const std::string& str,
245  char pattern,
246  const std::string& replacement) {
247  std::string res = str;
248  for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
249  res.replace(id, 1, replacement);
250  return res;
251 }
252 
254 std::string dd4hep::detail::str_replace(const std::string& str,
255  char pattern,
256  char replacement) {
257  std::string res = str;
258  for(size_t id=res.find(pattern); id != std::string::npos; id = res.find(pattern) )
259  res.replace(id, 1, 1, replacement);
260  return res;
261 }
262 
264 std::string dd4hep::detail::str_lower(const std::string& str) {
265  std::string res = str.c_str();
266  std::transform(res.begin(), res.end(), res.begin(), ::tolower);
267  return res;
268 }
269 
271 std::string dd4hep::detail::str_upper(const std::string& str) {
272  std::string res = str.c_str();
273  std::transform(res.begin(), res.end(), res.begin(), ::toupper);
274  return res;
275 }
276 
277 long int dd4hep::detail::makeTime(int year, int month, int day,
278  int hour, int minutes, int seconds)
279 {
280  struct tm tm_init;
281  ::memset(&tm_init,0,sizeof(tm_init));
282  tm_init.tm_year = year > 1900 ? year-1900 : year;
283  tm_init.tm_mon = month;
284  tm_init.tm_mday = day;
285  tm_init.tm_hour = hour;
286  tm_init.tm_min = minutes;
287  tm_init.tm_sec = seconds;
288  tm_init.tm_isdst = -1;
289  long int ti = ::mktime(&tm_init);
290  if ( ti >= 0 ) return ti;
291  except("dd4hep","Invalid time data given for conversion to epoch: %d-%d-%d %02d:%02d:%02d",
292  year, month, day, hour, minutes, seconds);
293  return ti;
294 }
295 
297 long int dd4hep::detail::makeTime(const std::string& date, const char* fmt) {
298  struct tm tm;
299  char* c = ::strptime(date.c_str(),fmt,&tm);
300  if ( 0 == c ) {
301  except("dd4hep",
302  "Invalid time format given for update:%s should be: %s",
303  date.c_str(), fmt);
304  }
305  long ti = ::mktime(&tm);
306  if ( ti >= 0 ) return ti;
307  except("dd4hep",
308  "Invalid time string given for conversion to epoch: %s (fmt='%s')",
309  date.c_str(), fmt);
310  return ti;
311 }
312 
313 static const std::string __typeinfoName(const std::type_info& tinfo) {
314  const char* class_name = tinfo.name();
315  std::string result;
316 #ifdef WIN32
317  std::size_t off = 0;
318  if ( ::strncmp(class_name, "class ", 6) == 0 ) {
319  // The returned name is prefixed with "class "
320  off = 6;
321  }
322  if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
323  // The returned name is prefixed with "struct "
324  off = 7;
325  }
326  if ( off != std::string::npos ) {
327  std::string tmp = class_name + off;
328  size_t loc = 0;
329  while( (loc = tmp.find("class ")) != std::string::npos ) {
330  tmp.erase(loc, 6);
331  }
332  loc = 0;
333  while( (loc = tmp.find("struct ")) != std::string::npos ) {
334  tmp.erase(loc, 7);
335  }
336  result = tmp;
337  }
338  else {
339  result = class_name;
340  }
341  // Change any " *" to "*"
342  while ( (off=result.find(" *")) != std::string::npos ) {
343  result.replace(off, 2, "*");
344  }
345  // Change any " &" to "&"
346  while ( (off=result.find(" &")) != std::string::npos ) {
347  result.replace(off, 2, "&");
348  }
349 #elif defined(sun)
350  result = class_name;
351 #elif !defined(__ICC)
352  if (::strlen(class_name) == 1) {
353  // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf
354  // for details
355  switch (class_name[0]) {
356  case 'v':
357  result = "void";
358  break;
359  case 'w':
360  result = "wchar_t";
361  break;
362  case 'b':
363  result = "bool";
364  break;
365  case 'c':
366  result = "char";
367  break;
368  case 'h':
369  result = "unsigned char";
370  break;
371  case 's':
372  result = "short";
373  break;
374  case 't':
375  result = "unsigned short";
376  break;
377  case 'i':
378  result = "int";
379  break;
380  case 'j':
381  result = "unsigned int";
382  break;
383  case 'l':
384  result = "long";
385  break;
386  case 'm':
387  result = "unsigned long";
388  break;
389  case 'x':
390  result = "long long";
391  break;
392  case 'y':
393  result = "unsigned long long";
394  break;
395  case 'n':
396  result = "__int128";
397  break;
398  case 'o':
399  result = "unsigned __int128";
400  break;
401  case 'f':
402  result = "float";
403  break;
404  case 'd':
405  result = "double";
406  break;
407  case 'e':
408  result = "long double";
409  break;
410  case 'g':
411  result = "__float128";
412  break;
413  case 'z':
414  result = "ellipsis";
415  break;
416  }
417  }
418  else {
419  char buff[16 * 1024];
420  std::size_t len = sizeof(buff);
421  int status = 0;
422  result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status);
423  }
424 #else
425  result = class_name;
426  throw std::runtime_error("CXXABI is missing for ICC!");
427 #endif
428  return result;
429 }
430 
431 std::string dd4hep::typeName(const std::type_info& typ) {
432  return __typeinfoName(typ);
433 }
434 
435 void dd4hep::invalidHandleError(const std::type_info& type)
436 {
437  throw invalid_handle_exception("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]");
438 }
439 
440 void dd4hep::invalidHandleAssignmentError(const std::type_info& from,
441  const std::type_info& to)
442 {
443  std::string msg = "Wrong assingment from ";
444  msg += typeName(from);
445  msg += " to ";
446  msg += typeName(to);
447  msg += " not possible!!";
448  throw invalid_handle_exception(msg);
449 }
450 
452 void dd4hep::notImplemented(const std::string& msg)
453 {
454  std::string m = "The requested feature " + msg + " is not implemented!";
455  throw std::runtime_error(m);
456 }
457 
458 void dd4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text)
459 {
460  if (typ1 != typ2) {
461  throw unrelated_type_error(typ1, typ2, text);
462  }
463 }
464 
465 namespace dd4hep {
466  namespace detail {
467  template<> const char* Primitive<bool>::default_format() { return "%d"; }
468  template<> const char* Primitive<char>::default_format() { return "%c"; }
469  template<> const char* Primitive<unsigned char>::default_format() { return "%02X"; }
470  template<> const char* Primitive<short>::default_format() { return "%d"; }
471  template<> const char* Primitive<unsigned short>::default_format() { return "%04X"; }
472  template<> const char* Primitive<int>::default_format() { return "%d"; }
473  template<> const char* Primitive<unsigned int>::default_format() { return "%08X"; }
474  template<> const char* Primitive<long>::default_format() { return "%ld"; }
475  template<> const char* Primitive<unsigned long>::default_format() { return "%016X"; }
476  template<> const char* Primitive<float>::default_format() { return "%f"; }
477  template<> const char* Primitive<double>::default_format() { return "%g"; }
478  template<> const char* Primitive<char*>::default_format() { return "%s"; }
479  template<> const char* Primitive<const char*>::default_format() { return "%s"; }
480  template<> const char* Primitive<std::string>::default_format() { return "%s"; }
481 
483  template <typename T> std::string Primitive<T>::toString(T value) {
484  char text[1024];
485  ::snprintf(text,sizeof(text),default_format(),value);
486  return text;
487  }
488 
490  template <> std::string Primitive<const char*>::toString(const char* value) {
491  if ( value ) {
492  return value;
493  }
494  throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
495  }
497  template <> std::string Primitive<char*>::toString(char* value) {
498  if ( value ) {
499  return value;
500  }
501  throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
502  }
504  template <> std::string Primitive<std::string>::toString(std::string value) {
505  return value;
506  }
507 
508  template std::string Primitive<bool>::toString(bool value);
509  template std::string Primitive<char>::toString(char value);
510  template std::string Primitive<unsigned char>::toString(unsigned char value);
511  template std::string Primitive<short>::toString(short value);
512  template std::string Primitive<unsigned short>::toString(unsigned short value);
513  template std::string Primitive<int>::toString(int value);
514  template std::string Primitive<unsigned int>::toString(unsigned int value);
515  template std::string Primitive<long>::toString(long value);
516  template std::string Primitive<unsigned long>::toString(unsigned long value);
517  template std::string Primitive<float>::toString(float value);
518  template std::string Primitive<double>::toString(double value);
519  }
520 }
521 
522 #ifdef __APPLE__
523 dd4hep::Cast::Cast(const std::type_info& t, cast_t c) : type(t), cast(c) {
525 }
526 #else
527 dd4hep::Cast::Cast(const std::type_info& t) : type(t) {
529  abi_class = dynamic_cast<const class_t*>(&type);
530  if (!abi_class) {
531  throw std::runtime_error("Class type " + typeName(type) + " is not an abi object type!");
532  }
533 }
534 #endif
535 
537 dd4hep::Cast::~Cast() {
538 }
539 
541 void* dd4hep::Cast::apply_dynCast(const Cast& to, const void* ptr) const
542 {
543  if (&to == this) {
544  return (void*) ptr;
545  }
546 #ifdef __APPLE__
547  // First try down cast
548  void *r = (*to.cast)(ptr);
549  if (r)
550  return r;
551  // Now try the up-cast
552  r = (*cast)(ptr);
553  if (r) return r;
554  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
555 #else
556  void* r = (void*)ptr;
557  if ( to.abi_class ) {
558  bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
559  if ( cast_worked ) return r;
560  r = (void*)ptr;
561  cast_worked = to.type.__do_upcast((const class_t*)abi_class,&r);
562  if ( cast_worked ) return r;
563 #if 0
564  const class_t* src_type = (const class_t*)to.abi_class;
565  if (src_type) {
566  // First try down cast
567  void *r = cast_wrap(ptr, src_type, (const class_t*) abi_class, -1);
568  if ( r ) return r;
569  // Now try the up-cast
570  r = cast_wrap(ptr, (const class_t*) abi_class, src_type, -1);
571  if (r) return r;
572  }
573 #endif
574  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
575  }
576 #endif
577  throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
578 }
579 
581 void* dd4hep::Cast::apply_upCast(const Cast& to, const void* ptr) const
582 {
583  if (&to == this) {
584  return (void*) ptr;
585  }
586  return apply_dynCast(to, ptr);
587 }
588 
590 void* dd4hep::Cast::apply_downCast(const Cast& to, const void* ptr) const
591 {
592  if (&to == this) {
593  return (void*) ptr;
594  }
595 #ifdef __APPLE__
596  void *r = (*to.cast)(ptr);
597  if (r) return r;
598  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
599 #else
600  if ( to.abi_class ) {
601  // Since we have to cast a 'to' pointer up to the real pointer
602  // no virtual inheritance can be supported!
603  void* r = (void*)ptr;
604  bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
605  if ( cast_worked ) return r;
606 #if 0
607  void *r = cast_wrap(ptr, src_type, (const class_t*)abi_class, -1);
608  if (r) return r;
609 #endif
610  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
611  }
612  throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
613 #endif
614 }
Primitives.h
VolumeID
dd4hep::DDSegmentation::VolumeID VolumeID
Definition: SegmentationDictionary.h:49
key
unsigned char key
Definition: AlignmentsCalculator.cpp:69
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::detail::tools::toString
std::string toString(const PlacedVolume::VolIDs &ids)
Convert VolumeID to string.
Definition: DetectorTools.cpp:378
dd4hep::sim::hash
unsigned int hash(unsigned int initialSeed, unsigned int eventNumber, unsigned int runNumber)
calculate hash from initialSeed, eventID and runID
Definition: Geant4EventSeed.h:201
Printout.h
Exceptions.h
dd4hep::DDSegmentation::Segmentation::type
virtual const std::string & type() const
Access the segmentation type.
Definition: Segmentation.h:104