DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Primitives.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation for LCD
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 <stdexcept>
21 #include <cstring>
22 #include <map>
23 
24 #if defined(__linux) || defined(__APPLE__)
25 #include <cxxabi.h>
26 #ifndef __APPLE__
27 typedef abi::__class_type_info class_t;
28 using abi::__dynamic_cast;
29 #endif
30 #endif
31 
32 long int DD4hep::makeTime(int year, int month, int day,
33  int hour, int minutes, int seconds)
34 {
35  struct tm tm_init;
36  ::memset(&tm_init,0,sizeof(tm_init));
37  tm_init.tm_year = year > 1900 ? year-1900 : year;
38  tm_init.tm_mon = month;
39  tm_init.tm_mday = day;
40  tm_init.tm_hour = hour;
41  tm_init.tm_min = minutes;
42  tm_init.tm_sec = seconds;
43  tm_init.tm_isdst = -1;
44  long int ti = ::mktime(&tm_init);
45  if ( ti >= 0 ) return ti;
46  except("DD4hep","Invalid time data given for conversion to epoch: %d-%d-%d %02d:%02d:%02d",
47  year, month, day, hour, minutes, seconds);
48  return ti;
49 }
50 
52 long int DD4hep::makeTime(const std::string& date, const char* fmt) {
53  struct tm tm;
54  char* c = ::strptime(date.c_str(),fmt,&tm);
55  if ( 0 == c ) {
56  except("DD4hep",
57  "Invalid time format given for update:%s should be: %s",
58  date.c_str(), fmt);
59  }
60  long ti = ::mktime(&tm);
61  if ( ti >= 0 ) return ti;
62  except("DD4hep",
63  "Invalid time string given for conversion to epoch: %s (fmt='%s')",
64  date.c_str(), fmt);
65  return ti;
66 }
67 
68 static const std::string __typeinfoName(const std::type_info& tinfo) {
69  const char* class_name = tinfo.name();
70  std::string result;
71 #ifdef WIN32
72  std::size_t off = 0;
73  if ( ::strncmp(class_name, "class ", 6) == 0 ) {
74  // The returned name is prefixed with "class "
75  off = 6;
76  }
77  if ( ::strncmp(class_name, "struct ", 7) == 0 ) {
78  // The returned name is prefixed with "struct "
79  off = 7;
80  }
81  if ( off != std::string::npos ) {
82  std::string tmp = class_name + off;
83  size_t loc = 0;
84  while( (loc = tmp.find("class ")) != std::string::npos ) {
85  tmp.erase(loc, 6);
86  }
87  loc = 0;
88  while( (loc = tmp.find("struct ")) != std::string::npos ) {
89  tmp.erase(loc, 7);
90  }
91  result = tmp;
92  }
93  else {
94  result = class_name;
95  }
96  // Change any " *" to "*"
97  while ( (off=result.find(" *")) != std::string::npos ) {
98  result.replace(off, 2, "*");
99  }
100  // Change any " &" to "&"
101  while ( (off=result.find(" &")) != std::string::npos ) {
102  result.replace(off, 2, "&");
103  }
104 #elif defined(sun)
105  result = class_name;
106 #elif !defined(__ICC)
107  if (::strlen(class_name) == 1) {
108  // See http://www.realitydiluted.com/mirrors/reality.sgi.com/dehnert_engr/cxx/abi.pdf
109  // for details
110  switch (class_name[0]) {
111  case 'v':
112  result = "void";
113  break;
114  case 'w':
115  result = "wchar_t";
116  break;
117  case 'b':
118  result = "bool";
119  break;
120  case 'c':
121  result = "char";
122  break;
123  case 'h':
124  result = "unsigned char";
125  break;
126  case 's':
127  result = "short";
128  break;
129  case 't':
130  result = "unsigned short";
131  break;
132  case 'i':
133  result = "int";
134  break;
135  case 'j':
136  result = "unsigned int";
137  break;
138  case 'l':
139  result = "long";
140  break;
141  case 'm':
142  result = "unsigned long";
143  break;
144  case 'x':
145  result = "long long";
146  break;
147  case 'y':
148  result = "unsigned long long";
149  break;
150  case 'n':
151  result = "__int128";
152  break;
153  case 'o':
154  result = "unsigned __int128";
155  break;
156  case 'f':
157  result = "float";
158  break;
159  case 'd':
160  result = "double";
161  break;
162  case 'e':
163  result = "long double";
164  break;
165  case 'g':
166  result = "__float128";
167  break;
168  case 'z':
169  result = "ellipsis";
170  break;
171  }
172  }
173  else {
174  char buff[16 * 1024];
175  std::size_t len = sizeof(buff);
176  int status = 0;
177  result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status);
178  }
179 #else
180  result = class_name;
181  throw std::runtime_error("CXXABI is missing for ICC!");
182 #endif
183  return result;
184 }
185 
186 std::string DD4hep::typeName(const std::type_info& typ) {
187  return __typeinfoName(typ);
188 }
189 
190 void DD4hep::invalidHandleError(const std::type_info& type)
191 {
192  throw invalid_handle_exception("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]");
193 }
194 
195 void DD4hep::invalidHandleAssignmentError(const std::type_info& from,
196  const std::type_info& to)
197 {
198  std::string msg = "Wrong assingment from ";
199  msg += typeName(from);
200  msg += " to ";
201  msg += typeName(to);
202  msg += " not possible!!";
203  throw invalid_handle_exception(msg);
204 }
205 
207 void DD4hep::notImplemented(const std::string& msg)
208 {
209  std::string m = "The requested feature " + msg + " is not implemented!";
210  throw std::runtime_error(m);
211 }
212 
213 void DD4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text)
214 {
215  if (typ1 != typ2) {
216  throw unrelated_type_error(typ1, typ2, text);
217  }
218 }
219 
220 namespace DD4hep {
221  template<> const char* Primitive<bool>::default_format() { return "%d"; }
222  template<> const char* Primitive<char>::default_format() { return "%c"; }
223  template<> const char* Primitive<unsigned char>::default_format() { return "%02X"; }
224  template<> const char* Primitive<short>::default_format() { return "%d"; }
225  template<> const char* Primitive<unsigned short>::default_format() { return "%04X"; }
226  template<> const char* Primitive<int>::default_format() { return "%d"; }
227  template<> const char* Primitive<unsigned int>::default_format() { return "%08X"; }
228  template<> const char* Primitive<long>::default_format() { return "%ld"; }
229  template<> const char* Primitive<unsigned long>::default_format() { return "%016X"; }
230  template<> const char* Primitive<float>::default_format() { return "%f"; }
231  template<> const char* Primitive<double>::default_format() { return "%g"; }
232  template<> const char* Primitive<char*>::default_format() { return "%s"; }
233  template<> const char* Primitive<const char*>::default_format() { return "%s"; }
234  template<> const char* Primitive<std::string>::default_format() { return "%s"; }
235 
237  template <typename T> std::string Primitive<T>::toString(T value) {
238  char text[1024];
239  ::snprintf(text,sizeof(text),default_format(),value);
240  return text;
241  }
242 
244  template <> std::string Primitive<const char*>::toString(const char* value) {
245  if ( value ) {
246  return value;
247  }
248  throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
249  }
251  template <> std::string Primitive<char*>::toString(char* value) {
252  if ( value ) {
253  return value;
254  }
255  throw std::runtime_error("Failed to convert (char*)NULL to std::string!");
256  }
258  template <> std::string Primitive<std::string>::toString(std::string value) {
259  return value;
260  }
261 
262  template std::string Primitive<bool>::toString(bool value);
263  template std::string Primitive<char>::toString(char value);
264  template std::string Primitive<unsigned char>::toString(unsigned char value);
265  template std::string Primitive<short>::toString(short value);
266  template std::string Primitive<unsigned short>::toString(unsigned short value);
267  template std::string Primitive<int>::toString(int value);
268  template std::string Primitive<unsigned int>::toString(unsigned int value);
269  template std::string Primitive<long>::toString(long value);
270  template std::string Primitive<unsigned long>::toString(unsigned long value);
271  template std::string Primitive<float>::toString(float value);
272  template std::string Primitive<double>::toString(double value);
273 }
274 
276 DD4hep::ComponentCast::ComponentCast(const std::type_info& t, destroy_t d, cast_t c)
277  : type(t), destroy(d), cast(c) {
278 #ifdef __APPLE__
279  abi_class = 0;
280 #else
281  abi_class = dynamic_cast<const class_t*>(&type);
282  if (!abi_class) {
283  throw std::runtime_error("Class type " + typeName(type) + " is not an abi object type!");
284  }
285 #endif
286 }
287 
290 }
291 
292 #if 0
293 // Dynamic cast runtime.
294 // src2dst has the following possible values
295 // >-1: src_type is a unique public non-virtual base of dst_type
296 // dst_ptr + src2dst == src_ptr
297 // -1: unspecified relationship
298 // -2: src_type is not a public base of dst_type
299 // -3: src_type is a multiple public non-virtual base of dst_type
300 extern "C" void*
301 __dynamic_cast(const void* __src_ptr,// Starting object.
302  const abi::__class_type_info* __src_type,// Static type of object.
303  const abi::__class_type_info* __dst_type,// Desired target type.
304  ptrdiff_t __src2dst);// How src and dst are related.
305 #endif
306 
307 #ifndef __APPLE__
308 static inline void* cast_wrap(const void* p,
309  const abi::__class_type_info* src,
310  const abi::__class_type_info* dst,
311  ptrdiff_t src2dst)
312 {
313  return abi::__dynamic_cast(p,src,dst,src2dst);
314 }
315 #endif
316 
318 void* DD4hep::ComponentCast::apply_dynCast(const ComponentCast& to, const void* ptr) const
319 {
320  if (&to == this) {
321  return (void*) ptr;
322  }
323 #ifdef __APPLE__
324  // First try down cast
325  void *r = (*to.cast)(ptr);
326  if (r)
327  return r;
328  // Now try the up-cast
329  r = (*cast)(ptr);
330  if (r) return r;
331  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
332 #else
333  void* r = (void*)ptr;
334  if ( to.abi_class ) {
335  bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
336  if ( cast_worked ) return r;
337  r = (void*)ptr;
338  cast_worked = to.type.__do_upcast((const class_t*)abi_class,&r);
339  if ( cast_worked ) return r;
340 #if 0
341  const class_t* src_type = (const class_t*)to.abi_class;
342  if (src_type) {
343  // First try down cast
344  void *r = cast_wrap(ptr, src_type, (const class_t*) abi_class, -1);
345  if ( r ) return r;
346  // Now try the up-cast
347  r = cast_wrap(ptr, (const class_t*) abi_class, src_type, -1);
348  if (r) return r;
349  }
350 #endif
351  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
352  }
353  throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
354 #endif
355 }
356 
358 void* DD4hep::ComponentCast::apply_upCast(const ComponentCast& to, const void* ptr) const
359 {
360  if (&to == this) {
361  return (void*) ptr;
362  }
363  return apply_dynCast(to, ptr);
364 }
365 
367 void* DD4hep::ComponentCast::apply_downCast(const ComponentCast& to, const void* ptr) const
368 {
369  if (&to == this) {
370  return (void*) ptr;
371  }
372 #ifdef __APPLE__
373  void *r = (*to.cast)(ptr);
374  if (r) return r;
375  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
376 #else
377  if ( to.abi_class ) {
378  // Since we have to cast a 'to' pointer up to the real pointer
379  // no virtual inheritance can be supported!
380  void* r = (void*)ptr;
381  bool cast_worked = type.__do_upcast((const class_t*)to.abi_class,&r);
382  if ( cast_worked ) return r;
383 #if 0
384  void *r = cast_wrap(ptr, src_type, (const class_t*)abi_class, -1);
385  if (r) return r;
386 #endif
387  throw unrelated_type_error(type, to.type, "Failed to apply abi dynamic cast operation!");
388  }
389  throw unrelated_type_error(type, to.type, "Target type is not an abi class type!");
390 #endif
391 }
392 
static void * cast_wrap(const void *p, const abi::__class_type_info *src, const abi::__class_type_info *dst, ptrdiff_t src2dst)
Definition: Primitives.cpp:308
void notImplemented(const std::string &msg)
Throw exception when handles are check for validity.
Definition: Primitives.cpp:207
const void * abi_class
Definition: Primitives.h:177
std::string typeName(const std::type_info &type)
ABI information about type names.
Definition: Primitives.cpp:186
int except(const std::string &src, const std::string &fmt,...)
Calls the display action with ERROR and throws an std::runtime_error exception.
Definition: Printout.cpp:217
virtual ~ComponentCast()
Defautl destructor.
Definition: Primitives.cpp:289
static const char * default_format()
Access to default printf format.
void invalidHandleAssignmentError(const std::type_info &from, const std::type_info &to)
Throw exception when handles are badly assigned.
Definition: Primitives.cpp:195
void * apply_dynCast(const ComponentCast &to, const void *ptr) const
Apply cast using typeinfo instead of dynamic_cast.
Definition: Primitives.cpp:318
void * apply_downCast(const ComponentCast &to, const void *ptr) const
Apply cast using typeinfo instead of dynamic_cast.
Definition: Primitives.cpp:367
Specialized exception to be thrown if invalid handles are accessed.
Definition: Primitives.h:63
const std::type_info & type
Definition: Primitives.h:175
Exception class to signal operations on unrelated classes.
Definition: Exceptions.h:31
Class to perform dynamic casts using unknown pointers.
Definition: Primitives.h:168
static const std::string __typeinfoName(const std::type_info &tinfo)
Definition: Primitives.cpp:68
long int makeTime(int year, int month, int day, int hour=0, int minutes=0, int seconds=0)
Convert date into epoch time (seconds since 1970)
Definition: Primitives.cpp:32
ComponentCast(const std::type_info &t, destroy_t d, cast_t c)
Initializing Constructor.
Definition: Primitives.cpp:276
void invalidHandleError(const std::type_info &type)
Throw exception when handles are check for validity.
Definition: Primitives.cpp:190
void * apply_upCast(const ComponentCast &to, const void *ptr) const
Apply cast using typeinfo instead of dynamic_cast.
Definition: Primitives.cpp:358
static std::string toString(T value)
Auto conversion to string using the default format.
Definition: Primitives.cpp:237
void typeinfoCheck(const std::type_info &typ1, const std::type_info &typ2, const std::string &text="")
Check type infos for equivalence (dynamic casts) using ABI information.
Definition: Primitives.cpp:213
TGeoShape TGeoMedium * m
Definition: Volumes.cpp:294