ATLAS Offline Software
Loading...
Searching...
No Matches
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
11
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
26namespace {
27
28
38UInt_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),
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
164/**
165 * @brief Constructor, with class names.
166 * @param trans_cls The name of the transient class to which
167 * we will be converting.
168 * @param pers_cls The name of the persistent class from which
169 * we will be converting.
170 *
171 * The checksum will be calculated automatically from the provided classes.
172 */
173TVirtualConverter::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();
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
217/**
218 * @brief Return the transient class, to which we're converting.
219 */
221{
222 return fTransClass;
223}
224
225
226/**
227 * @brief Return the persistent class, from which we're converting.
228 */
230{
231 return fPersClass;
232}
233
239{
240 return fCheckSum;
241}
243
249 */
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)
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.
300 ConvertVoid (obj, fPersObj);
301}
302
303
310TClass* TVirtualConverter::ToClass (const std::string& name)
311{
312 return gROOT->GetClass (name.c_str());
313}
314
315
322TClass* 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
430void 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}
Base class for Root converters.
virtual void ReadBuffer(TBuffer &b, void *obj, Version_t version, UInt_t R__S, UInt_t R__c)
Read object in non-split mode.
TClass * fPersClass
The declared persistent class.
TClass * GetTransClass()
Return the transient class, to which we're converting.
virtual void * NewPersObj()
Create a new instance of the persistent class.
int fOldLast
Used by CheckStreamInfos: the length of the streamerinfo list that we saw on the last CheckStreamInfo...
virtual ~TVirtualConverter()
Destructor.
TVirtualConverter()
Default constructor.
virtual void DeletePersObj(void *persobj)
Destroy an instance of the persistent class.
void CheckStreamInfos()
Helper to allow for automatic schema evolution for persistent classes.
int GetCheckSum() const
Return the checksum of the class from which we're converting.
void SetCtorInfo(UInt_t checksum, TClass *trans_cls, TClass *pers_cls)
Set the parameters that would normally be passed to the constructor.
virtual void ConvertVoid(void *transobj, const void *persobj)=0
Do the conversion.
TClass * GetPersClass()
Return the persistent class, from which we're converting.
static TClass * ToClass(const std::string &name)
Helper to convert a class name to a Root class pointer.
void * fPersObj
The temporary persistent object instance, used for conversions (in non-split mode).
TClass * fTransClass
The declared transient class.
UInt_t fCheckSum
The declared checksum.
void CheckClasses()
Helper to check that the classes have been defined properly.
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]