ATLAS Offline Software
TVirtualConverter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
13 #include <cassert>
14 #include <cstdlib>
15 #include "TBaseClass.h"
16 #include "TBuffer.h"
17 #include "TClass.h"
18 #include "TClassEdit.h"
19 #include "TDataMember.h"
20 #include "TDataType.h"
21 #include "TError.h"
22 #include "TROOT.h"
23 #include "TStreamerInfo.h"
24 
25 
26 namespace {
27 
28 
38 UInt_t CalculateCheckSum (TClass* cl, const char* name_in)
39 {
40  UInt_t id = 0;
41  int il;
42  TString name = name_in;
43  TString type;
44  il = name.Length();
45  for (int i=0; i<il; i++) id = id*3+name[i];
46 
47  TList *tlb = cl->GetListOfBases();
48  if (tlb) { // Loop over bases
49 
50  TIter nextBase(tlb);
51 
52  TBaseClass *tbc=0;
53  while((tbc=(TBaseClass*)nextBase())) {
54  name = tbc->GetName();
55  il = name.Length();
56  for (int i=0; i<il; i++) id = id*3+name[i];
57  }/*EndBaseLoop*/
58  }
59  TList *tlm = cl->GetListOfDataMembers();
60  if (tlm) { // Loop over members
61  TIter nextMemb(tlm);
62  TDataMember *tdm=0;
63  Long_t prop = 0;
64  while((tdm=(TDataMember*)nextMemb())) {
65  if (!tdm->IsPersistent()) continue;
66  // combine properties
67  prop = (tdm->Property());
68  TDataType* tdt = tdm->GetDataType();
69  if (tdt) prop |= tdt->Property();
70 
71  if ( prop&kIsStatic) continue;
72  name = tdm->GetName(); il = name.Length();
73  if (prop&kIsEnum) id = id*3 + 1;
74 
75  int i;
76  for (i=0; i<il; i++) id = id*3+name[i];
77  type = tdm->GetFullTypeName();
78  {
79  // Protect against data race inside TClassEdit.
80  // https://github.com/root-project/root/issues/10353
81  // Should be fixed in root 6.26.02.
82  R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
83  if (TClassEdit::IsSTLCont(type) != ROOT::kNotSTL)
84  type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
85  }
86 
87  il = type.Length();
88  for (i=0; i<il; i++) id = id*3+type[i];
89 
90  int dim = tdm->GetArrayDim();
91  if (prop&kIsArray) {
92  for (int i=0;i<dim;i++) id = id*3+tdm->GetMaxIndex(i);
93  }
94 
95  }/*EndMembLoop*/
96  }
97  return id;
98 }
99 
100 
101 } // anonymous namespace
102 
103 
111  TClass* trans_cls,
112  TClass* pers_cls)
113  : fTransClass (trans_cls),
114  fPersClass (pers_cls),
115  fCheckSum (checksum),
116  fOldLast (-3),
117  fPersObj (nullptr)
118 {
119  CheckClasses();
120 }
121 
122 
131  TClass* pers_cls)
132  : fTransClass (trans_cls),
133  fPersClass (pers_cls),
134  fCheckSum (fTransClass ?
135  CalculateCheckSum (fPersClass, fTransClass->GetName()) : 0),
136  fOldLast (-3),
137  fPersObj (nullptr)
138 {
139  CheckClasses();
140 }
141 
142 
152  const std::string& trans_cls,
153  const std::string& pers_cls)
154  : fTransClass (ToClass (trans_cls)),
155  fPersClass (ToClass (pers_cls)),
156  fCheckSum (checksum),
157  fOldLast (-3),
158  fPersObj (nullptr)
159 {
160  CheckClasses();
161 }
162 
163 
173 TVirtualConverter::TVirtualConverter (const std::string& trans_cls,
174  const std::string& pers_cls)
175  : fTransClass (ToClass (trans_cls)),
176  fPersClass (ToClass (pers_cls)),
177  fCheckSum (CalculateCheckSum (fPersClass, fTransClass->GetName())),
178  fOldLast (-3),
179  fPersObj (nullptr)
180 {
181  CheckClasses();
182 }
183 
184 
189 {
190  if (fTransClass == nullptr) {
191  if (fPersClass == nullptr)
192  Error ("TVirtualConverter",
193  "Both transient and persistent classes are null.");
194  else
195  Error ("TVirtualConverter",
196  "Transient class is null for persistent class `%s'",
197  fPersClass->GetName());
198  }
199  else if (fPersClass == nullptr)
200  Error ("TVirtualConverter",
201  "Persistent class is null for transient class `%s'",
202  fTransClass->GetName());
203 }
204 
205 
210 {
211  // If we made an instance of the persistent class, get rid of it here.
212  if (fPersObj)
214 }
215 
216 
221 {
222  return fTransClass;
223 }
224 
225 
230 {
231  return fPersClass;
232 }
233 
234 
239 {
240  return fCheckSum;
241 }
242 
243 
251 {
252  return fPersClass->New();
253 }
254 
255 
264 {
265  return fPersClass->Destructor (persobj);
266 }
267 
268 
283  void* obj,
284  Version_t version,
285  UInt_t R__s,
286  UInt_t R__c)
287 {
288  // Make sure that we've done automatic schema evolution on the
289  // persistent side.
291 
292  // Make an instance of the persistent class, if we haven't done so already.
293  if (fPersObj == nullptr)
294  fPersObj = NewPersObj();
295 
296  // Read in the object, as an instance of the persistent class.
297  fPersClass->ReadBuffer (b, fPersObj, version, R__s, R__c);
298 
299  // Convert to the transient representation.
301 }
302 
303 
310 TClass* TVirtualConverter::ToClass (const std::string& name)
311 {
312  return gROOT->GetClass (name.c_str());
313 }
314 
315 
322 TClass* TVirtualConverter::ToClass (const std::type_info& id)
323 {
324  TClass* cl = gROOT->GetClass (id);
325  if (cl) return cl;
326 
327  // This may fail if the dictionary hasn't been loaded yet,
328  // since we can auto-load only on the name.
329  // Make some attempt to get a name from the type_info.
330  const char* name = id.name();
331  cl = gROOT->GetClass (name);
332  if (cl) return cl;
333 
334  const char* n2 = name;
335  while (isdigit(*n2))
336  ++n2;
337  cl = gROOT->GetClass (n2);
338  if (cl) return cl;
339 
340  int errorCode = 0;
341  char* demname = nullptr;
342  {
343  // Protect against data race inside TClassEdit.
344  // https://github.com/root-project/root/issues/10353
345  // Should be fixed in root 6.26.02.
346  R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
347  demname = TClassEdit::DemangleTypeIdName (id, errorCode);
348  }
349  if (demname) {
350  cl = gROOT->GetClass (demname);
351  free (demname);
352  }
353  return cl;
354 }
355 
356 
369 {
370  // First check to see if the list of TStreamerInfo's for the transient
371  // class has changed since the last time we were called. If not,
372  // then don't do anything.
373  const TObjArray* trans_sis = fTransClass->GetStreamerInfos();
374  if (trans_sis->GetLast() != fOldLast) {
375  // There was a change. Compare the TStreamerInfo list for the
376  // persistent class and the transient class. Look for entries
377  // where the transient class has a TStreamerInfo but the persistent
378  // class does not.
379  //
380  // Note: don't do this for `version' -1.
381  // That should always be built from the internal dictionary.
382  // (Otherwise, root can crash.)
383  const TObjArray* pers_sis = fPersClass->GetStreamerInfos();
384  assert (trans_sis->LowerBound() == pers_sis->LowerBound());
385  for (Int_t v = trans_sis->LowerBound(); v <= trans_sis->GetLast(); ++v) {
386  if (v != -1 &&
387  trans_sis->At(v) != 0 &&
388  (v > pers_sis->GetLast() || pers_sis->At(v) == 0))
389  {
390  // Ok, at this index, the transient class has a TStreamerInfo
391  // but the persistent class does not. Copy the TStreamerInfo
392  // (changing the class that it applies to to the persistent
393  // class), and add it to the persistent class's list.
394  TStreamerInfo* new_si =(TStreamerInfo*)(trans_sis->At(v)->Clone());
395  new_si->SetClass (fPersClass);
396  fPersClass->RegisterStreamerInfo (new_si);
397  }
398  }
399 
400  // Remember how many entries there were in the list for next time.
401  fOldLast = trans_sis->GetLast();
402  }
403 }
404 
405 
413  : fTransClass (nullptr),
414  fPersClass (nullptr),
415  fCheckSum (0),
416  fOldLast (-3),
417  fPersObj (nullptr)
418 {
419 }
420 
421 
430 void TVirtualConverter::SetCtorInfo (UInt_t checksum,
431  TClass* trans_cls,
432  TClass* pers_cls)
433 {
434  assert (fTransClass == nullptr);
435 
436  fCheckSum = checksum;
437  fTransClass = trans_cls;
438  fPersClass = pers_cls;
439  CheckClasses();
440 }
PlotCalibFromCool.il
il
Definition: PlotCalibFromCool.py:381
TVirtualConverter::GetPersClass
TClass * GetPersClass()
Return the persistent class, from which we're converting.
Definition: TVirtualConverter.cxx:229
TVirtualConverter::ToClass
static TClass * ToClass(const std::string &name)
Helper to convert a class name to a Root class pointer.
Definition: TVirtualConverter.cxx:310
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
TVirtualConverter::GetCheckSum
int GetCheckSum() const
Return the checksum of the class from which we're converting.
Definition: TVirtualConverter.cxx:238
TVirtualConverter::fOldLast
int fOldLast
Used by CheckStreamInfos: the length of the streamerinfo list that we saw on the last CheckStreamInfo...
Definition: TVirtualConverter.h:265
TVirtualConverter::TVirtualConverter
TVirtualConverter()
Default constructor.
Definition: TVirtualConverter.cxx:412
LArDigits2NtupleDumper.tdt
tdt
Definition: LArDigits2NtupleDumper.py:138
TVirtualConverter::~TVirtualConverter
virtual ~TVirtualConverter()
Destructor.
Definition: TVirtualConverter.cxx:209
TVirtualConverter::ReadBuffer
virtual void ReadBuffer(TBuffer &b, void *obj, Version_t version, UInt_t R__S, UInt_t R__c)
Read object in non-split mode.
Definition: TVirtualConverter.cxx:282
TVirtualConverter.h
Base class for Root converters.
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
TVirtualConverter::fCheckSum
UInt_t fCheckSum
The declared checksum.
Definition: TVirtualConverter.h:261
TVirtualConverter::fTransClass
TClass * fTransClass
The declared transient class.
Definition: TVirtualConverter.h:255
TVirtualConverter::fPersObj
void * fPersObj
The temporary persistent object instance, used for conversions (in non-split mode).
Definition: TVirtualConverter.h:271
TVirtualConverter::CheckClasses
void CheckClasses()
Helper to check that the classes have been defined properly.
Definition: TVirtualConverter.cxx:188
lumiFormat.i
int i
Definition: lumiFormat.py:85
TVirtualConverter::CheckStreamInfos
void CheckStreamInfos()
Helper to allow for automatic schema evolution for persistent classes.
Definition: TVirtualConverter.cxx:368
TVirtualConverter::GetTransClass
TClass * GetTransClass()
Return the transient class, to which we're converting.
Definition: TVirtualConverter.cxx:220
TVirtualConverter::fPersClass
TClass * fPersClass
The declared persistent class.
Definition: TVirtualConverter.h:258
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
python.PyAthena.v
v
Definition: PyAthena.py:154
get_generator_info.version
version
Definition: get_generator_info.py:33
TVirtualConverter::SetCtorInfo
void SetCtorInfo(UInt_t checksum, TClass *trans_cls, TClass *pers_cls)
Set the parameters that would normally be passed to the constructor.
Definition: TVirtualConverter.cxx:430
TVirtualConverter::NewPersObj
virtual void * NewPersObj()
Create a new instance of the persistent class.
Definition: TVirtualConverter.cxx:250
TVirtualConverter::DeletePersObj
virtual void DeletePersObj(void *persobj)
Destroy an instance of the persistent class.
Definition: TVirtualConverter.cxx:263
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
python.PyAthena.obj
obj
Definition: PyAthena.py:132
TVirtualConverter::ConvertVoid
virtual void ConvertVoid(void *transobj, const void *persobj)=0
Do the conversion.
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25