ATLAS Offline Software
Type.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
12 #include "RootUtils/Type.h"
14 #include "TError.h"
15 #include "TROOT.h"
16 #include <memory>
17 #include <sstream>
18 #include <stdexcept>
19 #include <cassert>
20 
21 
22 namespace RootUtils {
23 
24 
36  : m_cls(0),
37  m_type(kNoType_t),
38  m_ti(0),
39  m_size(0),
40  m_defElt(0)
41 {
42 }
43 
44 
49 Type::Type (TClass* cls)
50  : m_cls(0),
51  m_type(kNoType_t),
52  m_ti(0),
53  m_size(0),
54  m_defElt(0)
55 {
56  init (cls);
57 }
58 
59 
64 Type::Type (EDataType type)
65  : m_cls(0),
66  m_type(kNoType_t),
67  m_ti(0),
68  m_size(0),
69  m_defElt(0)
70 {
71  init (type);
72 }
73 
74 
83 Type::Type (const std::string& typname)
84  : m_cls(0),
85  m_type(kNoType_t),
86  m_ti(0),
87  m_size(0),
88  m_defElt(0)
89 {
90  init (typname);
91 }
92 
93 
99  : m_cls (other.m_cls),
100  m_type (other.m_type),
101  m_ti (other.m_ti),
102  m_size (other.m_size),
103  m_assign (other.m_assign),
104  m_defElt (0)
105 {
106  if (m_cls)
107  m_defElt = create();
108 }
109 
110 
116 {
117  if (this != &other) {
118  m_cls = other.m_cls;
119  m_type = other.m_type;
120  m_ti = other.m_ti;
121  m_size = other.m_size;
122  m_assign = other.m_assign;
123  if (m_defElt)
124  destroy (m_defElt);
125  if (m_cls)
126  m_defElt = create();
127  else
128  m_defElt = 0;
129  }
130  return *this;
131 }
132 
133 
138 {
139  if (m_defElt)
140  destroy (m_defElt);
141 }
142 
143 
154 void Type::init (const std::string& type_name)
155 {
156  // Make sure root's table of types is initialized.
157  // May be needed for root 6.
158  gROOT->GetListOfTypes();
159 
160  assert (m_cls == 0 && m_type == kNoType_t);
161 
162  TClass* cls = TClass::GetClass (type_name.c_str());
163  if (cls) {
164  init (cls);
165  return;
166  }
167 
168  for (int i = 0; i < kNumDataTypes; ++i) {
169  EDataType type = static_cast<EDataType>(i);
170  TDataType* dt = TDataType::GetDataType(type);
171  if (dt && type_name == dt->GetTypeName()) {
172  init (type);
173  return;
174  }
175  }
176 
177  EDataType type = kNoType_t;
178  // Check for some other synonyms.
179  // RNTuple likes to prepend "std::" to type names - remove it before comparison
180  std::string tname;
181  if( type_name.rfind("std::", 0) == 0 ) {
182  // remove std:: prefix if present
183  tname = type_name.substr(5);
184  } else {
185  tname = type_name;
186  }
187  if (tname == "uint32_t") {
188  if (sizeof (unsigned int) == 4)
189  type = kUInt_t;
190  }
191  else if (tname == "int32_t") {
192  if (sizeof (unsigned int) == 4)
193  type = kInt_t;
194  }
195  else if (tname == "uint16_t") {
196  if (sizeof (unsigned short) == 2)
197  type = kUShort_t;
198  }
199  else if (tname == "int16_t") {
200  if (sizeof (short) == 2)
201  type = kShort_t;
202  }
203  else if (tname == "uint8_t") {
204  type = kUChar_t;
205  }
206  else if (tname == "int8_t") {
207  type = kChar_t;
208  }
209  else if (tname == "uint64_t") {
210  if (sizeof(unsigned long) == 8)
211  type = kULong_t;
212  else if (sizeof(unsigned long long) == 8)
213  type = kULong64_t;
214 
215  }
216  else if (tname == "int64_t") {
217  if (sizeof(long) == 8)
218  type = kLong_t;
219  else if (sizeof(long long) == 8)
220  type = kLong64_t;
221  }
222 
223  if (type != kNoType_t) {
224  init (type);
225  return;
226  }
227 
228  throw std::runtime_error (std::string ("RootUtils::Type: Can't find type `") +
229  type_name + "'.");
230 }
231 
232 
239 void Type::init (TClass* cls)
240 {
241  assert (m_cls == 0 && m_type == kNoType_t);
242  m_cls = cls;
243  m_type = kNoType_t;
244  m_size = cls->Size();
245  m_defElt = create();
246  m_ti = cls->GetTypeInfo();
247 
248  std::string fname = "operator=";
249 
250  std::string assignProto = "const ";
251  assignProto += m_cls->GetName();
252  assignProto += "&";
253 
254  m_assign.setProto (m_cls, fname, assignProto);
255 }
256 
257 
264 void Type::init (EDataType type)
265 {
266  // Make sure root's table of types is initialized.
267  // May be needed for root 6.
268  gROOT->GetListOfTypes();
269 
270  assert (m_cls == 0 && m_type == kNoType_t);
271  TDataType* dt = TDataType::GetDataType (type);
272  if (!dt) {
273  throw std::runtime_error ("Unknown data type");
274  }
275 
276  m_cls = 0;
277  m_type = type;
278  m_size = dt->Size();
279  m_defElt = 0;
280 
281  switch (type) {
282 #define TYPE(CODE, TYP, IOTYP) case CODE: m_ti = &typeid(TYP); break
283 #include "Types.def"
284 #undef TYPE
285  default: break;
286  }
287 }
288 
289 
296 void* Type::create() const
297 {
298  if (m_cls)
299  return m_cls->New();
300  void* p = new char[m_size];
301  clear (p);
302  return p;
303 }
304 
305 
310 void Type::destroy (void* p) const
311 {
312  if (p) {
313  if (m_cls) {
314  // TClass::Destructor is non-const.
315  // But there's nothing obviously problematic in it...
316  // just suppress the checker warning for now.
317  TClass* cls ATLAS_THREAD_SAFE = m_cls;
318  cls->Destructor (p);
319  }
320  else
321  delete [] (reinterpret_cast<char*> (p));
322  }
323 }
324 
325 
329 std::string Type::getTypeName() const
330 {
331  if (m_type != kNoType_t)
332  return TDataType::GetTypeName (m_type);
333 
334  if (m_cls)
335  return m_cls->GetName();
336 
337  return "";
338 }
339 
340 
346 const TClass* Type::getClass() const
347 {
348  return m_cls;
349 }
350 
351 
357 EDataType Type::getDataType() const
358 {
359  return m_type;
360 }
361 
362 
366 const std::type_info* Type::getTypeInfo() const
367 {
368  return m_ti;
369 }
370 
371 
375 size_t Type::getSize() const
376 {
377  return m_size;
378 }
379 
380 
389 void Type::copyRange (void* dst, const void* src, size_t n) const
390 {
391  if (m_cls) {
392  if (dst > src && reinterpret_cast<unsigned long>(src) + n*m_size > reinterpret_cast<unsigned long>(dst))
393  {
394  for (size_t i = n-1; i < n; --i) {
395  assign (dst, i, src, i);
396  }
397  }
398  else
399  {
400  for (size_t i = 0; i < n; ++i) {
401  assign (dst, i, src, i);
402  }
403  }
404  }
405  else {
406  memmove (dst, src, n * m_size);
407  }
408 }
409 
410 
420 void Type::clearRange (void* dst, size_t n) const
421 {
422  if (m_cls) {
423  for (size_t i = 0; i < n; ++i) {
424  clear (dst, i);
425  }
426  }
427  else {
428  memset (dst, 0, n * m_size);
429  }
430 }
431 
432 
443 void Type::clearRange (void* dst, size_t index, size_t n) const
444 {
445  clearRange (reinterpret_cast<char*> (dst) + index * m_size, n);
446 }
447 
448 
454 void Type::clear (void* dst, size_t index) const
455 {
456  dst = reinterpret_cast<void*>(reinterpret_cast<unsigned long>(dst) + m_size* index);
457  assign (dst, m_defElt);
458 }
459 
460 
465 void Type::clear (void* dst) const
466 {
467  assign (dst, m_defElt);
468 }
469 
470 
480 void Type::assign (void* dst, size_t dst_index,
481  const void* src, size_t src_index) const
482 {
483  dst = reinterpret_cast<void*>(reinterpret_cast<unsigned long>(dst) + m_size* dst_index);
484  src = reinterpret_cast<const void*>(reinterpret_cast<unsigned long>(src) + m_size * src_index);
485  assign (dst, src);
486 }
487 
488 
499 void Type::assign (void* dst, const void* src) const
500 {
501  if (TMethodCall* meth = m_assign.call()) {
502  meth->ResetParam();
503  meth->SetParam (reinterpret_cast<Long_t>(src));
504  meth->Execute (dst);
505  }
506  else {
507  if (src)
508  memcpy (dst, src, m_size);
509  else
510  memset (dst, 0, m_size);
511  }
512 }
513 
514 
524 void Type::swap (void* a, size_t a_index,
525  void* b, size_t b_index) const
526 {
527  a = reinterpret_cast<void*>(reinterpret_cast<unsigned long>(a) + m_size*a_index);
528  b = reinterpret_cast<void*>(reinterpret_cast<unsigned long>(b) + m_size*b_index);
529  swap (a, b);
530 }
531 
532 
538 void Type::swap (void* a, void* b) const
539 {
540  if (m_assign.call() != nullptr) {
541  void* tmp = create();
542  assign (tmp, a);
543  assign (a, b);
544  assign (b, tmp);
545  destroy (tmp);
546  }
547  else {
548  std::vector<char> tmp (m_size);
549  memcpy (tmp.data(), a, m_size);
550  memcpy (a, b, m_size);
551  memcpy (b, tmp.data(), m_size);
552  }
553 }
554 
555 
567 void Type::swapRange (void* a, size_t a_index,
568  void* b, size_t b_index,
569  size_t n) const
570 {
571  char* aptr = reinterpret_cast<char*>(a) + m_size * a_index;
572  char* bptr = reinterpret_cast<char*>(b) + m_size * b_index;
573 
574  if (m_assign.call() != nullptr) {
575  void* tmp = create();
576  for (size_t i = 0; i < n; i++) {
577  assign (tmp, aptr);
578  assign (aptr, bptr);
579  assign (bptr, tmp);
580  aptr += m_size;
581  bptr += m_size;
582  }
583  destroy (tmp);
584  }
585  else {
586  std::vector<char> tmp (m_size * n);
587  memcpy (tmp.data(), aptr, m_size * n);
588  memcpy (aptr, bptr, m_size * n);
589  memcpy (bptr, tmp.data(), m_size * n);
590  }
591 }
592 
593 
601 void Type::fromString (void* p, const std::string& s) const
602 {
603  std::istringstream is (s);
604  switch (m_type) {
605 #define TYPE(CODE, TYP, IOTYP) case CODE: { IOTYP tmp=0; is >> tmp; *reinterpret_cast<TYP*>(p) = tmp; } return
606 #include "Types.def"
607 #undef TYPE
608  default: break;
609  }
610 
611  if (m_cls == TClass::GetClass ("string")) {
612  *reinterpret_cast<std::string*>(p) = s;
613  return;
614  }
615 
616  throw std::runtime_error
617  (std::string ("RootUtils::Type::fromString: Can't convert objects of type `" +
618  getTypeName() + "'."));
619 }
620 
621 
622 } // namespace RootUtils
RootUtils
Definition: ILogger.h:20
RootUtils::Type::swapRange
void swapRange(void *a, size_t a_index, void *b, size_t b_index, size_t n) const
Swap a range of objects between vectors.
Definition: Type.cxx:567
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
RootUtils::Type::init
void init(const std::string &typname)
Initialize from a type name.
Definition: Type.cxx:154
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
RootUtils::Type::m_cls
TClass * m_cls
The class of the derived type, or 0 if it's not a class type.
Definition: Type.h:349
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
RootUtils::Type::getClass
const TClass * getClass() const
Return the ROOT class for the described type.
Definition: Type.cxx:346
index
Definition: index.py:1
RootUtils::Type::swap
void swap(void *a, size_t a_index, void *b, size_t b_index) const
Swap an object between vectors.
Definition: Type.cxx:524
RootUtils::Type::getTypeInfo
const std::type_info * getTypeInfo() const
Return the type_info for the described type.
Definition: Type.cxx:366
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
RootUtils::Type::m_defElt
void * m_defElt
Pointer to a default-constructed instance of the payload object.
Definition: Type.h:365
RootUtils::Type::assign
void assign(void *dst, size_t dst_index, const void *src, size_t src_index) const
Copy an object within vectors.
Definition: Type.cxx:480
RootUtils::Type::m_type
EDataType m_type
The ROOT type code of the derived type, or kNoType_t for a class type.
Definition: Type.h:352
RootUtils::Type::getSize
size_t getSize() const
Return the size in bytes of an instance of the described type.
Definition: Type.cxx:375
m_type
TokenType m_type
the type
Definition: TProperty.cxx:44
RootUtils::Type::clear
void clear(void *dst, size_t index) const
Clear an object in a vector.
Definition: Type.cxx:454
RootUtils::Type::destroy
void destroy(void *p) const
Destroy an instance of the object (and free memory).
Definition: Type.cxx:310
Type.h
Wrapper for ROOT types.
lumiFormat.i
int i
Definition: lumiFormat.py:92
RootUtils::Type::clearRange
void clearRange(void *dst, size_t n) const
Clear a range of objects.
Definition: Type.cxx:420
beamspotman.n
n
Definition: beamspotman.py:731
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:58
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
xAODType
Definition: ObjectType.h:13
RootUtils::Type::fromString
void fromString(void *p, const std::string &s) const
Initialize an object from a string.
Definition: Type.cxx:601
RootUtils::Type::m_size
size_t m_size
The size in bytes of an instance of the described type.
Definition: Type.h:358
RootUtils::Type::getDataType
EDataType getDataType() const
Return the ROOT data type code for the described type.
Definition: Type.cxx:357
RootUtils::Type::m_ti
const std::type_info * m_ti
The type_info for the described type.
Definition: Type.h:355
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
python.AthDsoLogger.fname
string fname
Definition: AthDsoLogger.py:67
RootUtils::Type::ATLAS_THREAD_SAFE
TSMethodCall m_assign ATLAS_THREAD_SAFE
Definition: Type.h:361
RootUtils::Type::Type
Type()
Default constructor.
Definition: Type.cxx:35
a
TList * a
Definition: liststreamerinfos.cxx:10
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
RootUtils::Type::copyRange
void copyRange(void *dst, const void *src, size_t n) const
Copy a range of objects.
Definition: Type.cxx:389
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
RootUtils::Type::~Type
~Type()
Destructor.
Definition: Type.cxx:137
RootUtils::Type::create
void * create() const
Create an instance of the object.
Definition: Type.cxx:296
RootUtils::Type::getTypeName
std::string getTypeName() const
Return the name of this type.
Definition: Type.cxx:329
RootUtils::Type::operator=
Type & operator=(const RootUtils::Type &other)
Assignment.
Definition: Type.cxx:115
checker_macros.h
Define macros for attributes used to control the static checker.